Added basic README
Getty Ritter
8 years ago
| 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. |