matsuri-0.0.1: Config.hs
-- | Config.hs
-- A module which parse config file and contain Config structure for
-- further usage.
module Config (
Config,
readConfig,
getCF,
setCF
) where
import Buffers
import Data.ConfigFile
import qualified Data.Map as M
import System.Directory
import Control.Monad.Error
import Control.OldException
import Data.List
type Config = M.Map OptionSpec String
-- | Default config. If no value in config file, then default value
-- will be used.
defaultConfig = [ ("client", "matsuri")
, ("version", "unknown")
, ("OS", "unknown")
, ("roster_width", "30")
, ("show_roster", "1")
]
-- | Reading "main" and "account_*" sections of config file.
readConfig :: FilePath -> IO (Config, Buffers)
readConfig filePath = do
home <- getHomeDirectory
fileCnt <- handle (\_ -> return "[main]") (readFile (home++"/"++filePath))
let def_conf = M.fromList defaultConfig
confs <- runErrorT $ do
conf <- readstring emptyCP fileCnt
-- reading and updating main options
mainOptions <- items conf "main"
let config = foldr updateValue def_conf mainOptions
-- reading account_* sections
let sects = filter (\acc -> take 8 acc == "account_") (sections conf)
accountsList <- forM sects $ \account -> do
accountItems <- items conf account
return (drop 8 account, accountItems)
let start = M.singleton "help" (BufHelp [])
accounts = foldr updateAccount start accountsList
return (config, accounts)
case confs of
Left _ -> error "can't parse config file (wrong format)"
Right conf -> return conf
-- | Update option's value or exit with error if no such option.
updateValue :: (OptionSpec, String) -> Config -> Config
updateValue (option, value) config =
let (value', config') = M.updateLookupWithKey
(\_ _ -> Just value)
option
config
in case value' of
Just _ -> config'
Nothing -> error $ "can't parse config file\
\ (unknown \"" ++ option ++ "\" option)"
-- | Update account in HashTable or exit with error if wrong options.
updateAccount :: (String, [(OptionSpec, String)]) -> Buffers -> Buffers
updateAccount (accountName, accountItems) =
M.insert
accountName
(BufAccount Account
{ accName = accountName
, username = findItem "username"
, server = findItem "server"
, password = findItem "password"
, resource = findItem "resource"
, defaultNick = findItem "nick"
, connection = NoConnection
, accCollapsed = False
})
where findItem itemName =
case find (\(name, _) -> name == itemName) accountItems of
Just value -> snd value
_ -> error $ "can't parse config file\
\ (wrong \"" ++ accountName ++ "\" account options)"
getCF :: String -> Config -> String
getCF k = maybe "" id . M.lookup k
setCF :: String -> String -> Config -> Config
setCF k v = M.adjust (const v) k