optparse应用bash自动补全如何工作?

时间:2019-11-30 16:13:30

标签: haskell optparse-applicative

我正在构建一个令人难以置信的编译器。该可执行文件接受两个命令$ brainfuck compile ...$ brainfuck run。我希望可执行文件在按Tab键时自动完成。例如。编写$ brainfuck com,然后按Tab键应生成$ brainfuck compile

data Command = Compile CompileArgs | Run RunArgs
  deriving (Show)

main :: IO ()
main = execute =<< execParser opts
  where
    opts = info (helper <*> argsParser) fullDesc

execute :: Command -> IO ()
execute (Compile args)  = compile args
execute (Run args)      = run args

argsParser :: Parser Command
argsParser = subparser (compileCommand <> runCommand)
  where
    compileCommand  = command "compile" $ info compileOptions $ progDesc "Compile brainfuck to an executable"
    runCommand      = command "run"     $ info runOptions     $ progDesc "Execute brainfuck code"

在optparse的github页面here上有一节,但我不太了解。

函数completeWith :: Options.Applicative.Builder.Internal.HasCompleter f => [String] -> Mod f a看起来与我已经在使用的command :: String -> ParserInfo a -> Mod CommandFields a类似。因此,我认为可以使用它,并将其与<>组合在一起,但是事实证明CommandFields不是HasCompleter的实例。

您应该如何使自动完成功能正常工作?

2 个答案:

答案 0 :(得分:0)

我还没有对此进行测试,但是在阅读了文档之后,在我看来,通过在execParser中调用main,您的程序会自动支持命令完成所需的选项。您只需要按照记录运行--bash-completion-script来运行程序即可生成Shell脚本,然后将该脚本加载到bash中。

答案 1 :(得分:0)

经过RTFM处理后,我发现了如何配置自动完成功能。 为各个参数构造解析器时,将应用completeWith。 像这样:

data CompileArgs = CompileArgs
  {
    debug :: Bool,
    optimizations :: OptimizationLevel,
    file :: String
  }
  deriving (Show, Read)

compileArgsParser :: Parser CompileArgs
compileArgsParser = CompileArgs
  <$> switch (
    long "debug" <>
    help "Outputs object and assembly files")
  <*> option auto (
    long "optimization-level" <>
    value All <>
    metavar "LEVEL" <>
    help "all | none, default: all" <>
    completeWith ["all", "none"])
  <*> argument str (
    metavar "FILE" <>
    help "brainfuck source code" <>
    action "file")
  <**> helper

action是关于如何自动完成的说明。 "file"表示自动完成任何文件或目录。有关更多信息,请参见this页。

为了使这些自动完成功能生效,您需要生成一个脚本并确保该脚本是源文件。按照惯例,使用bash时,它会放在/etc/bash_completion.d/下。

brainfuck --bash-completion-script `which brainfuck` | sudo tee /etc/bash_completion.d/brainfuck

在我的程序名为brainfuck的情况下。