Bug #7537 ยป 259.patch
lib/optparse.rb | ||
---|---|---|
class PlacedArgument < self
|
||
#
|
||
# Returns nil if argument is not present or begins with '-'.
|
||
# Returns nil if argument is not present or begins with '-' and is not a negative number.
|
||
#
|
||
def parse(arg, argv, &error)
|
||
if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
|
||
if !(val = arg) and (argv.empty? or /\A-\D/ =~ (val = argv[0]))
|
||
return nil, block, nil
|
||
end
|
||
opt = (val = parse_arg(val, &error))[1]
|
||
... | ... | |
end
|
||
end
|
||
end
|
||
#
|
||
# any of keys in list is negative number, such as -2
|
||
#
|
||
def has_digit_options?
|
||
digits = (0..9).map{|x|x.to_s}
|
||
short.keys.any?{|k| digits.include?(k) }
|
||
end
|
||
end
|
||
#
|
||
... | ... | |
nolong
|
||
end
|
||
#
|
||
# any of keys is negative number, such as -2
|
||
#
|
||
def has_digit_options?
|
||
@stack.any?{|list| list.has_digit_options? }
|
||
end
|
||
def define(*opts, &block)
|
||
top.append(*(sw = make_switch(opts, block)))
|
||
sw[0]
|
||
... | ... | |
# short option
|
||
when /\A-(.)((=).*|.+)?/m
|
||
# negative digit works as option if any digit-options
|
||
# were explicitly specified
|
||
if negative_numeric?(arg) && !has_digit_options?
|
||
parse_non_option(arg, &nonopt)
|
||
next
|
||
end
|
||
opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
|
||
begin
|
||
sw, = search(:short, opt)
|
||
... | ... | |
# non-option argument
|
||
else
|
||
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
|
||
parse_non_option(arg, &nonopt)
|
||
end
|
||
end
|
||
... | ... | |
end
|
||
private :parse_in_order
|
||
def parse_non_option(arg, &nonopt)
|
||
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
|
||
private :parse_non_option
|
||
#
|
||
# Parses command line arguments +argv+ in permutation mode and returns
|
||
# list of non-option arguments.
|
||
... | ... | |
accept(DecimalNumeric) {|s,| eval(s) if s}
|
||
#
|
||
# Pattern for negative numerics matching which shouldn't be accidentally
|
||
# treated as options
|
||
#
|
||
NegativeNumeric = /\A-\d+(\.\d*)?/
|
||
#
|
||
# this method is used to create a local scope
|
||
# and not to clear old values of regex variables such as $~
|
||
#
|
||
def negative_numeric?(arg)
|
||
NegativeNumeric === arg
|
||
end
|
||
#
|
||
# Boolean switch, which means whether it is present or not, whether it is
|
||
# absent or not with prefix no-, or it takes an argument
|
||
# yes/no/true/false/+/-.
|
test/optparse/test_digitarg.rb | ||
---|---|---|
require_relative 'test_optparse'
|
||
class WithDigitOptions < TestOptionParser
|
||
def setup
|
||
super
|
||
@flags = {}
|
||
@opt.def_option("-x"){|x| @flag = @flags[:x] = x }
|
||
@opt.def_option("-o VAL"){|x| @flag = @flags[:o] = x}
|
||
@opt.def_option("-p [VAL]"){|x| @flag = @flags[:p] = x}
|
||
@opt.def_option("-2"){|x| @flag = @flags[2] = x}
|
||
@opt.def_option("-4"){|x| @flag = @flags[4] = x}
|
||
end
|
||
|
||
def test_negative_digits
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-2 -4")})
|
||
assert_equal(true, @flags[2])
|
||
assert_equal(true, @flags[4])
|
||
@flags.clear
|
||
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-42")})
|
||
assert_equal(true, @flags[2])
|
||
assert_equal(true, @flags[4])
|
||
@flags.clear
|
||
assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-x -1")}
|
||
assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-x -2 -1")}
|
||
assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-x -12")}
|
||
@flags.clear
|
||
end
|
||
|
||
def test_negative_digits_with_noargs
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-x -2 -4")})
|
||
assert_equal(true, @flags[:x])
|
||
assert_equal(true, @flags[2])
|
||
assert_equal(true, @flags[4])
|
||
@flags.clear
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-x2")})
|
||
assert_equal(true, @flags[:x])
|
||
assert_equal(true, @flags[2])
|
||
@flags.clear
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-2x")})
|
||
assert_equal(true, @flags[:x])
|
||
assert_equal(true, @flags[2])
|
||
@flags.clear
|
||
end
|
||
|
||
def test_negative_digits_with_reqargs
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-o -4 -2")})
|
||
assert_equal('-4', @flags[:o])
|
||
assert_equal(false, @flags.has_key?(4))
|
||
assert_equal(true, @flags[2])
|
||
@flags.clear
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-o42")})
|
||
assert_equal('42', @flags[:o])
|
||
assert_equal(false, @flags.has_key?(4))
|
||
assert_equal(false, @flags.has_key?(2))
|
||
@flags.clear
|
||
end
|
||
# negative numerics after optional arguments are treated as argument
|
||
# even if it can be an option
|
||
def test_negative_digits_with_optargs
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-p -4 -2")})
|
||
assert_equal('-4', @flags[:p])
|
||
assert_equal(false, @flags.has_key?(4))
|
||
assert_equal(true, @flags[2])
|
||
@flags.clear
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-p-4 -2")})
|
||
assert_equal('-4', @flags[:p])
|
||
assert_equal(false, @flags.has_key?(4))
|
||
assert_equal(true, @flags[2])
|
||
@flags.clear
|
||
end
|
||
end
|
||
class WithoutDigitOptions < TestOptionParser
|
||
def setup
|
||
super
|
||
@flags = {}
|
||
@opt.def_option("-x"){|x| @flag = @flags[:x] = x}
|
||
@opt.def_option("-o VAL"){|x| @flag = @flags[:o] = x}
|
||
@opt.def_option("-p [VAL]"){|x| @flag = @flags[:p] = x}
|
||
end
|
||
|
||
def test_negative_digits
|
||
assert_equal(%w"-1 -2", no_error {@opt.parse!(%w"-1 -2")})
|
||
assert_equal(%w"-12", no_error {@opt.parse!(%w"-12")})
|
||
assert_equal(%w"-3.14", no_error {@opt.parse!(%w"-3.14")})
|
||
@flags.clear
|
||
end
|
||
def test_negative_digits_with_noargs
|
||
assert_equal(%w"-1 -2", no_error {@opt.parse!(%w"-x -1 -2")})
|
||
assert_equal(true, @flags[:x])
|
||
@flags.clear
|
||
end
|
||
def test_negative_digits_with_reqargs
|
||
assert_equal(%w"-2", no_error {@opt.parse!(%w"-o -1 -2")})
|
||
assert_equal('-1', @flags[:o])
|
||
@flags.clear
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-o -3.14")})
|
||
assert_equal('-3.14', @flags[:o])
|
||
@flags.clear
|
||
end
|
||
def test_negative_digits_with_optargs
|
||
assert_equal(%w"-2", no_error {@opt.parse!(%w"-p -1 -2")})
|
||
assert_equal('-1', @flags[:p])
|
||
@flags.clear
|
||
assert_equal(%w"-2", no_error {@opt.parse!(%w"-p-1 -2")})
|
||
assert_equal('-1', @flags[:p])
|
||
@flags.clear
|
||
end
|
||
end
|
||
-
|
test/optparse/test_digitarg.rb | ||
---|---|---|
@opt.def_option("-x"){|x| @flag = @flags[:x] = x }
|
||
@opt.def_option("-o VAL"){|x| @flag = @flags[:o] = x}
|
||
@opt.def_option("-p [VAL]"){|x| @flag = @flags[:p] = x}
|
||
@opt.def_option("-q=[VAL]"){|x| @flag = @flags[:q] = x}
|
||
@opt.def_option("-2"){|x| @flag = @flags[2] = x}
|
||
@opt.def_option("-4"){|x| @flag = @flags[4] = x}
|
||
end
|
||
... | ... | |
assert_equal(true, @flags[2])
|
||
@flags.clear
|
||
end
|
||
# When one uses option with optional argument
|
||
# with equal sign in its specification (instead of spaces)
|
||
# argument should be just after option letter without any spaces
|
||
def test_negative_digits_with_optargs_with_eq_sign
|
||
assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-q -1")}
|
||
@flags.clear
|
||
assert_equal(%w"", no_error {@opt.parse!(%w"-q-1")})
|
||
assert_equal('-1', @flags[:q])
|
||
@flags.clear
|
||
end
|
||
end
|
||
class WithoutDigitOptions < TestOptionParser
|
||
... | ... | |
@opt.def_option("-x"){|x| @flag = @flags[:x] = x}
|
||
@opt.def_option("-o VAL"){|x| @flag = @flags[:o] = x}
|
||
@opt.def_option("-p [VAL]"){|x| @flag = @flags[:p] = x}
|
||
@opt.def_option("-q=[VAL]"){|x| @flag = @flags[:q] = x}
|
||
end
|
||
|
||
def test_negative_digits
|
||
... | ... | |
assert_equal('-1', @flags[:p])
|
||
@flags.clear
|
||
end
|
||
# When one uses option with optional argument
|
||
# with equal sign in its specification (instead of spaces)
|
||
# argument should be just after option letter without any spaces
|
||
def test_negative_digits_with_optargs_with_eq_sign
|
||
assert_equal(%w"-1 -2", no_error {@opt.parse!(%w"-q -1 -2")})
|
||
assert_equal(true, @flags.has_key?(:q))
|
||
assert_equal(nil, @flags[:q])
|
||
@flags.clear
|
||
assert_equal(%w"-2", no_error {@opt.parse!(%w"-q-1 -2")})
|
||
assert_equal('-1', @flags[:q])
|
||
@flags.clear
|
||
end
|
||
end
|