Ruby OptionParser 短代码用于布尔选项?

6

我正在使用 Ruby 的 OptionParser (require 'optparse') 处理一个“verbose”选项,它可以是 true 或 false。代码如下:

  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找到了源代码,但是没有从中找到答案。

我该怎么做呢?


如果你完全不传递它,那么它将是falsey(例如nil),所以我不确定为什么你需要使用短代码覆盖它?你也可以将其初始化为false,例如def initialize; self.verbose = false; end - engineersmnky
我在问题的第二段(非代码)中解释了为什么我需要这个,请您再次阅读一下,如果还不清楚,我会尝试另一种方式来解释。 - Keith Bennett
那么您的意思是环境将被配置为冗长,但有时您希望从命令行关闭它?您如何在 ARGV 前面添加它,您能贴出那段代码吗? - engineersmnky
是的,确切地说,这是为了创建一个非标准的默认临时环境,但可以在单个rexe调用中被覆盖。目前,将参数添加到ARGV的方法prepend_environment_options位于https://github.com/keithrbennett/rexe/blob/master/exe/rexe#L53-L59,但代码可能会随时间而改变;如果有更改,请搜索方法名称或`ARGV`。 - Keith Bennett
2个回答

9

基于 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 - 正常工作)。
  • 添加了显式 argument coercion TrueClass。没有它,该参数将被解释为字符串(例如 'false')。
  • 通过使用 [ ] 将参数定义包装起来,并确保 true 被视为默认值,使参数变为可选。如果没有大括号,参数解析器不接受 -v(没有参数)。

我无法将这些与空格一起使用。我能够通过-vn让它工作。如果您想进行测试,可以在此处安装“rexe”,这是一个简单的命令行:rexe -mn -v off_flag 1,其中off_flag-v -',-v no等。我尝试用反斜杠转义空格并使用双引号将选项放入其中(例如,“-v n”),但都没有起作用。 - Keith Bennett
@KeithBennett,我在自己尝试后更新了我的答案。之前,我只是简单地浏览了文档。对于我的匆忙,我很抱歉。 - ulferts
1
干得好,我的朋友!非常感谢。顺便说一下,我喜欢使用 OpenStruct 对象来处理选项。比哈希表更方便。 - Keith Bennett
我学到了很多东西,所以这是值得的。是的,OpenStruct在大多数情况下都很好并且更易读。虽然这里没有问题,但它们也往往非常慢。 - ulferts

0

在布尔标志后直接放置n(例如-vn)会将其设置为false。此示例打开然后关闭详细布尔标志,然后打印数字1:

rexe -mn -v -vn 1


Ruby中没有布尔类是可悲的和反用户友好的。使用“-vn 1”是神秘的、hacky的,根本不直观。 - hipertracker
在Ruby中,值具有类而不是变量,并且事实证明只有很少的常见方法可以应用于“true”和“false”。 - karatedog
true的类是TrueClass,false的类是FalseClass。最近我遇到了这样一种情况,我希望这两个类都是一个名为Boolean的公共类的子类。此外,我想知道为什么true和false不能是Boolean类的实例。我不知道有什么好的方法来测试一个值是否为布尔值,除了像[true, false].include?(value)(value == true || value == false)这样的方法。 - Keith Bennett
@hipertracker 我不知道你是否明白...Ruby确实有true和false;这篇文章的问题是如何在Posix命令行上指定布尔值。必须使用某种字符串来完成这个任务。只要opts.on的参数正确,Ruby的OptionParser类就可以将该字符串转换为true或false。 - Keith Bennett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接