Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion doc/optparse/option_params.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -396,12 +396,22 @@ Executions:
$ ruby matched_values.rb --help
Usage: matched_values [options]
--xxx XXX Matched values
--yyy YYY Check by range
--zzz ZZZ Check by list
$ ruby matched_values.rb --xxx foo
["--xxx", "foo"]
$ ruby matched_values.rb --xxx FOO
["--xxx", "FOO"]
$ ruby matched_values.rb --xxx bar
matched_values.rb:6:in '<main>': invalid argument: --xxx bar (OptionParser::InvalidArgument)
matched_values.rb:12:in '<main>': invalid argument: --xxx bar (OptionParser::InvalidArgument)
$ ruby matched_values.rb --yyy 1
["--yyy", 1]
$ ruby matched_values.rb --yyy 4
matched_values.rb:12:in '<main>': invalid argument: --yyy 4 (OptionParser::InvalidArgument)
$ ruby matched_values.rb --zzz 1
["--zzz", 1]
$ ruby matched_values.rb --zzz 2
matched_values.rb:12:in '<main>': invalid argument: --zzz 2 (OptionParser::InvalidArgument)

=== Argument Converters

Expand Down
6 changes: 6 additions & 0 deletions doc/optparse/ruby/matched_values.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
parser.on('--xxx XXX', /foo/i, 'Matched values') do |value|
p ['--xxx', value]
end
parser.on('--yyy YYY', Integer, 'Check by range', 1..3) do |value|
p ['--yyy', value]
end
parser.on('--zzz ZZZ', Integer, 'Check by list', [1, 3, 4]) do |value|
p ['--zzz', value]
end
parser.parse!
38 changes: 30 additions & 8 deletions lib/optparse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ def self.candidate(key, icase = false, pat = nil, &block)
candidates
end

def self.completable?(key)
String.try_convert(key) or defined?(key.id2name)
end

def candidate(key, icase = false, pat = nil, &_)
Completion.candidate(key, icase, pat, &method(:each))
end
Expand Down Expand Up @@ -544,11 +548,11 @@ def self.pattern

def initialize(pattern = nil, conv = nil,
short = nil, long = nil, arg = nil,
desc = ([] if short or long), block = nil, &_block)
desc = ([] if short or long), block = nil, values = nil, &_block)
raise if Array === pattern
block ||= _block
@pattern, @conv, @short, @long, @arg, @desc, @block =
pattern, conv, short, long, arg, desc, block
@pattern, @conv, @short, @long, @arg, @desc, @block, @values =
pattern, conv, short, long, arg, desc, block, values
end

#
Expand Down Expand Up @@ -581,11 +585,15 @@ def parse_arg(arg) # :nodoc:
# exception.
#
def conv_arg(arg, val = []) # :nodoc:
v, = *val
if conv
val = conv.call(*val)
else
val = proc {|v| v}.call(*val)
end
if @values
@values.include?(val) or raise InvalidArgument, v
end
return arg, block, val
end
private :conv_arg
Expand Down Expand Up @@ -780,7 +788,7 @@ class PlacedArgument < self
# Returns nil if argument is not present or begins with '-' and is not '-'.
#
def parse(arg, argv, &error)
if !(val = arg) and !(val = argv[0])&.match?(/\A(?!-.)/)
if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0]))
return nil, block
end
opt = (val = parse_arg(val, &error))[1]
Expand Down Expand Up @@ -1464,6 +1472,7 @@ def make_switch(opts, block = nil)
klass = nil
q, a = nil
has_arg = false
values = nil

opts.each do |o|
# argument class
Expand All @@ -1477,7 +1486,7 @@ def make_switch(opts, block = nil)
end

# directly specified pattern(any object possible to match)
if (!(String === o || Symbol === o)) and o.respond_to?(:match)
if !Completion.completable?(o) and o.respond_to?(:match)
pattern = notwice(o, pattern, 'pattern')
if pattern.respond_to?(:convert)
conv = pattern.method(:convert).to_proc
Expand All @@ -1492,6 +1501,11 @@ def make_switch(opts, block = nil)
when Proc, Method
block = notwice(o, block, 'block')
when Array, Hash
if Array === o
o, v = o.partition {|v| Completion.completable?(v)}
values = notwice(v, values, 'values') unless v.empty?
next if o.empty?
end
case pattern
when CompletingHash
when nil
Expand All @@ -1500,7 +1514,9 @@ def make_switch(opts, block = nil)
else
raise ArgumentError, "argument pattern given twice"
end
o.each {|pat, *v| pattern[pat.to_s] = v.fetch(0) {pat}}
o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
when Range
values = notwice(o, values, 'values')
when Module
raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
when *ArgumentStyle.keys
Expand Down Expand Up @@ -1568,12 +1584,18 @@ def make_switch(opts, block = nil)
end

default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
if Range === values and klass
unless (!values.begin or klass === values.begin) and
(!values.end or klass === values.end)
raise ArgumentError, "range does not match class"
end
end
if !(short.empty? and long.empty?)
if has_arg and default_style == Switch::NoArgument
default_style = Switch::RequiredArgument
end
s = (style || default_style).new(pattern || default_pattern,
conv, sdesc, ldesc, arg, desc, block)
conv, sdesc, ldesc, arg, desc, block, values)
elsif !block
if style or pattern
raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
Expand All @@ -1582,7 +1604,7 @@ def make_switch(opts, block = nil)
else
short << pattern
s = (style || default_style).new(pattern,
conv, nil, nil, arg, desc, block)
conv, nil, nil, arg, desc, block, values)
end
return s, short, long,
(not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
Expand Down
9 changes: 8 additions & 1 deletion test/optparse/test_placearg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ def setup
@opt.def_option("--option [VAL]") {|x| @flag = x}
@opt.def_option("-T [level]", /^[0-4]$/, Integer) {|x| @topt = x}
@opt.def_option("--enum [VAL]", [:Alpha, :Bravo, :Charlie]) {|x| @enum = x}
@opt.def_option("--integer [VAL]", [1, 2, 3]) {|x| @integer = x}
@opt.def_option("--integer [VAL]", Integer, [1, 2, 3]) {|x| @integer = x}
@opt.def_option("--range [VAL]", Integer, 1..3) {|x| @range = x}
@topt = nil
@opt.def_option("-n") {}
@opt.def_option("--regexp [REGEXP]", Regexp) {|x| @reopt = x}
Expand Down Expand Up @@ -105,4 +106,10 @@ def test_enum_conversion
assert_equal([], no_error {@opt.parse!(%w"--integer=1")})
assert_equal(1, @integer)
end

def test_enum_range
assert_equal([], no_error {@opt.parse!(%w"--range=1")})
assert_equal(1, @range)
assert_raise(OptionParser::InvalidArgument) {@opt.parse!(%w"--range=4")}
end
end