Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add exact: keyword argument #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 23, 2024
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
58 changes: 29 additions & 29 deletions lib/optparse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1654,21 +1654,21 @@ def separator(string)
#
# Returns the rest of +argv+ left unparsed.
#
def order(*argv, into: nil, &nonopt)
def order(*argv, **keywords, &nonopt)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
order!(argv, into: into, &nonopt)
order!(argv, **keywords, &nonopt)
end

#
# Same as #order, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
def order!(argv = default_argv, into: nil, &nonopt)
def order!(argv = default_argv, into: nil, **keywords, &nonopt)
setter = ->(name, val) {into[name.to_sym] = val} if into
parse_in_order(argv, setter, &nonopt)
parse_in_order(argv, setter, **keywords, &nonopt)
end

def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc:
opt, arg, val, rest = nil
nonopt ||= proc {|a| throw :terminate, a}
argv.unshift(arg) if arg = catch(:terminate) {
Expand All @@ -1679,7 +1679,7 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
opt, rest = $1, $2
opt.tr!('_', '-')
begin
if require_exact
if exact
sw, = search(:long, opt)
else
sw, = complete(:long, opt, true)
Expand Down Expand Up @@ -1714,7 +1714,7 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
val = arg.delete_prefix('-')
has_arg = true
rescue InvalidOption
raise if require_exact
raise if exact
# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)
Expand Down Expand Up @@ -1779,18 +1779,18 @@ def callback!(cb, max_arity, *args) # :nodoc:
# <code>[]=</code> method (so it can be Hash, or OpenStruct, or other
# similar object).
#
def permute(*argv, into: nil)
def permute(*argv, **keywords)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
permute!(argv, into: into)
permute!(argv, **keywords)
end

#
# Same as #permute, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
def permute!(argv = default_argv, into: nil)
def permute!(argv = default_argv, **keywords)
nonopts = []
order!(argv, into: into, &nonopts.method(:<<))
order!(argv, **keywords, &nonopts.method(:<<))
argv[0, 0] = nonopts
argv
end
Expand All @@ -1802,20 +1802,20 @@ def permute!(argv = default_argv, into: nil)
# values are stored there via <code>[]=</code> method (so it can be Hash,
# or OpenStruct, or other similar object).
#
def parse(*argv, into: nil)
def parse(*argv, **keywords)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
parse!(argv, into: into)
parse!(argv, **keywords)
end

#
# Same as #parse, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
def parse!(argv = default_argv, into: nil)
def parse!(argv = default_argv, **keywords)
if ENV.include?('POSIXLY_CORRECT')
order!(argv, into: into)
order!(argv, **keywords)
else
permute!(argv, into: into)
permute!(argv, **keywords)
end
end

Expand All @@ -1838,7 +1838,7 @@ def parse!(argv = default_argv, into: nil)
# # params[:bar] = "x" # --bar x
# # params[:zot] = "z" # --zot Z
#
def getopts(*args, symbolize_names: false)
def getopts(*args, symbolize_names: false, **keywords)
argv = Array === args.first ? args.shift : default_argv
single_options, *long_options = *args

Expand Down Expand Up @@ -1866,7 +1866,7 @@ def getopts(*args, symbolize_names: false)
end
end

parse_in_order(argv, result.method(:[]=))
parse_in_order(argv, result.method(:[]=), **keywords)
symbolize_names ? result.transform_keys(&:to_sym) : result
end

Expand Down Expand Up @@ -1979,10 +1979,10 @@ def candidate(word)
# The optional +into+ keyword argument works exactly like that accepted in
# method #parse.
#
def load(filename = nil, into: nil)
def load(filename = nil, **keywords)
unless filename
basename = File.basename($0, '.*')
return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil
return true if load(File.expand_path(basename, '~/.options'), **keywords) rescue nil
basename << ".options"
return [
# XDG
Expand All @@ -1994,11 +1994,11 @@ def load(filename = nil, into: nil)
'~/config/settings',
].any? {|dir|
next if !dir or dir.empty?
load(File.expand_path(basename, dir), into: into) rescue nil
load(File.expand_path(basename, dir), **keywords) rescue nil
}
end
begin
parse(*File.readlines(filename, chomp: true), into: into)
parse(*File.readlines(filename, chomp: true), **keywords)
true
rescue Errno::ENOENT, Errno::ENOTDIR
false
Expand All @@ -2011,10 +2011,10 @@ def load(filename = nil, into: nil)
#
# +env+ defaults to the basename of the program.
#
def environment(env = File.basename($0, '.*'))
def environment(env = File.basename($0, '.*'), **keywords)
env = ENV[env] || ENV[env.upcase] or return
require 'shellwords'
parse(*Shellwords.shellwords(env))
parse(*Shellwords.shellwords(env), **keywords)
end

#
Expand Down Expand Up @@ -2331,19 +2331,19 @@ def options
# Parses +self+ destructively in order and returns +self+ containing the
# rest arguments left unparsed.
#
def order!(&blk) options.order!(self, &blk) end
def order!(**keywords, &blk) options.order!(self, **keywords, &blk) end

#
# Parses +self+ destructively in permutation mode and returns +self+
# containing the rest arguments left unparsed.
#
def permute!() options.permute!(self) end
def permute!(**keywords) options.permute!(self, **keywords) end

#
# Parses +self+ destructively and returns +self+ containing the
# rest arguments left unparsed.
#
def parse!() options.parse!(self) end
def parse!(**keywords) options.parse!(self, **keywords) end

#
# Substitution of getopts is possible as follows. Also see
Expand All @@ -2356,8 +2356,8 @@ def parse!() options.parse!(self) end
# rescue OptionParser::ParseError
# end
#
def getopts(*args, symbolize_names: false)
options.getopts(self, *args, symbolize_names: symbolize_names)
def getopts(*args, symbolize_names: false, **keywords)
options.getopts(self, *args, symbolize_names: symbolize_names, **keywords)
end

#
Expand Down
29 changes: 29 additions & 0 deletions test/optparse/test_optparse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,35 @@ def test_require_exact
assert_equal(false, @foo)
end

def test_exact_option
@opt.def_option('-F', '--zrs=IRS', 'zrs')
%w(--zrs --zr --z -zfoo -z -F -Ffoo).each do |arg|
result = {}
@opt.parse([arg, 'foo'], into: result)
assert_equal({zrs: 'foo'}, result)
end

[%w(--zrs foo), %w(--zrs=foo), %w(-F foo), %w(-Ffoo)].each do |args|
result = {}
@opt.parse(args, into: result, exact: true)
assert_equal({zrs: 'foo'}, result)
end

assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--zr foo), exact: true)}
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--z foo), exact: true)}
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo), exact: true)}
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo), exact: true)}
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo), exact: true)}

@opt.def_option('-f', '--[no-]foo', 'foo') {|arg| @foo = arg}
@opt.parse(%w[-f], exact: true)
assert_equal(true, @foo)
@opt.parse(%w[--foo], exact: true)
assert_equal(true, @foo)
@opt.parse(%w[--no-foo], exact: true)
assert_equal(false, @foo)
end

def test_raise_unknown
@opt.def_option('--my-foo [ARG]') {|arg| @foo = arg}
assert @opt.raise_unknown
Expand Down