gdritter repos config-ini / deb55ff
Added basic README Getty Ritter 7 years ago
1 changed file(s) with 58 addition(s) and 0 deletion(s). Collapse all Expand all
1 # `config-ini`
2
3 The `config-ini` library is a Haskell library for doing elementary INI file parsing in a quick and painless way.
4
5 ## Basic Usage
6
7 The `config-ini` library exports some simple monadic functions to make parsing INI-like configuration easier. INI files have a two-level structure: the top-level named chunks of configuration, and the individual key-value pairs contained within those chunks. For example, the following INI file has two sections, `NETWORK` and `LOCAL`, and each section contains its own key-value pairs separated by either `=` or `:`. Comments, which begin with `#` or `;`, are ignored:
8
9 ~~~.ini
10 [NETWORK]
11 host = example.com
12 port = 7878
13
14 # here is a comment
15 [LOCAL]
16 user = terry
17 ~~~
18
19 The combinators provided here are designed to write quick and idiomatic parsers for basic INI files. Sections are parsed by `IniParser` computations, like `section` and its variations, while the fields within sections are parsed by `SectionParser` computations, like `field` and its variations. If we want to parse an INI file like the one above, treating the entire `LOCAL` section as optional, we can write it like this:
20
21 ~~~.haskell
22 data Config = Config
23 { cfNetwork :: NetworkConfig, cfLocal :: Maybe LocalConfig }
24 deriving (Eq, Show)
25
26 data NetworkConfig = NetworkConfig
27 { netHost :: String, netPort :: Int }
28 deriving (Eq, Show)
29
30 data LocalConfig = LocalConfig
31 { localUser :: Text }
32 deriving (Eq, Show)
33
34 configParser :: IniParser Config
35 configParser = do
36 netCf <- section "NETWORK" $ do
37 host <- fieldOf "host" string
38 port <- fieldOf "port" number
39 return NetworkConfig { netHost = host, netPort = port }
40 locCf <- sectionMb "LOCAL" $
41 LocalConfig <$field "user"
42 return Config { cfNetwork = netCf, cfLocal = locCf }
43 ~~~
44
45 We can run our computation with `parseIniFile`, which, when run on our example file above, would produce the following:
46
47 ~~~.haskell
48 >>> parseIniFile example configParser
49 Right (Config {cfNetwork = NetworkConfig {netHost = "example.com", netPort = 7878}, cfLocal = Just (LocalConfig {localUser = "terry"})})
50 ~~~
51
52 ## Combinators and Conventions
53
54 There are several variations on the same basic functionality that appear in `config-ini`. All functions that start with `section` are for parsing section-level chunks of an INI file, while all functions that start with `field` are for parsing key-value pairs within a section. Because it's reasonably common, there are also special `fieldFlag` functions which return `Bool` values, parsed in a relatively loose way.
55
56 All functions which end in `Mb` return a `Maybe` value, returning `Nothing` if the section or key was not found. All functions which end in `Def` take an additional default value, returning it if the section or key was not found. All functions which contain `Of` take a function of the type `Text -> Either String a`, which is used to attempt to decode or parse the extracted value.
57
58 In total, there are three section-level parsers (`section`, `sectionMb`, and `sectionDef`) and eight field-level parsers (`field`, `fieldOf`, `fieldMb`, `fieldMbOf`, `fieldDef`, `fieldDefOf`, `fieldFlag`, `fieldFlagDef`). For the `_Of` functions, `config-ini` also provides several built-in parser functions which provide nice error messages on failure.