Thursday, May 14, 2020

OptionParser Command-Line Options the Ruby Way

Ruby comes equipped with a powerful and flexible tool to parse command-line options, OptionParser. Once you learn how to use this, youll never go back to looking through ARGV manually. OptionParser has a number of features that make it quite appealing to Ruby programmers. If youve ever parsed options by hand in Ruby or C, or with the getoptlong C function, youll see how welcome some of these changes are. OptionParser is DRY. You only have to write the command-line switch, its arguments, the code to run when its encountered, and the command-line switch description once in your script. OptionParser will automatically generate help screens for you from this description, as well as infer everything about the argument from its description. For example, it will know the --file [FILE] option is optional and takes a single argument. Also, it will know that --[-no]-verbose is really two options and will accept both forms.OptionParser will automatically convert options to a specific class. If the option takes an integer, it can convert any string passed on the command-line to an integer. This cuts down on some of the tedium involved in parsing command-line options.Everything is very contained. All of the options are in the same place, and the effect of the option is right along-side the definition for the option. If options have to be added, changed or someone simply wants to see what they do, there is only one place to look. Once the command-line is parsed, a single Hash or OpenStruct will hold the results. Enough Already, Show Me Some Code So heres a simple example of how to use OptionParser. It doesnt use any of the advanced features, just the basics. There are three options, and one of them takes a parameter. All of the options are mandatory. There are the -v/--verbose and -q/--quick options, as well as the -l/--logfile FILE option. Additionally, the script takes a list of files independent of the options. #!/usr/bin/env ruby # A script that will pretend to resize a number of images require optparse # This hash will hold all of the options # parsed from the command-line by # OptionParser. options {} optparse OptionParser.new do|opts|   Ã‚  # Set a banner, displayed at the top   Ã‚  # of the help screen.   Ã‚  opts.banner Usage: optparse1.rb [options] file1 file2 ...   Ã‚  # Define the options, and what they do   Ã‚  options[:verbose] false   Ã‚  opts.on( -v, --verbose, Output more information ) do   Ã‚  Ã‚  Ã‚  options[:verbose] true   Ã‚  end   Ã‚  options[:quick] false   Ã‚  opts.on( -q, --quick, Perform the task quickly ) do   Ã‚  Ã‚  Ã‚  options[:quick] true   Ã‚  end   Ã‚  options[:logfile] nil   Ã‚  opts.on( -l, --logfile FILE, Write log to FILE ) do|file|   Ã‚  Ã‚  Ã‚  options[:logfile] file   Ã‚  end   Ã‚  # This displays the help screen, all programs are   Ã‚  # assumed to have this option.   Ã‚  opts.on( -h, --help, Displa y this screen ) do   Ã‚  Ã‚  Ã‚  puts opts   Ã‚  Ã‚  Ã‚  exit   Ã‚  end end # Parse the command-line. Remember there are two forms # of the parse method. The parse method simply parses # ARGV, while the parse! method parses ARGV and removes # any options found there, as well as any parameters for # the options. Whats left is the list of files to resize. optparse.parse! puts Being verbose if options[:verbose] puts Being quick if options[:quick] puts Logging to file #{options[:logfile]} if options[:logfile] ARGV.each do|f|   Ã‚  puts Resizing image #{f}...   Ã‚  sleep 0.5 end Examining the Code To start off with, the optparse library is required. Remember, this isnt a gem. It comes with Ruby, so theres no need to install a gem or require rubygems before optparse. There are two interesting objects in this script. The first is options, declared at the top-most scope. Its a simple empty hash. When options are defined, they write their default values to this hash. For example, the default behavior is for this script to not be verbose, so options[:verbose] is set to false. When options are encountered on the command-line, theyll change the values in options to reflect their effect. For example, when -v/--verbose is encountered, it will assign true to options[:verbose]. The second interesting object is optparse. This is the OptionParser object itself. When you construct this object, you pass it a block. This block is run during construction and will build a list of options in internal data structures, and get ready to parse everything. Its in this block that all the magic happens. You define all the options here. Defining Options Each option follows the same pattern. You first write the default value into the hash. This will happen as soon as the OptionParser is constructed. Next, you call the on method, which defines the option itself. There are several forms of this method, but only one is used here. The other forms allow you to define automatic type conversions and sets of values an option is restricted to. The three arguments used here are the short form, long form, and description of the option. The on method will infer a number of things from the long form. One thing is will infer is the presence of any parameters. If there are any parameters present on the option, it will pass them as parameters to the block. If the option is encountered on the command-line, the block passed to the on method is run. Here, the blocks dont do much, they just set values in the options hash. More could be done, such as checking that a file referred to exists, etc. If there are any errors, exceptions can be thrown from these blocks. Finally, the command-line is parsed. This happens by calling the parse! method on an OptionParser object. There are actually two forms of this method, parse and parse!. As the version with the exclamation point implies, it is destructive. Not only does it parse the command-line, but it will remove any options found from ARGV. This is an important thing, it will leave only the list of files supplied after the options in ARGV.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.