{-# LANGUAGE UndecidableInstances, OverlappingInstances #-}
module Data.ConfigFile
(
SectionSpec, OptionSpec, ConfigParser(..),
CPErrorData(..), CPError,
emptyCP,
simpleAccess, interpolatingAccess,
readfile, readhandle, readstring,
Get_C(..),
sections, has_section,
options, has_option,
items,
set, setshow, remove_option,
add_section, remove_section,
merge,
to_string
) where
import Data.ConfigFile.Types
import Data.ConfigFile.Parser
import Data.Either.Utils
import Data.String.Utils
import qualified Data.Map as Map
import Data.List
import System.IO(Handle)
import Data.Char
import Control.Monad.Error
import Text.ParserCombinators.Parsec.Error (errorMessages, Message(..))
import Text.ParserCombinators.Parsec (parse)
emptyCP :: ConfigParser
emptyCP :: ConfigParser
emptyCP = ConfigParser :: CPData
-> (OptionSpec -> OptionSpec)
-> (ConfigParser
-> OptionSpec -> OptionSpec -> Either CPError OptionSpec)
-> Bool
-> (ConfigParser
-> OptionSpec -> OptionSpec -> Either CPError OptionSpec)
-> ConfigParser
ConfigParser { content :: CPData
content = ParseOutput -> CPData
fromAL [(OptionSpec
"DEFAULT", [])],
defaulthandler :: ConfigParser
-> OptionSpec -> OptionSpec -> Either CPError OptionSpec
defaulthandler = ConfigParser
-> OptionSpec -> OptionSpec -> Either CPError OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
defdefaulthandler,
optionxform :: OptionSpec -> OptionSpec
optionxform = (Char -> Char) -> OptionSpec -> OptionSpec
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower,
usedefault :: Bool
usedefault = Bool
True,
accessfunc :: ConfigParser
-> OptionSpec -> OptionSpec -> Either CPError OptionSpec
accessfunc = ConfigParser
-> OptionSpec -> OptionSpec -> Either CPError OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
simpleAccess}
fromAL :: ParseOutput -> CPData
fromAL :: ParseOutput -> CPData
fromAL ParseOutput
origal =
let conv :: CPData -> (String, [(String, String)]) -> CPData
conv :: CPData -> (OptionSpec, [(OptionSpec, OptionSpec)]) -> CPData
conv CPData
fm (OptionSpec, [(OptionSpec, OptionSpec)])
sect = OptionSpec -> Map OptionSpec OptionSpec -> CPData -> CPData
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert ((OptionSpec, [(OptionSpec, OptionSpec)]) -> OptionSpec
forall a b. (a, b) -> a
fst (OptionSpec, [(OptionSpec, OptionSpec)])
sect) ([(OptionSpec, OptionSpec)] -> Map OptionSpec OptionSpec
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(OptionSpec, OptionSpec)] -> Map OptionSpec OptionSpec)
-> [(OptionSpec, OptionSpec)] -> Map OptionSpec OptionSpec
forall a b. (a -> b) -> a -> b
$ (OptionSpec, [(OptionSpec, OptionSpec)])
-> [(OptionSpec, OptionSpec)]
forall a b. (a, b) -> b
snd (OptionSpec, [(OptionSpec, OptionSpec)])
sect) CPData
fm
in
(CPData -> (OptionSpec, [(OptionSpec, OptionSpec)]) -> CPData)
-> CPData -> ParseOutput -> CPData
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl CPData -> (OptionSpec, [(OptionSpec, OptionSpec)]) -> CPData
conv CPData
forall k a. Map k a
Map.empty ParseOutput
origal
simpleAccess :: MonadError CPError m =>
ConfigParser -> SectionSpec -> OptionSpec -> m String
simpleAccess :: ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
simpleAccess ConfigParser
cp OptionSpec
s OptionSpec
o = ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
defdefaulthandler ConfigParser
cp OptionSpec
s (ConfigParser -> OptionSpec -> OptionSpec
optionxform ConfigParser
cp (OptionSpec -> OptionSpec) -> OptionSpec -> OptionSpec
forall a b. (a -> b) -> a -> b
$ OptionSpec
o)
interpolatingAccess :: MonadError CPError m =>
Int ->
ConfigParser -> SectionSpec -> OptionSpec
-> m String
interpolatingAccess :: Int -> ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
interpolatingAccess Int
maxdepth ConfigParser
cp OptionSpec
s OptionSpec
o =
if Int
maxdepth Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1
then OptionSpec -> m OptionSpec
forall (m :: * -> *) a. MonadError CPError m => OptionSpec -> m a
interError OptionSpec
"maximum interpolation depth exceeded"
else do OptionSpec
x <- ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
simpleAccess ConfigParser
cp OptionSpec
s OptionSpec
o
case Parsec OptionSpec () OptionSpec
-> OptionSpec -> OptionSpec -> Either ParseError OptionSpec
forall s t a.
Stream s Identity t =>
Parsec s () a -> OptionSpec -> s -> Either ParseError a
parse ((OptionSpec -> Either CPError OptionSpec)
-> Parsec OptionSpec () OptionSpec
interpmain ((OptionSpec -> Either CPError OptionSpec)
-> Parsec OptionSpec () OptionSpec)
-> (OptionSpec -> Either CPError OptionSpec)
-> Parsec OptionSpec () OptionSpec
forall a b. (a -> b) -> a -> b
$ OptionSpec -> Either CPError OptionSpec
lookupfunc) (OptionSpec
s OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
"/" OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
o) OptionSpec
x of
Left ParseError
y -> case [Message] -> Message
forall a. [a] -> a
head (ParseError -> [Message]
errorMessages ParseError
y) of
Message OptionSpec
z -> OptionSpec -> m OptionSpec
forall (m :: * -> *) a. MonadError CPError m => OptionSpec -> m a
interError OptionSpec
z
Message
_ -> OptionSpec -> m OptionSpec
forall (m :: * -> *) a. MonadError CPError m => OptionSpec -> m a
interError (ParseError -> OptionSpec
forall a. Show a => a -> OptionSpec
show ParseError
y)
Right OptionSpec
y -> OptionSpec -> m OptionSpec
forall (m :: * -> *) a. Monad m => a -> m a
return OptionSpec
y
where
lookupfunc :: OptionSpec -> Either CPError OptionSpec
lookupfunc = Int
-> ConfigParser
-> OptionSpec
-> OptionSpec
-> Either CPError OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
Int -> ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
interpolatingAccess (Int
maxdepth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ConfigParser
cp OptionSpec
s
interError :: OptionSpec -> m a
interError OptionSpec
x = CPError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (OptionSpec -> CPErrorData
InterpolationError OptionSpec
x, OptionSpec
"interpolatingAccess")
defdefaulthandler :: MonadError CPError m =>
ConfigParser -> SectionSpec -> OptionSpec -> m String
defdefaulthandler :: ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
defdefaulthandler ConfigParser
cp OptionSpec
sectn OptionSpec
opt =
let fm :: CPData
fm = ConfigParser -> CPData
content ConfigParser
cp
lookUp :: OptionSpec -> OptionSpec -> m OptionSpec
lookUp OptionSpec
s OptionSpec
o = do Map OptionSpec OptionSpec
sect <- CPError
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
maybeToEither (OptionSpec -> CPErrorData
NoSection OptionSpec
s,
OptionSpec
"get " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
sectn OptionSpec
opt) (Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec))
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall a b. (a -> b) -> a -> b
$
OptionSpec -> CPData -> Maybe (Map OptionSpec OptionSpec)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup OptionSpec
s CPData
fm
CPError -> Maybe OptionSpec -> m OptionSpec
forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
maybeToEither (OptionSpec -> CPErrorData
NoOption OptionSpec
o,
OptionSpec
"get " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
sectn OptionSpec
opt) (Maybe OptionSpec -> m OptionSpec)
-> Maybe OptionSpec -> m OptionSpec
forall a b. (a -> b) -> a -> b
$
OptionSpec -> Map OptionSpec OptionSpec -> Maybe OptionSpec
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup OptionSpec
o Map OptionSpec OptionSpec
sect
trydefault :: CPError -> m OptionSpec
trydefault CPError
e = if (ConfigParser -> Bool
usedefault ConfigParser
cp)
then
OptionSpec -> OptionSpec -> m OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
OptionSpec -> OptionSpec -> m OptionSpec
lookUp OptionSpec
"DEFAULT" OptionSpec
opt
m OptionSpec -> (CPError -> m OptionSpec) -> m OptionSpec
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` (\CPError
_ -> CPError -> m OptionSpec
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError CPError
e)
else CPError -> m OptionSpec
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError CPError
e
in
OptionSpec -> OptionSpec -> m OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
OptionSpec -> OptionSpec -> m OptionSpec
lookUp OptionSpec
sectn OptionSpec
opt m OptionSpec -> (CPError -> m OptionSpec) -> m OptionSpec
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` CPError -> m OptionSpec
forall (m :: * -> *).
MonadError CPError m =>
CPError -> m OptionSpec
trydefault
merge :: ConfigParser -> ConfigParser -> ConfigParser
merge :: ConfigParser -> ConfigParser -> ConfigParser
merge ConfigParser
src ConfigParser
dest =
let conv :: String -> String
conv :: OptionSpec -> OptionSpec
conv = ConfigParser -> OptionSpec -> OptionSpec
optionxform ConfigParser
dest
convFM :: CPOptions -> CPOptions
convFM :: Map OptionSpec OptionSpec -> Map OptionSpec OptionSpec
convFM = [(OptionSpec, OptionSpec)] -> Map OptionSpec OptionSpec
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(OptionSpec, OptionSpec)] -> Map OptionSpec OptionSpec)
-> (Map OptionSpec OptionSpec -> [(OptionSpec, OptionSpec)])
-> Map OptionSpec OptionSpec
-> Map OptionSpec OptionSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((OptionSpec, OptionSpec) -> (OptionSpec, OptionSpec))
-> [(OptionSpec, OptionSpec)] -> [(OptionSpec, OptionSpec)]
forall a b. (a -> b) -> [a] -> [b]
map (\(OptionSpec, OptionSpec)
x -> (OptionSpec -> OptionSpec
conv ((OptionSpec, OptionSpec) -> OptionSpec
forall a b. (a, b) -> a
fst (OptionSpec, OptionSpec)
x), (OptionSpec, OptionSpec) -> OptionSpec
forall a b. (a, b) -> b
snd (OptionSpec, OptionSpec)
x)) ([(OptionSpec, OptionSpec)] -> [(OptionSpec, OptionSpec)])
-> (Map OptionSpec OptionSpec -> [(OptionSpec, OptionSpec)])
-> Map OptionSpec OptionSpec
-> [(OptionSpec, OptionSpec)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map OptionSpec OptionSpec -> [(OptionSpec, OptionSpec)]
forall k a. Map k a -> [(k, a)]
Map.toList
mergesects :: Map k a -> Map k a -> Map k a
mergesects Map k a
a Map k a
b = Map k a -> Map k a -> Map k a
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union Map k a
a Map k a
b
in
ConfigParser
dest { content :: CPData
content = (Map OptionSpec OptionSpec
-> Map OptionSpec OptionSpec -> Map OptionSpec OptionSpec)
-> CPData -> CPData -> CPData
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith Map OptionSpec OptionSpec
-> Map OptionSpec OptionSpec -> Map OptionSpec OptionSpec
forall k a. Ord k => Map k a -> Map k a -> Map k a
mergesects
(ConfigParser -> CPData
content ConfigParser
dest) ((Map OptionSpec OptionSpec -> Map OptionSpec OptionSpec)
-> CPData -> CPData
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map Map OptionSpec OptionSpec -> Map OptionSpec OptionSpec
convFM (ConfigParser -> CPData
content ConfigParser
src)) }
readutil :: ConfigParser -> ParseOutput -> ConfigParser
readutil :: ConfigParser -> ParseOutput -> ConfigParser
readutil ConfigParser
old ParseOutput
new = ConfigParser -> ConfigParser -> ConfigParser
merge ConfigParser
old (ConfigParser -> ConfigParser) -> ConfigParser -> ConfigParser
forall a b. (a -> b) -> a -> b
$ ConfigParser
old { content :: CPData
content = ParseOutput -> CPData
fromAL ParseOutput
new }
readfile :: MonadError CPError m => ConfigParser -> FilePath -> IO (m ConfigParser)
readfile :: ConfigParser -> OptionSpec -> IO (m ConfigParser)
readfile ConfigParser
cp OptionSpec
fp = do m ParseOutput
n <- OptionSpec -> IO (m ParseOutput)
forall (m :: * -> *).
MonadError CPError m =>
OptionSpec -> IO (m ParseOutput)
parse_file OptionSpec
fp
m ConfigParser -> IO (m ConfigParser)
forall (m :: * -> *) a. Monad m => a -> m a
return (m ConfigParser -> IO (m ConfigParser))
-> m ConfigParser -> IO (m ConfigParser)
forall a b. (a -> b) -> a -> b
$ m ParseOutput
n m ParseOutput -> (ParseOutput -> m ConfigParser) -> m ConfigParser
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (ConfigParser -> m ConfigParser
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigParser -> m ConfigParser)
-> (ParseOutput -> ConfigParser) -> ParseOutput -> m ConfigParser
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConfigParser -> ParseOutput -> ConfigParser
readutil ConfigParser
cp)
readhandle :: MonadError CPError m => ConfigParser -> Handle -> IO (m ConfigParser)
readhandle :: ConfigParser -> Handle -> IO (m ConfigParser)
readhandle ConfigParser
cp Handle
h = do m ParseOutput
n <- Handle -> IO (m ParseOutput)
forall (m :: * -> *).
MonadError CPError m =>
Handle -> IO (m ParseOutput)
parse_handle Handle
h
m ConfigParser -> IO (m ConfigParser)
forall (m :: * -> *) a. Monad m => a -> m a
return (m ConfigParser -> IO (m ConfigParser))
-> m ConfigParser -> IO (m ConfigParser)
forall a b. (a -> b) -> a -> b
$ m ParseOutput
n m ParseOutput -> (ParseOutput -> m ConfigParser) -> m ConfigParser
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (ConfigParser -> m ConfigParser
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigParser -> m ConfigParser)
-> (ParseOutput -> ConfigParser) -> ParseOutput -> m ConfigParser
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ConfigParser -> ParseOutput -> ConfigParser
readutil ConfigParser
cp))
readstring :: MonadError CPError m =>
ConfigParser -> String -> m ConfigParser
readstring :: ConfigParser -> OptionSpec -> m ConfigParser
readstring ConfigParser
cp OptionSpec
s = do
ParseOutput
n <- OptionSpec -> m ParseOutput
forall (m :: * -> *).
MonadError CPError m =>
OptionSpec -> m ParseOutput
parse_string OptionSpec
s
ConfigParser -> m ConfigParser
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigParser -> m ConfigParser) -> ConfigParser -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ ConfigParser -> ParseOutput -> ConfigParser
readutil ConfigParser
cp ParseOutput
n
sections :: ConfigParser -> [SectionSpec]
sections :: ConfigParser -> [OptionSpec]
sections = (OptionSpec -> Bool) -> [OptionSpec] -> [OptionSpec]
forall a. (a -> Bool) -> [a] -> [a]
filter (OptionSpec -> OptionSpec -> Bool
forall a. Eq a => a -> a -> Bool
/= OptionSpec
"DEFAULT") ([OptionSpec] -> [OptionSpec])
-> (ConfigParser -> [OptionSpec]) -> ConfigParser -> [OptionSpec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CPData -> [OptionSpec]
forall k a. Map k a -> [k]
Map.keys (CPData -> [OptionSpec])
-> (ConfigParser -> CPData) -> ConfigParser -> [OptionSpec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConfigParser -> CPData
content
has_section :: ConfigParser -> SectionSpec -> Bool
has_section :: ConfigParser -> OptionSpec -> Bool
has_section ConfigParser
cp OptionSpec
x = OptionSpec -> CPData -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member OptionSpec
x (ConfigParser -> CPData
content ConfigParser
cp)
add_section :: MonadError CPError m =>
ConfigParser -> SectionSpec -> m ConfigParser
add_section :: ConfigParser -> OptionSpec -> m ConfigParser
add_section ConfigParser
cp OptionSpec
s =
if ConfigParser -> OptionSpec -> Bool
has_section ConfigParser
cp OptionSpec
s
then CPError -> m ConfigParser
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (CPError -> m ConfigParser) -> CPError -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ (OptionSpec -> CPErrorData
SectionAlreadyExists OptionSpec
s, OptionSpec
"add_section")
else ConfigParser -> m ConfigParser
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigParser -> m ConfigParser) -> ConfigParser -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ ConfigParser
cp {content :: CPData
content = OptionSpec -> Map OptionSpec OptionSpec -> CPData -> CPData
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert OptionSpec
s Map OptionSpec OptionSpec
forall k a. Map k a
Map.empty (ConfigParser -> CPData
content ConfigParser
cp)}
remove_section :: MonadError CPError m =>
ConfigParser -> SectionSpec -> m ConfigParser
remove_section :: ConfigParser -> OptionSpec -> m ConfigParser
remove_section ConfigParser
_ OptionSpec
"DEFAULT" = CPError -> m ConfigParser
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (CPError -> m ConfigParser) -> CPError -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ (OptionSpec -> CPErrorData
NoSection OptionSpec
"DEFAULT", OptionSpec
"remove_section")
remove_section ConfigParser
cp OptionSpec
s =
if ConfigParser -> OptionSpec -> Bool
has_section ConfigParser
cp OptionSpec
s
then ConfigParser -> m ConfigParser
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigParser -> m ConfigParser) -> ConfigParser -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ ConfigParser
cp {content :: CPData
content = OptionSpec -> CPData -> CPData
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete OptionSpec
s (ConfigParser -> CPData
content ConfigParser
cp)}
else CPError -> m ConfigParser
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (CPError -> m ConfigParser) -> CPError -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ (OptionSpec -> CPErrorData
NoSection OptionSpec
s, OptionSpec
"remove_section")
remove_option :: MonadError CPError m =>
ConfigParser -> SectionSpec -> OptionSpec -> m ConfigParser
remove_option :: ConfigParser -> OptionSpec -> OptionSpec -> m ConfigParser
remove_option ConfigParser
cp OptionSpec
s OptionSpec
passedo =
do Map OptionSpec OptionSpec
sectmap <- CPError
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
maybeToEither (OptionSpec -> CPErrorData
NoSection OptionSpec
s,
OptionSpec
"remove_option " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
s OptionSpec
passedo) (Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec))
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall a b. (a -> b) -> a -> b
$
OptionSpec -> CPData -> Maybe (Map OptionSpec OptionSpec)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup OptionSpec
s (ConfigParser -> CPData
content ConfigParser
cp)
let o :: OptionSpec
o = (ConfigParser -> OptionSpec -> OptionSpec
optionxform ConfigParser
cp) OptionSpec
passedo
let newsect :: Map OptionSpec OptionSpec
newsect = OptionSpec
-> Map OptionSpec OptionSpec -> Map OptionSpec OptionSpec
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete OptionSpec
o Map OptionSpec OptionSpec
sectmap
let newmap :: CPData
newmap = OptionSpec -> Map OptionSpec OptionSpec -> CPData -> CPData
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert OptionSpec
s Map OptionSpec OptionSpec
newsect (ConfigParser -> CPData
content ConfigParser
cp)
if OptionSpec -> Map OptionSpec OptionSpec -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member OptionSpec
o Map OptionSpec OptionSpec
sectmap
then ConfigParser -> m ConfigParser
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigParser -> m ConfigParser) -> ConfigParser -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ ConfigParser
cp {content :: CPData
content = CPData
newmap}
else CPError -> m ConfigParser
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (CPError -> m ConfigParser) -> CPError -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ (OptionSpec -> CPErrorData
NoOption OptionSpec
o,
OptionSpec
"remove_option " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
s OptionSpec
passedo)
options :: MonadError CPError m =>
ConfigParser -> SectionSpec -> m [OptionSpec]
options :: ConfigParser -> OptionSpec -> m [OptionSpec]
options ConfigParser
cp OptionSpec
x = CPError -> Maybe [OptionSpec] -> m [OptionSpec]
forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
maybeToEither (OptionSpec -> CPErrorData
NoSection OptionSpec
x, OptionSpec
"options") (Maybe [OptionSpec] -> m [OptionSpec])
-> Maybe [OptionSpec] -> m [OptionSpec]
forall a b. (a -> b) -> a -> b
$
do
Map OptionSpec OptionSpec
o <- OptionSpec -> CPData -> Maybe (Map OptionSpec OptionSpec)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup OptionSpec
x (ConfigParser -> CPData
content ConfigParser
cp)
[OptionSpec] -> Maybe [OptionSpec]
forall (m :: * -> *) a. Monad m => a -> m a
return ([OptionSpec] -> Maybe [OptionSpec])
-> [OptionSpec] -> Maybe [OptionSpec]
forall a b. (a -> b) -> a -> b
$ Map OptionSpec OptionSpec -> [OptionSpec]
forall k a. Map k a -> [k]
Map.keys Map OptionSpec OptionSpec
o
has_option :: ConfigParser -> SectionSpec -> OptionSpec -> Bool
has_option :: ConfigParser -> OptionSpec -> OptionSpec -> Bool
has_option ConfigParser
cp OptionSpec
s OptionSpec
o =
let c :: CPData
c = ConfigParser -> CPData
content ConfigParser
cp
v :: Maybe Bool
v = do Map OptionSpec OptionSpec
secthash <- OptionSpec -> CPData -> Maybe (Map OptionSpec OptionSpec)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup OptionSpec
s CPData
c
Bool -> Maybe Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Maybe Bool) -> Bool -> Maybe Bool
forall a b. (a -> b) -> a -> b
$ OptionSpec -> Map OptionSpec OptionSpec -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member (ConfigParser -> OptionSpec -> OptionSpec
optionxform ConfigParser
cp (OptionSpec -> OptionSpec) -> OptionSpec -> OptionSpec
forall a b. (a -> b) -> a -> b
$ OptionSpec
o) Map OptionSpec OptionSpec
secthash
in Bool -> (Bool -> Bool) -> Maybe Bool -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False Bool -> Bool
forall a. a -> a
id Maybe Bool
v
class Get_C a where
get :: MonadError CPError m => ConfigParser -> SectionSpec -> OptionSpec -> m a
instance Get_C String where
get :: ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
get ConfigParser
cp OptionSpec
s OptionSpec
o = Either CPError OptionSpec -> m OptionSpec
forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
eitherToMonadError (Either CPError OptionSpec -> m OptionSpec)
-> Either CPError OptionSpec -> m OptionSpec
forall a b. (a -> b) -> a -> b
$ (ConfigParser
-> ConfigParser
-> OptionSpec
-> OptionSpec
-> Either CPError OptionSpec
accessfunc ConfigParser
cp) ConfigParser
cp OptionSpec
s OptionSpec
o
instance Get_C Bool where
get :: ConfigParser -> OptionSpec -> OptionSpec -> m Bool
get = ConfigParser -> OptionSpec -> OptionSpec -> m Bool
forall (m :: * -> *).
MonadError CPError m =>
ConfigParser -> OptionSpec -> OptionSpec -> m Bool
getbool
instance Read t => Get_C t where
get :: ConfigParser -> OptionSpec -> OptionSpec -> m t
get = ConfigParser -> OptionSpec -> OptionSpec -> m t
forall b (m :: * -> *).
(Read b, MonadError CPError m) =>
ConfigParser -> OptionSpec -> OptionSpec -> m b
genericget
readMaybe :: Read a => String -> Maybe a
readMaybe :: OptionSpec -> Maybe a
readMaybe OptionSpec
s = case [a
x | (a
x, OptionSpec
t) <- ReadS a
forall a. Read a => ReadS a
reads OptionSpec
s, (OptionSpec
"",OptionSpec
"") <- ReadS OptionSpec
lex OptionSpec
t] of
[a
x] -> a -> Maybe a
forall a. a -> Maybe a
Just a
x
[a]
_ -> Maybe a
forall a. Maybe a
Nothing
genericget :: (Read b, MonadError CPError m) => ConfigParser -> SectionSpec -> OptionSpec -> m b
genericget :: ConfigParser -> OptionSpec -> OptionSpec -> m b
genericget ConfigParser
cp OptionSpec
s OptionSpec
o = do
OptionSpec
val <- ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
forall a (m :: * -> *).
(Get_C a, MonadError CPError m) =>
ConfigParser -> OptionSpec -> OptionSpec -> m a
get ConfigParser
cp OptionSpec
s OptionSpec
o
let errMsg :: OptionSpec
errMsg = OptionSpec
"couldn't parse value " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
val OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
" from " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
s OptionSpec
o
m b -> (b -> m b) -> Maybe b -> m b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (CPError -> m b
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (OptionSpec -> CPErrorData
ParseError OptionSpec
errMsg, OptionSpec
"genericget"))
b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return
(Maybe b -> m b) -> Maybe b -> m b
forall a b. (a -> b) -> a -> b
$ OptionSpec -> Maybe b
forall a. Read a => OptionSpec -> Maybe a
readMaybe OptionSpec
val
getbool :: MonadError CPError m =>
ConfigParser -> SectionSpec -> OptionSpec -> m Bool
getbool :: ConfigParser -> OptionSpec -> OptionSpec -> m Bool
getbool ConfigParser
cp OptionSpec
s OptionSpec
o =
do OptionSpec
val <- ConfigParser -> OptionSpec -> OptionSpec -> m OptionSpec
forall a (m :: * -> *).
(Get_C a, MonadError CPError m) =>
ConfigParser -> OptionSpec -> OptionSpec -> m a
get ConfigParser
cp OptionSpec
s OptionSpec
o
case (Char -> Char) -> OptionSpec -> OptionSpec
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (OptionSpec -> OptionSpec)
-> (OptionSpec -> OptionSpec) -> OptionSpec -> OptionSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OptionSpec -> OptionSpec
strip (OptionSpec -> OptionSpec) -> OptionSpec -> OptionSpec
forall a b. (a -> b) -> a -> b
$ OptionSpec
val of
OptionSpec
"1" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
OptionSpec
"yes" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
OptionSpec
"on" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
OptionSpec
"enabled" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
OptionSpec
"true" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
OptionSpec
"0" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
OptionSpec
"no" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
OptionSpec
"off" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
OptionSpec
"disabled" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
OptionSpec
"false" -> Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
OptionSpec
_ -> CPError -> m Bool
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (OptionSpec -> CPErrorData
ParseError (OptionSpec -> CPErrorData) -> OptionSpec -> CPErrorData
forall a b. (a -> b) -> a -> b
$ OptionSpec
"couldn't parse bool " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++
OptionSpec
val OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
" from " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
s OptionSpec
o, OptionSpec
"getbool")
formatSO :: [Char] -> [Char] -> [Char]
formatSO :: OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
s OptionSpec
o =
OptionSpec
"(" OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
s OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
"/" OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
o OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
")"
items :: MonadError CPError m =>
ConfigParser -> SectionSpec -> m [(OptionSpec, String)]
items :: ConfigParser -> OptionSpec -> m [(OptionSpec, OptionSpec)]
items ConfigParser
cp OptionSpec
s = do Map OptionSpec OptionSpec
fm <- CPError
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
maybeToEither (OptionSpec -> CPErrorData
NoSection OptionSpec
s, OptionSpec
"items") (Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec))
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall a b. (a -> b) -> a -> b
$
OptionSpec -> CPData -> Maybe (Map OptionSpec OptionSpec)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup OptionSpec
s (ConfigParser -> CPData
content ConfigParser
cp)
[(OptionSpec, OptionSpec)] -> m [(OptionSpec, OptionSpec)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(OptionSpec, OptionSpec)] -> m [(OptionSpec, OptionSpec)])
-> [(OptionSpec, OptionSpec)] -> m [(OptionSpec, OptionSpec)]
forall a b. (a -> b) -> a -> b
$ Map OptionSpec OptionSpec -> [(OptionSpec, OptionSpec)]
forall k a. Map k a -> [(k, a)]
Map.toList Map OptionSpec OptionSpec
fm
set :: MonadError CPError m =>
ConfigParser -> SectionSpec -> OptionSpec -> String -> m ConfigParser
set :: ConfigParser
-> OptionSpec -> OptionSpec -> OptionSpec -> m ConfigParser
set ConfigParser
cp OptionSpec
s OptionSpec
passedo OptionSpec
val =
do Map OptionSpec OptionSpec
sectmap <- CPError
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
maybeToEither (OptionSpec -> CPErrorData
NoSection OptionSpec
s, OptionSpec
"set " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec -> OptionSpec -> OptionSpec
formatSO OptionSpec
s OptionSpec
passedo) (Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec))
-> Maybe (Map OptionSpec OptionSpec)
-> m (Map OptionSpec OptionSpec)
forall a b. (a -> b) -> a -> b
$
OptionSpec -> CPData -> Maybe (Map OptionSpec OptionSpec)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup OptionSpec
s (ConfigParser -> CPData
content ConfigParser
cp)
let o :: OptionSpec
o = (ConfigParser -> OptionSpec -> OptionSpec
optionxform ConfigParser
cp) OptionSpec
passedo
let newsect :: Map OptionSpec OptionSpec
newsect = OptionSpec
-> OptionSpec
-> Map OptionSpec OptionSpec
-> Map OptionSpec OptionSpec
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert OptionSpec
o OptionSpec
val Map OptionSpec OptionSpec
sectmap
let newmap :: CPData
newmap = OptionSpec -> Map OptionSpec OptionSpec -> CPData -> CPData
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert OptionSpec
s Map OptionSpec OptionSpec
newsect (ConfigParser -> CPData
content ConfigParser
cp)
ConfigParser -> m ConfigParser
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigParser -> m ConfigParser) -> ConfigParser -> m ConfigParser
forall a b. (a -> b) -> a -> b
$ ConfigParser
cp { content :: CPData
content = CPData
newmap}
setshow :: (Show a, MonadError CPError m) =>
ConfigParser -> SectionSpec -> OptionSpec -> a -> m ConfigParser
setshow :: ConfigParser -> OptionSpec -> OptionSpec -> a -> m ConfigParser
setshow ConfigParser
cp OptionSpec
s OptionSpec
o a
val = ConfigParser
-> OptionSpec -> OptionSpec -> OptionSpec -> m ConfigParser
forall (m :: * -> *).
MonadError CPError m =>
ConfigParser
-> OptionSpec -> OptionSpec -> OptionSpec -> m ConfigParser
set ConfigParser
cp OptionSpec
s OptionSpec
o (a -> OptionSpec
forall a. Show a => a -> OptionSpec
show a
val)
to_string :: ConfigParser -> String
to_string :: ConfigParser -> OptionSpec
to_string ConfigParser
cp =
let gen_option :: (OptionSpec, OptionSpec) -> OptionSpec
gen_option (OptionSpec
key, OptionSpec
value) =
OptionSpec
key OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
": " OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ (OptionSpec -> OptionSpec -> OptionSpec -> OptionSpec
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace OptionSpec
"\n" OptionSpec
"\n " OptionSpec
value) OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
"\n"
gen_section :: (OptionSpec, Map OptionSpec OptionSpec) -> OptionSpec
gen_section (OptionSpec
sect, Map OptionSpec OptionSpec
valfm) =
if (OptionSpec
sect OptionSpec -> OptionSpec -> Bool
forall a. Eq a => a -> a -> Bool
/= OptionSpec
"DEFAULT") Bool -> Bool -> Bool
|| (Map OptionSpec OptionSpec -> Int
forall k a. Map k a -> Int
Map.size Map OptionSpec OptionSpec
valfm Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0)
then OptionSpec
"[" OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
sect OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
"]\n" OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++
([OptionSpec] -> OptionSpec
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([OptionSpec] -> OptionSpec) -> [OptionSpec] -> OptionSpec
forall a b. (a -> b) -> a -> b
$ ((OptionSpec, OptionSpec) -> OptionSpec)
-> [(OptionSpec, OptionSpec)] -> [OptionSpec]
forall a b. (a -> b) -> [a] -> [b]
map (OptionSpec, OptionSpec) -> OptionSpec
gen_option (Map OptionSpec OptionSpec -> [(OptionSpec, OptionSpec)]
forall k a. Map k a -> [(k, a)]
Map.toList Map OptionSpec OptionSpec
valfm)) OptionSpec -> OptionSpec -> OptionSpec
forall a. [a] -> [a] -> [a]
++ OptionSpec
"\n"
else OptionSpec
""
in
[OptionSpec] -> OptionSpec
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([OptionSpec] -> OptionSpec) -> [OptionSpec] -> OptionSpec
forall a b. (a -> b) -> a -> b
$ ((OptionSpec, Map OptionSpec OptionSpec) -> OptionSpec)
-> [(OptionSpec, Map OptionSpec OptionSpec)] -> [OptionSpec]
forall a b. (a -> b) -> [a] -> [b]
map (OptionSpec, Map OptionSpec OptionSpec) -> OptionSpec
gen_section (CPData -> [(OptionSpec, Map OptionSpec OptionSpec)]
forall k a. Map k a -> [(k, a)]
Map.toList (ConfigParser -> CPData
content ConfigParser
cp))