@@ 0,0 1,30 @@
+module Network.URI.XDG.Ini(parseIni) where
+
+import Data.Char (isSpace)
+import Data.List (dropWhile, dropWhileEnd)
+
+type INI = [(String, [(String, String)])]
+
+parseIni :: String -> INI
+parseIni source = parseIni' $ filter (not . isComment) $ map strip $ lines source
+
+strip cs = dropWhile isSpace $ dropWhileEnd isSpace cs
+strip2 (a, b) = (strip a, strip b)
+
+isComment ('#':_) = True
+isComment "" = True
+isComment _ = False
+
+parseIni' (('[':cs):lines) | ']':header <- reverse cs =
+ let (keys, rest) = parseKeys lines in (reverse header, keys) : parseIni' rest
+parseIni' _ = []
+
+parseKeys :: [String] -> ([(String, String)], [String])
+parseKeys lines@(('[':_):_) = ([], lines)
+parseKeys (line:lines) =
+ let (keys, rest) = parseKeys lines in (strip2 (parseKey line) : keys, rest)
+parseKeys [] = ([], [])
+
+parseKey ('=':as) = ([], as)
+parseKey (a:as) = let (x, y) = parseKey as in (a:x, y)
+parseKey [] = ([], [])