Search code examples
rubybooleanflagsoptparseoptionparser

Ruby OptionParser Short Code for Boolean Option?


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?


Solution

  • 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)