{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
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 (Typeable, Proxy(..), typeRep)
import GHC.Exts (IsList(..))
import Text.Read (readMaybe)
lkp :: NormalizedText -> Seq (NormalizedText, a) -> Maybe a
lkp :: 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 :: Int -> Text -> StParser s a -> StParser s a
addLineInformation Int
lineNo Text
sec = ([Char] -> [Char]) -> StParser s a -> StParser 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 (a -> IniParser b -> IniParser a
(a -> b) -> IniParser a -> IniParser b
(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
<$ :: a -> IniParser b -> IniParser a
$c<$ :: forall a b. a -> IniParser b -> IniParser a
fmap :: (a -> b) -> IniParser a -> IniParser b
$cfmap :: forall a b. (a -> b) -> IniParser a -> IniParser b
Functor, Functor IniParser
a -> IniParser a
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
IniParser a -> IniParser b -> IniParser b
IniParser a -> IniParser b -> IniParser a
IniParser (a -> b) -> IniParser a -> IniParser b
(a -> b -> c) -> IniParser a -> IniParser b -> IniParser c
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
<* :: IniParser a -> IniParser b -> IniParser a
$c<* :: forall a b. IniParser a -> IniParser b -> IniParser a
*> :: IniParser a -> IniParser b -> IniParser b
$c*> :: forall a b. IniParser a -> IniParser b -> IniParser b
liftA2 :: (a -> b -> c) -> IniParser a -> IniParser b -> IniParser c
$cliftA2 :: forall a b c.
(a -> b -> c) -> IniParser a -> IniParser b -> IniParser c
<*> :: IniParser (a -> b) -> IniParser a -> IniParser b
$c<*> :: forall a b. IniParser (a -> b) -> IniParser a -> IniParser b
pure :: a -> IniParser a
$cpure :: forall a. a -> IniParser a
$cp1Applicative :: Functor IniParser
Applicative, Applicative IniParser
IniParser a
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
IniParser a -> IniParser a -> IniParser a
IniParser a -> IniParser [a]
IniParser a -> IniParser [a]
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
many :: IniParser a -> IniParser [a]
$cmany :: forall a. IniParser a -> IniParser [a]
some :: IniParser a -> IniParser [a]
$csome :: forall a. IniParser a -> IniParser [a]
<|> :: IniParser a -> IniParser a -> IniParser a
$c<|> :: forall a. IniParser a -> IniParser a -> IniParser a
empty :: IniParser a
$cempty :: forall a. IniParser a
$cp1Alternative :: Applicative IniParser
Alternative, Applicative IniParser
a -> IniParser a
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
IniParser a -> (a -> IniParser b) -> IniParser b
IniParser a -> IniParser b -> IniParser b
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
return :: a -> IniParser a
$creturn :: forall a. a -> IniParser a
>> :: IniParser a -> IniParser b -> IniParser b
$c>> :: forall a b. IniParser a -> IniParser b -> IniParser b
>>= :: IniParser a -> (a -> IniParser b) -> IniParser b
$c>>= :: forall a b. IniParser a -> (a -> IniParser b) -> IniParser b
$cp1Monad :: Applicative IniParser
Monad)
newtype SectionParser a = SectionParser (StParser IniSection a)
deriving (a -> SectionParser b -> SectionParser a
(a -> b) -> SectionParser a -> SectionParser b
(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
<$ :: a -> SectionParser b -> SectionParser a
$c<$ :: forall a b. a -> SectionParser b -> SectionParser a
fmap :: (a -> b) -> SectionParser a -> SectionParser b
$cfmap :: forall a b. (a -> b) -> SectionParser a -> SectionParser b
Functor, Functor SectionParser
a -> SectionParser a
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
SectionParser a -> SectionParser b -> SectionParser b
SectionParser a -> SectionParser b -> SectionParser a
SectionParser (a -> b) -> SectionParser a -> SectionParser b
(a -> b -> c)
-> SectionParser a -> SectionParser b -> SectionParser c
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
<* :: SectionParser a -> SectionParser b -> SectionParser a
$c<* :: forall a b. SectionParser a -> SectionParser b -> SectionParser a
*> :: SectionParser a -> SectionParser b -> SectionParser b
$c*> :: forall a b. SectionParser a -> SectionParser b -> SectionParser b
liftA2 :: (a -> b -> c)
-> SectionParser a -> SectionParser b -> SectionParser c
$cliftA2 :: forall a b c.
(a -> b -> c)
-> SectionParser a -> SectionParser b -> SectionParser c
<*> :: SectionParser (a -> b) -> SectionParser a -> SectionParser b
$c<*> :: forall a b.
SectionParser (a -> b) -> SectionParser a -> SectionParser b
pure :: a -> SectionParser a
$cpure :: forall a. a -> SectionParser a
$cp1Applicative :: Functor SectionParser
Applicative, Applicative SectionParser
SectionParser a
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
SectionParser a -> SectionParser a -> SectionParser a
SectionParser a -> SectionParser [a]
SectionParser a -> SectionParser [a]
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
many :: SectionParser a -> SectionParser [a]
$cmany :: forall a. SectionParser a -> SectionParser [a]
some :: SectionParser a -> SectionParser [a]
$csome :: forall a. SectionParser a -> SectionParser [a]
<|> :: SectionParser a -> SectionParser a -> SectionParser a
$c<|> :: forall a. SectionParser a -> SectionParser a -> SectionParser a
empty :: SectionParser a
$cempty :: forall a. SectionParser a
$cp1Alternative :: Applicative SectionParser
Alternative, Applicative SectionParser
a -> SectionParser a
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
SectionParser a -> (a -> SectionParser b) -> SectionParser b
SectionParser a -> SectionParser b -> SectionParser b
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
return :: a -> SectionParser a
$creturn :: forall a. a -> SectionParser a
>> :: SectionParser a -> SectionParser b -> SectionParser b
$c>> :: forall a b. SectionParser a -> SectionParser b -> SectionParser b
>>= :: SectionParser a -> (a -> SectionParser b) -> SectionParser b
$c>>= :: forall a b.
SectionParser a -> (a -> SectionParser b) -> SectionParser b
$cp1Monad :: Applicative SectionParser
Monad)
parseIniFile :: Text -> IniParser a -> Either String a
parseIniFile :: Text -> IniParser a -> Either [Char] a
parseIniFile Text
text (IniParser StParser RawIni a
mote) = do
RawIni
ini <- Text -> Either [Char] RawIni
parseRawIni Text
text
StParser RawIni a -> RawIni -> Either [Char] a
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT StParser RawIni a
mote RawIni
ini
section :: Text -> SectionParser a -> IniParser a
section :: 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 :: 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)
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 :: (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 :: (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 (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
a
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
Seq a
xs <- 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)
Seq a -> Either [Char] (Seq a)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
x a -> Seq a -> Seq a
forall a. a -> Seq a -> Seq a
Seq.<| Seq a
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 :: 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 (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 (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 :: 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 (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 :: [Char] -> StParser s a
throw [Char]
msg = (s -> Either [Char] a) -> StParser s a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT ((s -> Either [Char] a) -> StParser s a)
-> (s -> Either [Char] a) -> StParser s a
forall a b. (a -> b) -> a -> b
$ (\ 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 ((IniSection -> Either [Char] Text) -> StParser IniSection Text)
-> (IniSection -> Either [Char] Text) -> StParser IniSection Text
forall a b. (a -> b) -> a -> b
$ (\ IniSection
m -> Text -> Either [Char] Text
forall (m :: * -> *) a. Monad m => a -> m a
return (IniSection -> Text
isName IniSection
m))
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 (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
Text
sec <- StParser IniSection Text
getSectionName
Maybe IniValue
valMb <- Text -> StParser IniSection (Maybe IniValue)
rawFieldMb Text
name
case Maybe IniValue
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 (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 (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 :: 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
Text
sec <- StParser IniSection Text
getSectionName
IniValue
val <- Text -> StParser IniSection IniValue
rawField Text
name
case Text -> Either [Char] a
parse (IniValue -> Text
getVal IniValue
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 (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 (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 (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 :: 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
Text
sec <- StParser IniSection Text
getSectionName
Maybe IniValue
mb <- Text -> StParser IniSection (Maybe IniValue)
rawFieldMb Text
name
case Maybe IniValue
mb of
Maybe IniValue
Nothing -> Maybe a -> StParser IniSection (Maybe 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 (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 (m :: * -> *) a. Monad m => a -> m a
return Text
def
Just IniValue
x -> Text -> Either [Char] Text
forall (m :: * -> *) a. Monad m => a -> m a
return (IniValue -> Text
getVal IniValue
x)
fieldDefOf :: Text -> (Text -> Either String a) -> a -> SectionParser a
fieldDefOf :: 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
Text
sec <- StParser IniSection Text
getSectionName
Maybe IniValue
mb <- Text -> StParser IniSection (Maybe IniValue)
rawFieldMb Text
name
case Maybe IniValue
mb of
Maybe IniValue
Nothing -> a -> StParser 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 (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 Bool
def = 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 Bool
def
readable :: forall a. (Read a, Typeable a) => Text -> Either String a
readable :: 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 :: 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 :: Text -> Either [Char] a
string = 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 :: 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 (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)
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
. Text -> Text -> [Text]
T.splitOn Text
sep