module Rascal.Conf where
import Data.Map (Map, union, fromList)
import Data.Char (isSpace)
import Data.List (dropWhileEnd)
import Control.Exception (handle)
import Control.Monad (liftM)
import System.Directory (getHomeDirectory)
import System.FilePath ((</>))
type Key = String
type Value = String
type Conf = Map Key Value
parseConfig :: String -> Conf
parseConfig = fromList . map getKeyValue . filter configLine . lines
configLine :: String -> Bool
configLine l =
not (null l) && head l /= '#' && (':' `elem` l || '=' `elem` l)
getKeyValue :: String -> (Key, Value)
getKeyValue line =
let (key, _:value) = break (`elem` ":=") line
in (stripWhite key, stripWhite value)
stripWhite :: String -> String
stripWhite =
dropWhile isSpace . dropWhileEnd isSpace
getUserConfig :: String -> [(String, String)] -> IO Conf
getUserConfig fileName defaultOptions = do
home <- getHomeDirectory
let userConfFile = home </> fileName
defaultConf = fromList defaultOptions
handle (\(_ :: IOError) -> return defaultConf) $
liftM ((`union` defaultConf) . parseConfig) (readFile userConfFile)