blob: 37da8b6a6d2fe0c251f00572647c774b27822693 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module: Data.ConfigManager
-- License: GPL-3
-- Maintainer: Joris Guyonvarch <joris@guyonvarch.me>
-- Stability: experimental
--
-- A configuration management library.
module Data.ConfigManager
(
-- * Configuration file format
-- $format
-- ** Binding a name to a value
-- $bindings
-- ** Import other files
-- $import
-- ** Comments
-- $comments
-- ** Example
-- $example
-- * Configuration loading
readConfig
-- * Lookup functions
, lookup
, lookupDefault
) where
import Prelude hiding (lookup)
import Text.Read (readMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.HashMap.Strict as M
import qualified Data.ConfigManager.Reader as R
import Data.ConfigManager.Types
-- | Load a 'Config' from a given 'FilePath'.
readConfig :: FilePath -> IO (Either Text Config)
readConfig = R.readConfig Required
-- | Lookup for the value associated to a name.
lookup :: Read a => Name -> Config -> Either Text a
lookup name config =
case M.lookup name (hashMap config) of
Nothing ->
Left . T.concat $ ["Value not found for Key ", name]
Just value ->
case readMaybe . T.unpack $ value of
Nothing -> Left . T.concat $ ["Reading error for key ", name]
Just result -> Right result
-- | Lookup for the value associated to a name and return the default value if
-- no binding exists with the given name.
lookupDefault :: Read a => a -> Name -> Config -> a
lookupDefault defaultValue name config = foldl (flip const) defaultValue $ lookup name config
-- $format
--
-- A configuration file consists of a series of:
--
-- * bindings,
-- * imports,
-- * and comments.
-- $bindings
--
-- A binding associates a name to a value:
--
-- > number = 1
-- > my-string = "Hello"
-- > a_double = 4.0
-- > thatIsABoolean = True
-- > a_double = 5.0
--
-- If two or more bindings have the same name, only the last one is kept.
-- $import
--
-- An import is either required or optional:
--
-- > import "database.conf"
-- > importMaybe "local.conf"
-- $comments
--
-- A comment begins with '#' and continues to the end of the line:
--
-- > # Comment
-- > x = 8 # Another comment
-- $example
--
-- From application.conf:
--
-- > port = 3000
-- > mailFrom = "no-reply@mail.com"
-- > currency = "$"
--
-- Read the configuration:
--
-- > import qualified Data.ConfigManager as Conf
-- >
-- > data Conf = Conf
-- > { port :: Int
-- > , mailFrom :: String
-- > , currency :: String
-- > } deriving (Read, Eq, Show)
-- >
-- > getConfig :: IO (Either Text Conf)
-- > getConfig =
-- > (flip fmap) (Conf.readConfig "application.conf") (\configOrError -> do
-- > conf <- configOrError
-- > Conf <$>
-- > Conf.lookup "port" conf <*>
-- > Conf.lookup "mailFrom" conf <*>
-- > Conf.lookup "currency" conf
-- > )
|