{-# LANGUAGE ApplicativeDo #-}
module Xrefcheck.CLI
( VerifyMode (..)
, shouldCheckLocal
, shouldCheckExternal
, Command (..)
, Options (..)
, TraversalOptions (..)
, addTraversalOptions
, defaultConfigPaths
, getCommand
) where
import Data.Version (showVersion)
import Options.Applicative (Parser, ReadM, command, eitherReader, execParser, flag', fullDesc, help,
helper, hsubparser, info, infoOption, long, metavar, option, progDesc,
short, strOption, switch, value)
import Paths_xrefcheck (version)
import Xrefcheck.Config
import Xrefcheck.Core
modeReadM :: ReadM VerifyMode
modeReadM = eitherReader $ \s ->
case find ((== s) . fst) modes of
Just (_, mode) -> Right mode
Nothing -> Left . mconcat $ intersperse "\n"
[ "Unknown mode " <> show s <> "."
, "Allowed values: " <> mconcat (intersperse ", " $ map (show . fst) modes)
]
where
modes =
[ ("local-only", LocalOnlyMode)
, ("external-only", ExternalOnlyMode)
, ("full", FullMode)
]
data Command
= DefaultCommand Options
| DumpConfig FilePath
data Options = Options
{ oConfigPath :: Maybe FilePath
, oRoot :: FilePath
, oMode :: VerifyMode
, oVerbose :: Bool
, oShowProgressBar :: Maybe Bool
, oTraversalOptions :: TraversalOptions
}
data TraversalOptions = TraversalOptions
{ toIgnored :: [FilePath]
}
addTraversalOptions :: TraversalConfig -> TraversalOptions -> TraversalConfig
addTraversalOptions TraversalConfig{..} (TraversalOptions ignored) =
TraversalConfig
{ tcIgnored = tcIgnored ++ ignored
, ..
}
defaultConfigPaths :: [FilePath]
defaultConfigPaths = ["./xrefcheck.yaml", "./.xrefcheck.yaml"]
optionsParser :: Parser Options
optionsParser = do
oConfigPath <- optional . strOption $
short 'c' <>
long "config" <>
metavar "FILEPATH" <>
help ("Path to configuration file. \
\If not specified, tries to read config from one of " <>
(mconcat . intersperse ", " $ map show defaultConfigPaths) <> ". \
\If none of these files exist, default configuration is used."
)
oRoot <- strOption $
short 'r' <>
long "root" <>
metavar "DIRECTORY" <>
help "Path to repository root." <>
value "."
oMode <- option modeReadM $
short 'm' <>
long "mode" <>
metavar "KEYWORD" <>
value FullMode <>
help "Which parts of verification to invoke. \
\You can enable only verification of repository-local references, \
\only verification of external references or both. \
\Default mode: full."
oVerbose <- switch $
short 'v' <>
long "verbose" <>
help "Report repository scan and verification details."
oShowProgressBar <- asum
[ flag' (Just True) $
long "progress" <>
help "Display progress bar during verification. \
\This is enabled by default unless `CI` env var is set to true."
, flag' (Just False) $
long "no-progress" <>
help "Do not display progress bar during verification."
, pure Nothing
]
oTraversalOptions <- traversalOptionsParser
return Options{..}
traversalOptionsParser :: Parser TraversalOptions
traversalOptionsParser = do
toIgnored <- many . strOption $
long "ignored" <>
metavar "FILEPATH" <>
help "Files and folders which we pretend do not exist."
return TraversalOptions{..}
dumpConfigOptions :: Parser FilePath
dumpConfigOptions = hsubparser $
command "dump-config" $
info parser $
progDesc "Dump default configuration into a file."
where
parser = strOption $
short 'o' <>
long "output" <>
metavar "FILEPATH" <>
value ".xrefcheck.yaml" <>
help "Name of created config file."
totalParser :: Parser Command
totalParser = asum
[ DefaultCommand <$> optionsParser
, DumpConfig <$> dumpConfigOptions
]
versionOption :: Parser (a -> a)
versionOption = infoOption ("xrefcheck-" <> showVersion version) $
long "version" <>
help "Show version."
getCommand :: IO Command
getCommand = do
execParser $
info (helper <*> versionOption <*> totalParser) $
fullDesc <>
progDesc "Cross-references verifier for markdown documentation in \
\Git repositories."