2017-01-27 2 views
0

У нас есть классические флаги в инструментах командной строки, те, которые позволяют что-то (без аргументов, например, --help или --version) и других родов флагов, которые принимают аргументы (например, --output-dir=/home/ или --input-file="in.a", что угодно) ,Реализация другого вида флагов в Haskell

Но на этот раз я хотел бы реализовать следующий вид.

$ myprogram --GCC-option="--stdlib 11" --debug 

В общем случае, флаг, как "--PROGRAM-option=ARGUMENT". Затем я сохраняю этот флаг, PROGRAM и ARGUMENT значений, они являются переменными. В приведенном выше примере мы имеем PROG=GCC и ARGUMENT=--stdlib 11.

Как я могу реализовать эту функцию в Haskell? У меня есть некоторые варианты анализа синтаксиса в классическом стиле.

+2

Если вы знаете перед всеми вариантами «ПРОГРАММА», это легко. В противном случае, я думаю, вы будете писать большую часть логики. –

+0

Возможно, действительно, только если вы знаете заранее возможные значения «ПРОГРАММА»: https://wiki.haskell.org/Command_line_option_parsers – Alec

+0

@ DanielWagner Нет. Я не знаю имен, они постоянно меняются. – jonaprieto

ответ

2

В недавнем моем проекте я использовал подход, основанный на «Data.Tree» узлов обработки опций. Конечно, я не выпустил этот код, поэтому он очень ограничен, но я думаю, что эта схема может быть полезна.

data OptHandle = Op { optSat :: String -> Bool 
        , opBuild :: [String] -> State Env [String] 
        } 

Поля узла: проверьте, удовлетворен ли аргумент узлу; и постепенно наращивает начальную программную среду на основе оставшихся аргументов (возвращая неиспользуемые аргументы для обработки узлами ниже в дереве.)

Дерево обработки опций затем жестко закодировано, например, ниже.

pgmOptTree :: [Tree OptHandle] 
pgmOptTree = [mainHelpT,pgmOptT,dbgT] 

mainHelpT :: Tree OptHandle 
mainHelpT = Node (Op sat bld) [] 
    where 
    sat "--help" = True 
    sat _ = False 
    bld _ = do 
     mySetEnvShowHelp 
     return [] 

pgmOptT :: Tree OptHandle 
pgmOptT = Node (Op sat bld) [dbgT] 
    where 
    sat = functionOn . someParse 
    bld ss = do 
     let (d,ss') = parsePgmOption ss 
     mySetEnvPgmOpt d 
     return ss' 

Вам также понадобится функция, которая подает аргументы командной строки к дереву, проверка выполнимости каждого узла в лесу, выполняя opBuild и вызова subforests. После запуска обработчика в государственной монаде вам нужно вернуть начальную начальную среду, которая может использоваться для указания основных функций, которые вы хотите вызвать.

Обработчик опций, который я использовал, был на самом деле немного сложнее этого, так как моя программа общалась с Bash для выполнения вкладок и включала помощь для большинства основных опций. Я нашел преимущество в том, что я мог более легко синхронизировать три проблемы с командной строкой: включение вкладок, которые могли бы сообщить пользователям о следующих доступных командах; предоставление помощи для неполных команд; и фактически запускает программу для полных команд.

Поддержание дерева, как это хорошо, потому что вы можете повторно использовать узлы в разных точках и добавлять параметры, которые работают с другими довольно легко.

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