Ruby OptionParser Short Code for Boolean Option?

3.3k Views Asked by At

I am using Ruby's OptionParser (require 'optparse') processing a "verbose" option that can be either true or false. It is in the code like this:

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

I support specifying options in an environment variable (I prepend its content to ARGV), so it is possible to set verbose mode on in that environment variable, and override it on the command line with --no-verbose. However, I cannot find a way to override it with a short option. I've tried these without success:

-v-
-v0
-v=0

I found the source code at https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb but could not figure out the answer from that.

How can I do this?

2

There are 2 best solutions below

4
ulferts On BEST ANSWER

Based on https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1936-L1949 and given how a -v flag works for most commands the following should work:

  • -v - similar to what you tried but with a space
  • -v no
  • -v false

Edit

After the comment I looked further into the problem and tried it out myself. This is what I ended up with:

# 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

The important changes to the code by OP are:

  • Adding the [FLAG] 'argument'. This will enable an argument for the option like -v no, -v yes, -v false, -v true, -v n, -v y, -v + (I did not get the -v - to work).
  • Adding the explicit argument coercion TrueClass. Without it, the argument will be interpreted as a string (e.g. 'false').
  • Turning the argument optional by wrapping the argument definition in [ ] and then ensuring that true is considered the default via v.nil? ? true : v. Without the braces, the argument parser does not accept -v (without an argument)
4
Keith Bennett On

Putting n directly after the boolean flag (e.g. -vn) sets it to false. This example turns on and then off the verbose boolean flag and then prints the number 1:

rexe -mn -v -vn 1