imp: Hledger.Cli.Conf: refactor, expose more info about config files
This commit is contained in:
parent
320d197735
commit
daf550bbb0
@ -8,7 +8,14 @@ Read extra CLI arguments from a hledger config file.
|
|||||||
|
|
||||||
module Hledger.Cli.Conf (
|
module Hledger.Cli.Conf (
|
||||||
getConf
|
getConf
|
||||||
|
,nullconf
|
||||||
,confLookup
|
,confLookup
|
||||||
|
,activeConfFile
|
||||||
|
,activeLocalConfFile
|
||||||
|
,activeUserConfFile
|
||||||
|
,confFiles
|
||||||
|
,userConfFiles
|
||||||
|
,parseConf
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
@ -19,6 +26,7 @@ import qualified Data.Map as M
|
|||||||
import Data.Maybe (catMaybes)
|
import Data.Maybe (catMaybes)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T (pack)
|
import qualified Data.Text as T (pack)
|
||||||
|
import Safe (headMay)
|
||||||
import System.Directory (getHomeDirectory, getXdgDirectory, XdgDirectory (XdgConfig), doesFileExist, getCurrentDirectory)
|
import System.Directory (getHomeDirectory, getXdgDirectory, XdgDirectory (XdgConfig), doesFileExist, getCurrentDirectory)
|
||||||
import System.FilePath ((</>), takeDirectory)
|
import System.FilePath ((</>), takeDirectory)
|
||||||
import Text.Megaparsec
|
import Text.Megaparsec
|
||||||
@ -99,12 +107,9 @@ getConf rawopts = do
|
|||||||
NoConfFile -> return $ traceAt 1 "ignoring config files" (nullconf, Nothing)
|
NoConfFile -> return $ traceAt 1 "ignoring config files" (nullconf, Nothing)
|
||||||
SomeConfFile f -> getCurrentDirectory >>= flip expandPath f >>= readConfFile . dbg1 "using specified config file"
|
SomeConfFile f -> getCurrentDirectory >>= flip expandPath f >>= readConfFile . dbg1 "using specified config file"
|
||||||
AutoConfFile -> do
|
AutoConfFile -> do
|
||||||
defconfpaths <- defaultConfFilePaths
|
fs <- confFiles
|
||||||
conffiles <- fmap catMaybes $ forM defconfpaths $ \f -> do
|
case fs of
|
||||||
exists <- doesFileExist f
|
f:_ -> dbg8IO "found config files" fs >> dbg1IO "using nearest config file" f >> readConfFile f
|
||||||
return $ if exists then Just f else Nothing
|
|
||||||
case conffiles of
|
|
||||||
f:_ -> dbg8IO "found config files" conffiles >> dbg1IO "using nearest config file" f >> readConfFile f
|
|
||||||
[] -> return $ traceAt 1 "no config file found" (nullconf, Nothing)
|
[] -> return $ traceAt 1 "no config file found" (nullconf, Nothing)
|
||||||
|
|
||||||
-- | Read this config file and parse its contents, or raise an error.
|
-- | Read this config file and parse its contents, or raise an error.
|
||||||
@ -113,7 +118,6 @@ readConfFile f = do
|
|||||||
-- avoid GHC 9.10.1's ugly stack trace when calling readFile on a nonexistent file
|
-- avoid GHC 9.10.1's ugly stack trace when calling readFile on a nonexistent file
|
||||||
exists <- doesFileExist f
|
exists <- doesFileExist f
|
||||||
when (not exists) $ error' $ f <> " does not exist"
|
when (not exists) $ error' $ f <> " does not exist"
|
||||||
|
|
||||||
ecs <- readFile f <&> parseConf f . T.pack
|
ecs <- readFile f <&> parseConf f . T.pack
|
||||||
case ecs of
|
case ecs of
|
||||||
Left err -> error' $ errorBundlePretty err -- customErrorBundlePretty err
|
Left err -> error' $ errorBundlePretty err -- customErrorBundlePretty err
|
||||||
@ -125,17 +129,67 @@ readConfFile f = do
|
|||||||
Just f
|
Just f
|
||||||
)
|
)
|
||||||
|
|
||||||
-- | Get the possible paths for a hledger config file, depending on the current directory.
|
-- | Get the highest precedence config file, based on the current directory.
|
||||||
defaultConfFilePaths :: IO [FilePath]
|
activeConfFile :: IO (Maybe FilePath)
|
||||||
defaultConfFilePaths = do
|
activeConfFile = headMay <$> confFiles
|
||||||
ds <- confDirs
|
|
||||||
|
-- | Get the highest precedence local config file:
|
||||||
|
-- a config file in the current directory or above, that is not a user-wide config file.
|
||||||
|
activeLocalConfFile :: IO (Maybe FilePath)
|
||||||
|
activeLocalConfFile = do
|
||||||
|
ufs <- userConfFiles
|
||||||
|
mf <- headMay <$> confFiles
|
||||||
|
return $ case mf of
|
||||||
|
Just f | f `notElem` ufs -> Just f
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
|
-- | Get the highest precedence user-wide config file, based on the current directory.
|
||||||
|
-- (This may not be the active config file.)
|
||||||
|
activeUserConfFile :: IO (Maybe FilePath)
|
||||||
|
activeUserConfFile = headMay <$> userConfFiles
|
||||||
|
|
||||||
|
-- | Get the possibleConfFiles which exist, based on the current directory.
|
||||||
|
confFiles :: IO [FilePath]
|
||||||
|
confFiles = possibleConfFiles >>= existingFiles
|
||||||
|
|
||||||
|
-- | Get the possibleUserConfFiles which exist, based on the current directory.
|
||||||
|
userConfFiles :: IO [FilePath]
|
||||||
|
userConfFiles = possibleUserConfFiles >>= existingFiles
|
||||||
|
|
||||||
|
-- | Filter a list of paths to just the existing files.
|
||||||
|
existingFiles :: [FilePath] -> IO [FilePath]
|
||||||
|
existingFiles fs =
|
||||||
|
fmap catMaybes $ forM fs $ \f -> do
|
||||||
|
exists <- doesFileExist f
|
||||||
|
return $ if exists then Just f else Nothing
|
||||||
|
|
||||||
|
-- | Get the possible paths for a hledger config file, highest precedence first:
|
||||||
|
-- hledger.conf in the current directory,
|
||||||
|
-- hledger.conf in any parent directory,
|
||||||
|
-- .hledger.conf in the home directory,
|
||||||
|
-- or hledger.conf in the XdgConfig directory.
|
||||||
|
possibleConfFiles :: IO [FilePath]
|
||||||
|
possibleConfFiles = do
|
||||||
|
ds <- possibleConfDirs
|
||||||
home <- getHomeDirectory
|
home <- getHomeDirectory
|
||||||
return $ dbg8 "possible config file paths" $
|
return $ dbg8 "possible config file paths" $
|
||||||
flip map ds $ \d -> d </> if d==home then ".hledger.conf" else "hledger.conf"
|
flip map ds $ \d -> d </> if d==home then ".hledger.conf" else "hledger.conf"
|
||||||
|
|
||||||
-- | Get the directories to check for a hledger config file.
|
-- | Like possibleConfFiles, but consider only user-wide hledger config files:
|
||||||
confDirs :: IO [FilePath]
|
-- .hledger.conf in the home directory,
|
||||||
confDirs = do
|
-- or hledger.conf in the XdgConfig directory.
|
||||||
|
possibleUserConfFiles :: IO [FilePath]
|
||||||
|
possibleUserConfFiles = do
|
||||||
|
home <- getHomeDirectory
|
||||||
|
xdgc <- getXdgDirectory XdgConfig "hledger"
|
||||||
|
let ds = [home,xdgc]
|
||||||
|
return $ dbg8 "possible user config file paths" $
|
||||||
|
flip map ds $ \d -> d </> if d==home then ".hledger.conf" else "hledger.conf"
|
||||||
|
|
||||||
|
-- | Get the directories where a hledger config file could be, highest precedence first:
|
||||||
|
-- the current directory, any parent directory, the home directory, or the XdgConfig directory.
|
||||||
|
possibleConfDirs :: IO [FilePath]
|
||||||
|
possibleConfDirs = do
|
||||||
xdgc <- getXdgDirectory XdgConfig "hledger"
|
xdgc <- getXdgDirectory XdgConfig "hledger"
|
||||||
home <- getHomeDirectory
|
home <- getHomeDirectory
|
||||||
here <- getCurrentDirectory
|
here <- getCurrentDirectory
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user