将 optparse-applicative 与多个子命令和全局选项一起使用

Using optparse-applicative with multiple subcommands and global options

我正在编写一个采用多个子命令的命令行程序,这些子命令需要 flags/arguments。

该程序还应该采用一些适用于所有子命令的'global-flags'。例如:

myProgram --configfile=~/.customrc UPLOADFILE --binary myfile.x
myProgram --configfile=~/.customrc SEARCH --regex "[a-z]+"

本例中子命令为UPLOADFILESEARCHconfigfile与这两个子命令相关,binaryregex适用于具体的子命令。

我觉得这个库一定可以做到这一点,但我正在努力弄清楚把什么放在哪里!我是 Haskell 的新手,试图了解应用程序,这让我的大脑很受伤 :)

文档中有一个子命令示例 模块,但我似乎不知道如何让全局标志工作。

如果有人能给我指出一个小的工作示例,或者深入了解我应该如何构建代码来做到这一点,我将不胜感激,我发现这些高阶函数有点神奇!

非常感谢您的宝贵时间。最良好的祝愿,

麦克

您链接的文档是这样说的:

Commands are useful to implement command line programs with multiple functions, each with its own set of options, and possibly some global options that apply to all of them.

尽管它没有准确说明应如何应用这些选项。但是,如果您查看这些类型,您可以获得一些见解。该示例表示使用subparser,其类型为Mod CommandFields a -> Parser a。这可能并没有说明什么(尤其是左侧),但关键是这个函数只产生一个 Parser - 所以你可以像往常一样将它与其他解析器结合起来:

data Subcommand 
  = Upload { binary :: String } 
  | Search { regex  :: String } deriving Show 

data Options = Options 
  { configFile :: FilePath 
  , subcommand :: Subcommand 
  } deriving Show 

commandO = Options <$> configFileO <*> subcommandO 

configFileO = strOption
   ( long "configfile"
  <> help "Filepath of configuration file" 
   )

subcommandO :: Parser Subcommand
subcommandO = subparser ...

自己定义子命令非常简单 - 我只是从文档中复制示例并根据您的具体示例重命名一些内容:

subcommandO = 
  subparser
    ( command "UPLOADFILE" (info uploadO
        ( progDesc "Upload a file" ))
   <> command "SEARCH" (info searchO
        ( progDesc "Search in a file" ))
   )

uploadO = Upload <$> 
  ( strOption
     ( long "binary"
    <> help "Binary file to upload" 
     )
  )

searchO = Upload <$> 
  ( strOption
     ( long "regex"
    <> help "Regular expression to search for" 
     )
  )

main = execParser opt >>= print where 
  opt = info (helper <*> commandO)
     ( fullDesc
    <> progDesc "Example for multiple subcommands"
    <> header "myProgram" )

运行 该程序给出以下内容:

>:main --configfile=~/.customrc UPLOADFILE --binary myfile.x
Options {configFile = "~/.customrc", subcommand = Upload {binary = "myfile.x"}}

>:main --configfile=~/.customrc SEARCH --regex "[a-z]+"
Options {configFile = "~/.customrc", subcommand = Upload {binary = "[a-z]+"}}

>:main --help
myProgram

Usage: <interactive> --configfile ARG COMMAND
  Example for multiple subcommands

Available options:
  -h,--help                Show this help text
  --configfile ARG         Filepath of configuration file

Available commands:
  UPLOADFILE               Upload a file
  SEARCH                   Search in a file
*** Exception: ExitSuccess