2017-02-22 63 views
1

我有复杂的命令行选项,Option.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" 

我有什么写在???

回答

1

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

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

+0

我问了图书馆的作者。这是不可能的(现在)。看Paolo Capriotti的水管 – Pieter