{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module OptEnvConf.Main
  ( runSettingsParser,
    runParser,
    internalParser,
  )
where

import qualified Data.Text as T
import Data.Version
import OptEnvConf.Args as Args
import OptEnvConf.Capability
import OptEnvConf.Check
import OptEnvConf.Completion
import OptEnvConf.Doc
import qualified OptEnvConf.EnvMap as EnvMap
import OptEnvConf.Error
import OptEnvConf.Lint
import OptEnvConf.Nix
import OptEnvConf.Parser
import OptEnvConf.Reader
import OptEnvConf.Run
import OptEnvConf.Setting
import OptEnvConf.Terminal (getTerminalCapabilitiesFromHandle)
import Path
import System.Environment (getArgs, getEnvironment, getProgName)
import System.Exit
import System.IO
import Text.Colour

-- | Run 'runParser' on your @Settings@' type's 'settingsParser'.
--
-- __This is most likely the function you want to be using.__
runSettingsParser ::
  (HasParser a) =>
  -- | Program version, get this from Paths_your_package_name
  Version ->
  -- | Program description
  String ->
  IO a
runSettingsParser :: forall a. HasParser a => Version -> String -> IO a
runSettingsParser Version
version String
progDesc =
  Version -> String -> Parser a -> IO a
forall a. Version -> String -> Parser a -> IO a
runParser Version
version String
progDesc Parser a
forall a. HasParser a => Parser a
settingsParser

-- | Run a parser
--
-- This function with exit on:
--
--     * Parse failure: show a nice error message.
--     * @-h|--help@: Show help text
--     * @--version@: Show version information
--     * @--render-man-page@: Render a man page
--     * @--bash-completion-script@: Render a bash completion script
--     * @--zsh-completion-script@: Render a zsh completion script
--     * @--fish-completion-script@: Render a fish completion script
--     * @query-opt-env-conf-completion@: Perform a completion query
--
-- This gets the arguments and environment variables from the current process.
runParser ::
  -- | Program version, get this from Paths_your_package_name
  Version ->
  -- | Program description
  String ->
  Parser a ->
  IO a
runParser :: forall a. Version -> String -> Parser a -> IO a
runParser Version
version String
progDesc Parser a
p = do
  [(String, String)]
completeEnv <- IO [(String, String)]
getEnvironment
  let envVars :: EnvMap
envVars = [(String, String)] -> EnvMap
EnvMap.parse [(String, String)]
completeEnv

  case Parser a -> Maybe (NonEmpty LintError)
forall a. Parser a -> Maybe (NonEmpty LintError)
lintParser Parser a
p of
    Just NonEmpty LintError
errs -> do
      TerminalCapabilities
tc <- Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stderr
      TerminalCapabilities -> Handle -> [Chunk] -> IO ()
hPutChunksLocaleWith TerminalCapabilities
tc Handle
stderr ([Chunk] -> IO ()) -> [Chunk] -> IO ()
forall a b. (a -> b) -> a -> b
$ NonEmpty LintError -> [Chunk]
renderLintErrors NonEmpty LintError
errs
      IO a
forall a. IO a
exitFailure
    Maybe (NonEmpty LintError)
Nothing -> do
      let docs :: AnyDocs (Maybe SetDoc)
docs = Parser a -> AnyDocs (Maybe SetDoc)
forall a. Parser a -> AnyDocs (Maybe SetDoc)
parserDocs Parser a
p

      [String]
allArgs <- IO [String]
getArgs
      let (Bool
debugMode, [String]
args) = [String] -> (Bool, [String])
consumeDebugMode [String]
allArgs

      Maybe TerminalCapabilities
mDebugMode <-
        if Bool
debugMode
          then TerminalCapabilities -> Maybe TerminalCapabilities
forall a. a -> Maybe a
Just (TerminalCapabilities -> Maybe TerminalCapabilities)
-> IO TerminalCapabilities -> IO (Maybe TerminalCapabilities)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stderr
          else Maybe TerminalCapabilities -> IO (Maybe TerminalCapabilities)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe TerminalCapabilities
forall a. Maybe a
Nothing

      let (Bool
helpMode, [String]
args') = [String] -> (Bool, [String])
consumeHelpMode [String]
args

      if Bool
helpMode
        then do
          String
progname <- IO String
getProgName
          Either
  (NonEmpty ParseError) (Maybe ([String], CommandDoc (Maybe SetDoc)))
errOrDocs <- Maybe TerminalCapabilities
-> Args
-> Parser a
-> IO
     (Either
        (NonEmpty ParseError)
        (Maybe ([String], CommandDoc (Maybe SetDoc))))
forall a.
Maybe TerminalCapabilities
-> Args
-> Parser a
-> IO
     (Either
        (NonEmpty ParseError)
        (Maybe ([String], CommandDoc (Maybe SetDoc))))
runHelpParser Maybe TerminalCapabilities
mDebugMode ([String] -> Args
Args.parseArgs [String]
args') Parser a
p
          case Either
  (NonEmpty ParseError) (Maybe ([String], CommandDoc (Maybe SetDoc)))
errOrDocs of
            Left NonEmpty ParseError
errs -> do
              TerminalCapabilities
stderrTc <- Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stderr
              TerminalCapabilities -> Handle -> [Chunk] -> IO ()
hPutChunksLocaleWith TerminalCapabilities
stderrTc Handle
stderr ([Chunk] -> IO ()) -> [Chunk] -> IO ()
forall a b. (a -> b) -> a -> b
$ NonEmpty ParseError -> [Chunk]
renderErrors NonEmpty ParseError
errs
              IO a
forall a. IO a
exitFailure
            Right Maybe ([String], CommandDoc (Maybe SetDoc))
mCommandDoc -> do
              TerminalCapabilities
tc <- Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stdout
              TerminalCapabilities -> Handle -> [Chunk] -> IO ()
hPutChunksLocaleWith TerminalCapabilities
tc Handle
stdout ([Chunk] -> IO ()) -> [Chunk] -> IO ()
forall a b. (a -> b) -> a -> b
$ case Maybe ([String], CommandDoc (Maybe SetDoc))
mCommandDoc of
                Maybe ([String], CommandDoc (Maybe SetDoc))
Nothing -> String -> Version -> String -> AnyDocs (Maybe SetDoc) -> [Chunk]
renderHelpPage String
progname Version
version String
progDesc AnyDocs (Maybe SetDoc)
docs
                Just ([String]
path, CommandDoc (Maybe SetDoc)
cDoc) -> String -> [String] -> CommandDoc (Maybe SetDoc) -> [Chunk]
renderCommandHelpPage String
progname [String]
path CommandDoc (Maybe SetDoc)
cDoc
              IO a
forall a. IO a
exitSuccess
        else do
          let (Capabilities
capabilities, [String]
args'') = [String] -> (Capabilities, [String])
consumeCapabilities [String]
args'
          let (Bool
checkMode, [String]
args''') = [String] -> (Bool, [String])
consumeCheckMode [String]
args''

          let readyArgs :: Args
readyArgs = [String] -> Args
Args.parseArgs [String]
args'''

          let mConfig :: Maybe a
mConfig = Maybe a
forall a. Maybe a
Nothing -- We start with no config loaded.
          if Bool
checkMode
            then Capabilities -> Parser a -> Args -> EnvMap -> Maybe Object -> IO a
forall a void.
Capabilities
-> Parser a -> Args -> EnvMap -> Maybe Object -> IO void
runSettingsCheck Capabilities
capabilities Parser a
p Args
readyArgs EnvMap
envVars Maybe Object
forall a. Maybe a
mConfig
            else do
              let p' :: Parser (Internal a)
p' = Parser a -> Parser (Internal a)
forall a. Parser a -> Parser (Internal a)
internalParser Parser a
p
              Either (NonEmpty ParseError) (Internal a)
errOrResult <-
                Capabilities
-> Maybe TerminalCapabilities
-> Parser (Internal a)
-> Args
-> EnvMap
-> Maybe Object
-> IO (Either (NonEmpty ParseError) (Internal a))
forall a.
Capabilities
-> Maybe TerminalCapabilities
-> Parser a
-> Args
-> EnvMap
-> Maybe Object
-> IO (Either (NonEmpty ParseError) a)
runParserOn
                  Capabilities
capabilities
                  Maybe TerminalCapabilities
mDebugMode
                  Parser (Internal a)
p'
                  Args
readyArgs
                  EnvMap
envVars
                  Maybe Object
forall a. Maybe a
mConfig
              case Either (NonEmpty ParseError) (Internal a)
errOrResult of
                Left NonEmpty ParseError
errs -> do
                  TerminalCapabilities
tc <- Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stderr
                  TerminalCapabilities -> Handle -> [Chunk] -> IO ()
hPutChunksLocaleWith TerminalCapabilities
tc Handle
stderr ([Chunk] -> IO ()) -> [Chunk] -> IO ()
forall a b. (a -> b) -> a -> b
$ NonEmpty ParseError -> [Chunk]
renderErrors NonEmpty ParseError
errs
                  IO a
forall a. IO a
exitFailure
                Right Internal a
i -> case Internal a
i of
                  Internal a
ShowVersion -> do
                    String
progname <- IO String
getProgName
                    TerminalCapabilities
tc <- Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stdout
                    TerminalCapabilities -> Handle -> [Chunk] -> IO ()
hPutChunksLocaleWith TerminalCapabilities
tc Handle
stdout ([Chunk] -> IO ()) -> [Chunk] -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Version -> [Chunk]
renderVersionPage String
progname Version
version
                    IO a
forall a. IO a
exitSuccess
                  Internal a
RenderMan -> do
                    String
progname <- IO String
getProgName
                    TerminalCapabilities
tc <- Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stdout
                    TerminalCapabilities -> Handle -> [Chunk] -> IO ()
hPutChunksLocaleWith TerminalCapabilities
tc Handle
stdout ([Chunk] -> IO ()) -> [Chunk] -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> Version -> String -> AnyDocs (Maybe SetDoc) -> [Chunk]
renderManPage String
progname Version
version String
progDesc AnyDocs (Maybe SetDoc)
docs
                    IO a
forall a. IO a
exitSuccess
                  Internal a
RenderDocumentation -> do
                    String
progname <- IO String
getProgName
                    TerminalCapabilities
tc <- Handle -> IO TerminalCapabilities
getTerminalCapabilitiesFromHandle Handle
stdout
                    TerminalCapabilities -> Handle -> [Chunk] -> IO ()
hPutChunksLocaleWith TerminalCapabilities
tc Handle
stdout ([Chunk] -> IO ()) -> [Chunk] -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> AnyDocs (Maybe SetDoc) -> [Chunk]
renderReferenceDocumentation String
progname AnyDocs (Maybe SetDoc)
docs
                    IO a
forall a. IO a
exitSuccess
                  Internal a
RenderNixosOptions -> do
                    String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ Parser (Internal a) -> Text
forall a. Parser a -> Text
renderParserNixOptions Parser (Internal a)
p'
                    IO a
forall a. IO a
exitSuccess
                  BashCompletionScript Path Abs File
progPath -> do
                    String
progname <- IO String
getProgName
                    Path Abs File -> String -> IO ()
generateBashCompletionScript Path Abs File
progPath String
progname
                    IO a
forall a. IO a
exitSuccess
                  ZshCompletionScript Path Abs File
progPath -> do
                    String
progname <- IO String
getProgName
                    Path Abs File -> String -> IO ()
generateZshCompletionScript Path Abs File
progPath String
progname
                    IO a
forall a. IO a
exitSuccess
                  FishCompletionScript Path Abs File
progPath -> do
                    String
progname <- IO String
getProgName
                    Path Abs File -> String -> IO ()
generateFishCompletionScript Path Abs File
progPath String
progname
                    IO a
forall a. IO a
exitSuccess
                  CompletionQuery Bool
enriched Int
index [String]
ws -> do
                    Parser (Internal a) -> Bool -> Int -> [String] -> IO ()
forall a. Parser a -> Bool -> Int -> [String] -> IO ()
runCompletionQuery Parser (Internal a)
p' Bool
enriched Int
index [String]
ws
                    IO a
forall a. IO a
exitSuccess
                  ParsedNormally a
a -> a -> IO a
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a

-- We use [String] instead of [Args] because we want to remove these args, and act on them, before any real arg parsing happens.
consumeExactArg :: String -> [String] -> (Bool, [String])
consumeExactArg :: String -> [String] -> (Bool, [String])
consumeExactArg String
arg = [String] -> (Bool, [String])
go
  where
    go :: [String] -> (Bool, [String])
go = \case
      [] -> (Bool
False, [])
      (String
x : [String]
xs)
        | String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
arg -> (Bool
True, [String]
xs)
        | Bool
otherwise ->
            let (Bool
found, [String]
rest) = [String] -> (Bool, [String])
go [String]
xs
             in (Bool
found, String
x String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
rest)

consumeDebugMode :: [String] -> (Bool, [String])
consumeDebugMode :: [String] -> (Bool, [String])
consumeDebugMode = String -> [String] -> (Bool, [String])
consumeExactArg String
"--debug-optparse"

-- Note: Here we only consume exact -h as an arg, not -h as part of another arg like -hu
consumeHelpMode :: [String] -> (Bool, [String])
consumeHelpMode :: [String] -> (Bool, [String])
consumeHelpMode [String]
as =
  let (Bool
found, [String]
as') = String -> [String] -> (Bool, [String])
consumeExactArg String
"--help" [String]
as
   in if Bool
found
        then (Bool
True, [String]
as')
        else String -> [String] -> (Bool, [String])
consumeExactArg String
"-h" [String]
as'

consumeCheckMode :: [String] -> (Bool, [String])
consumeCheckMode :: [String] -> (Bool, [String])
consumeCheckMode = String -> [String] -> (Bool, [String])
consumeExactArg String
"--run-settings-check"

consumeCapabilities :: [String] -> (Capabilities, [String])
consumeCapabilities :: [String] -> (Capabilities, [String])
consumeCapabilities = Capabilities -> [String] -> (Capabilities, [String])
go Capabilities
allCapabilities
  where
    go :: Capabilities -> [String] -> (Capabilities, [String])
    go :: Capabilities -> [String] -> (Capabilities, [String])
go Capabilities
caps = \case
      [] -> (Capabilities
caps, [])
      (String
x : [String]
xs) ->
        let t :: Text
t = String -> Text
T.pack String
x
         in case Text -> Text -> Maybe Text
T.stripPrefix Text
"--settings-capabilities-disable-" Text
t of
              Just Text
capName -> Capabilities -> [String] -> (Capabilities, [String])
go (Capability -> Capabilities -> Capabilities
disableCapability (Text -> Capability
Capability Text
capName) Capabilities
caps) [String]
xs
              Maybe Text
Nothing -> case Text -> Text -> Maybe Text
T.stripPrefix Text
"--settings-capabilities-enable-" Text
t of
                Just Text
capName -> Capabilities -> [String] -> (Capabilities, [String])
go (Capability -> Capabilities -> Capabilities
enableCapability (Text -> Capability
Capability Text
capName) Capabilities
caps) [String]
xs
                Maybe Text
Nothing ->
                  let (Capabilities
finalCaps, [String]
rest) = Capabilities -> [String] -> (Capabilities, [String])
go Capabilities
caps [String]
xs
                   in (Capabilities
finalCaps, String
x String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
rest)

-- Internal structure to help us do what the framework
-- is supposed to.
data Internal a
  = ShowVersion
  | RenderMan
  | RenderDocumentation
  | RenderNixosOptions
  | BashCompletionScript (Path Abs File)
  | ZshCompletionScript (Path Abs File)
  | FishCompletionScript (Path Abs File)
  | CompletionQuery
      -- Enriched
      !Bool
      -- Index
      !Int
      -- Args
      ![String]
  | ParsedNormally !a

internalParser :: Parser a -> Parser (Internal a)
internalParser :: forall a. Parser a -> Parser (Internal a)
internalParser Parser a
p =
  [Parser (Internal a)] -> Parser (Internal a)
forall a. HasCallStack => [Parser a] -> Parser a
choice
    [ [Builder (Internal a)] -> Parser (Internal a)
forall a. HasCallStack => [Builder a] -> Parser a
setting
        [ Internal a -> Builder (Internal a)
forall a. a -> Builder a
switch Internal a
forall a. Internal a
ShowVersion,
          String -> Builder (Internal a)
forall a. String -> Builder a
long String
"version",
          Builder (Internal a)
forall a. Builder a
hidden
        ],
      [Builder (Internal a)] -> Parser (Internal a)
forall a. HasCallStack => [Builder a] -> Parser a
setting
        [ Internal a -> Builder (Internal a)
forall a. a -> Builder a
switch Internal a
forall a. Internal a
RenderMan,
          String -> Builder (Internal a)
forall a. String -> Builder a
long String
"render-man-page",
          Builder (Internal a)
forall a. Builder a
hidden,
          String -> Builder (Internal a)
forall a. String -> Builder a
help String
"Render a manpage"
        ],
      [Builder (Internal a)] -> Parser (Internal a)
forall a. HasCallStack => [Builder a] -> Parser a
setting
        [ Internal a -> Builder (Internal a)
forall a. a -> Builder a
switch Internal a
forall a. Internal a
RenderDocumentation,
          String -> Builder (Internal a)
forall a. String -> Builder a
long String
"render-reference-documentation",
          Builder (Internal a)
forall a. Builder a
hidden,
          String -> Builder (Internal a)
forall a. String -> Builder a
help String
"Render reference documentation"
        ],
      [Builder (Internal a)] -> Parser (Internal a)
forall a. HasCallStack => [Builder a] -> Parser a
setting
        [ Internal a -> Builder (Internal a)
forall a. a -> Builder a
switch Internal a
forall a. Internal a
RenderNixosOptions,
          String -> Builder (Internal a)
forall a. String -> Builder a
long String
"render-nix-options",
          Builder (Internal a)
forall a. Builder a
hidden,
          String -> Builder (Internal a)
forall a. String -> Builder a
help String
"Render Nix options"
        ],
      Path Abs File -> Internal a
forall a. Path Abs File -> Internal a
BashCompletionScript
        (Path Abs File -> Internal a)
-> Parser (Path Abs File) -> Parser (Internal a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Builder (Path Abs File)] -> Parser (Path Abs File)
forall a. HasCallStack => [Builder a] -> Parser a
setting
          [ Builder (Path Abs File)
forall a. Builder a
option,
            Reader (Path Abs File) -> Builder (Path Abs File)
forall a. Reader a -> Builder a
reader (Reader (Path Abs File) -> Builder (Path Abs File))
-> Reader (Path Abs File) -> Builder (Path Abs File)
forall a b. (a -> b) -> a -> b
$ (String -> Maybe (Path Abs File)) -> Reader (Path Abs File)
forall a. (String -> Maybe a) -> Reader a
maybeReader String -> Maybe (Path Abs File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Abs File)
parseAbsFile,
            String -> Builder (Path Abs File)
forall a. String -> Builder a
long String
"bash-completion-script",
            Builder (Path Abs File)
forall a. Builder a
hidden,
            String -> Builder (Path Abs File)
forall a. String -> Builder a
help String
"Render the bash completion script"
          ],
      Path Abs File -> Internal a
forall a. Path Abs File -> Internal a
ZshCompletionScript
        (Path Abs File -> Internal a)
-> Parser (Path Abs File) -> Parser (Internal a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Builder (Path Abs File)] -> Parser (Path Abs File)
forall a. HasCallStack => [Builder a] -> Parser a
setting
          [ Builder (Path Abs File)
forall a. Builder a
option,
            Reader (Path Abs File) -> Builder (Path Abs File)
forall a. Reader a -> Builder a
reader (Reader (Path Abs File) -> Builder (Path Abs File))
-> Reader (Path Abs File) -> Builder (Path Abs File)
forall a b. (a -> b) -> a -> b
$ (String -> Maybe (Path Abs File)) -> Reader (Path Abs File)
forall a. (String -> Maybe a) -> Reader a
maybeReader String -> Maybe (Path Abs File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Abs File)
parseAbsFile,
            String -> Builder (Path Abs File)
forall a. String -> Builder a
long String
"zsh-completion-script",
            Builder (Path Abs File)
forall a. Builder a
hidden,
            String -> Builder (Path Abs File)
forall a. String -> Builder a
help String
"Render the zsh completion script"
          ],
      Path Abs File -> Internal a
forall a. Path Abs File -> Internal a
ZshCompletionScript
        (Path Abs File -> Internal a)
-> Parser (Path Abs File) -> Parser (Internal a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Builder (Path Abs File)] -> Parser (Path Abs File)
forall a. HasCallStack => [Builder a] -> Parser a
setting
          [ Builder (Path Abs File)
forall a. Builder a
option,
            Reader (Path Abs File) -> Builder (Path Abs File)
forall a. Reader a -> Builder a
reader (Reader (Path Abs File) -> Builder (Path Abs File))
-> Reader (Path Abs File) -> Builder (Path Abs File)
forall a b. (a -> b) -> a -> b
$ (String -> Maybe (Path Abs File)) -> Reader (Path Abs File)
forall a. (String -> Maybe a) -> Reader a
maybeReader String -> Maybe (Path Abs File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Abs File)
parseAbsFile,
            String -> Builder (Path Abs File)
forall a. String -> Builder a
long String
"fish-completion-script",
            Builder (Path Abs File)
forall a. Builder a
hidden,
            String -> Builder (Path Abs File)
forall a. String -> Builder a
help String
"Render the fish completion script"
          ],
      [Builder (Bool -> Int -> [String] -> Internal a)]
-> Parser (Bool -> Int -> [String] -> Internal a)
forall a. HasCallStack => [Builder a] -> Parser a
setting
        [ String -> Builder (Bool -> Int -> [String] -> Internal a)
forall a. String -> Builder a
help String
"Query completion",
          (Bool -> Int -> [String] -> Internal a)
-> Builder (Bool -> Int -> [String] -> Internal a)
forall a. a -> Builder a
switch Bool -> Int -> [String] -> Internal a
forall a. Bool -> Int -> [String] -> Internal a
CompletionQuery,
          -- Long string that no normal user would ever use.
          String -> Builder (Bool -> Int -> [String] -> Internal a)
forall a. String -> Builder a
long String
"query-opt-env-conf-completion",
          Builder (Bool -> Int -> [String] -> Internal a)
forall a. Builder a
hidden
        ]
        Parser (Bool -> Int -> [String] -> Internal a)
-> Parser Bool -> Parser (Int -> [String] -> Internal a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Builder Bool] -> Parser Bool
forall a. HasCallStack => [Builder a] -> Parser a
setting
          [ Bool -> Builder Bool
forall a. a -> Builder a
switch Bool
True,
            String -> Builder Bool
forall a. String -> Builder a
long String
"completion-enriched",
            Bool -> Builder Bool
forall a. Show a => a -> Builder a
value Bool
False,
            Builder Bool
forall a. Builder a
hidden,
            String -> Builder Bool
forall a. String -> Builder a
help String
"Whether to enable enriched completion"
          ]
        Parser (Int -> [String] -> Internal a)
-> Parser Int -> Parser ([String] -> Internal a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Builder Int] -> Parser Int
forall a. HasCallStack => [Builder a] -> Parser a
setting
          [ Builder Int
forall a. Builder a
option,
            Reader Int -> Builder Int
forall a. Reader a -> Builder a
reader Reader Int
forall a. Read a => Reader a
auto,
            String -> Builder Int
forall a. String -> Builder a
long String
"completion-index",
            Builder Int
forall a. Builder a
hidden,
            String -> Builder Int
forall a. String -> Builder a
help String
"The index between the arguments where completion was invoked."
          ]
        Parser ([String] -> Internal a)
-> Parser [String] -> Parser (Internal a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String -> Parser [String]
forall a. Parser a -> Parser [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many
          ( [Builder String] -> Parser String
forall a. HasCallStack => [Builder a] -> Parser a
setting
              [ Builder String
forall a. Builder a
option,
                Reader String -> Builder String
forall a. Reader a -> Builder a
reader Reader String
forall s. IsString s => Reader s
str,
                String -> Builder String
forall a. String -> Builder a
long String
"completion-word",
                Builder String
forall a. Builder a
hidden,
                String -> Builder String
forall a. String -> Builder a
help String
"The words (arguments) that have already been typed"
              ]
          ),
      a -> Internal a
forall a. a -> Internal a
ParsedNormally (a -> Internal a) -> Parser a -> Parser (Internal a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser a
p
    ]