configifier 0.0.8 → 0.1.0
raw patch · 3 files changed
+27/−25 lines, 3 files
Files
- configifier.cabal +1/−1
- src/Data/Configifier.hs +20/−18
- tests/Data/ConfigifierSpec.hs +6/−6
configifier.cabal view
@@ -1,5 +1,5 @@ name: configifier-version: 0.0.8+version: 0.1.0 synopsis: parser for config files, shell variables, command line args. description: See <https://github.com/zerobuzz/configifier/blob/master/README.md README> license: AGPL-3
src/Data/Configifier.hs view
@@ -117,7 +117,7 @@ data Source = YamlString SBS- | YamlFile FilePath -- FIXME: { yamlFilePath :: FilePath, yamlFileOptional :: Bool }+ | YamlFile { yamlFileOptional :: Bool, yamlFilePath :: FilePath } | ShellEnv [(String, String)] | CommandLine [String] deriving (Eq, Ord, Show, Typeable)@@ -208,7 +208,7 @@ get :: Source -> IO tm get (YamlString sbs) = run $ parseConfigFile sbs- get (YamlFile fpath) = parseConfigFileWithIncludes fpath >>= run+ get (YamlFile opt fpath) = parseConfigFileWithIncludes opt fpath >>= run get (ShellEnv env) = run $ parseShellEnv env get (CommandLine args) = run $ parseCommandLine args @@ -223,18 +223,15 @@ -- -- File path arguments are optiona; config paths to non-existent -- files are silently dropped.-defaultSources :: [FilePath] -> IO [Source]-defaultSources filePaths = do- files <- YamlFile <$$> filterM doesFileExist filePaths- env <- ShellEnv <$> (getEnvironment >>= withShellEnvPrefix)+defaultSources' :: String -> [FilePath] -> IO [Source]+defaultSources' progName filePaths = do+ files <- YamlFile False <$$> filterM doesFileExist filePaths+ env <- ShellEnv . withShellEnvPrefix progName <$> getEnvironment args <- CommandLine <$> getArgs return $ files ++ [env] ++ readUserConfigFiles [args] --- | Require that all shell env variables start with executable name.--- (This is just a call to 'requireShellEnvPrefix'' with the result of--- 'progName'.)-withShellEnvPrefix :: Env -> IO Env-withShellEnvPrefix env = (`withShellEnvPrefix'` env) <$> getProgName+defaultSources :: [FilePath] -> IO [Source]+defaultSources filePaths = getProgName >>= (`defaultSources'` filePaths) . (<> "_") -- * corner cases@@ -254,24 +251,24 @@ where f :: Source -> [Source] f s@(YamlString _) = [s]- f s@(YamlFile _) = [s]+ f s@(YamlFile _ _) = [s] f s@(ShellEnv _) = [s] f (CommandLine args) = filter (not . (== CommandLine [])) $ g [] args g :: [String] -> [String] -> [Source] g acc [] = [CommandLine (reverse acc)] g acc fresh@(freshHead:freshTail) = case popArg fresh of- Right (("config", v), fresh') -> CommandLine (reverse acc) : YamlFile v : g [] fresh'+ Right (("config", v), fresh') -> CommandLine (reverse acc) : YamlFile True v : g [] fresh' _ -> g (freshHead : acc) freshTail -- | Require prefix for shell env variables. This function will chop -- off the given prefix of all env entries, and filter all entries -- that do not have this prefix.-withShellEnvPrefix' :: String -> Env -> Env-withShellEnvPrefix' prefix = catMaybes . map f+withShellEnvPrefix :: String -> Env -> Env+withShellEnvPrefix prefix = catMaybes . map f where f (k, v) = if prefix `isPrefixOf` k- then Just (take (length prefix) k, v)+ then Just (drop (length prefix) k, v) else Nothing @@ -284,8 +281,13 @@ trunc s = if SBS.length s > l then SBS.take l s <> "..." else s -- | See "Data.Yaml.Include".-parseConfigFileWithIncludes :: (FromJSON (TaggedM cfg)) => FilePath -> IO (Either Error (TaggedM cfg))-parseConfigFileWithIncludes fpath = mapLeft (InvalidYamlFile fpath) <$> decodeFileEither fpath+parseConfigFileWithIncludes :: (Monoid (TaggedM cfg), FromJSON (TaggedM cfg)) =>+ Bool -> FilePath -> IO (Either Error (TaggedM cfg))+parseConfigFileWithIncludes optional fpath = f optional <$> decodeFileEither fpath+ where+ f _ (Right v) = Right v+ f True (Left _) = Right mempty+ f False (Left e) = Left $ InvalidYamlFile fpath e renderConfigFile :: (Freeze cfg, t ~ Tagged cfg, ToJSON (TaggedM cfg)) => t -> SBS renderConfigFile = Yaml.encode . thaw
tests/Data/ConfigifierSpec.hs view
@@ -209,7 +209,7 @@ it "(\"l\" :> Int :*> \"l'\" :> Int)" $ let t :: forall c . ( c ~ ToConfigCode ("l" :> Int :*> "l'" :> Int)- , ToVal c '["l"] ~ Just Int -- (redundant)+ , ToVal c '["l"] ~ 'Just Int -- (redundant) , ToConfig c Id ~ (Id Int :*> Id Int) -- (redundant) ) => IO () t = do@@ -223,7 +223,7 @@ it "(\"l\" :> Int :*> Maybe (\"l'\" :> Int))" $ let t :: forall c . ( c ~ ToConfigCode ("l" :> Int :*> Maybe ("l'" :> Int))- , ToVal c '["l"] ~ Just Int -- (redundant)+ , ToVal c '["l"] ~ 'Just Int -- (redundant) , ToConfig c Id ~ (Id Int :*> MaybeO (Id Int)) -- (redundant) ) => IO () t = do@@ -357,15 +357,15 @@ readUserConfigFilesSpec :: Spec readUserConfigFilesSpec = describe "readUserConfigFiles" $ do it "finds --config args" $- readUserConfigFiles [CommandLine ["--config=FILE"]] `shouldBe` [YamlFile "FILE"]+ readUserConfigFiles [CommandLine ["--config=FILE"]] `shouldBe` [YamlFile True "FILE"] it "keeps surrounding args intact" $ do readUserConfigFiles [CommandLine ["1", "2", "--config=FILE", "3", "4"]] `shouldBe`- [CommandLine ["1", "2"], YamlFile "FILE", CommandLine ["3", "4"]]+ [CommandLine ["1", "2"], YamlFile True "FILE", CommandLine ["3", "4"]] readUserConfigFiles [CommandLine ["--config=FILE", "2"]] `shouldBe`- [YamlFile "FILE", CommandLine ["2"]]+ [YamlFile True "FILE", CommandLine ["2"]] readUserConfigFiles [CommandLine ["1", "--config=FILE"]] `shouldBe`- [CommandLine ["1"], YamlFile "FILE"]+ [CommandLine ["1"], YamlFile True "FILE"] stringAsCharList :: Spec