Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get only long options work in OptionParser in Ruby?

I have such a simple code in Ruby (test.rb):

#! /usr/bin/env ruby

require 'optparse'

OptionParser.new do |option|
  option.on("--sort", "Sort data") do 
    puts "--sort passed"
  end
end.parse!

then I run it: ./test.rb -s and got:

--sort passed

Have I missed something?

I want the only --sort (long) option works, not the short one.

How do I get it?

like image 844
blackst0ne Avatar asked Dec 18 '13 09:12

blackst0ne


3 Answers

I found the code which causes this behavior, in optparse.rb, lines 1378-1380:

# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)

If you don't like that behavior, it seems your best option is to create a copy of optparse.rb within your project, remove the offending rescue InvalidOption clause within the copy, and load that rather than the standard library's version.

like image 79
Alex D Avatar answered Nov 18 '22 09:11

Alex D


It is interesting behaviour that if you define the similar long option that begins with the same letter, in the example is s. It does not allow to use -s key with exception OptionParser::AmbiguousOption, but it seems that there no a way to disable the short option for OptionParser without invading into its code:

#! /usr/bin/env ruby

require 'optparse'

OptionParser.new do |option|
  option.on("--sport", "Sport data") do
    puts "--sport passed"
  end
  option.on("--sort", "Sort data") do
    puts "--sort passed"
  end
end.parse!

This is the expanded version of on method:

OptionParser.new do |option|
  opts = [ "--sort", "Sort data" ]
  sw = option.make_switch(opts) 
  block = proc { puts "--sort passed" }
  sw[0].instance_variable_set :@block, block
  option.top.append *sw
  p sw
  # => [#<OptionParser::Switch::NoArgument:0x806c770 @pattern=/.*/m, @conv=#<Proc:0x806dd8c@/home/malo/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/optparse.rb:1617>, @short=[], @long=["--sort"], @arg=nil, @desc=["Sort data"], @block=#<Proc:0x806c70c@./1.rb:8>>, [], ["sort"], nil, []]
end.parse!
# => --sort passed when  ./1.rb --sort and ./1.rb -s

It is interesting that @short variable is empty but the app reacts on -s key.

I would prefer to use micro-optparse gem. Use it as follows:

Gemfile

gem 'micro-optparse', :git => 'https://github.com/3aHyga/micro-optparse.git', :branch => 'no-short' # for now it is available only from git repo

ruby_script.rb

require 'micro-optparse'

options = Parser.new do |p|
   p.banner = "This is a fancy script, for usage see below"
   p.option :sport, "sport", :default => "Sport", :short => "p"
   p.option :sort, "sort", :default => "Sort", :short => false
end.process!

p options

Simulation:

$ bundle exec ./1.rb --sort 111
{:sport=>"Sport", :sort=>"111"}

$ bundle exec ./1.rb -s 111
ambiguous option: -s

$ bundle exec ./1.rb -p 111
{:sport=>"111", :sort=>"Sort"}
like image 2
Малъ Скрылевъ Avatar answered Nov 18 '22 08:11

Малъ Скрылевъ


You can reopen OptionParser::OptionMap to disable completions with:

class OptionParser::OptionMap
  def complete(key, icase = false, pat = nil)
    # disable completions
    nil
  end
end

This will disable the predefined behavior of searching for stuff to complete.

like image 2
Sam Saffron Avatar answered Nov 18 '22 09:11

Sam Saffron