【问题标题】:Option.Applicative: How to parse a combined parser with a flag?Option.Applicative:如何解析带有标志的组合解析器?
【发布时间】:2017-02-23 07:20:58
【问题描述】:

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

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"

我要写什么???

【问题讨论】:

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


    【解决方案1】:

    事实证明,您的问题比您想象的要复杂。当前的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

    【讨论】:

    • 我问了图书馆的作者。这是不可能的(目前)。查看 Paolo Capriotti 的答案
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      • 2013-10-09
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多