{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Ini.Config
(
parseIniFile,
IniParser,
SectionParser,
section,
sections,
sectionOf,
sectionsOf,
sectionMb,
sectionDef,
field,
fieldOf,
fieldMb,
fieldMbOf,
fieldDef,
fieldDefOf,
fieldFlag,
fieldFlagDef,
readable,
number,
string,
flag,
listWithSeparator,
)
where
import Control.Applicative (Alternative (..))
import Control.Monad.Trans.Except
import Data.Ini.Config.Raw
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import Data.String (IsString (..))
import Data.Text (Text)
import qualified Data.Text as T
import Data.Typeable (Proxy (..), Typeable, typeRep)
import GHC.Exts (IsList (..))
import Text.Read (readMaybe)
lkp :: NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp :: forall a. NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp NormalizedText
t = ViewL (NormalizedText, a) -> Maybe a
forall {a}. ViewL (NormalizedText, a) -> Maybe a
go (ViewL (NormalizedText, a) -> Maybe a)
-> (Seq (NormalizedText, a) -> ViewL (NormalizedText, a))
-> Seq (NormalizedText, a)
-> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq (NormalizedText, a) -> ViewL (NormalizedText, a)
forall a. Seq a -> ViewL a
Seq.viewl
where
go :: ViewL (NormalizedText, a) -> Maybe a
go ((NormalizedText
t', a
x) Seq.:< Seq (NormalizedText, a)
rs)
| NormalizedText
t NormalizedText -> NormalizedText -> Bool
forall a. Eq a => a -> a -> Bool
== NormalizedText
t' = a -> Maybe a
forall a. a -> Maybe a
Just a
x
| Bool
otherwise = ViewL (NormalizedText, a) -> Maybe a
go (Seq (NormalizedText, a) -> ViewL (NormalizedText, a)
forall a. Seq a -> ViewL a
Seq.viewl Seq (NormalizedText, a)
rs)
go ViewL (NormalizedText, a)
Seq.EmptyL = Maybe a
forall a. Maybe a
Nothing
addLineInformation :: Int -> Text -> StParser s a -> StParser s a
addLineInformation :: forall s a. Int -> Text -> StParser s a -> StParser s a
addLineInformation Int
lineNo Text
sec = ([Char] -> [Char])
-> ExceptT [Char] ((->) s) a -> ExceptT [Char] ((->) s) a
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT [Char] -> [Char]
go
where
go :: [Char] -> [Char]
go [Char]
e =
[Char]
"Line " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
lineNo
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
", in section "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
forall a. Show a => a -> [Char]
show Text
sec
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
e
type StParser s a = ExceptT String ((->) s) a
newtype IniParser a = IniParser (StParser RawIni a)
deriving ((forall a b. (a -> b) -> IniParser a -> IniParser b)
-> (forall a b. a -> IniParser b -> IniParser a)
-> Functor IniParser
forall a b. a -> IniParser b -> IniParser a
forall a b. (a -> b) -> IniParser a -> IniParser b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> IniParser a -> IniParser b
fmap :: forall a b. (a -> b) -> IniParser a -> IniParser b
$c<$ :: forall a b. a -> IniParser b -> IniParser a
<$ :: forall a b. a -> IniParser b -> IniParser a
Functor, Functor IniParser
Functor IniParser =>
(forall a. a -> IniParser a)
-> (forall a b. IniParser (a -> b) -> IniParser a -> IniParser b)
-> (forall a b c.
(a -> b -> c) -> IniParser a -> IniParser b -> IniParser c)
-> (forall a b. IniParser a -> IniParser b -> IniParser b)
-> (forall a b. IniParser a -> IniParser b -> IniParser a)
-> Applicative IniParser
forall a. a -> IniParser a
forall a b. IniParser a -> IniParser b -> IniParser a
forall a b. IniParser a -> IniParser b -> IniParser b
forall a b. IniParser (a -> b) -> IniParser a -> IniParser b
forall a b c.
(a -> b -> c) -> IniParser a -> IniParser b -> IniParser c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall a. a -> IniParser a
pure :: forall a. a -> IniParser a
$c<*> :: forall a b. IniParser (a -> b) -> IniParser a -> IniParser b
<*> :: forall a b. IniParser (a -> b) -> IniParser a -> IniParser b
$cliftA2 :: forall a b c.
(a -> b -> c) -> IniParser a -> IniParser b -> IniParser c
liftA2 :: forall a b c.
(a -> b -> c) -> IniParser a -> IniParser b -> IniParser c
$c*> :: forall a b. IniParser a -> IniParser b -> IniParser b
*> :: forall a b. IniParser a -> IniParser b -> IniParser b
$c<* :: forall a b. IniParser a -> IniParser b -> IniParser a
<* :: forall a b. IniParser a -> IniParser b -> IniParser a
Applicative, Applicative IniParser
Applicative IniParser =>
(forall a. IniParser a)
-> (forall a. IniParser a -> IniParser a -> IniParser a)
-> (forall a. IniParser a -> IniParser [a])
-> (forall a. IniParser a -> IniParser [a])
-> Alternative IniParser
forall a. IniParser a
forall a. IniParser a -> IniParser [a]
forall a. IniParser a -> IniParser a -> IniParser a
forall (f :: * -> *).
Applicative f =>
(forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
$cempty :: forall a. IniParser a
empty :: forall a. IniParser a
$c<|> :: forall a. IniParser a -> IniParser a -> IniParser a
<|> :: forall a. IniParser a -> IniParser a -> IniParser a
$csome :: forall a. IniParser a -> IniParser [a]
some :: forall a. IniParser a -> IniParser [a]
$cmany :: forall a. IniParser a -> IniParser [a]
many :: forall a. IniParser a -> IniParser [a]
Alternative, Applicative IniParser
Applicative IniParser =>
(forall a b. IniParser a -> (a -> IniParser b) -> IniParser b)
-> (forall a b. IniParser a -> IniParser b -> IniParser b)
-> (forall a. a -> IniParser a)
-> Monad IniParser
forall a. a -> IniParser a
forall a b. IniParser a -> IniParser b -> IniParser b
forall a b. IniParser a -> (a -> IniParser b) -> IniParser b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall a b. IniParser a -> (a -> IniParser b) -> IniParser b
>>= :: forall a b. IniParser a -> (a -> IniParser b) -> IniParser b
$c>> :: forall a b. IniParser a -> IniParser b -> IniParser b
>> :: forall a b. IniParser a -> IniParser b -> IniParser b
$creturn :: forall a. a -> IniParser a
return :: forall a. a -> IniParser a
Monad)
newtype SectionParser a = SectionParser (StParser IniSection a)
deriving ((forall a b. (a -> b) -> SectionParser a -> SectionParser b)
-> (forall a b. a -> SectionParser b -> SectionParser a)
-> Functor SectionParser
forall a b. a -> SectionParser b -> SectionParser a
forall a b. (a -> b) -> SectionParser a -> SectionParser b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> SectionParser a -> SectionParser b
fmap :: forall a b. (a -> b) -> SectionParser a -> SectionParser b
$c<$ :: forall a b. a -> SectionParser b -> SectionParser a
<$ :: forall a b. a -> SectionParser b -> SectionParser a
Functor, Functor SectionParser
Functor SectionParser =>
(forall a. a -> SectionParser a)
-> (forall a b.
SectionParser (a -> b) -> SectionParser a -> SectionParser b)
-> (forall a b c.
(a -> b -> c)
-> SectionParser a -> SectionParser b -> SectionParser c)
-> (forall a b.
SectionParser a -> SectionParser b -> SectionParser b)
-> (forall a b.
SectionParser a -> SectionParser b -> SectionParser a)
-> Applicative SectionParser
forall a. a -> SectionParser a
forall a b. SectionParser a -> SectionParser b -> SectionParser a
forall a b. SectionParser a -> SectionParser b -> SectionParser b
forall a b.
SectionParser (a -> b) -> SectionParser a -> SectionParser b
forall a b c.
(a -> b -> c)
-> SectionParser a -> SectionParser b -> SectionParser c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall a. a -> SectionParser a
pure :: forall a. a -> SectionParser a
$c<*> :: forall a b.
SectionParser (a -> b) -> SectionParser a -> SectionParser b
<*> :: forall a b.
SectionParser (a -> b) -> SectionParser a -> SectionParser b
$cliftA2 :: forall a b c.
(a -> b -> c)
-> SectionParser a -> SectionParser b -> SectionParser c
liftA2 :: forall a b c.
(a -> b -> c)
-> SectionParser a -> SectionParser b -> SectionParser c
$c*> :: forall a b. SectionParser a -> SectionParser b -> SectionParser b
*> :: forall a b. SectionParser a -> SectionParser b -> SectionParser b
$c<* :: forall a b. SectionParser a -> SectionParser b -> SectionParser a
<* :: forall a b. SectionParser a -> SectionParser b -> SectionParser a
Applicative, Applicative SectionParser
Applicative SectionParser =>
(forall a. SectionParser a)
-> (forall a.
SectionParser a -> SectionParser a -> SectionParser a)
-> (forall a. SectionParser a -> SectionParser [a])
-> (forall a. SectionParser a -> SectionParser [a])
-> Alternative SectionParser
forall a. SectionParser a
forall a. SectionParser a -> SectionParser [a]
forall a. SectionParser a -> SectionParser a -> SectionParser a
forall (f :: * -> *).
Applicative f =>
(forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
$cempty :: forall a. SectionParser a
empty :: forall a. SectionParser a
$c<|> :: forall a. SectionParser a -> SectionParser a -> SectionParser a
<|> :: forall a. SectionParser a -> SectionParser a -> SectionParser a
$csome :: forall a. SectionParser a -> SectionParser [a]
some :: forall a. SectionParser a -> SectionParser [a]
$cmany :: forall a. SectionParser a -> SectionParser [a]
many :: forall a. SectionParser a -> SectionParser [a]
Alternative, Applicative SectionParser
Applicative SectionParser =>
(forall a b.
SectionParser a -> (a -> SectionParser b) -> SectionParser b)
-> (forall a b.
SectionParser a -> SectionParser b -> SectionParser b)
-> (forall a. a -> SectionParser a)
-> Monad SectionParser
forall a. a -> SectionParser a
forall a b. SectionParser a -> SectionParser b -> SectionParser b
forall a b.
SectionParser a -> (a -> SectionParser b) -> SectionParser b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall a b.
SectionParser a -> (a -> SectionParser b) -> SectionParser b
>>= :: forall a b.
SectionParser a -> (a -> SectionParser b) -> SectionParser b
$c>> :: forall a b. SectionParser a -> SectionParser b -> SectionParser b
>> :: forall a b. SectionParser a -> SectionParser b -> SectionParser b
$creturn :: forall a. a -> SectionParser a
return :: forall a. a -> SectionParser a
Monad)
parseIniFile :: Text -> IniParser a -> Either String a
parseIniFile :: forall a. Text -> IniParser a -> Either [Char] a
parseIniFile Text
text (IniParser StParser RawIni a
mote) = do
ini <- Text -> Either [Char] RawIni
parseRawIni Text
text
runExceptT mote ini
section :: Text -> SectionParser a -> IniParser a
section :: forall a. Text -> SectionParser a -> IniParser a
section Text
name (SectionParser StParser IniSection a
thunk) = StParser RawIni a -> IniParser a
forall a. StParser RawIni a -> IniParser a
IniParser (StParser RawIni a -> IniParser a)
-> StParser RawIni a -> IniParser a
forall a b. (a -> b) -> a -> b
$
(RawIni -> Either [Char] a) -> StParser RawIni a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((RawIni -> Either [Char] a) -> StParser RawIni a)
-> (RawIni -> Either [Char] a) -> StParser RawIni a
forall a b. (a -> b) -> a -> b
$ \(RawIni Seq (NormalizedText, IniSection)
ini) ->
case NormalizedText
-> Seq (NormalizedText, IniSection) -> Maybe IniSection
forall a. NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp (Text -> NormalizedText
normalize Text
name) Seq (NormalizedText, IniSection)
ini of
Maybe IniSection
Nothing -> [Char] -> Either [Char] a
forall a b. a -> Either a b
Left ([Char]
"No top-level section named " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
forall a. Show a => a -> [Char]
show Text
name)
Just IniSection
sec -> StParser IniSection a -> IniSection -> Either [Char] a
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT StParser IniSection a
thunk IniSection
sec
sections :: Text -> SectionParser a -> IniParser (Seq a)
sections :: forall a. Text -> SectionParser a -> IniParser (Seq a)
sections Text
name (SectionParser StParser IniSection a
thunk) = StParser RawIni (Seq a) -> IniParser (Seq a)
forall a. StParser RawIni a -> IniParser a
IniParser (StParser RawIni (Seq a) -> IniParser (Seq a))
-> StParser RawIni (Seq a) -> IniParser (Seq a)
forall a b. (a -> b) -> a -> b
$
(RawIni -> Either [Char] (Seq a)) -> StParser RawIni (Seq a)
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((RawIni -> Either [Char] (Seq a)) -> StParser RawIni (Seq a))
-> (RawIni -> Either [Char] (Seq a)) -> StParser RawIni (Seq a)
forall a b. (a -> b) -> a -> b
$ \(RawIni Seq (NormalizedText, IniSection)
ini) ->
let name' :: NormalizedText
name' = Text -> NormalizedText
normalize Text
name
in ((NormalizedText, IniSection) -> Either [Char] a)
-> Seq (NormalizedText, IniSection) -> Either [Char] (Seq a)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Seq a -> m (Seq b)
mapM
(StParser IniSection a -> IniSection -> Either [Char] a
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT StParser IniSection a
thunk (IniSection -> Either [Char] a)
-> ((NormalizedText, IniSection) -> IniSection)
-> (NormalizedText, IniSection)
-> Either [Char] a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NormalizedText, IniSection) -> IniSection
forall a b. (a, b) -> b
snd)
(((NormalizedText, IniSection) -> Bool)
-> Seq (NormalizedText, IniSection)
-> Seq (NormalizedText, IniSection)
forall a. (a -> Bool) -> Seq a -> Seq a
Seq.filter (\(NormalizedText
t, IniSection
_) -> NormalizedText
t NormalizedText -> NormalizedText -> Bool
forall a. Eq a => a -> a -> Bool
== NormalizedText
name') Seq (NormalizedText, IniSection)
ini)
sectionOf :: (Text -> Maybe b) -> (b -> SectionParser a) -> IniParser a
sectionOf :: forall b a.
(Text -> Maybe b) -> (b -> SectionParser a) -> IniParser a
sectionOf Text -> Maybe b
fn b -> SectionParser a
sectionParser = StParser RawIni a -> IniParser a
forall a. StParser RawIni a -> IniParser a
IniParser (StParser RawIni a -> IniParser a)
-> StParser RawIni a -> IniParser a
forall a b. (a -> b) -> a -> b
$
(RawIni -> Either [Char] a) -> StParser RawIni a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((RawIni -> Either [Char] a) -> StParser RawIni a)
-> (RawIni -> Either [Char] a) -> StParser RawIni a
forall a b. (a -> b) -> a -> b
$ \(RawIni Seq (NormalizedText, IniSection)
ini) ->
let go :: ViewL (NormalizedText, IniSection) -> Either [Char] a
go ViewL (NormalizedText, IniSection)
Seq.EmptyL = [Char] -> Either [Char] a
forall a b. a -> Either a b
Left [Char]
"No matching top-level section"
go ((NormalizedText
t, IniSection
sec) Seq.:< Seq (NormalizedText, IniSection)
rs)
| Just b
v <- Text -> Maybe b
fn (NormalizedText -> Text
actualText NormalizedText
t) =
let SectionParser StParser IniSection a
thunk = b -> SectionParser a
sectionParser b
v
in StParser IniSection a -> IniSection -> Either [Char] a
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT StParser IniSection a
thunk IniSection
sec
| Bool
otherwise = ViewL (NormalizedText, IniSection) -> Either [Char] a
go (Seq (NormalizedText, IniSection)
-> ViewL (NormalizedText, IniSection)
forall a. Seq a -> ViewL a
Seq.viewl Seq (NormalizedText, IniSection)
rs)
in ViewL (NormalizedText, IniSection) -> Either [Char] a
go (Seq (NormalizedText, IniSection)
-> ViewL (NormalizedText, IniSection)
forall a. Seq a -> ViewL a
Seq.viewl Seq (NormalizedText, IniSection)
ini)
sectionsOf :: (Text -> Maybe b) -> (b -> SectionParser a) -> IniParser (Seq a)
sectionsOf :: forall b a.
(Text -> Maybe b) -> (b -> SectionParser a) -> IniParser (Seq a)
sectionsOf Text -> Maybe b
fn b -> SectionParser a
sectionParser = StParser RawIni (Seq a) -> IniParser (Seq a)
forall a. StParser RawIni a -> IniParser a
IniParser (StParser RawIni (Seq a) -> IniParser (Seq a))
-> StParser RawIni (Seq a) -> IniParser (Seq a)
forall a b. (a -> b) -> a -> b
$
(RawIni -> Either [Char] (Seq a)) -> StParser RawIni (Seq a)
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((RawIni -> Either [Char] (Seq a)) -> StParser RawIni (Seq a))
-> (RawIni -> Either [Char] (Seq a)) -> StParser RawIni (Seq a)
forall a b. (a -> b) -> a -> b
$ \(RawIni Seq (NormalizedText, IniSection)
ini) ->
let go :: ViewL (NormalizedText, IniSection) -> Either [Char] (Seq a)
go ViewL (NormalizedText, IniSection)
Seq.EmptyL = Seq a -> Either [Char] (Seq a)
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return Seq a
forall a. Seq a
Seq.empty
go ((NormalizedText
t, IniSection
sec) Seq.:< Seq (NormalizedText, IniSection)
rs)
| Just b
v <- Text -> Maybe b
fn (NormalizedText -> Text
actualText NormalizedText
t) =
let SectionParser StParser IniSection a
thunk = b -> SectionParser a
sectionParser b
v
in do
x <- StParser IniSection a -> IniSection -> Either [Char] a
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT StParser IniSection a
thunk IniSection
sec
xs <- go (Seq.viewl rs)
return (x Seq.<| xs)
| Bool
otherwise = ViewL (NormalizedText, IniSection) -> Either [Char] (Seq a)
go (Seq (NormalizedText, IniSection)
-> ViewL (NormalizedText, IniSection)
forall a. Seq a -> ViewL a
Seq.viewl Seq (NormalizedText, IniSection)
rs)
in ViewL (NormalizedText, IniSection) -> Either [Char] (Seq a)
go (Seq (NormalizedText, IniSection)
-> ViewL (NormalizedText, IniSection)
forall a. Seq a -> ViewL a
Seq.viewl Seq (NormalizedText, IniSection)
ini)
sectionMb :: Text -> SectionParser a -> IniParser (Maybe a)
sectionMb :: forall a. Text -> SectionParser a -> IniParser (Maybe a)
sectionMb Text
name (SectionParser StParser IniSection a
thunk) = StParser RawIni (Maybe a) -> IniParser (Maybe a)
forall a. StParser RawIni a -> IniParser a
IniParser (StParser RawIni (Maybe a) -> IniParser (Maybe a))
-> StParser RawIni (Maybe a) -> IniParser (Maybe a)
forall a b. (a -> b) -> a -> b
$
(RawIni -> Either [Char] (Maybe a)) -> StParser RawIni (Maybe a)
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((RawIni -> Either [Char] (Maybe a)) -> StParser RawIni (Maybe a))
-> (RawIni -> Either [Char] (Maybe a)) -> StParser RawIni (Maybe a)
forall a b. (a -> b) -> a -> b
$ \(RawIni Seq (NormalizedText, IniSection)
ini) ->
case NormalizedText
-> Seq (NormalizedText, IniSection) -> Maybe IniSection
forall a. NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp (Text -> NormalizedText
normalize Text
name) Seq (NormalizedText, IniSection)
ini of
Maybe IniSection
Nothing -> Maybe a -> Either [Char] (Maybe a)
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
Just IniSection
sec -> a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> Either [Char] a -> Either [Char] (Maybe a)
forall a b. (a -> b) -> Either [Char] a -> Either [Char] b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` StParser IniSection a -> IniSection -> Either [Char] a
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT StParser IniSection a
thunk IniSection
sec
sectionDef :: Text -> a -> SectionParser a -> IniParser a
sectionDef :: forall a. Text -> a -> SectionParser a -> IniParser a
sectionDef Text
name a
def (SectionParser StParser IniSection a
thunk) = StParser RawIni a -> IniParser a
forall a. StParser RawIni a -> IniParser a
IniParser (StParser RawIni a -> IniParser a)
-> StParser RawIni a -> IniParser a
forall a b. (a -> b) -> a -> b
$
(RawIni -> Either [Char] a) -> StParser RawIni a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((RawIni -> Either [Char] a) -> StParser RawIni a)
-> (RawIni -> Either [Char] a) -> StParser RawIni a
forall a b. (a -> b) -> a -> b
$ \(RawIni Seq (NormalizedText, IniSection)
ini) ->
case NormalizedText
-> Seq (NormalizedText, IniSection) -> Maybe IniSection
forall a. NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp (Text -> NormalizedText
normalize Text
name) Seq (NormalizedText, IniSection)
ini of
Maybe IniSection
Nothing -> a -> Either [Char] a
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return a
def
Just IniSection
sec -> StParser IniSection a -> IniSection -> Either [Char] a
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT StParser IniSection a
thunk IniSection
sec
throw :: String -> StParser s a
throw :: forall s a. [Char] -> StParser s a
throw [Char]
msg = (s -> Either [Char] a) -> ExceptT [Char] ((->) s) a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (\s
_ -> [Char] -> Either [Char] a
forall a b. a -> Either a b
Left [Char]
msg)
getSectionName :: StParser IniSection Text
getSectionName :: StParser IniSection Text
getSectionName = (IniSection -> Either [Char] Text) -> StParser IniSection Text
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (Text -> Either [Char] Text
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Either [Char] Text)
-> (IniSection -> Text) -> IniSection -> Either [Char] Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IniSection -> Text
isName)
rawFieldMb :: Text -> StParser IniSection (Maybe IniValue)
rawFieldMb :: Text -> StParser IniSection (Maybe IniValue)
rawFieldMb Text
name = (IniSection -> Either [Char] (Maybe IniValue))
-> StParser IniSection (Maybe IniValue)
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((IniSection -> Either [Char] (Maybe IniValue))
-> StParser IniSection (Maybe IniValue))
-> (IniSection -> Either [Char] (Maybe IniValue))
-> StParser IniSection (Maybe IniValue)
forall a b. (a -> b) -> a -> b
$ \IniSection
m ->
Maybe IniValue -> Either [Char] (Maybe IniValue)
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return (NormalizedText -> Seq (NormalizedText, IniValue) -> Maybe IniValue
forall a. NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp (Text -> NormalizedText
normalize Text
name) (IniSection -> Seq (NormalizedText, IniValue)
isVals IniSection
m))
rawField :: Text -> StParser IniSection IniValue
rawField :: Text -> StParser IniSection IniValue
rawField Text
name = do
sec <- StParser IniSection Text
getSectionName
valMb <- rawFieldMb name
case valMb of
Maybe IniValue
Nothing ->
[Char] -> StParser IniSection IniValue
forall s a. [Char] -> StParser s a
throw
( [Char]
"Missing field " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
forall a. Show a => a -> [Char]
show Text
name
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" in section "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
forall a. Show a => a -> [Char]
show Text
sec
)
Just IniValue
x -> IniValue -> StParser IniSection IniValue
forall a. a -> ExceptT [Char] ((->) IniSection) a
forall (m :: * -> *) a. Monad m => a -> m a
return IniValue
x
getVal :: IniValue -> Text
getVal :: IniValue -> Text
getVal = Text -> Text
T.strip (Text -> Text) -> (IniValue -> Text) -> IniValue -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IniValue -> Text
vValue
field :: Text -> SectionParser Text
field :: Text -> SectionParser Text
field Text
name = StParser IniSection Text -> SectionParser Text
forall a. StParser IniSection a -> SectionParser a
SectionParser (StParser IniSection Text -> SectionParser Text)
-> StParser IniSection Text -> SectionParser Text
forall a b. (a -> b) -> a -> b
$ IniValue -> Text
getVal (IniValue -> Text)
-> StParser IniSection IniValue -> StParser IniSection Text
forall a b.
(a -> b)
-> ExceptT [Char] ((->) IniSection) a
-> ExceptT [Char] ((->) IniSection) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Text -> StParser IniSection IniValue
rawField Text
name
fieldOf :: Text -> (Text -> Either String a) -> SectionParser a
fieldOf :: forall a. Text -> (Text -> Either [Char] a) -> SectionParser a
fieldOf Text
name Text -> Either [Char] a
parse = StParser IniSection a -> SectionParser a
forall a. StParser IniSection a -> SectionParser a
SectionParser (StParser IniSection a -> SectionParser a)
-> StParser IniSection a -> SectionParser a
forall a b. (a -> b) -> a -> b
$ do
sec <- StParser IniSection Text
getSectionName
val <- rawField name
case parse (getVal val) of
Left [Char]
err -> Int -> Text -> StParser IniSection a -> StParser IniSection a
forall s a. Int -> Text -> StParser s a -> StParser s a
addLineInformation (IniValue -> Int
vLineNo IniValue
val) Text
sec ([Char] -> StParser IniSection a
forall s a. [Char] -> StParser s a
throw [Char]
err)
Right a
x -> a -> StParser IniSection a
forall a. a -> ExceptT [Char] ((->) IniSection) a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
fieldMb :: Text -> SectionParser (Maybe Text)
fieldMb :: Text -> SectionParser (Maybe Text)
fieldMb Text
name = StParser IniSection (Maybe Text) -> SectionParser (Maybe Text)
forall a. StParser IniSection a -> SectionParser a
SectionParser (StParser IniSection (Maybe Text) -> SectionParser (Maybe Text))
-> StParser IniSection (Maybe Text) -> SectionParser (Maybe Text)
forall a b. (a -> b) -> a -> b
$ (IniValue -> Text) -> Maybe IniValue -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IniValue -> Text
getVal (Maybe IniValue -> Maybe Text)
-> StParser IniSection (Maybe IniValue)
-> StParser IniSection (Maybe Text)
forall a b.
(a -> b)
-> ExceptT [Char] ((->) IniSection) a
-> ExceptT [Char] ((->) IniSection) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Text -> StParser IniSection (Maybe IniValue)
rawFieldMb Text
name
fieldMbOf :: Text -> (Text -> Either String a) -> SectionParser (Maybe a)
fieldMbOf :: forall a.
Text -> (Text -> Either [Char] a) -> SectionParser (Maybe a)
fieldMbOf Text
name Text -> Either [Char] a
parse = StParser IniSection (Maybe a) -> SectionParser (Maybe a)
forall a. StParser IniSection a -> SectionParser a
SectionParser (StParser IniSection (Maybe a) -> SectionParser (Maybe a))
-> StParser IniSection (Maybe a) -> SectionParser (Maybe a)
forall a b. (a -> b) -> a -> b
$ do
sec <- StParser IniSection Text
getSectionName
mb <- rawFieldMb name
case mb of
Maybe IniValue
Nothing -> Maybe a -> StParser IniSection (Maybe a)
forall a. a -> ExceptT [Char] ((->) IniSection) a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
Just IniValue
v -> case Text -> Either [Char] a
parse (IniValue -> Text
getVal IniValue
v) of
Left [Char]
err -> Int
-> Text
-> StParser IniSection (Maybe a)
-> StParser IniSection (Maybe a)
forall s a. Int -> Text -> StParser s a -> StParser s a
addLineInformation (IniValue -> Int
vLineNo IniValue
v) Text
sec ([Char] -> StParser IniSection (Maybe a)
forall s a. [Char] -> StParser s a
throw [Char]
err)
Right a
x -> Maybe a -> StParser IniSection (Maybe a)
forall a. a -> ExceptT [Char] ((->) IniSection) a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Maybe a
forall a. a -> Maybe a
Just a
x)
fieldDef :: Text -> Text -> SectionParser Text
fieldDef :: Text -> Text -> SectionParser Text
fieldDef Text
name Text
def = StParser IniSection Text -> SectionParser Text
forall a. StParser IniSection a -> SectionParser a
SectionParser (StParser IniSection Text -> SectionParser Text)
-> StParser IniSection Text -> SectionParser Text
forall a b. (a -> b) -> a -> b
$
(IniSection -> Either [Char] Text) -> StParser IniSection Text
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((IniSection -> Either [Char] Text) -> StParser IniSection Text)
-> (IniSection -> Either [Char] Text) -> StParser IniSection Text
forall a b. (a -> b) -> a -> b
$ \IniSection
m ->
case NormalizedText -> Seq (NormalizedText, IniValue) -> Maybe IniValue
forall a. NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp (Text -> NormalizedText
normalize Text
name) (IniSection -> Seq (NormalizedText, IniValue)
isVals IniSection
m) of
Maybe IniValue
Nothing -> Text -> Either [Char] Text
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return Text
def
Just IniValue
x -> Text -> Either [Char] Text
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return (IniValue -> Text
getVal IniValue
x)
fieldDefOf :: Text -> (Text -> Either String a) -> a -> SectionParser a
fieldDefOf :: forall a. Text -> (Text -> Either [Char] a) -> a -> SectionParser a
fieldDefOf Text
name Text -> Either [Char] a
parse a
def = StParser IniSection a -> SectionParser a
forall a. StParser IniSection a -> SectionParser a
SectionParser (StParser IniSection a -> SectionParser a)
-> StParser IniSection a -> SectionParser a
forall a b. (a -> b) -> a -> b
$ do
sec <- StParser IniSection Text
getSectionName
mb <- rawFieldMb name
case mb of
Maybe IniValue
Nothing -> a -> StParser IniSection a
forall a. a -> ExceptT [Char] ((->) IniSection) a
forall (m :: * -> *) a. Monad m => a -> m a
return a
def
Just IniValue
v -> case Text -> Either [Char] a
parse (IniValue -> Text
getVal IniValue
v) of
Left [Char]
err -> Int -> Text -> StParser IniSection a -> StParser IniSection a
forall s a. Int -> Text -> StParser s a -> StParser s a
addLineInformation (IniValue -> Int
vLineNo IniValue
v) Text
sec ([Char] -> StParser IniSection a
forall s a. [Char] -> StParser s a
throw [Char]
err)
Right a
x -> a -> StParser IniSection a
forall a. a -> ExceptT [Char] ((->) IniSection) a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
fieldFlag :: Text -> SectionParser Bool
fieldFlag :: Text -> SectionParser Bool
fieldFlag Text
name = Text -> (Text -> Either [Char] Bool) -> SectionParser Bool
forall a. Text -> (Text -> Either [Char] a) -> SectionParser a
fieldOf Text
name Text -> Either [Char] Bool
flag
fieldFlagDef :: Text -> Bool -> SectionParser Bool
fieldFlagDef :: Text -> Bool -> SectionParser Bool
fieldFlagDef Text
name = Text -> (Text -> Either [Char] Bool) -> Bool -> SectionParser Bool
forall a. Text -> (Text -> Either [Char] a) -> a -> SectionParser a
fieldDefOf Text
name Text -> Either [Char] Bool
flag
readable :: forall a. (Read a, Typeable a) => Text -> Either String a
readable :: forall a. (Read a, Typeable a) => Text -> Either [Char] a
readable Text
t = case [Char] -> Maybe a
forall a. Read a => [Char] -> Maybe a
readMaybe [Char]
str of
Just a
v -> a -> Either [Char] a
forall a b. b -> Either a b
Right a
v
Maybe a
Nothing ->
[Char] -> Either [Char] a
forall a b. a -> Either a b
Left
( [Char]
"Unable to parse " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
forall a. Show a => a -> [Char]
show [Char]
str
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" as a value of type "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ TypeRep -> [Char]
forall a. Show a => a -> [Char]
show TypeRep
typ
)
where
str :: [Char]
str = Text -> [Char]
T.unpack Text
t
typ :: TypeRep
typ = Proxy a -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep Proxy a
prx
prx :: Proxy a
prx :: Proxy a
prx = Proxy a
forall {k} (t :: k). Proxy t
Proxy
number :: (Num a, Read a, Typeable a) => Text -> Either String a
number :: forall a. (Num a, Read a, Typeable a) => Text -> Either [Char] a
number = Text -> Either [Char] a
forall a. (Read a, Typeable a) => Text -> Either [Char] a
readable
string :: (IsString a) => Text -> Either String a
string :: forall a. IsString a => Text -> Either [Char] a
string = a -> Either [Char] a
forall a. a -> Either [Char] a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Either [Char] a) -> (Text -> a) -> Text -> Either [Char] a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> a
forall a. IsString a => [Char] -> a
fromString ([Char] -> a) -> (Text -> [Char]) -> Text -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack
flag :: Text -> Either String Bool
flag :: Text -> Either [Char] Bool
flag Text
s = case Text -> Text
T.toLower Text
s of
Text
"true" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
True
Text
"yes" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
True
Text
"t" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
True
Text
"y" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
True
Text
"false" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
False
Text
"no" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
False
Text
"f" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
False
Text
"n" -> Bool -> Either [Char] Bool
forall a b. b -> Either a b
Right Bool
False
Text
_ -> [Char] -> Either [Char] Bool
forall a b. a -> Either a b
Left ([Char]
"Unable to parse " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
forall a. Show a => a -> [Char]
show Text
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" as a boolean")
listWithSeparator ::
(IsList l) =>
Text ->
(Text -> Either String (Item l)) ->
Text ->
Either String l
listWithSeparator :: forall l.
IsList l =>
Text -> (Text -> Either [Char] (Item l)) -> Text -> Either [Char] l
listWithSeparator Text
sep Text -> Either [Char] (Item l)
rd =
([Item l] -> l) -> Either [Char] [Item l] -> Either [Char] l
forall a b. (a -> b) -> Either [Char] a -> Either [Char] b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Item l] -> l
forall l. IsList l => [Item l] -> l
fromList (Either [Char] [Item l] -> Either [Char] l)
-> (Text -> Either [Char] [Item l]) -> Text -> Either [Char] l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Either [Char] (Item l))
-> [Text] -> Either [Char] [Item l]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Text -> Either [Char] (Item l)
rd (Text -> Either [Char] (Item l))
-> (Text -> Text) -> Text -> Either [Char] (Item l)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.strip) ([Text] -> Either [Char] [Item l])
-> (Text -> [Text]) -> Text -> Either [Char] [Item l]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
sep