optparse-applicative 的(子)命令同义词
(Sub)command synonyms for optparse-applicative
我想在我的 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 John
获得 Hello, John!
,使用 ./opt_ex.hs groot John
获得 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
我认为你做不到。它适用于选项,因为 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
我想在我的 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 John
获得 Hello, John!
,使用 ./opt_ex.hs groot John
获得 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
我认为你做不到。它适用于选项,因为 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