Skip to content

subcommand parser #41

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
Prev Previous commit
Extract OptionParser#parse_option
  • Loading branch information
nobu committed Dec 22, 2022
commit 4b131cea9ed8de96d37106f6886629fae799f703
168 changes: 92 additions & 76 deletions lib/optparse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1643,93 +1643,109 @@ def sym_set(name, val)
end
end

def parse_option(arg, argv, setter = nil)
case arg
when /\A--([^=]*)(?:=(.*))?/m
opt, rest = $1, $2
opt.tr!('_', '-')
begin
sw, = complete(:long, opt, true)
if require_exact && !sw.long.include?(arg)
throw :terminate, arg unless raise_unknown
raise InvalidOption, arg
end
rescue ParseError
throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
end
begin
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

when /\A-(.)((=).*|.+)?/m
eq, rest, opt = $3, $2, $1
has_arg, val = eq, rest
begin
sw, = search(:short, opt)
unless sw
begin
sw, = complete(:short, opt)
# short option matched.
val = arg.delete_prefix('-')
has_arg = true
rescue InvalidOption
raise if require_exact
# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)
eq ||= !rest
end
end
rescue ParseError
throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
end
begin
opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
else
raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
end
begin
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

else
return false
end

true
end

def parse_in_order(argv = default_argv, setter = nil, raise_unknown: self.raise_unknown, &nonopt) # :nodoc:
opt, arg, val, rest, sub = nil
nonopt ||= proc {|a| throw :terminate, a}
argv.unshift(arg) if arg = catch(:terminate) {
while arg = argv.shift
case arg
# long option
when /\A--([^=]*)(?:=(.*))?/m
opt, rest = $1, $2
opt.tr!('_', '-')
begin
sw, = complete(:long, opt, true)
if require_exact && !sw.long.include?(arg)
throw :terminate, arg unless raise_unknown
raise InvalidOption, arg
end
rescue ParseError
throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
next if parse_option(arg, argv, setter)

# sub-command
if (key, (sub, block) = @subparsers&.complete(arg))
block.call if block
if setter
into = setter.receiver.class.new.extend(SymSetter)
setter.call(key, into)
subsetter = into.method(:sym_set)
end
begin
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-(.)((=).*|.+)?/m
eq, rest, opt = $3, $2, $1
has_arg, val = eq, rest
begin
sw, = search(:short, opt)
unless sw
begin
sw, = complete(:short, opt)
# short option matched.
val = arg.delete_prefix('-')
has_arg = true
rescue InvalidOption
raise if require_exact
# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)
eq ||= !rest
end
pp argv: argv
sub.parse_in_order(argv, subsetter, raise_unknown: true) do |a|
pp arg: arg, a: a, argv: argv
nonopt.call(a) unless parse_option(a, argv)
end
rescue ParseError
throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
end
begin
opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
else
raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
end
begin
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
# sub-command
if (key, (sub, block) = @subparsers&.complete(arg))
block.call if block
if setter
into = setter.receiver.class.new.extend(SymSetter)
setter.call(key, into)
setter = into.method(:sym_set)
end
return sub.parse_in_order(argv, setter, &nonopt)
rescue InvalidOption => e
e.recover(argv)
arg = argv.shift
retry if parse_option(arg, argv, setter)
raise
end
end

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)
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

Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy