module HsKu.Config where import Data.List import Data.Maybe import Data.Map (Map, assocs, fromList) import Text.ParserCombinators.ReadP import System.Environment type Config = Map String (Map String String) newtype Ini = Ini {Ini -> Config sections :: Config} deriving Ini -> Ini -> Bool (Ini -> Ini -> Bool) -> (Ini -> Ini -> Bool) -> Eq Ini forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a $c== :: Ini -> Ini -> Bool == :: Ini -> Ini -> Bool $c/= :: Ini -> Ini -> Bool /= :: Ini -> Ini -> Bool Eq instance Show Ini where show :: Ini -> String show = [String] -> String unlines ([String] -> String) -> (Ini -> [String]) -> Ini -> String forall b c a. (b -> c) -> (a -> b) -> a -> c . ((String, Map String String) -> String) -> [(String, Map String String)] -> [String] forall a b. (a -> b) -> [a] -> [b] map (String, Map String String) -> String section ([(String, Map String String)] -> [String]) -> (Ini -> [(String, Map String String)]) -> Ini -> [String] forall b c a. (b -> c) -> (a -> b) -> a -> c . Config -> [(String, Map String String)] forall k a. Map k a -> [(k, a)] assocs (Config -> [(String, Map String String)]) -> (Ini -> Config) -> Ini -> [(String, Map String String)] forall b c a. (b -> c) -> (a -> b) -> a -> c . Ini -> Config sections where section :: (String, Map String String) -> String section (String name, Map String String sec) = String "[" String -> ShowS forall a. [a] -> [a] -> [a] ++ String name String -> ShowS forall a. [a] -> [a] -> [a] ++ String "]\n" String -> ShowS forall a. [a] -> [a] -> [a] ++ Map String String -> String pairs Map String String sec pairs :: Map String String -> String pairs = [String] -> String unlines ([String] -> String) -> (Map String String -> [String]) -> Map String String -> String forall b c a. (b -> c) -> (a -> b) -> a -> c . ((String, String) -> String) -> [(String, String)] -> [String] forall a b. (a -> b) -> [a] -> [b] map (String, String) -> String pair ([(String, String)] -> [String]) -> (Map String String -> [(String, String)]) -> Map String String -> [String] forall b c a. (b -> c) -> (a -> b) -> a -> c . Map String String -> [(String, String)] forall k a. Map k a -> [(k, a)] assocs pair :: (String, String) -> String pair (String k, String v) = String k String -> ShowS forall a. [a] -> [a] -> [a] ++ String " = " String -> ShowS forall a. [a] -> [a] -> [a] ++ String v instance Read Ini where readsPrec :: Int -> ReadS Ini readsPrec Int _ = ReadP Ini -> ReadS Ini forall a. ReadP a -> ReadS a readP_to_S ReadP Ini parser where parser :: ReadP Ini parser = Config -> Ini Ini (Config -> Ini) -> ([(String, Map String String)] -> Config) -> [(String, Map String String)] -> Ini forall b c a. (b -> c) -> (a -> b) -> a -> c . [(String, Map String String)] -> Config forall k a. Ord k => [(k, a)] -> Map k a fromList ([(String, Map String String)] -> Ini) -> ReadP [(String, Map String String)] -> ReadP Ini forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> ReadP (String, Map String String) -> ReadP [(String, Map String String)] forall a. ReadP a -> ReadP [a] many ReadP (String, Map String String) section section :: ReadP (String, Map String String) section = do String name <- ShowS trim ShowS -> ReadP String -> ReadP String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> ReadP Char -> ReadP String -> ReadP String -> ReadP String forall open close a. ReadP open -> ReadP close -> ReadP a -> ReadP a between (Char -> ReadP Char char Char '[') (Char -> ReadP Char char Char ']' ReadP Char -> ReadP String -> ReadP String forall a b. ReadP a -> ReadP b -> ReadP b forall (m :: * -> *) a b. Monad m => m a -> m b -> m b >> ReadP String nls) (String -> ReadP String no String "=\n]") [(String, String)] pairs <- ReadP (String, String) -> ReadP [(String, String)] forall a. ReadP a -> ReadP [a] many ReadP (String, String) pair (String, Map String String) -> ReadP (String, Map String String) forall a. a -> ReadP a forall (m :: * -> *) a. Monad m => a -> m a return (String name, [(String, String)] -> Map String String forall k a. Ord k => [(k, a)] -> Map k a fromList [(String, String)] pairs) pair :: ReadP (String, String) pair = do String key <- ShowS trim ShowS -> ReadP String -> ReadP String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> ReadP String no String "\n[=" String val <- ShowS trim ShowS -> ReadP String -> ReadP String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> ReadP Char -> ReadP String -> ReadP String -> ReadP String forall open close a. ReadP open -> ReadP close -> ReadP a -> ReadP a between (Char -> ReadP Char char Char '=') ReadP String nls (String -> ReadP String no String "\n") (String, String) -> ReadP (String, String) forall a. a -> ReadP a forall (m :: * -> *) a. Monad m => a -> m a return (String key, String val) nls :: ReadP String nls = (Char -> Bool) -> ReadP String munch1 (Char -> Char -> Bool forall a. Eq a => a -> a -> Bool == Char '\n') no :: String -> ReadP String no = (Char -> Bool) -> ReadP String munch1 ((Char -> Bool) -> ReadP String) -> (String -> Char -> Bool) -> String -> ReadP String forall b c a. (b -> c) -> (a -> b) -> a -> c . (Char -> String -> Bool) -> String -> Char -> Bool forall a b c. (a -> b -> c) -> b -> a -> c flip Char -> String -> Bool forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool notElem :: String -> ReadP String trim :: ShowS trim = (Char -> Bool) -> ShowS forall a. (a -> Bool) -> [a] -> [a] dropWhile (Char -> Char -> Bool forall a. Eq a => a -> a -> Bool == Char ' ') ShowS -> ShowS -> ShowS forall b c a. (b -> c) -> (a -> b) -> a -> c . (Char -> Bool) -> ShowS forall a. (a -> Bool) -> [a] -> [a] dropWhileEnd (Char -> Char -> Bool forall a. Eq a => a -> a -> Bool == Char ' ') loadConfig :: IO Config loadConfig :: IO Config loadConfig = do String configFileName <- String -> Maybe String -> String forall a. a -> Maybe a -> a fromMaybe String "config.ini" (Maybe String -> String) -> IO (Maybe String) -> IO String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> IO (Maybe String) lookupEnv String "HSKU_CONFIG_FILE" Ini -> Config sections (Ini -> Config) -> (String -> Ini) -> String -> Config forall b c a. (b -> c) -> (a -> b) -> a -> c . String -> Ini forall a. Read a => String -> a read (String -> Config) -> IO String -> IO Config forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> IO String readFile String configFileName