summaryrefslogtreecommitdiff
path: root/lib/optparse.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/optparse.rb')
-rw-r--r--lib/optparse.rb357
1 files changed, 227 insertions, 130 deletions
diff --git a/lib/optparse.rb b/lib/optparse.rb
index c1df9586c8..1751aa0a5f 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -1,15 +1,15 @@
#
# optparse.rb - command-line option analysis with the OptionParser class.
-#
+#
# Author:: Nobu Nakada
# Documentation:: Nobu Nakada and Gavin Sinclair.
#
-# See OptionParser for documentation.
+# See OptionParser for documentation.
#
-# == Developer Documentation (not for RDoc output)
-#
+# == Developer Documentation (not for RDoc output)
+#
# === Class tree
#
# - OptionParser:: front end
@@ -51,7 +51,7 @@
# solution.
#
# === Features
-#
+#
# 1. The argument specification and the code to handle it are written in the
# same place.
# 2. It can output an option summary; you don't need to maintain this string
@@ -88,12 +88,12 @@
# require 'optparse/time'
# require 'ostruct'
# require 'pp'
-#
+#
# class OptparseExample
-#
+#
# CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
# CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
-#
+#
# #
# # Return a structure describing the options.
# #
@@ -106,19 +106,19 @@
# options.encoding = "utf8"
# options.transfer_type = :auto
# options.verbose = false
-#
+#
# opts = OptionParser.new do |opts|
# opts.banner = "Usage: example.rb [options]"
-#
+#
# opts.separator ""
# opts.separator "Specific options:"
-#
+#
# # Mandatory argument.
# opts.on("-r", "--require LIBRARY",
# "Require the LIBRARY before executing your script") do |lib|
# options.library << lib
# end
-#
+#
# # Optional argument; multi-line description.
# opts.on("-i", "--inplace [EXTENSION]",
# "Edit ARGV files in place",
@@ -127,28 +127,28 @@
# options.extension = ext || ''
# options.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot.
# end
-#
+#
# # Cast 'delay' argument to a Float.
# opts.on("--delay N", Float, "Delay N seconds before executing") do |n|
# options.delay = n
# end
-#
+#
# # Cast 'time' argument to a Time object.
# opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
# options.time = time
# end
-#
+#
# # Cast to octal integer.
# opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
# "Specify record separator (default \\0)") do |rs|
# options.record_separator = rs
# end
-#
+#
# # List of arguments.
# opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
# options.list = list
# end
-#
+#
# # 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.
@@ -157,41 +157,41 @@
# " (#{code_list})") do |encoding|
# options.encoding = encoding
# end
-#
+#
# # Optional argument with keyword completion.
# opts.on("--type [TYPE]", [:text, :binary, :auto],
# "Select transfer type (text, binary, auto)") do |t|
# options.transfer_type = t
# end
-#
+#
# # Boolean switch.
# opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
# options.verbose = v
# end
-#
+#
# opts.separator ""
# opts.separator "Common options:"
-#
+#
# # No argument, shows at tail. This will print an options summary.
# # Try it and see!
# opts.on_tail("-h", "--help", "Show this message") do
# puts opts
# exit
# end
-#
+#
# # Another typical switch to print the version.
# opts.on_tail("--version", "Show version") do
# puts OptionParser::Version.join('.')
# exit
# end
# end
-#
+#
# opts.parse!(args)
# options
# end # parse()
-#
+#
# end # class OptparseExample
-#
+#
# options = OptparseExample.parse(ARGV)
# pp options
#
@@ -203,7 +203,7 @@
#
class OptionParser
# :stopdoc:
- RCSID = %w$Id: optparse.rb,v 1.40.2.12 2006/08/04 22:00:21 drbrain Exp $[1..-1].each {|s| s.freeze}.freeze
+ RCSID = %w$Id$[1..-1].each {|s| s.freeze}.freeze
Version = (RCSID[1].split('.').collect {|s| s.to_i}.extend(Comparable).freeze if RCSID[1])
LastModified = (Time.gm(*RCSID[2, 2].join('-').scan(/\d+/).collect {|s| s.to_i}) if RCSID[2])
Release = RCSID[2]
@@ -221,7 +221,7 @@ class OptionParser
def complete(key, icase = false, pat = nil)
pat ||= Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'),
icase)
- canon, sw, k, v, cn = nil
+ canon, sw, cn = nil
candidates = []
each do |k, *v|
(if Regexp === k
@@ -276,7 +276,7 @@ class OptionParser
# Individual switch class. Not important to the user.
#
# Defined within Switch are several Switch-derived classes: NoArgument,
- # RequiredArgument, etc.
+ # RequiredArgument, etc.
#
class Switch
attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
@@ -301,7 +301,8 @@ class OptionParser
end
def self.incompatible_argument_styles(arg, t)
- raise ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}"
+ raise(ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}",
+ ParseError.filter_backtrace(caller(2)))
end
def self.pattern
@@ -321,10 +322,10 @@ class OptionParser
# argument pattern. Yields when the pattern doesn't match substring.
#
def parse_arg(arg)
- pattern or return nil, arg
+ pattern or return nil, [arg]
unless m = pattern.match(arg)
yield(InvalidArgument, arg)
- return arg, nil
+ return arg, []
end
if String === m
m = [s = m]
@@ -345,17 +346,13 @@ class OptionParser
# conversion. Yields at semi-error condition instead of raising an
# exception.
#
- def conv_arg(arg, val = nil)
- if block
- if conv
- val = conv.call(*val)
- else
- val = *val
- end
- return arg, block, val
+ def conv_arg(arg, val = [])
+ if conv
+ val = conv.call(*val)
else
- return arg, nil
+ val = proc {|v| v}.call(*val)
end
+ return arg, block, val
end
private :conv_arg
@@ -372,7 +369,7 @@ class OptionParser
# +indent+:: Prefix string indents all summarized lines.
#
def summarize(sdone = [], ldone = [], width = 1, max = width - 1, indent = "")
- sopts, lopts, s = [], [], nil
+ sopts, lopts = [], [], nil
@short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short
@long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long
return if sopts.empty? and lopts.empty? # completely hidden
@@ -383,18 +380,24 @@ class OptionParser
while s = lopts.shift
l = left[-1].length + s.length
l += arg.length if left.size == 1 && arg
- l < max or left << ''
+ l < max or sopts.empty? or left << ''
left[-1] << if left[-1].empty? then ' ' * 4 else ', ' end << s
end
- left[0] << arg if arg
- mlen = left.collect {|s| s.length}.max.to_i
+ if arg
+ left[0] << (left[1] ? arg.sub(/\A(\[?)=/, '\1') + ',' : arg)
+ end
+ mlen = left.collect {|ss| ss.length}.max.to_i
while mlen > width and l = left.shift
- mlen = left.collect {|s| s.length}.max.to_i if l.length == mlen
+ mlen = left.collect {|ss| ss.length}.max.to_i if l.length == mlen
+ if l.length < width and (r = right[0]) and !r.empty?
+ l = l.to_s.ljust(width) + ' ' + r
+ right.shift
+ end
yield(indent + l)
end
- while (l = left.shift; r = right.shift; l or r)
+ while begin l = left.shift; r = right.shift; l or r end
l = l.to_s.ljust(width) + ' ' + r if r and !r.empty?
yield(indent + l)
end
@@ -402,6 +405,25 @@ class OptionParser
self
end
+ def add_banner(to) # :nodoc:
+ unless @short or @long
+ s = desc.join
+ to << " [" + s + "]..." unless s.empty?
+ end
+ to
+ end
+
+ def match_nonswitch?(str) # :nodoc:
+ @pattern =~ str unless @short or @long
+ end
+
+ #
+ # Main name of the switch.
+ #
+ def switch_name
+ (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '')
+ end
+
#
# Switch that takes no arguments.
#
@@ -410,7 +432,7 @@ class OptionParser
#
# Raises an exception if any arguments given.
#
- def parse(arg, argv, &error)
+ def parse(arg, argv)
yield(NeedlessArgument, arg) if arg
conv_arg(arg)
end
@@ -436,7 +458,7 @@ class OptionParser
raise MissingArgument if argv.empty?
arg = argv.shift
end
- conv_arg(*parse_arg(arg) {|*exc| raise(*exc)})
+ conv_arg(*parse_arg(arg, &method(:raise)))
end
end
@@ -489,13 +511,13 @@ class OptionParser
class List
# Map from acceptable argument types to pattern and converter pairs.
attr_reader :atype
-
+
# Map from short style option switches to actual switch objects.
attr_reader :short
-
+
# Map from long style option switches to actual switch objects.
attr_reader :long
-
+
# List of all switches and summary string.
attr_reader :list
@@ -512,9 +534,10 @@ class OptionParser
#
# See OptionParser.accept.
#
- def accept(t, pat = /.*/nm, &block)
+ def accept(t, pat = /.*/m, &block)
if pat
- pat.respond_to?(:match) or raise TypeError, "has no `match'"
+ pat.respond_to?(:match) or
+ raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2))
else
pat = t if t.respond_to?(:match)
end
@@ -540,7 +563,6 @@ class OptionParser
# +nlopts+:: Negated long style options list.
#
def update(sw, sopts, lopts, nsw = nil, nlopts = nil)
- o = nil
sopts.each {|o| @short[o] = sw} if sopts
lopts.each {|o| @long[o] = sw} if lopts
nlopts.each {|o| @long[o] = nsw} if nsw and nlopts
@@ -552,7 +574,7 @@ class OptionParser
#
# Inserts +switch+ at the head of the list, and associates short, long
# and negated long options. Arguments are:
- #
+ #
# +switch+:: OptionParser::Switch instance to be inserted.
# +short_opts+:: List of short style options.
# +long_opts+:: List of long style options.
@@ -568,7 +590,7 @@ class OptionParser
#
# Appends +switch+ at the tail of the list, and associates short, long
# and negated long options. Arguments are:
- #
+ #
# +switch+:: OptionParser::Switch instance to be inserted.
# +short_opts+:: List of short style options.
# +long_opts+:: List of long style options.
@@ -588,8 +610,7 @@ class OptionParser
def search(id, key)
if list = __send__(id)
val = list.fetch(key) {return nil}
- return val unless block_given?
- yield(val)
+ block_given? ? yield(val) : val
end
end
@@ -604,20 +625,42 @@ class OptionParser
end
#
+ # Iterates over each option, passing the option to the +block+.
+ #
+ def each_option(&block)
+ list.each(&block)
+ end
+
+ #
# Creates the summary table, passing each line to the +block+ (without
# newline). The arguments +args+ are passed along to the summarize
# method which is called on every option.
#
def summarize(*args, &block)
- list.each do |opt|
+ sum = []
+ list.reverse_each do |opt|
if opt.respond_to?(:summarize) # perhaps OptionParser::Switch
- opt.summarize(*args, &block)
- elsif opt.empty?
- yield("")
+ s = []
+ opt.summarize(*args) {|l| s << l}
+ sum.concat(s.reverse)
+ elsif !opt or opt.empty?
+ sum << ""
+ elsif opt.respond_to?(:each_line)
+ sum.concat([*opt.each_line].reverse)
else
- opt.each(&block)
+ sum.concat([*opt.each].reverse)
+ end
+ end
+ sum.reverse_each(&block)
+ end
+
+ def add_banner(to) # :nodoc:
+ list.each do |opt|
+ if opt.respond_to?(:add_banner)
+ opt.add_banner(to)
end
end
+ to
end
end
@@ -631,9 +674,10 @@ class OptionParser
# Completion for hash key.
#
def match(key)
- return key, *fetch(key) {
+ *values = fetch(key) {
raise AmbiguousArgument, catch(:ambiguous) {return complete(key)}
}
+ return key, *values
end
end
@@ -712,7 +756,7 @@ class OptionParser
# Initializes a new instance and evaluates the optional block in context
# of the instance. Arguments +args+ are passed to #new, see there for
# description of parameters.
- #
+ #
# This method is *deprecated*, its behavior corresponds to the older #new
# method.
#
@@ -757,7 +801,7 @@ class OptionParser
def add_officious # :nodoc:
list = base()
- Officious.each_pair do |opt, block|
+ Officious.each do |opt, block|
list.long[opt] ||= block.call(self)
end
end
@@ -794,7 +838,7 @@ class OptionParser
#
# Directs to reject specified class argument.
#
- # +t+:: Argument class speficier, any object including Class.
+ # +t+:: Argument class specifier, any object including Class.
#
# reject(t)
#
@@ -828,7 +872,11 @@ class OptionParser
# Heading banner preceding summary.
#
def banner
- @banner ||= "Usage: #{program_name} [options]"
+ unless @banner
+ @banner = "Usage: #{program_name} [options]"
+ visit(:add_banner, @banner)
+ end
+ @banner
end
#
@@ -926,7 +974,8 @@ class OptionParser
# +indent+:: Indentation, defaults to @summary_indent.
#
def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
- visit(:summarize, {}, {}, width, max, indent, &(blk || proc {|l| to << l + $/}))
+ blk ||= proc {|l| to << (l.index($/, -1) ? l : l + $/)}
+ visit(:summarize, {}, {}, width, max, indent, &blk)
to
end
@@ -951,17 +1000,14 @@ class OptionParser
#
def notwice(obj, prv, msg)
unless !prv or prv == obj
- begin
- raise ArgumentError, "argument #{msg} given twice: #{obj}"
- rescue
- $@[0, 2] = nil
- raise
- end
+ raise(ArgumentError, "argument #{msg} given twice: #{obj}",
+ ParseError.filter_backtrace(caller(2)))
end
obj
end
private :notwice
+ SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a}
#
# Creates an OptionParser::Switch from the parameters. The parsed argument
# value is passed to the given block, where it can be processed.
@@ -1001,13 +1047,13 @@ class OptionParser
# "-x[OPTIONAL]"
# "-x"
# There is also a special form which matches character range (not full
- # set of regural expression):
+ # set of regular expression):
# "-[a-z]MANDATORY"
- # "-[a-z][OPTIONAL]"
+ # "-[a-z][OPTIONAL]"
# "-[a-z]"
#
# [Argument style and description:]
- # Instead of specifying mandatory or optional orguments directly in the
+ # Instead of specifying mandatory or optional arguments directly in the
# switch parameter, this separate parameter can be used.
# "=MANDATORY"
# "=[OPTIONAL]"
@@ -1015,18 +1061,17 @@ class OptionParser
# [Description:]
# Description string for the option.
# "Run verbosely"
- #
+ #
# [Handler:]
# Handler for the parsed argument value. Either give a block or pass a
# Proc or Method as an argument.
#
- def make_switch(*opts, &block)
+ def make_switch(opts, block = nil)
short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
ldesc, sdesc, desc, arg = [], [], []
default_style = Switch::NoArgument
default_pattern = nil
klass = nil
- o = nil
n, q, a = nil
opts.each do |o|
@@ -1041,9 +1086,13 @@ class OptionParser
end
# directly specified pattern(any object possible to match)
- if !(String === o) and o.respond_to?(:match)
+ if (!(String === o || Symbol === o)) and o.respond_to?(:match)
pattern = notwice(o, pattern, 'pattern')
- conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
+ if pattern.respond_to?(:convert)
+ conv = pattern.method(:convert).to_proc
+ else
+ conv = SPLAT_PROC
+ end
next
end
@@ -1056,13 +1105,13 @@ class OptionParser
when CompletingHash
when nil
pattern = CompletingHash.new
- conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
+ conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert)
else
raise ArgumentError, "argument pattern given twice"
end
- o.each {|(o, *v)| pattern[o] = v.fetch(0) {o}}
+ o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
when Module
- raise ArgumentError, "unsupported argument type: #{o}"
+ raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
when *ArgumentStyle.keys
style = notwice(ArgumentStyle[o], style, 'style')
when /^--no-([^\[\]=\s]*)(.+)?/
@@ -1123,20 +1172,26 @@ class OptionParser
end
default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
- s = if short.empty? and long.empty?
- raise ArgumentError, "no switch given" if style or pattern or block
- desc
- else
- (style || default_style).new(pattern || default_pattern,
+ if !(short.empty? and long.empty?)
+ s = (style || default_style).new(pattern || default_pattern,
conv, sdesc, ldesc, arg, desc, block)
- end
+ elsif !block
+ if style or pattern
+ raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
+ end
+ s = desc
+ else
+ short << pattern
+ s = (style || default_style).new(pattern,
+ conv, nil, nil, arg, desc, block)
+ end
return s, short, long,
(not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
nolong
end
def define(*opts, &block)
- top.append(*(sw = make_switch(*opts, &block)))
+ top.append(*(sw = make_switch(opts, block)))
sw[0]
end
@@ -1151,7 +1206,7 @@ class OptionParser
alias def_option define
def define_head(*opts, &block)
- top.prepend(*(sw = make_switch(*opts, &block)))
+ top.prepend(*(sw = make_switch(opts, block)))
sw[0]
end
@@ -1165,7 +1220,7 @@ class OptionParser
alias def_head_option define_head
def define_tail(*opts, &block)
- base.append(*(sw = make_switch(*opts, &block)))
+ base.append(*(sw = make_switch(opts, block)))
sw[0]
end
@@ -1200,13 +1255,17 @@ class OptionParser
# Same as #order, but removes switches destructively.
#
def order!(argv = default_argv, &nonopt)
- opt, arg, sw, val, rest = nil
- nonopt ||= proc {|arg| throw :terminate, arg}
+ parse_in_order(argv, &nonopt)
+ end
+
+ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
+ opt, arg, val, rest = nil
+ nonopt ||= proc {|a| throw :terminate, a}
argv.unshift(arg) if arg = catch(:terminate) {
while arg = argv.shift
case arg
# long option
- when /\A--([^=]*)(?:=(.*))?/nm
+ when /\A--([^=]*)(?:=(.*))?/m
opt, rest = $1, $2
begin
sw, = complete(:long, opt, true)
@@ -1214,17 +1273,19 @@ class OptionParser
raise $!.set_option(arg, true)
end
begin
- opt, sw, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
- sw.call(val) if sw
+ opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
+ val = cb.call(val) if cb
+ setter.call(sw.switch_name, val) if setter
rescue ParseError
raise $!.set_option(arg, rest)
end
# short option
- when /\A-(.)((=).*|.+)?/nm
+ when /\A-(.)((=).*|.+)?/m
opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
begin
- unless sw = search(:short, opt)
+ sw, = search(:short, opt)
+ unless sw
begin
sw, = complete(:short, opt)
# short option matched.
@@ -1241,25 +1302,35 @@ class OptionParser
raise $!.set_option(arg, true)
end
begin
- opt, sw, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
+ opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
- argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
- sw.call(val) if sw
+ argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
+ val = cb.call(val) if cb
+ setter.call(sw.switch_name, val) if setter
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
end
# non-option argument
else
- nonopt.call(arg)
+ catch(:prune) do
+ visit(:each_option) do |sw0|
+ sw = sw0
+ sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg)
+ end
+ nonopt.call(arg)
+ end
end
end
nil
}
+ visit(:search, :short, nil) {|sw| sw.block.call(*argv) if !sw.pattern}
+
argv
end
+ private :parse_in_order
#
# Parses command line arguments +argv+ in permutation mode and returns
@@ -1275,8 +1346,7 @@ class OptionParser
#
def permute!(argv = default_argv)
nonopts = []
- arg = nil
- order!(argv) {|arg| nonopts << arg}
+ order!(argv, &nonopts.method(:<<))
argv[0, 0] = nonopts
argv
end
@@ -1304,16 +1374,25 @@ class OptionParser
#
# Wrapper method for getopts.rb.
#
- def getopts(argv, single_options, *long_options)
+ # params = ARGV.getopts("ab:", "foo", "bar:")
+ # # params[:a] = true # -a
+ # # params[:b] = "1" # -b1
+ # # params[:foo] = "1" # --foo
+ # # params[:bar] = "x" # --bar x
+ #
+ def getopts(*args)
+ argv = Array === args.first ? args.shift : default_argv
+ single_options, *long_options = *args
+
result = {}
single_options.scan(/(.)(:)?/) do |opt, val|
if val
result[opt] = nil
- define("-#{opt} VAL") {|val| result[opt] = val}
+ define("-#{opt} VAL")
else
result[opt] = false
- define("-#{opt}") {result[opt] = true}
+ define("-#{opt}")
end
end if single_options
@@ -1321,14 +1400,14 @@ class OptionParser
opt, val = arg.split(':', 2)
if val
result[opt] = val.empty? ? nil : val
- define("--#{opt} VAL") {|val| result[opt] = val}
+ define("--#{opt} VAL")
else
result[opt] = false
- define("--#{opt}") {result[opt] = true}
+ define("--#{opt}")
end
end
- order!(argv)
+ parse_in_order(argv, result.method(:[]=))
result
end
@@ -1344,7 +1423,6 @@ class OptionParser
# +block+.
#
def visit(id, *args, &block)
- el = nil
@stack.reverse_each do |el|
el.send(id, *args, &block)
end
@@ -1353,12 +1431,12 @@ class OptionParser
private :visit
#
- # Searches key +k+ in @stack for +id+ hash and returns or yields the result.
+ # Searches +key+ in @stack for +id+ hash and returns or yields the result.
#
- def search(id, k)
- visit(:search, id, k) do |k|
- return k unless block_given?
- return yield(k)
+ def search(id, key)
+ block_given = block_given?
+ visit(:search, id, key) do |k|
+ return block_given ? yield(k) : k
end
end
private :search
@@ -1377,7 +1455,7 @@ class OptionParser
search(typ, opt) {|sw| return [sw, opt]} # exact match or...
end
raise AmbiguousOption, catch(:ambiguous) {
- visit(:complete, typ, opt, icase, *pat) {|opt, *sw| return sw}
+ visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw}
raise InvalidOption, opt
}
end
@@ -1412,6 +1490,7 @@ class OptionParser
#
def environment(env = File.basename($0, '.*'))
env = ENV[env] || ENV[env.upcase] or return
+ require 'shellwords'
parse(*Shellwords.shellwords(env))
end
@@ -1429,7 +1508,7 @@ class OptionParser
#
# Any non-empty string, and no conversion.
#
- accept(String, /.+/nm) {|s,*|s}
+ accept(String, /.+/m) {|s,*|s}
#
# Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal
@@ -1452,9 +1531,16 @@ class OptionParser
#
# Generic numeric format, converts to Integer for integer format, Float
- # for float format.
- #
- accept(Numeric, %r"\A[-+]?(?:#{octal}|#{float})"io) {|s,| eval(s) if s}
+ # for float format, and Rational for rational format.
+ #
+ real = "[-+]?(?:#{octal}|#{float})"
+ accept(Numeric, /\A(#{real})(?:\/(#{real}))?/io) {|s, d, n|
+ if n
+ Rational(d, n)
+ elsif s
+ eval(s)
+ end
+ }
#
# Decimal integer format, to be converted to Integer.
@@ -1484,7 +1570,7 @@ class OptionParser
yesno = CompletingHash.new
%w[- no false].each {|el| yesno[el] = false}
%w[+ yes true].each {|el| yesno[el] = true}
- yesno['nil'] = false # shoud be nil?
+ yesno['nil'] = false # should be nil?
accept(TrueClass, yesno) {|arg, val| val == nil or val}
#
# Similar to TrueClass, but defaults to false.
@@ -1496,7 +1582,7 @@ class OptionParser
#
accept(Array) do |s,|
if s
- s = s.split(',').collect {|s| s unless s.empty?}
+ s = s.split(',').collect {|ss| ss unless ss.empty?}
end
s
end
@@ -1510,7 +1596,8 @@ class OptionParser
f |= Regexp::IGNORECASE if /i/ =~ o
f |= Regexp::MULTILINE if /m/ =~ o
f |= Regexp::EXTENDED if /x/ =~ o
- k = o.delete("^imx")
+ k = o.delete("imx")
+ k = nil if k.empty?
end
Regexp.new(s || all, f, k)
end
@@ -1542,6 +1629,17 @@ class OptionParser
argv
end
+ def self.filter_backtrace(array)
+ unless $DEBUG
+ array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
+ end
+ array
+ end
+
+ def set_backtrace(array)
+ super(self.class.filter_backtrace(array))
+ end
+
def set_option(opt, eq)
if eq
@args[0] = opt
@@ -1570,7 +1668,6 @@ class OptionParser
end
alias to_s message
- alias to_str message
end
#
@@ -1723,5 +1820,5 @@ if $0 == __FILE__
Version = OptionParser::Version
ARGV.options {|q|
q.parse!.empty? or puts "what's #{ARGV.join(' ')}?"
- } or exit 1
+ } or abort(ARGV.options.to_s)
end