1

我有复杂的命令行选项,如

data Arguments = Arguments Bool (Maybe SubArguments)
data SubArguments = SubArguments String String

我想用一个标志解析这些子参数:

programName --someflag --subarguments "a" "b"
programName --someflag

我已经有了

subArgParser = SubArguments <$> argument str <*> argument str
mainParser = MainArgs <$> switch
                  (long "someflag"
                   <> help "Some argument flag")
               <*> ???
                   (long "subarguments"
                   <> help "Sub arguments"

我要写什么???

4

2 回答 2

2

你的问题比你想象的要复杂。当前optparse-applicative的 API 不应该用于这种情况。因此,您可能想要更改处理 CLI 参数的方式或切换到另一个 CLI 解析库。但我将描述实现目标的最接近的方法。

首先,您需要阅读其他两个 SO 问题:

1. 如何使用 optparse-applicative 解析 Maybe

2. 是否可以有一个带有多个参数的 optparse-applicative 选项?

从第一个问题开始,您就知道如何使用optional函数解析可选参数。从一开始,您就会了解解析多个参数的一些问题。所以我将在这里写几种方法来解决这个问题。

1.幼稚丑陋

您可以将一对字符串表示为一对String类型,并使用这对的天真show。这是代码:

mainParser :: Parser Arguments
mainParser = Arguments
    <$> switch (long "someflag" <> help "Some argument flag")
    <*> optional (uncurry SubArguments <$>
                   (option auto $ long "subarguments" <> help "some desc"))

getArguments :: IO Arguments
getArguments = do
    (res, ()) <- simpleOptions "main example" "" "desc" mainParser empty
    return res

main :: IO ()
main = getArguments >>= print

这是结果ghci

ghci> :run main --someflag --subarguments "(\"a\",\"b\")"
Arguments True (Just (SubArguments "a" "b"))

2. 不那么天真

从回答到第二个问题,您应该了解如何在一个字符串中传递多个参数。下面是解析代码:

subArgParser :: ReadM SubArguments
subArgParser = do
    input <- str
    -- no error checking, don't actually do this
    let [a,b] = words input
    pure $ SubArguments a b

mainParser :: Parser Arguments
mainParser = Arguments
    <$> switch (long "someflag" <> help "Some argument flag")
    <*> optional (option subArgParser $ long "subarguments" <> help "some desc")

这是ghci输出:

ghci> :run main --someflag --subarguments "x yyy"
Arguments True (Just (SubArguments "x" "yyy"))

第二种解决方案唯一的坏处是没有错误检查。因此,您可以使用另一个通用解析库,例如megaparsec,而不仅仅是let [a,b] = words input.

于 2017-02-22T21:36:15.727 回答
1

这是不可能的,至少不是直接的。您可能会发现一些适合您的间接编码,但我不确定。选项接受参数,而不是子解析器。您可以拥有子解析器,但它们是由“命令”引入的,而不是选项(即没有前导--)。

于 2017-02-22T21:35:01.970 回答