2014-01-04 3 views
1

Я работал над созданием рубинового инструмента CLI немного более надежным с обработкой ошибок компонента CLI инструмента. Я использую optparse, и документация показывает, что флаги могут иметь обязательные и необязательные аргументы. Я просто вижу какое-то странное/раздражающее поведение.Нечетное поведение Ruby optparse с обработкой исключений

Для одного случая, когда аргумент флага является обязательным (с использованием знака равенства), я пытался сделать его неудачным, но он все еще работал, он просто захватил следующий флаг ('-u') в качестве аргумента для этот флаг вместо этого приводит к тому, что оставшаяся часть синтаксического анализа становится более чем идеальной. Я предполагаю, что это вроде ОК, так как «-....» может быть действительным, но поскольку я использую знак равенства для установки значения переключателя, я бы предположил, что присвоение стиля «пробел» не будет работать ,

op = OptionParser.new do |x| 
    x.on("-u", "--user=USER", "user flag") do |user| options[:user] = user end 
    x.on("-d", "--db=DATABASE", "database flag") do |db| options[:db] = db end 
end 

Если я прохожу следующий вход CLI:

myprog -u -d mydb positionalarg 

Затем во время синтаксического анализа, он задает параметры [: пользователя], чтобы быть -d и опции [: дБ] равна нулю, так как он не является и есть 2 позиционных аргумента вместо 1. Очевидно, что это ошибка пользователя, но я хочу поймать ее и отобразить реальную ошибку, а не просто вернуть ошибку (в случае инструмента), что должен быть принят только один позиционный аргумент из следующего списка: ... Истинная проблема в том, что флаг -u отсутствует, это требуемый аргумент, так что если у optparse есть исключение ArgumentMissing, я бы предположил, что это то, что .parse! будет бросать.

Однако с флагом, который имеет необязательный аргумент (с использованием знака равенства), на самом деле это необязательно, если вы делаете: -a -b = что-то, но это не работает: -a something -b = somethingelse. Единственный способ заставить значение - использовать знак равенства: -a = something -b = somethingelse. Учитывая предыдущее поведение с обязательным аргументом с равным знаком, я бы не подумал бы об этом. Пример:

op = OptionParser.new do |x| 
    x.on("-u", "--user[=USER]", "user flag") do |user| options[:user] = user unless user.nil? end 
    x.on("-d", "--db=DATABASE", "database flag") do |db| options[:db] = db end 
end 

Так с разбором:

myprog -u -d mydb positionalarg 

Затем опции [: пользователь] является нулевыми (КИ) и опция [: дБ] является MYDB и есть одна позиционная агд осталась.

С этим разбором:

myprog -u myuser -d mydb positionalarg 

Затем опции [: пользователь] равен нуль (не в порядке) и опция [: дБ] является MYDB и есть два позиционные арг перенесенный: MyUser и positionalarg (не в порядке). Моя ошибка снова проверяется с помощью позиционного аргумента arg. Кажется, что если с обязательными аргументами флага, что если оба пространства и = работают, то для необязательных аргументов флага они должны быть одинаковыми, но это не так.

Другая проблема заключается в том, что флаги с необязательными аргументами (используя пробел) являются точными, за исключением случаев, когда они находятся в конце команды, а затем принимают аргумент position как аргумент flags.

Пример:

op = OptionParser.new do |x| 
    x.on("-u", "--user [USER]", "user flag") do |user| options[:user] = user unless user.nil? end 
    x.on("-d", "--db=DATABASE", "database flag") do |db| options[:db] = db end 
end 

Так с разбором:

myprog -d mydb -u positionalarg 

Затем опции [: дБ] является MYDB (КИ) и опция [: пользователь] является positionalarg и неты позиционных аргументов остаются над. Обратите внимание, что -d mydb работает с пространством, даже те, которые я указываю с помощью знака равенства.

Кажется, что многие люди делают рубиновые CLI, делая optparse .parse! и взять остальные записи в ARGV в качестве позиционных аргументов, но я думаю, что лучше было бы отделить аргументы позиционирования от дальнего конца, прежде чем передавать ARGV на optparse (за исключением того, что это не выполняется в случае переменного числа позиционных аргументов.

Я уверен, что я могу программировать вокруг всего этого, но я предпочел бы не, если есть способы, чтобы сделать это в optparse, что я не догадывались.

может быть, лучше всего было бы, чтобы избежать флагов с необязательными аргументами :), но любые советы будут оценены.

+0

Почему бы вам не показать, что вы делаете, а не пытаетесь описать его? Исходный код, как картинка, стоит тысячи слов. Как есть, это не вопрос, который можно использовать: «Вопросы, связанные с проблемами с написанным кодом, должны описывать конкретную проблему - и включать в себя действительный код для его воспроизведения - в самом вопросе. См. Http://SSCCE.org для руководства «. –

ответ

1

Почему вы используете = в описании параметров? Пример в documentation не использует их.

Если я определяю эту MWE как test.rb:

require 'optparse' 

puts "\n=Call with #{ARGV.inspect}" 
options = {} 

op = OptionParser.new do |x| 
    x.on("-u", "--user [USER]", "user flag") do |user| options[:user] = user unless user.nil? end 
    x.on("-d", "--db DATABASE", "database flag") do |db| options[:db] = db end 
end 

op.parse! 

puts "Options: #{options.inspect}" 
puts "ARGV  #{ARGV.inspect}" 

И называть его этим batfile (Windows, удалить @echo off для Linux):

@echo off 
test.rb -h 
test.rb -u -d mydb positionalarg 
test.rb -u myuser -d mydb positionalarg 
test.rb --user=myuser -d mydb positionalarg 

я получаю:

=Call with ["-h"] 
Usage: test [options] 
    -u, --user [USER]    user flag 
    -d, --db DATABASE    database flag 

=Call with ["-u", "-d", "mydb", "positionalarg"] 
Options: {:db=>"mydb"} 
ARGV  ["positionalarg"] 

=Call with ["-u", "myuser", "-d", "mydb", "positionalarg"] 
Options: {:user=>"myuser", :db=>"mydb"} 
ARGV  ["positionalarg"] 

=Call with ["--user=myuser", "-d", "mydb", "positionalarg"] 
Options: {:user=>"myuser", :db=>"mydb"} 
ARGV  ["positionalarg"] 
+0

Использование знака равенства в форматах длинной формы - это идиоматический способ выполнения длинной формы CLI, тогда как короткая форма обычно не использует знак равенства. – jshort

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