summaryrefslogtreecommitdiffhomepage
path: root/lib/Language/Haskell/Stylish/Config.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Language/Haskell/Stylish/Config.hs')
-rw-r--r--lib/Language/Haskell/Stylish/Config.hs68
1 files changed, 54 insertions, 14 deletions
diff --git a/lib/Language/Haskell/Stylish/Config.hs b/lib/Language/Haskell/Stylish/Config.hs
index 8f43131..475a5e3 100644
--- a/lib/Language/Haskell/Stylish/Config.hs
+++ b/lib/Language/Haskell/Stylish/Config.hs
@@ -16,24 +16,29 @@ import Data.Aeson (FromJSON (..)
import qualified Data.Aeson as A
import qualified Data.Aeson.Types as A
import qualified Data.ByteString as B
+import Data.ByteString.Lazy (fromStrict)
+import Data.Char (toLower)
import qualified Data.FileEmbed as FileEmbed
import Data.List (intercalate,
nub)
import Data.Map (Map)
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
-import Data.Yaml (decodeEither',
- prettyPrintParseException)
+import qualified Data.Text as T
+import Data.YAML (prettyPosWithSource)
+import Data.YAML.Aeson (decode1Strict)
import System.Directory
import System.FilePath ((</>))
import qualified System.IO as IO (Newline (..),
nativeNewline)
+import Text.Read (readMaybe)
--------------------------------------------------------------------------------
import qualified Language.Haskell.Stylish.Config.Cabal as Cabal
import Language.Haskell.Stylish.Config.Internal
import Language.Haskell.Stylish.Step
+import qualified Language.Haskell.Stylish.Step.Data as Data
import qualified Language.Haskell.Stylish.Step.Imports as Imports
import qualified Language.Haskell.Stylish.Step.LanguagePragmas as LanguagePragmas
import qualified Language.Haskell.Stylish.Step.SimpleAlign as SimpleAlign
@@ -51,7 +56,7 @@ type Extensions = [String]
--------------------------------------------------------------------------------
data Config = Config
{ configSteps :: [Step]
- , configColumns :: Int
+ , configColumns :: Maybe Int
, configLanguageExtensions :: [String]
, configNewline :: IO.Newline
, configCabal :: Bool
@@ -80,12 +85,10 @@ configFilePath verbose Nothing = do
current <- getCurrentDirectory
configPath <- getXdgDirectory XdgConfig "stylish-haskell"
home <- getHomeDirectory
- mbConfig <- search verbose $
+ search verbose $
[d </> configFileName | d <- ancestors current] ++
[configPath </> "config.yaml", home </> configFileName]
- return mbConfig
-
search :: Verbose -> [FilePath] -> IO (Maybe FilePath)
search _ [] = return Nothing
search verbose (f : fs) = do
@@ -100,9 +103,8 @@ loadConfig verbose userSpecified = do
mbFp <- configFilePath verbose userSpecified
verbose $ "Loading configuration at " ++ fromMaybe "<embedded>" mbFp
bytes <- maybe (return defaultConfigBytes) B.readFile mbFp
- case decodeEither' bytes of
- Left err -> error $
- "Language.Haskell.Stylish.Config.loadConfig: " ++ prettyPrintParseException err
+ case decode1Strict bytes of
+ Left (pos, err) -> error $ prettyPosWithSource pos (fromStrict bytes) ("Language.Haskell.Stylish.Config.loadConfig: " ++ err)
Right config -> do
cabalLanguageExtensions <- if configCabal config
then map show <$> Cabal.findLanguageExtensions verbose
@@ -120,7 +122,7 @@ parseConfig (A.Object o) = do
-- First load the config without the actual steps
config <- Config
<$> pure []
- <*> (o A..:? "columns" A..!= 80)
+ <*> (o A..:! "columns" A..!= Just 80)
<*> (o A..:? "language_extensions" A..!= [])
<*> (o A..:? "newline" >>= parseEnum newlines IO.nativeNewline)
<*> (o A..:? "cabal" A..!= True)
@@ -142,6 +144,7 @@ parseConfig _ = mzero
catalog :: Map String (Config -> A.Object -> A.Parser Step)
catalog = M.fromList
[ ("imports", parseImports)
+ , ("records", parseRecords)
, ("language_pragmas", parseLanguagePragmas)
, ("simple_align", parseSimpleAlign)
, ("squash", parseSquash)
@@ -181,6 +184,28 @@ parseSimpleAlign c o = SimpleAlign.step
where
withDef f k = fromMaybe (f SimpleAlign.defaultConfig) <$> (o A..:? k)
+--------------------------------------------------------------------------------
+parseRecords :: Config -> A.Object -> A.Parser Step
+parseRecords _ o = Data.step
+ <$> (Data.Config
+ <$> (o A..: "equals" >>= parseIndent)
+ <*> (o A..: "first_field" >>= parseIndent)
+ <*> (o A..: "field_comment")
+ <*> (o A..: "deriving"))
+
+
+parseIndent :: A.Value -> A.Parser Data.Indent
+parseIndent = A.withText "Indent" $ \t ->
+ if t == "same_line"
+ then return Data.SameLine
+ else
+ if "indent " `T.isPrefixOf` t
+ then
+ case readMaybe (T.unpack $ T.drop 7 t) of
+ Just n -> return $ Data.Indent n
+ Nothing -> fail $ "Indent: not a number" <> T.unpack (T.drop 7 t)
+ else fail $ "can't parse indent setting: " <> T.unpack t
+
--------------------------------------------------------------------------------
parseSquash :: Config -> A.Object -> A.Parser Step
@@ -200,9 +225,9 @@ parseImports config o = Imports.step
-- Note that padding has to be at least 1. Default is 4.
<*> (o A..:? "empty_list_align"
>>= parseEnum emptyListAligns (def Imports.emptyListAlign))
- <*> o A..:? "list_padding" A..!= (def Imports.listPadding)
- <*> o A..:? "separate_lists" A..!= (def Imports.separateLists)
- <*> o A..:? "space_surround" A..!= (def Imports.spaceSurround))
+ <*> o A..:? "list_padding" A..!= def Imports.listPadding
+ <*> o A..:? "separate_lists" A..!= def Imports.separateLists
+ <*> o A..:? "space_surround" A..!= def Imports.spaceSurround)
where
def f = f Imports.defaultOptions
@@ -237,8 +262,9 @@ parseLanguagePragmas :: Config -> A.Object -> A.Parser Step
parseLanguagePragmas config o = LanguagePragmas.step
<$> pure (configColumns config)
<*> (o A..:? "style" >>= parseEnum styles LanguagePragmas.Vertical)
- <*> o A..:? "align" A..!= True
+ <*> o A..:? "align" A..!= True
<*> o A..:? "remove_redundant" A..!= True
+ <*> mkLanguage o
where
styles =
[ ("vertical", LanguagePragmas.Vertical)
@@ -248,6 +274,19 @@ parseLanguagePragmas config o = LanguagePragmas.step
--------------------------------------------------------------------------------
+-- | Utilities for validating language prefixes
+mkLanguage :: A.Object -> A.Parser String
+mkLanguage o = do
+ lang <- o A..:? "language_prefix"
+ maybe (pure "LANGUAGE") validate lang
+ where
+ validate :: String -> A.Parser String
+ validate s
+ | fmap toLower s == "language" = pure s
+ | otherwise = fail "please provide a valid language prefix"
+
+
+--------------------------------------------------------------------------------
parseTabs :: Config -> A.Object -> A.Parser Step
parseTabs _ o = Tabs.step
<$> o A..:? "spaces" A..!= 8
@@ -262,3 +301,4 @@ parseTrailingWhitespace _ _ = return TrailingWhitespace.step
parseUnicodeSyntax :: Config -> A.Object -> A.Parser Step
parseUnicodeSyntax _ o = UnicodeSyntax.step
<$> o A..:? "add_language_pragma" A..!= True
+ <*> mkLanguage o