2

I've written a working script that has several command line options. I want to make a few of these options required options. My research got me to the following code. You'll see at the end of the script I'm checking separately that the options have been supplied.

In python, the argparse module has an argument "required=True" that would automatically exit the program if the given argument was supplied. I couldn't find anything like that in the ruby module. Is there a different, more advanced argument parsing module? Is there a more concise way to write this code?

options = {}

optparse = OptionParser.new do |opts|
  opts.banner = "\nUsage: How to use the code"
  opts.on('--debug',
      "Change log level to debug. Default is INFO") do |l|
    options[:debug] = l
  end

  options[:logfile] = "stage_refresh.out"
  opts.on('-l', '--logfile LOGFILE', "Logfile to log results. Default is stage_refresh.out") do |l|
    options[:source] = l
  end

  options[:source] = "localhost"
  opts.on('-s', '--source SOURCE_HOST', "Source host for dump. Default is localhost") do |s|
    options[:source] = s
  end

  opts.on('-t', '--target TARGET', "Target host to refresh. Must specify.") do |t|
    options[:target] = t
  end
end

optparse.parse!

unless options[:source_pass]
  puts "Must have --source_pass PASSWORD"
end

unless options[:target]
  puts "Must have --target TARGET_SERVER"
end

if options[:debug]
  logger.level = Logger::DEBUG
else
  logger.level = Logger::INFO
end

puts options[:source_pass]
puts options[:target]

.................

sschuberth
  • 28,386
  • 6
  • 101
  • 146
numb3rs1x
  • 4,673
  • 5
  • 31
  • 44
  • See also http://stackoverflow.com/questions/15487628/ruby-optparse-limitations – Mark Thomas Aug 18 '14 at 22:15
  • Possible duplicate of [How do you specify a required switch (not argument) with Ruby OptionParser?](http://stackoverflow.com/questions/1541294/how-do-you-specify-a-required-switch-not-argument-with-ruby-optionparser) – sschuberth Dec 15 '15 at 16:43

4 Answers4

0

The trollop gem might be of interest to you. It has long/short options, default values, required flags, etc. Use of it is not unlike what you have right now.

Nick Veys
  • 23,458
  • 4
  • 47
  • 64
0

OptionParser is not very elegant.

There is also GetOptLang in ruby stdlib but it is also not great.

slop and trollop exist, also thor...

It's a bit annoying that ruby itself can not agree on a very elegant solution to this problem.

I myself actually end up parsing ARGV directly (though passed into a method that will handle the commandline parsing for me).

Most of the time I won't need something like:

--set_base_dir /tmp

So it is ok. But more advanced commandline scripts will need that, so I usually end up using OptionParser but inside of it, I call methods in the main app that handle the stuff. I only use OptionParser for the --set_foo extra stuff I get.

shevy
  • 920
  • 1
  • 12
  • 18
0

You can use Thor which allow you to write CLI tools in simple and easy way.

Hauleth
  • 22,873
  • 4
  • 61
  • 112
0

I agree that OptionParser is a bit verbose. I would recommend Slop. Of all the options listed in the Ruby Toolbox (where they are sorted by popularity) it seems to be the closest to the interface you are looking for. It was written specifically to be more concise than OptionParser.

Usage example (from the readme):

opts = Slop.parse do
  banner 'Usage: foo.rb [options]'

  on 'name=', 'Your name'
  on 'p', 'password', 'An optional password', argument: :optional
  on 'v', 'verbose', 'Enable verbose mode'
end

# if ARGV is `--name Lee -v`
opts.verbose?  #=> true
opts.password? #=> false
opts[:name]    #=> 'lee'
opts.to_hash   #=> {:name=>"Lee", :password=>nil, :verbose=>true}
Mark Thomas
  • 37,131
  • 11
  • 74
  • 101