# frozen_string_literal: true
# optparse.rb - command-line option analysis with the OptionParser class.
# Documentation:: Nobu Nakada and Gavin Sinclair.
# See OptionParser for documentation.
# == Developer Documentation (not for RDoc output)
# - OptionParser:: front end
# - OptionParser::Switch:: each switches
# - OptionParser::List:: options list
# - OptionParser::ParseError:: errors on parsing
# - OptionParser::AmbiguousOption
# - OptionParser::NeedlessArgument
# - OptionParser::MissingArgument
# - OptionParser::InvalidOption
# - OptionParser::InvalidArgument
# - OptionParser::AmbiguousArgument
# === Object relationship diagram
# | OptionParser |<>-----+
# +--------------+ | +--------+
# on_head -------->+---------------+ / +--------+
# accept/reject -->| List |<|>-
# on ------------->+---------------+ `-| argument |
# +---------------+ |==========|
# on_tail -------->| | |pattern |
# +---------------+ |----------|
# OptionParser.accept ->| DefaultList | |converter |
# reject |(shared between| +----------+
# === New to \OptionParser?
# See the {Tutorial}[optparse/tutorial.rdoc].
# OptionParser is a class for command-line option analysis. It is much more
# advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented
# 1. The argument specification and the code to handle it are written in the
# 2. It can output an option summary; you don't need to maintain this string
# 3. Optional and mandatory arguments are specified very gracefully.
# 4. Arguments can be automatically converted to a specified class.
# 5. Arguments can be restricted to a certain set.
# All of these features are demonstrated in the examples below. See
# #make_switch for full documentation.
# OptionParser.new do |parser|
# parser.banner = "Usage: example.rb [options]"
# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
# OptionParser can be used to automatically generate help for the commands you
# Options = Struct.new(:name)
# def self.parse(options)
# args = Options.new("world")
# opt_parser = OptionParser.new do |parser|
# parser.banner = "Usage: example.rb [options]"
# parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
# parser.on("-h", "--help", "Prints this help") do
# opt_parser.parse!(options)
# options = Parser.parse %w[--help]
# # Usage: example.rb [options]
# # -n, --name=NAME Name to say hello to
# # -h, --help Prints this help
# For options that require an argument, option specification strings may include an
# option name in all caps. If an option is used without the required argument,
# an exception will be raised.
# OptionParser.new do |parser|
# parser.on("-r", "--require LIBRARY",
# "Require the LIBRARY before executing your script") do |lib|
# puts "You required #{lib}!"
# $ ruby optparse-test.rb -r
# optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument)
# $ ruby optparse-test.rb -r my-library
# You required my-library!
# OptionParser supports the ability to coerce command line arguments
# OptionParser comes with a few ready-to-use kinds of type
# - Date -- Anything accepted by +Date.parse+
# - DateTime -- Anything accepted by +DateTime.parse+
# - Time -- Anything accepted by +Time.httpdate+ or +Time.parse+
# - URI -- Anything accepted by +URI.parse+
# - Shellwords -- Anything accepted by +Shellwords.shellwords+
# - String -- Any non-empty string
# - Integer -- Any integer. Will convert octal. (e.g. 124, -3, 040)
# - Float -- Any float. (e.g. 10, 3.14, -100E+13)
# - Numeric -- Any integer, float, or rational (1, 3.4, 1/3)
# - DecimalInteger -- Like +Integer+, but no octal format.
# - OctalInteger -- Like +Integer+, but no decimal format.
# - DecimalNumeric -- Decimal integer or float.
# - TrueClass -- Accepts '+, yes, true, -, no, false' and
# - FalseClass -- Same as +TrueClass+, but defaults to +false+
# - Array -- Strings separated by ',' (e.g. 1,2,3)
# - Regexp -- Regular expressions. Also includes options.
# We can also add our own coercions, which we will cover below.
# ==== Using Built-in Conversions
# As an example, the built-in +Time+ conversion is used. The other built-in
# conversions behave in the same way.
# OptionParser will attempt to parse the argument
# as a +Time+. If it succeeds, that time will be passed to the
# handler block. Otherwise, an exception will be raised.
# require 'optparse/time'
# OptionParser.new do |parser|
# parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
# $ ruby optparse-test.rb -t nonsense
# ... invalid argument: -t nonsense (OptionParser::InvalidArgument)
# $ ruby optparse-test.rb -t 10-11-12
# 2010-11-12 00:00:00 -0500
# $ ruby optparse-test.rb -t 9:30
# 2014-08-13 09:30:00 -0400
# ==== Creating Custom Conversions
# The +accept+ method on OptionParser may be used to create converters.
# It specifies which conversion block to call whenever a class is specified.
# The example below uses it to fetch a +User+ object before the +on+ handler receives it.
# User = Struct.new(:id, :name)
# not_found = ->{ raise "No User Found for id #{id}" }
# User.new(2, "Gandalf") ].find(not_found) do |u|
# op.accept(User) do |user_id|
# op.on("--user ID", User) do |user|
# $ ruby optparse-test.rb --user 1
# #<struct User id=1, name="Sam">
# $ ruby optparse-test.rb --user 2
# #<struct User id=2, name="Gandalf">
# $ ruby optparse-test.rb --user 3
# optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)
# === Store options to a Hash
# The +into+ option of +order+, +parse+ and so on methods stores command line options into a Hash.
# OptionParser.new do |parser|
# parser.on('-b NUM', Integer)
# parser.on('-v', '--verbose')
# end.parse!(into: options)
# $ ruby optparse-test.rb -a
# $ ruby optparse-test.rb -a -v
# {:a=>true, :verbose=>true}
# $ ruby optparse-test.rb -a -b 100
# The following example is a complete Ruby program. You can run it and see the
# effect of specifying various options. This is probably the best way to learn
# the features of +optparse+.
# require 'optparse/time'
# CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
# CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
# attr_accessor :library, :inplace, :encoding, :transfer_type,
# :verbose, :extension, :delay, :time, :record_separator,
# self.transfer_type = :auto
# def define_options(parser)
# parser.banner = "Usage: example.rb [options]"
# parser.separator "Specific options:"
# # add additional options
# perform_inplace_option(parser)
# delay_execution_option(parser)
# execute_at_time_option(parser)
# specify_record_separator_option(parser)
# list_example_option(parser)
# specify_encoding_option(parser)
# optional_option_argument_with_keyword_completion_option(parser)
# boolean_verbose_option(parser)
# parser.separator "Common options:"
# # No argument, shows at tail. This will print an options summary.
# parser.on_tail("-h", "--help", "Show this message") do
# # Another typical switch to print the version.
# parser.on_tail("--version", "Show version") do
# def perform_inplace_option(parser)
# # Specifies an optional option argument
# parser.on("-i", "--inplace [EXTENSION]",
# "Edit ARGV files in place",
# "(make backup if EXTENSION supplied)") do |ext|
# self.extension = ext || ''
# self.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot.
# def delay_execution_option(parser)
# # Cast 'delay' argument to a Float.
# parser.on("--delay N", Float, "Delay N seconds before executing") do |n|
# def execute_at_time_option(parser)
# # Cast 'time' argument to a Time object.
# parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
# def specify_record_separator_option(parser)
# # Cast to octal integer.
# parser.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
# "Specify record separator (default \\0)") do |rs|
# self.record_separator = rs
# def list_example_option(parser)
# parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
# def specify_encoding_option(parser)
# # Keyword completion. We are specifying a specific set of arguments (CODES
# # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
# # the shortest unambiguous text.
# code_list = (CODE_ALIASES.keys + CODES).join(', ')
# parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
# "(#{code_list})") do |encoding|
# self.encoding = encoding
# def optional_option_argument_with_keyword_completion_option(parser)
# # Optional '--type' option argument with keyword completion.
# parser.on("--type [TYPE]", [:text, :binary, :auto],
# "Select transfer type (text, binary, auto)") do |t|
# def boolean_verbose_option(parser)
# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
# # Return a structure describing the options.
# # The options specified on the command line will be collected in
# @options = ScriptOptions.new
# @args = OptionParser.new do |parser|
# @options.define_options(parser)
# attr_reader :parser, :options
# end # class OptparseExample
# example = OptparseExample.new
# options = example.parse(ARGV)
# pp options # example.options
# For modern shells (e.g. bash, zsh, etc.), you can use shell
# completion for command line options.
# === Further documentation
# The above examples, along with the accompanying
# {Tutorial}[optparse/tutorial.rdoc],
# should be enough to learn how to use this class.
# If you have any questions, file a ticket at http://bugs.ruby-lang.org.
OptionParser::Version = "0.3.1"
NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze
OptionalArgument = [OPTIONAL_ARGUMENT = :OPTIONAL, false].freeze
# Keyword completion module. This allows partial arguments to be specified
# and resolved against a list of acceptable values.
def self.regexp(key, icase)
Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase)
def self.candidate(key, icase = false, pat = nil, &block)
pat ||= Completion.regexp(key, icase)
kn = defined?(k.id2name) ? k.id2name : k
def candidate(key, icase = false, pat = nil)
Completion.candidate(key, icase, pat, &method(:each))
def complete(key, icase = false, pat = nil)
candidates = candidate(key, icase, pat, &method(:each)).sort_by {|k, v, kn| kn.size}
canon, sw, * = candidates[0]
elsif candidates.size > 1
canon, sw, cn = candidates.shift
candidates.each do |k, v, kn|
if String === cn and String === kn
block_given? or return key, *sw
def convert(opt = nil, val = nil, *)
# Map from option/keyword string to object with completion.