2017-02-22 59 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