6

I've just started using OptionParser for Ruby and I wanted to use flags that would use more than just one argument.

For instance, I would like to be able to run:

script --move src dst

Note how src and dst are not separated using a coma.

My initial idea was:

opts.on("-m src dst", "--move src dst ", "move file from SRCto DST") do |src|
    # do something
end

But this is not working. I assume that this is not the right approach. But how could this be done?

2
  • There is very good example in documentation ruby-doc.org/stdlib-2.2.4/libdoc/optparse/rdoc/… under heading Generating Help, which shows how to accept a parameter called name. Same can be extended for your case of src and dst. You need to repeat what example shows for name - once for src and once for dst as two separate opts.on statements Commented Dec 22, 2015 at 13:28
  • 3
    OP is specifically asking how to accept two consecutive values for the same option. Commented Dec 22, 2015 at 16:37

2 Answers 2

3

The example under the "Complete Example" section of the OptionParser details how a list of items can be accepted.

Here is a sample program based on that example. The third parameter Array in opts.on indicates that input src, dst should be used to create an array. To run this sample, you need to do gem install trollop.

# test.rb
require 'optparse'

options = {}
OptionParser.new do |opt|
  opt.on("-m src, dst", "--move src, dst", Array, "Move from src to dst") do |list|
    options[:src] = list[0]
    options[:dst] = list[1]
  end
end.parse!

puts options # It's a hash of parsed options

Sample run:

> ruby test.rb -m from,to
{:src=>"src", :dst=>"dst"}

>ruby test.rb -h
Usage: test [options]
    -m, --move src, dst              Move from src to dst

The above script forces one to separate the options using comma.


As indicated by "Really Cheap Command-Line Option Parsing in Ruby", there seems to be a gem, trollop, that can be quite easy to use for command-line parsing.

A sample program based on Trollop is given below, which allows usage of spaces for specifying options with multiple values

# test.rb

require "trollop"

opts = Trollop::options do
  banner "Command line parsing using Trollop"
  opt :move, "--move src dst', Move from src to dst", :short => "-m", :long => "--move", :type => :strings
end
# An array of option values
p opts.move

Sample run:

>ruby test.rb -m hello world
["hello", "world"]

>ruby test.rb -h
Command line parsing using Trollop
  -m, --move=<s+>    '--move src dst', Move from src to dst
  -h, --help         Show this message

There is a subtle difference between the help output between the two approaches. Trollop produces help text where --move=<s+> does not indicate clearly that it needs accepts two values, so I had to repeat the command syntax description.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much, as of today I am using this format. Do you reckon that there is away to get rid of the comma? So, instead of --move src, dst... you could just write --move src dst... but cheers anyway :)
I am trying to figure that out, if I discover something I will update the answer. I think OptionParser#accept method will play some role but documentation is bit weak in explaining the parameters of accept method
2

OptionParser doesn't support that; It could be patched to do so, but I'm not sure it's worth the trouble.

Consider this code:

require 'optparse'

options = {}
OptionParser.new do |opt|
  opt.on('-m', '--move') { |o| options[:move] = o }
end.parse!

from_name, to_name = ARGV

puts "Should move: #{ options.key?(:move) }"
puts "From: #{ from_name }"
puts "To: #{ to_name }"

Saving it and running it with various combinations of the parameters returns:

> ruby test.rb --move from to
Should move: true
From: from
To: to

> ruby test.rb  from to
Should move: false
From:
To:

If the code is supposed to move files by default then don't bother with the --move flag, simply use:

test.rb from to

and consider removing the OptionParser block entirely.

If the code is supposed to normally copy with the option to move, then --move becomes more sensible to act as a flag that moving is desired.

ruby test.rb --move from to

I'd have code that tests for options[:move] and run the code to move instead of copy at that point.

In either case, the filenames shouldn't be tied to the flag, they should be supplied separately and retrieved from ARGV after OptionParser has finished parsing the command-line and removing entries it's handled.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.