1{-# LANGUAGE UndecidableInstances, OverlappingInstances #-}
2{-
3Copyright (C) 2004-2008 John Goerzen <jgoerzen@complete.org>
4
5This program is free software; you can redistribute it and/or modify it, as
6specified in the COPYRIGHT file, under the terms of either version 2.1 of
7the LGPL (or, at your option, any later version) or the 3-clause BSD license.
8-}
9
10{- |
11   Module     : Data.ConfigFile
12   Copyright  : Copyright (C) 2004-2008 John Goerzen
13   License    : Either LGPL or BSD3, as specified in the COPYRIGHT file.
14
15   Maintainer : John Goerzen <jgoerzen@complete.org>
16   Stability  : provisional
17   Portability: portable
18
19Configuration file parsing, generation, and manipulation
20
21Copyright (c) 2004-2008 John Goerzen, jgoerzen\@complete.org
22
23This program is distributed in the hope that it will be useful,
24but WITHOUT ANY WARRANTY; without even the implied warranty of
25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26
27This module contains extensive documentation.  Please scroll down to the Introduction section to continue reading.
28-}
29module Data.ConfigFile
30    (
31     -- * Introduction
32     -- $introduction
33
34     -- ** Features
35     -- $features
36
37     -- ** History
38     -- $history
39
40     -- * Configuration File Format
41     -- $format
42
43     -- ** White Space
44     -- $whitespace
45
46     -- ** Comments
47     -- $comments
48
49     -- ** Case Sensitivity
50     -- $casesens
51
52     -- ** Interpolation
53     -- $interpolation
54
55     -- * Usage Examples
56     -- $usage
57
58     -- ** Non-Monadic Usage
59     -- $usagenomonad
60
61     -- ** Error Monad Usage
62     -- $usageerrormonad
63
64     -- ** Combined Error\/IO Monad Usage
65     -- $usageerroriomonad
66
67     -- * Types
68     -- $types
69     SectionSpec, OptionSpec, ConfigParser(..),
70     CPErrorData(..), CPError,
71     -- * Initialization
72     -- $initialization
73     emptyCP,
74
75     -- * Configuring the ConfigParser
76     -- $configuringcp
77
78     -- ** Access Functions
79     simpleAccess, interpolatingAccess,
80
81     -- * Reading
82     -- $reading
83     readfile, readhandle, readstring,
84
85     -- * Accessing Data
86     Get_C(..),
87     sections, has_section,
88     options, has_option,
89     items,
90
91     -- * Modifying Data
92     set, setshow, remove_option,
93     add_section, remove_section,
94     merge,
95
96     -- * Output Data
97     to_string
98
99    ) where
100
101import Data.ConfigFile.Types
102import Data.ConfigFile.Parser
103import Data.Either.Utils
104import Data.String.Utils
105import qualified Data.Map as Map
106import Data.List
107import System.IO(Handle)
108import Data.Char
109import Control.Monad.Error
110
111-- For interpolatingAccess
112import Text.ParserCombinators.Parsec.Error (errorMessages, Message(..))
113import Text.ParserCombinators.Parsec (parse)
114
115----------------------------------------------------------------------
116-- Basic types / default values
117----------------------------------------------------------------------
118
119{- | The default empty 'Data.ConfigFile' object.
120
121The content contains only an empty mandatory @DEFAULT@ section.
122
123'optionxform' is set to @map toLower@.
124
125'usedefault' is set to @True@.
126
127'accessfunc' is set to 'simpleAccess'.
128-}
129emptyCP :: ConfigParser
130emptyCP = ConfigParser { content = fromAL [("DEFAULT", [])],
131                       defaulthandler = defdefaulthandler,
132                       optionxform = map toLower,
133                       usedefault = True,
134                       accessfunc = simpleAccess}
135
136{- | Low-level tool to convert a parsed object into a 'CPData'
137representation.  Performs no option conversions or special handling
138of @DEFAULT@. -}
139fromAL :: ParseOutput -> CPData
140fromAL origal =
141    let conv :: CPData -> (String, [(String, String)]) -> CPData
142        conv fm sect = Map.insert (fst sect) (Map.fromList $ snd sect) fm
143        in
144        foldl conv Map.empty origal
145
146{- | Default (non-interpolating) access function -}
147simpleAccess ::  MonadError CPError m =>
148                 ConfigParser -> SectionSpec -> OptionSpec -> m String
149simpleAccess cp s o = defdefaulthandler cp s (optionxform cp $ o)
150
151{- | Interpolating access function.  Please see the Interpolation section
152above for a background on interpolation.
153
154Although the format string looks similar to one used by "Text.Printf",
155it is not the same.  In particular, only the %(...)s format is supported.
156No width specifiers are supported and no conversions other than s are supported.
157
158To use this function, you must specify a maximum recursion depth for
159interpolation.  This is used to prevent a stack overflow in the event that
160the configuration file contains an endless interpolation loop.  Values of 10
161or so are usually more than enough, though you could probably go into the
162hundreds or thousands before you have actual problems.
163
164A value less than one will cause an instant error every time you attempt
165a lookup.
166
167This access method can cause 'get' and friends to return a new 'CPError':
168'InterpolationError'.  This error would be returned when:
169
170 * The configuration file makes a reference to an option that does
171   not exist
172
173 * The maximum interpolation depth is exceeded
174
175 * There is a syntax error processing a %-directive in the configuration
176   file
177
178An interpolation lookup name specifies an option only.  There is no provision
179to specify a section.  Interpolation variables are looked up in the current
180section, and, if 'usedefault' is True, in @DEFAULT@ according to the normal
181logic.
182
183To use a literal percent sign, you must place @%%@ in the configuration
184file when interpolation is used.
185
186Here is how you might enable interpolation:
187
188>let cp2 = cp {accessfunc = interpolatingAccess 10}
189
190The @cp2@ object will now support interpolation with a maximum depth of 10.
191 -}
192interpolatingAccess :: MonadError CPError m =>
193                       Int ->
194                       ConfigParser -> SectionSpec -> OptionSpec
195                       -> m String
196
197interpolatingAccess maxdepth cp s o =
198    if maxdepth < 1
199       then interError "maximum interpolation depth exceeded"
200       else do x <- simpleAccess cp s o
201               case parse (interpmain $ lookupfunc) (s ++ "/" ++ o) x of
202                 Left y -> case head (errorMessages y) of
203                                Message z -> interError z
204                                _ -> interError (show y)
205                 Right y -> return y
206    where
207    lookupfunc = interpolatingAccess (maxdepth - 1) cp s
208    interError x = throwError (InterpolationError x, "interpolatingAccess")
209
210-- internal function: default handler
211defdefaulthandler ::  MonadError CPError m =>
212                      ConfigParser -> SectionSpec -> OptionSpec -> m String
213
214defdefaulthandler cp sectn opt =
215    let fm = content cp
216        lookUp s o = do sect <- maybeToEither (NoSection s,
217                                               "get " ++ formatSO sectn opt) $
218                                Map.lookup s fm
219                        maybeToEither (NoOption o,
220                                       "get " ++ formatSO sectn opt) $
221                                Map.lookup o sect
222        trydefault e = if (usedefault cp)
223                       then
224                            lookUp "DEFAULT" opt
225                                       -- Use original error if it's not in DEFAULT either
226                                       `catchError` (\_ -> throwError e)
227                       else throwError e
228        in
229        lookUp sectn opt `catchError` trydefault
230
231
232{- | Combines two 'ConfigParser's into one.
233
234Any duplicate options are resolved to contain the value specified in
235the second parser.
236
237The 'ConfigParser' options in the resulting object will be set as they
238are in the second one passed to this function. -}
239merge :: ConfigParser -> ConfigParser -> ConfigParser
240merge src dest =
241    let conv :: String -> String
242        conv = optionxform dest
243        convFM :: CPOptions -> CPOptions
244        convFM = Map.fromList . map (\x -> (conv (fst x), snd x)) . Map.toList
245        mergesects a b = Map.union a b
246        in
247        dest { content = Map.unionWith mergesects
248                         (content dest) (Map.map convFM (content src)) }
249
250{- | Utility to do a special case merge. -}
251readutil :: ConfigParser -> ParseOutput -> ConfigParser
252readutil old new = merge old $ old { content = fromAL new }
253
254{- | Loads data from the specified file.  It is then combined with the
255given 'ConfigParser' using the semantics documented under 'merge' with the
256new data taking precedence over the old.  However, unlike
257'merge', all the options
258as set in the old object are preserved since the on-disk representation
259does not convey those options.
260
261May return an error if there is a syntax error.  May raise an exception if the file could not be accessed.
262-}
263--readfile :: ConfigParser -> FilePath ->IO (CPResult ConfigParser)
264readfile :: MonadError CPError m => ConfigParser -> FilePath -> IO (m ConfigParser)
265{-
266readfile cp fp = do n <- parse_file fp
267                    return $ do y <- n
268                                return $ readutil cp y
269-}
270readfile cp fp = do n <- parse_file fp
271                    return $ n >>= (return . readutil cp)
272
273{- | Like 'readfile', but uses an already-open handle.  You should
274use 'readfile' instead of this if possible, since it will be able to
275generate better error messages.
276
277Errors would be returned on a syntax error.
278-}
279--readhandle :: ConfigParser -> Handle -> IO (CPResult ConfigParser)
280readhandle :: MonadError CPError m => ConfigParser -> Handle -> IO (m ConfigParser)
281readhandle cp h = do n <- parse_handle h
282                     return $ n >>= (return . (readutil cp))
283
284{- | Like 'readfile', but uses a string.  You should use 'readfile'
285instead of this if you are processing a file, since it can generate
286better error messages.
287
288Errors would be returned on a syntax error.
289-}
290readstring ::  MonadError CPError m =>
291               ConfigParser -> String -> m ConfigParser
292readstring cp s = do
293                  n <- parse_string s
294                  return $ readutil cp n
295
296{- | Returns a list of sections in your configuration file.  Never includes
297the always-present section @DEFAULT@. -}
298sections :: ConfigParser -> [SectionSpec]
299sections = filter (/= "DEFAULT") . Map.keys . content
300
301{- | Indicates whether the given section exists.
302
303No special @DEFAULT@ processing is done. -}
304has_section :: ConfigParser -> SectionSpec -> Bool
305has_section cp x = Map.member x (content cp)
306
307{- | Adds the specified section name.  Returns a
308'SectionAlreadyExists' error if the
309section was already present.  Otherwise, returns the new
310'ConfigParser' object.-}
311add_section ::  MonadError CPError m =>
312                ConfigParser -> SectionSpec -> m ConfigParser
313add_section cp s =
314    if has_section cp s
315       then throwError $ (SectionAlreadyExists s, "add_section")
316       else return $ cp {content = Map.insert s Map.empty (content cp)}
317
318{- | Removes the specified section.  Returns a 'NoSection' error if
319the section does not exist; otherwise, returns the new 'ConfigParser'
320object.
321
322This call may not be used to remove the @DEFAULT@ section.  Attempting to do
323so will always cause a 'NoSection' error.
324 -}
325remove_section ::  MonadError CPError m =>
326                   ConfigParser -> SectionSpec -> m ConfigParser
327remove_section _ "DEFAULT" = throwError $ (NoSection "DEFAULT", "remove_section")
328remove_section cp s =
329    if has_section cp s
330       then return $ cp {content = Map.delete s (content cp)}
331       else throwError $ (NoSection s, "remove_section")
332
333{- | Removes the specified option.  Returns a 'NoSection' error if the
334section does not exist and a 'NoOption' error if the option does not
335exist.  Otherwise, returns the new 'ConfigParser' object.
336-}
337remove_option ::  MonadError CPError m =>
338                  ConfigParser -> SectionSpec -> OptionSpec -> m ConfigParser
339remove_option cp s passedo =
340    do sectmap <- maybeToEither (NoSection s,
341                                 "remove_option " ++ formatSO s passedo) $
342                  Map.lookup s (content cp)
343       let o = (optionxform cp) passedo
344       let newsect = Map.delete o sectmap
345       let newmap = Map.insert s newsect (content cp)
346       if Map.member o sectmap
347          then return $ cp {content = newmap}
348          else throwError $ (NoOption o,
349                             "remove_option " ++ formatSO s passedo)
350
351{- | Returns a list of the names of all the options present in the
352given section.
353
354Returns an error if the given section does not exist.
355-}
356options ::  MonadError CPError m =>
357            ConfigParser -> SectionSpec -> m [OptionSpec]
358options cp x = maybeToEither (NoSection x, "options") $
359               do
360               o <- Map.lookup x (content cp)
361               return $ Map.keys o
362
363{- | Indicates whether the given option is present.  Returns True
364only if the given section is present AND the given option is present
365in that section.  No special @DEFAULT@ processing is done.  No
366exception could be raised or error returned.
367-}
368has_option :: ConfigParser -> SectionSpec -> OptionSpec -> Bool
369has_option cp s o =
370    let c = content cp
371        v = do secthash <- Map.lookup s c
372               return $ Map.member (optionxform cp $ o) secthash
373        in maybe False id v
374
375{- | The class representing the data types that can be returned by "get".
376-}
377class Get_C a where
378    {- | Retrieves a string from the configuration file.
379
380When used in a context where a String is expected, returns that string verbatim.
381
382When used in a context where a Bool is expected, parses the string to
383a Boolean value (see logic below).
384
385When used in a context where anything that is an instance of Read is expected,
386calls read to parse the item.
387
388An error will be returned of no such option could be found or if it could
389not be parsed as a boolean (when returning a Bool).
390
391When parsing to a Bool, strings are case-insentively converted as follows:
392
393The following will produce a True value:
394
395 * 1
396
397 * yes
398
399 * on
400
401 * enabled
402
403 * true
404
405The following will produce a False value:
406
407 * 0
408
409 * no
410
411 * off
412
413 * disabled
414
415 * false -}
416    get :: MonadError CPError m => ConfigParser -> SectionSpec -> OptionSpec -> m a
417
418instance Get_C String where
419    get cp s o = eitherToMonadError $ (accessfunc cp) cp s o
420
421instance Get_C Bool where
422    get = getbool
423
424instance Read t => Get_C t where
425    get = genericget
426
427-- Based on code from Neil Mitchell's safe-0.3.3 package.
428readMaybe :: Read a => String -> Maybe a
429readMaybe s = case [x | (x, t) <- reads s, ("","") <- lex t] of
430                [x] -> Just x
431                _   -> Nothing
432
433genericget :: (Read b, MonadError CPError m) => ConfigParser -> SectionSpec -> OptionSpec -> m b
434genericget cp s o = do
435    val <- get cp s o
436    let errMsg = "couldn't parse value " ++ val ++ " from " ++ formatSO s o
437    maybe (throwError (ParseError errMsg, "genericget"))
438          return
439          $ readMaybe val
440
441getbool ::  MonadError CPError m =>
442            ConfigParser -> SectionSpec -> OptionSpec -> m Bool
443getbool cp s o =
444    do val <- get cp s o
445       case map toLower . strip $ val of
446                  "1" -> return True
447                  "yes" -> return True
448                  "on" -> return True
449                  "enabled" -> return True
450                  "true" -> return True
451                  "0" -> return False
452                  "no" -> return False
453                  "off" -> return False
454                  "disabled" -> return False
455                  "false" -> return False
456                  _ -> throwError (ParseError $ "couldn't parse bool " ++
457                                   val ++ " from " ++ formatSO s o, "getbool")
458
459formatSO :: [Char] -> [Char] -> [Char]
460formatSO s o =
461    "(" ++ s ++ "/" ++ o ++ ")"
462
463
464{- | Returns a list of @(optionname, value)@ pairs representing the content
465of the given section.  Returns an error the section is invalid. -}
466items ::  MonadError CPError m =>
467          ConfigParser -> SectionSpec -> m [(OptionSpec, String)]
468items cp s = do fm <- maybeToEither (NoSection s, "items") $
469                      Map.lookup s (content cp)
470                return $ Map.toList fm
471
472{- | Sets the option to a new value, replacing an existing one if it exists.
473
474Returns an error if the section does not exist. -}
475set ::  MonadError CPError m =>
476        ConfigParser -> SectionSpec -> OptionSpec -> String -> m ConfigParser
477set cp s passedo val =
478    do sectmap <- maybeToEither (NoSection s, "set " ++ formatSO s passedo) $
479                  Map.lookup s (content cp)
480       let o = (optionxform cp) passedo
481       let newsect = Map.insert o val sectmap
482       let newmap = Map.insert s newsect (content cp)
483       return $ cp { content = newmap}
484
485{- | Sets the option to a new value, replacing an existing one if it exists.
486It requires only a showable value as its parameter.
487This can be used with bool values, as well as numeric ones.
488
489Returns an error if the section does not exist. -}
490setshow :: (Show a, MonadError CPError m) =>
491           ConfigParser -> SectionSpec -> OptionSpec -> a -> m ConfigParser
492setshow cp s o val = set cp s o (show val)
493
494{- | Converts the 'ConfigParser' to a string representation that could be
495later re-parsed by this module or modified by a human.
496
497Note that this does not necessarily re-create a file that was originally
498loaded.  Things may occur in a different order, comments will be removed,
499etc.  The conversion makes an effort to make the result human-editable,
500but it does not make an effort to make the result identical to the original
501input.
502
503The result is, however, guaranteed to parse the same as the original input.
504 -}
505to_string :: ConfigParser -> String
506to_string cp =
507    let gen_option (key, value) =
508            key ++ ": " ++ (replace "\n" "\n    " value) ++ "\n"
509        gen_section (sect, valfm) = -- gen a section, but omit DEFAULT if empty
510            if (sect /= "DEFAULT") || (Map.size valfm > 0)
511               then "[" ++ sect ++ "]\n" ++
512                        (concat $ map gen_option (Map.toList valfm)) ++ "\n"
513               else ""
514        in
515        concat $ map gen_section (Map.toList (content cp))
516
517----------------------------------------------------------------------
518-- Docs
519----------------------------------------------------------------------
520
521{- $introduction
522
523Many programs need configuration files. These configuration files are
524typically used to configure certain runtime behaviors that need to be
525saved across sessions. Various different configuration file formats
526exist.
527
528The ConfigParser module attempts to define a standard format that is
529easy for the user to edit, easy for the programmer to work with, yet
530remains powerful and flexible.
531-}
532
533{- $features
534
535For the programmer, this module provides:
536
537 * Simple calls to both read /and write/ configuration files
538
539 * Call that can generate a string version of a file that is
540   re-parsable by this module (useful for, for instance, sending the
541   file down a network)
542
543 * Segmented configuration files that let you separate configuration
544   into distinct sections, each with its own namespace. This can be
545   used to configure multiple modules in one file, to configure
546   multiple instances of a single object, etc.
547
548 * On-the-fly parsing of integer, boolean, float, multi-line string values,
549   and anything else Haskell's read can deal with
550
551 * It is possible to make a configuration file parsable by this
552   module, the Unix shell, and\/or Unix make, though some feautres are,
553   of course, not compatible with these other tools.
554
555 * Syntax checking with error reporting including line numbers
556
557 * Implemented in pure Haskell.  No dependencies on modules outside
558   the standard library distributed with Haskell compilers or interpreters.
559   All calls except those that read directly from a handle are pure calls
560   and can be used outside the IO monad.
561
562 * Comprehensive documentation
563
564 * Extensible API
565
566 * Complete compatibility with Python's ConfigParser module, or my
567   ConfigParser module for OCaml, part of my MissingLib package.
568
569For the user, this module provides:
570
571 * Easily human-editable configuration files with a clear, concise,
572   and consistent format
573
574 * Configuration file format consistent with other familiar formats
575   (\/etc\/passwd is a valid ConfigParser file)
576
577 * No need to understand semantics of markup languages like XML
578-}
579
580{- $history
581
582This module is based on Python's ConfigParser module at
583<http://www.python.org/doc/current/lib/module-ConfigParser.html>.  I had
584earlier developed an OCaml implementation as part of my MissingLib library
585at <gopher://gopher.quux.org/devel/missinglib>.
586
587While the API of these three modules is similar, and the aim is to preserve all
588useful features of the original Python module, there are some differences
589in the implementation details.  This module is a complete, clean re-implementation
590in Haskell, not a Haskell translation of a Python program.  As such, the feature
591set is slightly different.
592-}
593
594{- $format
595
596The basic configuration file format resembles that of an old-style
597Windows .INI file. Here are two samples:
598
599>debug = yes
600>inputfile = /etc/passwd
601>names = Peter, Paul, Mary, George, Abrahaham, John, Bill, Gerald, Richard,
602>        Franklin, Woodrow
603>color = red
604
605This defines a file without any explicit section, so all items will
606occur within the default section @DEFAULT@. The @debug@ option can be read
607as a boolean or a string. The remaining items can be read as a string
608only. The @names@ entry spans two lines -- any line starting with
609whitespace, and containing something other than whitespace or
610comments, is taken as a continuation of the previous line.
611
612Here's another example:
613
614># Default options
615>[DEFAULT]
616>hostname: localhost
617># Options for the first file
618>[file1]
619>location: /usr/local
620>user: Fred
621>uid: 1000
622>optionaltext: Hello, this  entire string is included
623>[file2]
624>location: /opt
625>user: Fred
626>uid: 1001
627
628This file defines three sections. The @DEFAULT@ section specifies an
629entry @hostname@. If you attempt to read the hostname option in any
630section, and that section doesn't define @hostname@, you will get the
631value from @DEFAULT@ instead. This is a nice time-saver. You can also
632note that you can use colons instead of the = character to separate
633option names from option entries.
634-}
635
636{- $whitespace
637
638Whitespace (spaces, tabs, etc) is automatically stripped from the
639beginning and end of all strings. Thus, users can insert whitespace
640before\/after the colon or equal sign if they like, and it will be
641automatically stripped.
642
643Blank lines or lines consisting solely of whitespace are ignored.
644
645A line giving an option or a section name may not begin with white space.
646This requirement is necessary so there is no ambiguity between such lines
647and continuation lines for multi-line options.
648
649-}
650
651{- $comments
652
653Comments are introduced with the pound sign @#@ or the semicolon @;@. They
654cause the parser to ignore everything from that character to the end
655of the line.
656
657Comments /may not/ occur within the definitions of options; that is, you
658may not place a comment in the middle of a line such as @user: Fred@.
659That is because the parser considers the comment characters part
660of the string; otherwise, you'd be unable to use those characters in
661your strings. You can, however, \"comment out\" options by putting the
662comment character at the start of the line.
663
664-}
665
666{- $casesens
667
668By default, section names are case-sensitive but option names are
669not. The latter can be adjusted by adjusting 'optionxform'.  -}
670
671{- $interpolation
672
673Interpolation is an optional feature, disabled by default.  If you replace
674the default 'accessfunc' ('simpleAccess') with 'interpolatingAccess',
675then you get interpolation support with 'get' and the other 'get'-based functions.
676
677As an example, consider the following file:
678
679>arch = i386
680>project = test
681>filename = test_%(arch)s.c
682>dir = /usr/src/%(filename)s
683>percent = 5%%
684
685With interpolation, you would get these results:
686
687>get cp "DEFAULT" "filename" -> "test_i386.c"
688>get cp "DEFAULT" "dir" -> "/usr/src/test_i386.c"
689>get cp "DEFAULT" "percent" -> "5%"
690
691For more details on interpolation, please see the documentation for the
692'interpolatingAccess' function.
693-}
694
695{- $usage
696
697The basic theory of working with ConfigParser is this:
698
699 1. Parse or build a 'ConfigParser' object
700
701 2. Work with it in one of several ways
702
703 3. To make changes, you discard the original object and use a new one.
704    Changes can be "chained" through one of several monads.
705
706The default 'ConfigParser' object that you always start with is 'emptyCP'.
707From here, you load data into it (merging data into the empty object),
708set up structures yourself, or adjust options.
709
710Let's take a look at some basic use cases.
711
712-}
713
714{- $usagenomonad
715You'll notice that many functions in this module return a
716@MonadError 'CPError'@ over some
717type.  Although its definition is not this simple, you can consider this to be
718the same as returning @Either CPError a@.
719
720That is, these functions will return @Left error@ if there's a problem
721or @Right result@ if things are fine.  The documentation for individual
722functions describes the specific circumstances in which an error may occur in
723more detail.
724
725Some people find it annoying to have to deal with errors manually.
726You can transform errors into exceptions in your code by using
727'Data.Either.Utils.forceEither'.  Here's an example of this style of programming:
728
729> import Data.Either.Utils
730> do
731>    val <- readfile emptyCP "/etc/foo.cfg"
732>    let cp = forceEither val
733>    putStrLn "Your setting is:"
734>    putStrLn $ forceEither $ get cp "sect1" "opt1"
735
736In short, you can just put @forceEither $@ in front of every call that returns
737something that is a MonadError.
738This is still a pure functional call, so it can be used outside
739of the IO monads.  The exception, however, can only be caught in the IO
740monad.
741
742If you don't want to bother with 'forceEither', you can use the error monad.  It's simple and better... read on.
743-}
744
745{- $usageerrormonad
746
747The return type is actually defined in terms of the Error monad, which is
748itself based on the Either data type.
749
750Here's a neat example of chaining together calls to build up a 'ConfigParser'
751object:
752
753>do let cp = emptyCP
754>   cp <- add_section cp "sect1"
755>   cp <- set cp "sect1" "opt1" "foo"
756>   cp <- set cp "sect1" "opt2" "bar"
757>   options cp "sect1"
758
759The return value of this little snippet is @Right [\"opt1\", \"opt2\"]@.
760(Note to beginners: unlike the IO monad, you /can/ escape from the Error
761monad.)
762
763Although it's not obvious, there actually was error checking there.  If
764any of those calls would have generated an error, processing would have
765stopped immediately and a @Left@ value would have been returned.  Consider
766this example:
767
768>do let cp = emptyCP
769>   cp <- add_section cp "sect1"
770>   cp <- set cp "sect1" "opt1" "foo"
771>   cp <- set cp "sect2" "opt2" "bar"
772>   options cp "sect1"
773
774The return value from this is @Left ('NoSection' \"sect2\", \"set\")@.  The
775second call to 'set' failed, so the final call was skipped, and the result
776of the entire computation was considered to be an error.
777
778You can combine this with the non-monadic style to get a final, pure value
779out of it:
780
781>forceEither $ do let cp = emptyCP
782>                 cp <- add_section cp "sect1"
783>                 cp <- set cp "sect1" "opt1" "foo"
784>                 cp <- set cp "sect1" "opt2" "bar"
785>                 options cp "sect1"
786
787This returns @[\"opt1\", \"opt2\"]@.  A quite normal value.
788
789-}
790
791{- $usageerroriomonad
792
793You've seen a nice way to use this module in the Error monad and get an Either
794value out.  But that's the Error monad, so IO is not permitted.
795Using Haskell's monad transformers, you can run it in the combined
796Error\/IO monad.  That is, you will get an IO result back.  Here is a full
797standalone example of doing that:
798
799>import Data.ConfigFile
800>import Control.Monad.Error
801>
802>main = do
803>          rv <- runErrorT $
804>              do
805>              cp <- join $ liftIO $ readfile emptyCP "/etc/passwd"
806>              let x = cp
807>              liftIO $ putStrLn "In the test"
808>              nb <- get x "DEFAULT" "nobody"
809>              liftIO $ putStrLn nb
810>              foo <- get x "DEFAULT" "foo"
811>              liftIO $ putStrLn foo
812>              return "done"
813>          print rv
814
815On my system, this prints:
816
817>In the test
818>x:65534:65534:nobody:/nonexistent:/bin/sh
819>Left (NoOption "foo","get")
820
821That is, my @\/etc\/passwd@ file contains a @nobody@ user but not a @foo@ user.
822
823Let's look at how that works.
824
825First, @main@ always runs in the IO monad only, so we take the result from
826the later calls and put it in @rv@.  Note that the combined block
827is started with @runErrorT $ do@ instead of just @do@.
828
829To get something out of the call to 'readfile', we use
830@join $ liftIO $ readfile@.  This will bring the result out of the IO monad
831into the combined monad and process it like usual.  From here on,
832everything looks normal, except for IO calls.  They are all executed under
833@liftIO@ so that the result value is properly brought into the combined
834monad.  This finally returns @\"done\"@.  Since we are in the Error monad, that means that the literal value is @Right \"done\"@.  Since we are also in the IO
835monad, this is wrapped in IO.  So the final return type after applying
836@runErrorT@ is @IO (Either CPError String)@.
837
838In this case, there was an error, and processing stopped at that point just
839like the example of the pure Error monad.  We print out the return value,
840so you see the error displayed as a @Left@ value.
841
842It all works quite easily.
843
844-}
845
846{- $configuringcp
847
848You may notice that the 'ConfigParser' object has some configurable parameters,
849such as 'usedefault'.  In case you're not familiar with the Haskell syntax
850for working with these, you can use syntax like this to set these options:
851
852>let cp2 = cp { usedefault = False }
853
854This will create a new 'ConfigParser' that is the same as @cp@ except for
855the 'usedefault' field, which is now always False.  The new object will be
856called @cp2@ in this example.
857-}
858
859{- $reading
860
861You can use these functions to read data from a file.
862
863A common idiom for loading a new object from stratch is:
864
865@cp <- 'readfile' 'emptyCP' \"\/etc\/foo.cfg\"@
866
867Note the use of 'emptyCP'; this will essentially cause the file's data
868to be merged with the empty 'ConfigParser'.
869-}
870
871{- $types
872
873The code used to say this:
874
875>type CPResult a = MonadError CPError m => m a
876>simpleAccess :: ConfigParser -> SectionSpec -> OptionSpec -> CPResult String
877
878But Hugs did not support that type declaration.  Therefore, types are now
879given like this:
880
881>simpleAccess :: MonadError CPError m =>
882>                ConfigParser -> SectionSpec -> OptionSpec -> m String
883
884Although it looks more confusing than before, it still means the same.
885The return value can still be treated as @Either CPError String@ if you so
886desire.
887-}
888