{-# LANGUAGE ExistentialQuantification #-}
module Text.Parser.HOCON.Internal
( objectParser
, stringParser
, parseProps
, parseLabel
, arrayParser
, numberParser
, booleanParser
, nullParser
, preProcessing
, hoconParser
, postProcessing
)
where
import Data.Bifunctor.Extra (mapValues)
import Data.HOCON (Config(..))
import Data.List.Split (splitOn)
import Data.Map (groupBy, sortByKey, Map)
import Data.String.Utils (replace, join, strip)
import Text.ParserCombinators.Parsec
(char, Parser, alphaNum, digit, letter, noneOf, oneOf, space, string, between, sepBy, (<|>), many, many1, skipMany, try)
whitespace :: Parser ()
whitespace :: Parser ()
whitespace = ParsecT String () Identity Char -> Parser ()
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
skipMany ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
space
objectParser :: Parser Config
objectParser :: Parser Config
objectParser = do
Parser ()
whitespace Parser ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'{' ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace
[(String, Config)]
props <- ParsecT String () Identity (String, Config)
-> Parser () -> ParsecT String () Identity [(String, Config)]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy ParsecT String () Identity (String, Config)
parseProps (Parser ()
whitespace Parser ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
',' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\n') ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace)
Parser ()
whitespace Parser ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'}' ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace
Config -> Parser Config
forall (m :: * -> *) a. Monad m => a -> m a
return (Config -> Parser Config) -> Config -> Parser Config
forall a b. (a -> b) -> a -> b
$ [(String, Config)] -> Config
HOCONNode [(String, Config)]
props
parseString :: Parser String
parseString :: Parser String
parseString = Parser String
parseStr Parser String -> Parser String -> Parser String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser String
parseOpenStr
parseStr :: Parser String
parseStr :: Parser String
parseStr = ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> Parser String
-> Parser String
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\"') (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\"') (ParsecT String () Identity Char -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (ParsecT String () Identity Char -> Parser String)
-> ParsecT String () Identity Char -> Parser String
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
"\"" ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsecT String () Identity Char -> ParsecT String () Identity Char
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\"\"" Parser String
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
'"'))
parseOpenStr :: Parser String
parseOpenStr :: Parser String
parseOpenStr = do
Char
l <- ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
letter
String
str <- ParsecT String () Identity Char -> Parser String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"._-")
String -> Parser String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Parser String) -> String -> Parser String
forall a b. (a -> b) -> a -> b
$ Char
l Char -> String -> String
forall a. a -> [a] -> [a]
: String
str
parseProps :: Parser (String, Config)
parseProps :: ParsecT String () Identity (String, Config)
parseProps = do
String
label <- Parser String
parseString
Config
value <- Parser ()
whitespace Parser () -> Parser Config -> Parser Config
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Parser Config
parseJsonLikeValue Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
parseObjectValue)
(String, Config) -> ParsecT String () Identity (String, Config)
forall (m :: * -> *) a. Monad m => a -> m a
return ((String, Config) -> ParsecT String () Identity (String, Config))
-> (String, Config) -> ParsecT String () Identity (String, Config)
forall a b. (a -> b) -> a -> b
$ String -> Config -> (String, Config)
splitProp String
label Config
value
where
parseJsonLikeValue :: Parser Config
parseJsonLikeValue = do
(Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
':' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'=') ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace
Parser Config
objectParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
arrayParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
booleanParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
nullParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
stringParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
numberParser
parseObjectValue :: Parser Config
parseObjectValue = Parser Config
objectParser
parseLabel :: Parser String
parseLabel :: Parser String
parseLabel = do
Parser ()
whitespace
String
label <- Parser String
parseString
Parser ()
whitespace Parser ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
':' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'=') ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace
String -> Parser String
forall (m :: * -> *) a. Monad m => a -> m a
return String
label
numberParser :: Parser Config
numberParser :: Parser Config
numberParser = do
Parser ()
whitespace
String
digits <- ParsecT String () Identity Char -> Parser String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
".-")
Parser ()
whitespace
Config -> Parser Config
forall (m :: * -> *) a. Monad m => a -> m a
return (Config -> Parser Config)
-> (Double -> Config) -> Double -> Parser Config
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Config
HOCONNumber (Double -> Parser Config) -> Double -> Parser Config
forall a b. (a -> b) -> a -> b
$ String -> Double
forall a. Read a => String -> a
read String
digits
stringParser :: Parser Config
stringParser :: Parser Config
stringParser = do
Parser ()
whitespace
String
str <- Parser String
parseStr Parser String -> Parser String -> Parser String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser String
parseOpenStr
Parser ()
whitespace
Config -> Parser Config
forall (m :: * -> *) a. Monad m => a -> m a
return (Config -> Parser Config) -> Config -> Parser Config
forall a b. (a -> b) -> a -> b
$ String -> Config
HOCONString String
str
booleanParser :: Parser Config
booleanParser :: Parser Config
booleanParser = do
Parser ()
whitespace
String
bool <- Parser String -> Parser String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"true" Parser String -> Parser String -> Parser String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"false")
Parser ()
whitespace
Config -> Parser Config
forall (m :: * -> *) a. Monad m => a -> m a
return (Config -> Parser Config) -> Config -> Parser Config
forall a b. (a -> b) -> a -> b
$ if String
bool String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"true" then Bool -> Config
HOCONBool Bool
True else Bool -> Config
HOCONBool Bool
False
nullParser :: Parser Config
nullParser :: Parser Config
nullParser = do
Parser ()
whitespace Parser () -> Parser String -> Parser String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Parser String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"null" Parser String -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace
Config -> Parser Config
forall (m :: * -> *) a. Monad m => a -> m a
return Config
HOCONNull
arrayParser :: Parser Config
arrayParser :: Parser Config
arrayParser = do
Parser ()
whitespace Parser ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'[' ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace
[Config]
array <- Parser Config -> Parser () -> ParsecT String () Identity [Config]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy
(Parser Config
objectParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
arrayParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
booleanParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
nullParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
stringParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser Config
numberParser)
(Parser ()
whitespace Parser ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
',' ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace)
Parser ()
whitespace Parser ()
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
']' ParsecT String () Identity Char -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
whitespace
Config -> Parser Config
forall (m :: * -> *) a. Monad m => a -> m a
return (Config -> Parser Config) -> Config -> Parser Config
forall a b. (a -> b) -> a -> b
$ [Config] -> Config
HOCONList [Config]
array
splitProp :: String -> Config -> (String, Config)
splitProp :: String -> Config -> (String, Config)
splitProp String
label Config
value = case String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
"." String
label of
[String
l ] -> (String
l, Config
value)
(String
l : [String]
nested) -> (String
l, [String] -> Config -> Config
join [String]
nested Config
value)
where
join :: [String] -> Config -> Config
join [String
l ] Config
value = [(String, Config)] -> Config
HOCONNode [(String
l, Config
value)]
join (String
l : [String]
ls) Config
value = [(String, Config)] -> Config
HOCONNode [(String
l, [String] -> Config -> Config
join [String]
ls Config
value)]
preProcessing :: String -> String
preProcessing :: String -> String
preProcessing =
String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"\n" String
","
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"[\n" String
"["
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"\n]" String
"]"
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"{\n" String
"{"
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"\n}" String
"}"
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
",\n" String
","
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
join String
"\n"
([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null)
([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
strip
([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
"\n"
postProcessing :: Config -> Config
postProcessing :: Config -> Config
postProcessing (HOCONNode [(String, Config)]
nodes) = [(String, Config)] -> Config
HOCONNode ([(String, Config)] -> Config)
-> ([(String, Config)] -> [(String, Config)])
-> [(String, Config)]
-> Config
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(String, Config)] -> [(String, Config)]
sort ([(String, Config)] -> [(String, Config)])
-> ([(String, Config)] -> [(String, Config)])
-> [(String, Config)]
-> [(String, Config)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(String, Config)] -> [(String, Config)]
removeDuplicates ([(String, Config)] -> [(String, Config)])
-> ([(String, Config)] -> [(String, Config)])
-> [(String, Config)]
-> [(String, Config)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(String, Config)] -> [(String, Config)]
group ([(String, Config)] -> Config) -> [(String, Config)] -> Config
forall a b. (a -> b) -> a -> b
$ [(String, Config)]
nodes
group :: Map String Config -> Map String Config
group :: [(String, Config)] -> [(String, Config)]
group [(String, Config)]
nodes = do
let grouped :: Map String [(String, Config)]
grouped = ((String, Config) -> String)
-> [(String, Config)] -> Map String [(String, Config)]
forall k v. (Ord k, Eq k) => (v -> k) -> [v] -> Map k [v]
groupBy (String, Config) -> String
forall a b. (a, b) -> a
fst [(String, Config)]
nodes
(String
key, [Config]
configs) <- ([(String, Config)] -> [Config])
-> Map String [(String, Config)] -> Map String [Config]
forall b c a. (b -> c) -> Map a b -> Map a c
mapValues (((String, Config) -> Config) -> [(String, Config)] -> [Config]
forall a b. (a -> b) -> [a] -> [b]
map (String, Config) -> Config
forall a b. (a, b) -> b
snd) Map String [(String, Config)]
grouped
(String, Config) -> [(String, Config)]
forall (m :: * -> *) a. Monad m => a -> m a
return (String
key, if (Config -> Bool) -> [Config] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Config -> Bool
isNode [Config]
configs then [Config] -> Config
mergeAll [Config]
configs else [Config] -> Config
forall a. [a] -> a
head [Config]
configs)
where
isNode :: Config -> Bool
isNode Config
n = case Config
n of
HOCONNode [(String, Config)]
_ -> Bool
True
Config
_ -> Bool
False
sort :: Map String Config -> Map String Config
sort :: [(String, Config)] -> [(String, Config)]
sort = [(String, Config)] -> [(String, Config)]
forall k v. Ord k => Map k v -> Map k v
sortByKey
hoconParser :: Parser Config
hoconParser :: Parser Config
hoconParser = Config -> Config
postProcessing (Config -> Config) -> Parser Config -> Parser Config
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Config
parser
where
parser :: Parser Config
parser = Parser Config
objectParser Parser Config -> Parser Config -> Parser Config
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> do
[(String, Config)]
values <- ParsecT String () Identity (String, Config)
-> ParsecT String () Identity Char
-> ParsecT String () Identity [(String, Config)]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy ParsecT String () Identity (String, Config)
parseProps (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
',')
Config -> Parser Config
forall (m :: * -> *) a. Monad m => a -> m a
return (Config -> Parser Config) -> Config -> Parser Config
forall a b. (a -> b) -> a -> b
$ [(String, Config)] -> Config
HOCONNode [(String, Config)]
values
removeDuplicates :: Map String Config -> Map String Config
removeDuplicates :: [(String, Config)] -> [(String, Config)]
removeDuplicates = ([(String, Config)] -> (String, Config) -> [(String, Config)])
-> [(String, Config)] -> [(String, Config)] -> [(String, Config)]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\[(String, Config)]
acc (String, Config)
e -> if ((String, Config) -> Bool) -> [(String, Config)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== (String, Config) -> String
forall a b. (a, b) -> a
fst (String, Config)
e) (String -> Bool)
-> ((String, Config) -> String) -> (String, Config) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, Config) -> String
forall a b. (a, b) -> a
fst) [(String, Config)]
acc then [(String, Config)]
acc else (String, Config)
e (String, Config) -> [(String, Config)] -> [(String, Config)]
forall a. a -> [a] -> [a]
: [(String, Config)]
acc) []
mergeAll :: [Config] -> Config
mergeAll :: [Config] -> Config
mergeAll = (Config -> Config -> Config) -> [Config] -> Config
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Config -> Config -> Config
merge
merge :: Config -> Config -> Config
merge :: Config -> Config -> Config
merge (HOCONNode [(String, Config)]
a) (HOCONNode [(String, Config)]
b) = [(String, Config)] -> Config
HOCONNode ([(String, Config)]
a [(String, Config)] -> [(String, Config)] -> [(String, Config)]
forall a. [a] -> [a] -> [a]
++ [(String, Config)]
b)