{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-} module Config ( getConfigValue , configDirectory , getSlatePath ) where import qualified Data.HashMap.Lazy as M (lookup) import Data.Maybe (listToMaybe) import Data.String (fromString) import Data.String.Conversions (convertString) import System.Directory (doesFileExist, getCurrentDirectory, getHomeDirectory) import System.FilePath.Posix (takeBaseName) import Text.Toml (parseTomlDoc) import Text.Toml.Types (Node(VString), Node(VTable)) class GetConfig a where getConfigValue :: (String, String) -> IO a instance GetConfig (Maybe String) where getConfigValue (s, k) = do f <- configFile config <- readFile f let Right c = parseTomlDoc "" (fromString config) return $ case (M.lookup (fromString s) c) of Just (VTable t) -> case (M.lookup (fromString k) t) of Just (VString v) -> Just (convertString v) _ -> Nothing _ -> Nothing instance GetConfig String where getConfigValue (s, k) = do f <- configFile c <- getConfigValue (s, k) return $ maybe (error $ "Key `" ++ k ++ "` not found in " ++ f ++ ".") id c configDirectory :: IO String configDirectory = do home <- getHomeDirectory return $ home ++ "/.config/slate/" configFile :: IO String configFile = do dir <- configDirectory return $ dir ++ "config.toml" slateName :: IO String slateName = do d <- getCurrentDirectory let headOrFail = \x -> maybe (error "Found a .slate file in the current directory but it is empty.") id (listToMaybe x) doesFileExist (d ++ "/.slate") >>= \case True -> readFile (d ++ "/.slate") >>= (return . headOrFail . lines) False -> return $ takeBaseName d getSlatePath :: Maybe String -> IO FilePath getSlatePath Nothing = do s <- slateName dir <- configDirectory return $ dir ++ s ++ ".md" getSlatePath (Just s) = do dir <- configDirectory return $ dir ++ s ++ ".md"