Короткий код Ruby OptionParser для логического варианта?

Я использую Ruby OptionParser (require 'optparse'), обрабатывая «подробный» параметр, который может быть либо истинным, либо ложным. Это в коде так:

  parser.on('-v', '--[no-]verbose', 'Verbose mode') do |v|
    self.verbose = v
  end

Я поддерживаю указание параметров в переменной среды (я добавляю ее содержимое к ARGV), поэтому можно включить подробный режим в этой переменной среды и переопределить его в командной строке с помощью --no-verbose. Однако я не могу найти способ переопределить его с помощью короткой опции. Я пробовал это без успеха:

-v-
-v0
-v=0

Я нашел исходный код по адресу https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb, но не смог найти ответ.

Как я могу это сделать?


person Keith Bennett    schedule 07.02.2019    source источник
comment
Если вы вообще не передадите его, это будет ложным (например, nil), поэтому я не уверен, зачем вам нужно переопределять его с помощью короткого кода? Вы также можете инициализировать его как false, например. def initialize; self.verbose = false; end   -  person engineersmnky    schedule 07.02.2019
comment
Я объяснил, зачем мне это нужно, во втором (не кодовом) абзаце вопроса; не могли бы вы прочитать это еще раз, пожалуйста, и если это все еще не ясно, я попытаюсь объяснить по-другому.   -  person Keith Bennett    schedule 08.02.2019
comment
Итак, вы говорите, что среда будет настроена на многословие, но иногда вы хотите отключить ее из командной строки? Как вы добавляете это в ARGV, можете ли вы также опубликовать этот код?   -  person engineersmnky    schedule 08.02.2019
comment
Да, точно, эффективно для временного создания нестандартного значения по умолчанию, но такого, которое можно переопределить для отдельного вызова rexe. Метод prepend_environment_options, который предшествует ARGV, находится по адресу github.com/keithrbennett. /rexe/blob/master/exe/rexe#L53-L59 на данный момент, но со временем код может измениться; если это так, найдите имя метода или ARGV.   -  person Keith Bennett    schedule 10.02.2019


Ответы (2)


На основе https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1936-L1949 и, учитывая, как работает флаг -v для большинства команд, должно работать следующее:

  • -v - похоже на то, что вы пробовали, но с пробелом
  • -v no
  • -v false

Изменить

После комментария я углубился в проблему и попробовал сам. Вот что у меня получилось:

# optparser.rb

require 'optparse'

options = {}
OptionParser.new do |opts|
  opts.on("-v", "--[no-]verbose [FLAG]", TrueClass, "Run verbosely") do |v|
    options[:verbose] = v.nil? ? true : v
  end
end.parse!

p options

Важные изменения в коде OP:

  • Добавление [FLAG] «аргумента». Это включит аргумент для такой опции, как -v no, -v yes, -v false, -v true, -v n, -v y, -v + (я не заставил -v - работать).
  • Добавление явного приведения аргумента TrueClass. Без него аргумент будет интерпретироваться как строка (например, 'false').
  • Сделать аргумент необязательным, заключив определение аргумента в [ ], а затем убедившись, что true считается значением по умолчанию через v.nil? ? true : v. Без фигурных скобок парсер аргументов не принимает -v (без аргумента)
person ulferts    schedule 07.02.2019
comment
Я не мог заставить ни один из них работать с пробелом. Мне удалось заставить его работать с -vn. Если вы хотите проверить это, вы можете установить gem install rexe вот простая командная строка: rexe -mn -v off_flag 1, где off_flag это `-v -', -v no' и т. д. Я попытался экранировать пробел обратной косой чертой и поставить опция в двойных кавычках (например, -vn), но ничего из этого не сработало. - person Keith Bennett; 10.02.2019
comment
@KeithBennett, я обновил свой ответ после того, как попробовал сам. Раньше я просто бегло просматривал документацию. Извините, что поторопился. - person ulferts; 10.02.2019
comment
Молодец, мой друг! Большое спасибо. Кстати, мне нравится использовать OpenStruct объекты для опций. Удобнее, чем хэши. - person Keith Bennett; 11.02.2019
comment
Я многому научился, так что это того стоило. Да, OpenStruct в порядке и более читабельны в большинстве сценариев. Не то, чтобы это было проблемой здесь, но они также имеют тенденцию быть довольно медленными. - person ulferts; 11.02.2019

Помещение n сразу после логического флага (например, -vn) устанавливает его в false. Этот пример включает, а затем выключает подробный логический флаг, а затем печатает число 1:

rexe -mn -v -vn 1

person Keith Bennett    schedule 10.02.2019
comment
Ни один логический класс в Ruby не является жалким и неудобным для пользователя. Использование -vn 1 загадочно, хакерски и совсем не интуитивно понятно. - person hipertracker; 05.06.2020
comment
В Ruby значения имеют классы, а не переменные, и оказывается, что для true и false существует всего несколько общих методов. rubytapas.com/2019/01/08/boolean - person karatedog; 21.07.2021
comment
класс true — TrueClass, а false — FalseClass. Недавно у меня была ситуация, когда я хотел, чтобы эти 2 класса были подклассами общего класса, такого как Boolean. Кроме того, мне интересно, почему true и false не могли быть экземплярами логического класса. Я не знаю никакого хорошего способа проверить, является ли значение логическим, кроме чего-то вроде [true, false].include?(value) или (value == true || value == false). - person Keith Bennett; 22.07.2021
comment
@hipertracker Я не знаю, понимаете ли вы ... У Ruby есть true и false; вопрос этого сообщения заключается в том, как указать логические значения в командной строке Posix. Это должно быть сделано с какой-то строкой. Класс Ruby OptionParser преобразует эту строку в значение true или false, если аргументы opts.on верны. - person Keith Bennett; 22.07.2021