2017-02-22 23 views
1

Я усложнил параметры командной строки, так какOption.Applicative: как разобрать объединенный парсер с флагом?

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

Я хочу, чтобы разобрать эти subarguments с флагом:

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

Я попросил автора библиотеки. Это невозможно (на данный момент). См. Андер Паоло Каприотти – Pieter

 Смежные вопросы

  • Нет связанных вопросов^_^