cmt-0.7.0.0: src/Cmt/IO/Config.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLists #-}
module Cmt.IO.Config
( load
, findFile
, readCfg
, checkFormat
) where
import ClassyPrelude
import Data.List (nub)
import System.Directory (doesFileExist, getCurrentDirectory, getHomeDirectory)
import System.FilePath (takeDirectory, (</>))
import Cmt.Parser.Config (config)
import Cmt.Types.Config
import Cmt.Utility ((<?>))
configFile :: FilePath
configFile = ".cmt"
checkFormat :: Outputs -> Config -> Either Text (Config, Outputs)
checkFormat output (Config parts format) = do
let partNames = nub $ partName <$> parts
let formatNames = nub . catMaybes $ formatName <$> format
let result
| isJust (find (== "*") formatNames) && null output = Left "Command line entry missing"
| (length partNames + length output) /= length formatNames =
Left "Parts and format do not match"
| otherwise = Right (Config parts format, output)
result
parse :: Outputs -> Text -> Either Text (Config, Outputs)
parse output cfg = config cfg >>= checkFormat output
read :: FilePath -> IO Text
read path = decodeUtf8 <$> readFile path
checkParent :: FilePath -> IO (Maybe FilePath)
checkParent path = do
let parent = takeDirectory path
if parent /= path
then checkDir parent
else pure Nothing
checkDir :: FilePath -> IO (Maybe FilePath)
checkDir path = do
let fp = path </> configFile
exists <- doesFileExist fp
if exists
then pure $ Just fp
else checkParent path
xdgCfg :: IO (Maybe FilePath)
xdgCfg = do
fp <- (</> ".config" </> "cmt" </> configFile) <$> getHomeDirectory
exists <- doesFileExist fp
pure $ bool Nothing (Just fp) exists
homeCfg :: IO (Maybe FilePath)
homeCfg = do
fp <- (</> configFile) <$> getHomeDirectory
exists <- doesFileExist fp
pure $ bool Nothing (Just fp) exists
globalCfg :: IO (Maybe FilePath)
globalCfg = do
xdg <- xdgCfg
home <- homeCfg
pure $ xdg <?> home
findFile :: IO (Maybe FilePath)
findFile = do
inDir <- checkDir =<< getCurrentDirectory
case inDir of
Just fp -> pure $ Just fp
Nothing -> globalCfg
load :: IO (Either Text Text)
load = do
exists <- findFile
case exists of
Just path -> Right <$> read path
Nothing -> pure $ Left ".cmt file not found"
readCfg :: Outputs -> IO (Either Text (Config, Outputs))
readCfg output = do
cfg <- load
pure (parse output =<< cfg)