module Network.URI.XDG.Ini(INI, parseIni, iniLookup, iniLookupLocalized) where
import Data.Char (isSpace, toLower)
import Data.List (dropWhile, dropWhileEnd)
type INI = [(String, [(String, String)])]
parseIni :: String -> INI
parseIni :: String -> INI
parseIni String
source = [String] -> INI
parseIni' forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Bool
isComment) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map String -> String
strip forall a b. (a -> b) -> a -> b
$ String -> [String]
lines String
source
strip :: String -> String
strip String
cs = forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
dropWhileEnd Char -> Bool
isSpace forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
cs
strip2 :: (String, String) -> (String, String)
strip2 (String
a, String
b) = (String -> String
strip String
a, String -> String
strip String
b)
(Char
'#':String
_) = Bool
True
isComment String
"" = Bool
True
isComment String
_ = Bool
False
parseIni' :: [String] -> INI
parseIni' ((Char
'[':String
cs):[String]
lines) | Char
']':String
header <- forall a. [a] -> [a]
reverse String
cs =
let ([(String, String)]
keys, [String]
rest) = [String] -> ([(String, String)], [String])
parseKeys [String]
lines in (String -> String
strip forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse String
header, [(String, String)]
keys) forall a. a -> [a] -> [a]
: [String] -> INI
parseIni' [String]
rest
parseIni' [String]
_ = []
parseKeys :: [String] -> ([(String, String)], [String])
parseKeys :: [String] -> ([(String, String)], [String])
parseKeys lines :: [String]
lines@((Char
'[':String
_):[String]
_) = ([], [String]
lines)
parseKeys (String
line:[String]
lines) =
let ([(String, String)]
keys, [String]
rest) = [String] -> ([(String, String)], [String])
parseKeys [String]
lines in ((String, String) -> (String, String)
strip2 (String -> (String, String)
parseKey String
line) forall a. a -> [a] -> [a]
: [(String, String)]
keys, [String]
rest)
parseKeys [] = ([], [])
parseKey :: String -> (String, String)
parseKey (Char
'=':String
as) = ([], String
as)
parseKey (Char
a:String
as) = let (String
x, String
y) = String -> (String, String)
parseKey String
as in (Char
aforall a. a -> [a] -> [a]
:String
x, String
y)
parseKey [] = ([], [])
iniLookup :: String -> String -> INI -> Maybe String
iniLookup :: String -> String -> INI -> Maybe String
iniLookup String
group String
key INI
ini = forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
group INI
ini forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
key
iniLookupLocalized :: [String] -> String -> String -> INI -> Maybe String
iniLookupLocalized :: [String] -> String -> String -> INI -> Maybe String
iniLookupLocalized (String
locale:[String]
locales) String
group String
key INI
ini
| Just String
ret <- String -> String -> INI -> Maybe String
iniLookup String
group (String
key forall a. [a] -> [a] -> [a]
++ String
"[" forall a. [a] -> [a] -> [a]
++ String
locale' forall a. [a] -> [a] -> [a]
++ String
"]") INI
ini = forall a. a -> Maybe a
Just String
ret
| Bool
otherwise = [String] -> String -> String -> INI -> Maybe String
iniLookupLocalized [String]
locales String
group String
key INI
ini
where locale' :: String
locale' = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
dash2under String
locale
iniLookupLocalized [] String
group String
key INI
ini = String -> String -> INI -> Maybe String
iniLookup String
group String
key INI
ini
dash2under :: Char -> Char
dash2under Char
'-' = Char
'_'
dash2under Char
c = Char
c