You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Haskell的optparse-applicative中对选项进行分组?

如何用optparse-applicative对命令行选项进行分组展示

我现在用optparse-applicative处理命令行选项,但--help输出把所有选项混在一起:

Usage: test-args [--to plain json toml] 
                 [(-f|--file FILENAME) | --from-current-dir]

Available options:
  --to plain json toml     Output style (default: plain)
  -f,--file FILENAME       Read data from specified cabal file
  --from-current-dir       (default)
  -h,--help                Show this help text

我希望调整成分组展示的形式:

Usage: test-args [--to plain json toml] 
                 [(-f|--file FILENAME) | --from-current-dir]

OUTPUT STYLE:
--to plain json toml (Default: plain)

READ OPTIONS:
--file FILE
--from-current-dir (default)

请问能否实现这个需求?以下是我的解析器代码:

data ReadOption = CabalFile !FilePath
                | CurrentDir deriving (Show, Eq)

fromFile :: Parser ReadOption
fromFile = CabalFile <$> strOption (
    long "file"
 <> short 'f'
 <> metavar "FILENAME"
 <> help "Read data from specified cabal file"
 )

searchFile :: Parser ReadOption
searchFile = flag CurrentDir CurrentDir (
    long "from-current-dir"
 <> help "(default)"
 )

readOptionsParser :: Parser ReadOption
readOptionsParser = fromFile <|> searchFile

outputStyleParser :: Parser OutputStyle
outputStyleParser = option auto
   ( long "to"
  <> help "Output style"
  <> completeWith outputStylesStrings
  <> value Plain
  <> metavar (unwords outputStylesStrings)
  <> showDefault
 )

data CLIOptions = CLIOptions
  { outputStyle :: !OutputStyle
  , readOptions :: !ReadOption} deriving (Show)

cliOptionsParser :: Parser CLIOptions
cliOptionsParser = CLIOptions <$> outputStyleParser <*> readOptionsParser

完全可以实现,optparse-applicative自带group修饰符,用来给选项添加分组标签,配合顶层解析器的构建就能生成分组式帮助输出。修改后的代码如下:

import Options.Applicative

data ReadOption = CabalFile !FilePath
                | CurrentDir deriving (Show, Eq)

fromFile :: Parser ReadOption
fromFile = CabalFile <$> strOption (
    long "file"
 <> short 'f'
 <> metavar "FILENAME"
 <> help "Read data from specified cabal file"
 )

searchFile :: Parser ReadOption
searchFile = flag CurrentDir CurrentDir (
    long "from-current-dir"
 <> help "Use current directory (default)"
 )

readOptionsParser :: Parser ReadOption
readOptionsParser = fromFile <|> searchFile

outputStyleParser :: Parser OutputStyle
outputStyleParser = option auto
   ( long "to"
  <> help "Output style"
  <> completeWith outputStylesStrings
  <> value Plain
  <> metavar (unwords outputStylesStrings)
  <> showDefault
 )

data CLIOptions = CLIOptions
  { outputStyle :: !OutputStyle
  , readOptions :: !ReadOption} deriving (Show)

-- 给每个选项组添加分组标识
cliOptionsParser :: Parser CLIOptions
cliOptionsParser = CLIOptions
  <$> group "OUTPUT STYLE" outputStyleParser
  <*> group "READ OPTIONS" readOptionsParser

-- 构建带有分组帮助的顶层解析器
main :: IO ()
main = do
  opts <- execParser optsInfo
  print opts
  where
    optsInfo = info (cliOptionsParser <**> helper)
      ( fullDesc
     <> progDesc "Your program description here"
      )

关键修改说明

  1. group修饰符:用group函数给每个解析器绑定分组名称,optparse-applicative会自动将同组选项归类展示。
  2. 优化帮助文本:把searchFile的帮助信息调整为更清晰的"Use current directory (default)",提升可读性。
  3. 顶层解析器构建:通过info和helper组合子确保--help选项正常生成分组格式的帮助内容。

修改后运行test-args --help,就能得到你期望的分组式帮助输出。

内容的提问来源于stack exchange,提问作者Leonid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:27:22