packages feed

helic-0.1.0.0: lib/Helic/Config/File.hs

{-# options_haddock prune #-}
-- |Config File Parsing, Internal
module Helic.Config.File where

import Data.Yaml (decodeFileEither, prettyPrintParseException)
import Path (Abs, File, Path, Rel, absfile, relfile, toFilePath, (</>))
import Path.IO (XdgDirectory (XdgConfig), doesFileExist, getXdgDir)
import qualified Polysemy.Log as Log
import Polysemy.Log (Log)

import Helic.Data.Config (Config)

parseFileConfig ::
  Members [Log, Error Text, Embed IO] r =>
  Path Abs File ->
  Sem r Config
parseFileConfig (toFilePath -> path) = do
  Log.info [exon|Reading config file #{toText path}|]
  fromEither =<< mapLeft formatError <$> embed (decodeFileEither path)
  where
    formatError exc =
      toText [exon|invalid config file: #{prettyPrintParseException exc}|]

findConfigPath ::
  Members [Log, Error Text, Embed IO] r =>
  Maybe (Path Abs File) ->
  Sem r (Maybe (Path Abs File))
findConfigPath = \case
  Just f ->
    doesFileExist f >>= \case
      True -> pure (Just f)
      False -> throw [exon|config file doesn't exist: #{toText (toFilePath f)}|]
  Nothing -> do
    xdgConf <- getXdgDir XdgConfig Nothing
    let
      xdgFile =
        xdgConf </> [relfile|helic.yaml|]
      etcFile =
        [absfile|/etc/helic.yaml|]
    doesFileExist xdgFile >>= \case
      True ->
        pure (Just xdgFile)
      False ->
        doesFileExist etcFile <&> \case
          True -> Just etcFile
          False -> Nothing

findFileConfig ::
  Members [Log, Error Text, Embed IO] r =>
  Maybe (Path Abs File) ->
  Sem r Config
findFileConfig cliFile = do
  f <- findConfigPath cliFile
  maybe (pure def) parseFileConfig f