{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLists #-}
module IO.Config where
import ClassyPrelude
import qualified Data.Text.IO as T (readFile)
import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist,
getHomeDirectory)
import System.Environment (lookupEnv)
import Brick (AttrMap)
import Brick.Themes (loadCustomizations, themeToAttrMap)
import Data.FileEmbed (embedFile)
import Data.Ini.Config
import IO.Keyboard (addMissing, badMapping, defaultBindings)
import IO.Keyboard.Parser (bindings)
import IO.Keyboard.Types (Bindings)
import UI.Theme (defaultTheme)
import qualified IO.Config.General as General
import qualified IO.Config.GitHub as GitHub
import qualified IO.Config.Layout as Layout
import qualified IO.Config.Markdown as Markdown
import qualified IO.Config.Trello as Trello
data Config = Config
{ general :: General.Config
, layout :: Layout.Config
, markdown :: Markdown.Config
, trello :: Trello.Config
, github :: GitHub.Config
}
defaultConfig :: Config
defaultConfig =
Config
General.defaultConfig
Layout.defaultConfig
Markdown.defaultConfig
Trello.defaultConfig
GitHub.defaultConfig
directoryName :: FilePath
directoryName = "taskell"
legacyConfigPath :: IO FilePath
legacyConfigPath = (</> "." <> directoryName) <$> getHomeDirectory
xdgDefaultConfig :: IO FilePath
xdgDefaultConfig = (</> ".config") <$> getHomeDirectory
xdgConfigPath :: IO FilePath
xdgConfigPath =
(</> directoryName) <$> (fromMaybe <$> xdgDefaultConfig <*> lookupEnv "XDG_CONFIG_HOME")
getDir :: IO FilePath
getDir = legacyConfigPath >>= doesDirectoryExist >>= bool xdgConfigPath legacyConfigPath
themePath :: FilePath -> FilePath
themePath = (</> "theme.ini")
configPath :: FilePath -> FilePath
configPath = (</> "config.ini")
bindingsPath :: FilePath -> FilePath
bindingsPath = (</> "bindings.ini")
setup :: IO Config
setup
= do
dir <- getDir
createDirectoryIfMissing True dir
create (configPath dir) $(embedFile "templates/config.ini")
create (themePath dir) $(embedFile "templates/theme.ini")
create (bindingsPath dir) $(embedFile "templates/bindings.ini")
getConfig
create :: FilePath -> ByteString -> IO ()
create path contents = doesFileExist path >>= flip unless (writeFile path contents)
configParser :: IniParser Config
configParser =
Config <$> General.parser <*> Layout.parser <*> Markdown.parser <*> Trello.parser <*>
GitHub.parser
getConfig :: IO Config
getConfig = do
content <- T.readFile =<< (configPath <$> getDir)
case parseIniFile content configParser of
Right config -> pure config
Left s -> putStrLn (pack $ "config.ini: " <> s) $> defaultConfig
getBindings :: IO Bindings
getBindings = do
bnds <- bindings <$> (T.readFile =<< (bindingsPath <$> getDir))
case addMissing <$> (badMapping =<< bnds) of
Right b -> pure b
Left err ->
putStrLn ("bindings.ini: " <> err <> " - using default bindings") $> defaultBindings
generateAttrMap :: IO AttrMap
generateAttrMap = do
dir <- getDir
customizedTheme <- loadCustomizations (themePath dir) defaultTheme
case customizedTheme of
Right theme -> pure $ themeToAttrMap theme
Left s -> putStrLn (pack $ "theme.ini: " <> s) $> themeToAttrMap defaultTheme