{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedLists #-} module Taskell.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 Taskell.IO.Keyboard (addMissing, badMapping, defaultBindings) import Taskell.IO.Keyboard.Parser (bindings) import Taskell.IO.Keyboard.Types (Bindings) import Taskell.UI.Theme (defaultTheme) import qualified Taskell.IO.Config.General as General import qualified Taskell.IO.Config.GitHub as GitHub import qualified Taskell.IO.Config.Layout as Layout import qualified Taskell.IO.Config.Markdown as Markdown import qualified Taskell.IO.Config.Trello as Trello data Config = Config { general :: General.Config , layout :: Layout.Config , markdown :: Markdown.Config , trello :: Trello.Config , github :: GitHub.Config } debugging :: Config -> Bool debugging config = General.debug (general 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") templatePath :: FilePath -> FilePath templatePath = ( "template.md") bindingsPath :: FilePath -> FilePath bindingsPath = ( "bindings.ini") setup :: IO Config setup -- create config dir = do dir <- getDir createDirectoryIfMissing True dir -- create config files create (configPath dir) $(embedFile "templates/config.ini") create (themePath dir) $(embedFile "templates/theme.ini") create (templatePath dir) $(embedFile "templates/template.md") create (bindingsPath dir) $(embedFile "templates/bindings.ini") -- get config 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 -- generate theme 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