https://github.com/apirogov/yaml-conf
Simple library to turn record types into a flexible YAML-based configuration
https://github.com/apirogov/yaml-conf
Last synced: over 1 year ago
JSON representation
Simple library to turn record types into a flexible YAML-based configuration
- Host: GitHub
- URL: https://github.com/apirogov/yaml-conf
- Owner: apirogov
- License: bsd-3-clause
- Created: 2017-09-02T16:52:15.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2017-09-04T18:48:03.000Z (almost 9 years ago)
- Last Synced: 2025-01-09T20:00:55.271Z (over 1 year ago)
- Language: Haskell
- Homepage:
- Size: 13.7 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# yaml-conf [](https://travis-ci.org/apirogov/yaml-conf)
You are looking for a configuration solution that:
* works with your own record-style datatype?
* does not require much additional work?
* integrates well with argument parsing?
* allows to obtain a configuration merging settings from multiple sources?
Then look no more! Look at this example program:
```haskell
{-# LANGUAGE TemplateHaskell, MultiParamTypeClasses, FunctionalDependencies #-}
module Main where
import Data.Monoid
import Options.Applicative
import Data.Default
import Data.Yaml.Conf
data SubConf = SubConf {
_uno :: Int
, _dos :: String
} deriving (Show)
---- only four magic lines required per Conf type:
instance Default SubConf where
def = SubConf 0 "default"
makeConfig ''SubConf
deriveConfigJSON ''SubConf
----
data TestConf = TestConf {
_foo :: Bool
, _bar :: SubConf
} deriving (Show)
---- for the main configuration type too:
instance Default TestConf where
def = TestConf False def
makeConfig ''TestConf
deriveConfigJSON ''TestConf
----
-- yaml-conf can take any action that returns a configuration as input...
argsParser :: IO TestConf
argsParser = execParser $ info (parseArgs <**> helper)
(fullDesc <> progDesc "yaml-conf demo")
-- ... so you can provide for example your optparse-applicative parser,
-- after ensuring that uses the specified default values.
parseArgs :: Parser TestConf
parseArgs = TestConf
<$> switch (long "foo" <> short 'f' <> help "foo blub")
<*> (SubConf
<$> option auto (long "uno" <> short 'u' <> value (_uno def))
<*> option str (long "dos" <> short 'd' <> value (_dos def))
)
main :: IO ()
main = do
let progname = "yaml-conf-demo"
let confname = "config"
putStrLn "Default configuration:"
print (def::TestConf)
putStrLn "Default file locations (descending priority):"
print =<< defaultConfPaths progname confname
sources <- addConfSource argsParser <$> defaultConfSources progname confname
putStrLn "Loaded configuration diffs (ascending priority):"
print =<< sequence sources
putStrLn "Resulting Conf:"
conf <- loadConf sources
print conf
```
The program defines a main configuration record type, TestConf,
and a nested sub-configuration, SubConf. The only thing required from you is to
provide default instances and issue the two Template Haskell incantations. The
rest ist done for you automatically!
Now you can obtain a configuration stitched together from multiple sources,
including multiple locations of files and e.g. an optparse-applicative parser. The
only thing that you need to buy into is the fact that the configuration files
are in YAML-format. A valid configuration for the program above looks like this:
```
foo: true
bar:
dos: "local override"
```
You can place such a configuration into e.g. `~/.config/yaml-conf-demo/config.yaml`.
Notice, that each field of a record marked as a configuration is optional and can be omitted,
you just need to put values for fields you want to override from lower priority
or the default configuration.
For a better understanding, just run this demo application and observe the output.