3

我想在我的 Haskell 命令行工具中添加子命令的同义词。例如summarise,并且summarize应该产生相同的结果。当然,我可以只添加一个完全独立的命令summarize,它作为自己的元素出现在--help. 但也许有更优雅的方式。

这是堆栈脚本中的一个独立示例opt_ex.hs

#!/usr/bin/env stack
-- stack --resolver lts-18.17 script --package optparse-applicative

import Options.Applicative
import Data.Semigroup ((<>))

data Options = CmdGreet GreetArgs | CmdGroot GreetArgs

newtype GreetArgs = GreetArgs String

main :: IO ()
main = do
    cmdOpts <- customExecParser (prefs showHelpOnEmpty) (info optParser fullDesc)
    runCmd cmdOpts

optParser :: Parser Options
optParser = subparser (
    command "greet" (info (CmdGreet <$> sample) (progDesc "Print greeting 1")) <>
    command "groot" (info (CmdGroot <$> sample) (progDesc "Print greeting 2"))
    )

runCmd :: Options -> IO ()
runCmd o = case o of
    CmdGreet opts -> greet opts
    CmdGroot opts -> groot opts

greet :: GreetArgs -> IO ()
greet (GreetArgs h) = putStrLn $ "Hello, " ++ h ++ "!"

groot :: GreetArgs -> IO ()
groot (GreetArgs h) = putStrLn $ "Howdy, " ++ h ++ "!"

sample :: Parser GreetArgs
sample = GreetArgs <$> strArgument ( metavar "TARGET" )

您可以使用./opt_ex.hs greet Johnto getHello, John!和 with ./opt_ex.hs groot Johnto get运行它Howdy, John!。运行./opt_ex.hs将为您提供以下概述:

Usage: opt_ex.hs COMMAND

Available commands:
  greet                    Print greeting 1
  groot                    Print greeting 2

什么是最优雅的方式,gruut在这个例子中添加一个命令,它的行为与 完全一样greet,但在代码和用户中产生最少的开销?

理想情况下,我想./opt_ex.hs产生这样的东西:

Usage: opt_ex.hs COMMAND

Available commands:
  greet|gruut              Print greeting 1
  groot                    Print greeting 2
4

1 回答 1

2

我不认为你能做到这一点。它适用于选项,因为 OptField 的定义包含一个 OptName 列表,并在您使用(<>). 但是,返回的东西 CommandFields 的定义command

data CommandFields a = CommandFields
  { cmdCommands :: [(String, ParserInfo a)]
  , cmdGroup :: Maybe String }

因此,每个字符串名称都与不同的 ParserInfo 相关联。当然,您可以定义一个包含任何您喜欢的 ParserInfo 的变量,并在两个命令中重用它,这样您就不必重复 ParserInfo。但是就 optparse-applicative 而言,这两个命令是不同的,所以它会在帮助文本中分别列出它们。对于您的示例,这看起来像

optParser = let greeting1 = info (CmdGreet <$> sample) (progDesc "Print greeting 1")
            in subparser $
               command "greet" greeting1 <>
               command "gruut" greeting1 <>
               command "groot" (info (CmdGroot <$> sample) (progDesc "Print greeting 2"))

事实上,在运行时,我们会看到列出的两个命令:

Usage: optparse COMMAND

Available commands:
  greet                    Print greeting 1
  gruut                    Print greeting 1
  groot                    Print greeting 2
于 2021-11-21T20:12:58.970 回答