Option.Applicative:如何用标志解析​​组合解析器?

时间:2017-02-22 12:58:58

标签: haskell command-line-arguments optparse-applicative

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

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"

我需要在???

写什么

2 个答案:

答案 0 :(得分:2)

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

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

1。 How to parse Maybe with optparse-applicative

2。 Is it possible to have a optparse-applicative option with several parameters?

从第一个问题开始,您知道如何使用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

答案 1 :(得分:1)

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