matsuri-0.0.4: Config.hs
-- | Config.hs
-- Config file reading; functions for working with config structure.
module Config (
Config,
readConfig,
getCF,
setCF
) where
import Buffers
import Help
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", "0.0.x")
, ("OS", "LEENOOPS OS")
, ("roster_width", "20")
, ("show_roster", "1")
, ("default_group", "other")
, ("conferences_group", "conferences")
]
-- | Reading "main" and "account_*" sections of config file.
readConfig :: FilePath -> IO (Config, Buffers)
readConfig filePath = do
home <- getHomeDirectory
fileCnt <- handle (\_ -> error help_noconfig)
(readFile (home++"/"++filePath))
confs <- runErrorT $ do
conf <- readstring emptyCP fileCnt
-- reading and updating main options
mainOptions <- items conf "main"
let def_conf = M.fromList defaultConfig
config = foldr updateValue def_conf mainOptions
-- reading account_* sections
let sects' = filter ("account_" `isPrefixOf`) (sections conf)
sects | length sects' == 0 = configError "no accounts"
| otherwise = sects'
readAcc acc = liftM2 (,) (return $ drop 8 acc) (items conf acc)
liftM2 (,)
(return config)
(mapM readAcc sects >>= return . foldr doAccount M.empty)
case confs of
Left _ -> configError "wrong format"
Right conf -> return conf
-- | Update option's value or exit with error if find unknown 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 -> if "alias " `isPrefixOf` option
then M.insert option value config
else configError ("unknown `"++option++"' option")
-- | Insert new account in buffer or exit with error if wrong options.
doAccount :: (String, [(OptionSpec, String)]) -> Buffers -> Buffers
doAccount (accountName, accountOpts) =
M.insert
accountName
(BufAccount Account
{ accName = accountName
, username = username'
, server = findOpt "server"
, password = findOpt "password"
, resource = resource'
, priority = priority'
, defaultNick = defaultNick'
, connection = NoConnection
, accCollapsed = False
, accContents = []
})
where
username' = findOpt "username"
resource' = maybe "matsuri" snd $ findOpt' "resource"
priority' = maybe 0 (read . snd) $ findOpt' "priority"
defaultNick' = maybe username' snd $ findOpt' "nick"
findOpt opt = maybe (noOpt opt) snd $ findOpt' opt
findOpt' optName = find (\(name, _) -> name == optName) accountOpts
noOpt opt = configError ("can't find `'"++opt++"' option\
\ for `"++accountName++"' account")
configError err = error ("can't read config file ("++err++")")
getCF :: String -> Config -> String
getCF k = maybe "" id . M.lookup k
setCF :: String -> String -> Config -> Config
setCF k v = M.adjust (const v) k