Skip to content

Commit 4b131ce

Browse files
committed
Extract OptionParser#parse_option
1 parent 6c388b3 commit 4b131ce

File tree

1 file changed

+92
-76
lines changed

1 file changed

+92
-76
lines changed

lib/optparse.rb

Lines changed: 92 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,93 +1643,109 @@ def sym_set(name, val)
16431643
end
16441644
end
16451645

1646+
def parse_option(arg, argv, setter = nil)
1647+
case arg
1648+
when /\A--([^=]*)(?:=(.*))?/m
1649+
opt, rest = $1, $2
1650+
opt.tr!('_', '-')
1651+
begin
1652+
sw, = complete(:long, opt, true)
1653+
if require_exact && !sw.long.include?(arg)
1654+
throw :terminate, arg unless raise_unknown
1655+
raise InvalidOption, arg
1656+
end
1657+
rescue ParseError
1658+
throw :terminate, arg unless raise_unknown
1659+
raise $!.set_option(arg, true)
1660+
end
1661+
begin
1662+
opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
1663+
val = cb.call(val) if cb
1664+
setter.call(sw.switch_name, val) if setter
1665+
rescue ParseError
1666+
raise $!.set_option(arg, rest)
1667+
end
1668+
1669+
when /\A-(.)((=).*|.+)?/m
1670+
eq, rest, opt = $3, $2, $1
1671+
has_arg, val = eq, rest
1672+
begin
1673+
sw, = search(:short, opt)
1674+
unless sw
1675+
begin
1676+
sw, = complete(:short, opt)
1677+
# short option matched.
1678+
val = arg.delete_prefix('-')
1679+
has_arg = true
1680+
rescue InvalidOption
1681+
raise if require_exact
1682+
# if no short options match, try completion with long
1683+
# options.
1684+
sw, = complete(:long, opt)
1685+
eq ||= !rest
1686+
end
1687+
end
1688+
rescue ParseError
1689+
throw :terminate, arg unless raise_unknown
1690+
raise $!.set_option(arg, true)
1691+
end
1692+
begin
1693+
opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
1694+
rescue ParseError
1695+
raise $!.set_option(arg, arg.length > 2)
1696+
else
1697+
raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
1698+
end
1699+
begin
1700+
argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
1701+
val = cb.call(val) if cb
1702+
setter.call(sw.switch_name, val) if setter
1703+
rescue ParseError
1704+
raise $!.set_option(arg, arg.length > 2)
1705+
end
1706+
1707+
else
1708+
return false
1709+
end
1710+
1711+
true
1712+
end
1713+
16461714
def parse_in_order(argv = default_argv, setter = nil, raise_unknown: self.raise_unknown, &nonopt) # :nodoc:
16471715
opt, arg, val, rest, sub = nil
16481716
nonopt ||= proc {|a| throw :terminate, a}
16491717
argv.unshift(arg) if arg = catch(:terminate) {
16501718
while arg = argv.shift
1651-
case arg
1652-
# long option
1653-
when /\A--([^=]*)(?:=(.*))?/m
1654-
opt, rest = $1, $2
1655-
opt.tr!('_', '-')
1656-
begin
1657-
sw, = complete(:long, opt, true)
1658-
if require_exact && !sw.long.include?(arg)
1659-
throw :terminate, arg unless raise_unknown
1660-
raise InvalidOption, arg
1661-
end
1662-
rescue ParseError
1663-
throw :terminate, arg unless raise_unknown
1664-
raise $!.set_option(arg, true)
1719+
next if parse_option(arg, argv, setter)
1720+
1721+
# sub-command
1722+
if (key, (sub, block) = @subparsers&.complete(arg))
1723+
block.call if block
1724+
if setter
1725+
into = setter.receiver.class.new.extend(SymSetter)
1726+
setter.call(key, into)
1727+
subsetter = into.method(:sym_set)
16651728
end
16661729
begin
1667-
opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
1668-
val = cb.call(val) if cb
1669-
setter.call(sw.switch_name, val) if setter
1670-
rescue ParseError
1671-
raise $!.set_option(arg, rest)
1672-
end
1673-
1674-
# short option
1675-
when /\A-(.)((=).*|.+)?/m
1676-
eq, rest, opt = $3, $2, $1
1677-
has_arg, val = eq, rest
1678-
begin
1679-
sw, = search(:short, opt)
1680-
unless sw
1681-
begin
1682-
sw, = complete(:short, opt)
1683-
# short option matched.
1684-
val = arg.delete_prefix('-')
1685-
has_arg = true
1686-
rescue InvalidOption
1687-
raise if require_exact
1688-
# if no short options match, try completion with long
1689-
# options.
1690-
sw, = complete(:long, opt)
1691-
eq ||= !rest
1692-
end
1730+
pp argv: argv
1731+
sub.parse_in_order(argv, subsetter, raise_unknown: true) do |a|
1732+
pp arg: arg, a: a, argv: argv
1733+
nonopt.call(a) unless parse_option(a, argv)
16931734
end
1694-
rescue ParseError
1695-
throw :terminate, arg unless raise_unknown
1696-
raise $!.set_option(arg, true)
1697-
end
1698-
begin
1699-
opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
1700-
rescue ParseError
1701-
raise $!.set_option(arg, arg.length > 2)
1702-
else
1703-
raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
1704-
end
1705-
begin
1706-
argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
1707-
val = cb.call(val) if cb
1708-
setter.call(sw.switch_name, val) if setter
1709-
rescue ParseError
1710-
raise $!.set_option(arg, arg.length > 2)
1711-
end
1712-
1713-
# non-option argument
1714-
else
1715-
# sub-command
1716-
if (key, (sub, block) = @subparsers&.complete(arg))
1717-
block.call if block
1718-
if setter
1719-
into = setter.receiver.class.new.extend(SymSetter)
1720-
setter.call(key, into)
1721-
setter = into.method(:sym_set)
1722-
end
1723-
return sub.parse_in_order(argv, setter, &nonopt)
1735+
rescue InvalidOption => e
1736+
e.recover(argv)
1737+
arg = argv.shift
1738+
retry if parse_option(arg, argv, setter)
1739+
raise
17241740
end
1741+
end
17251742

1726-
catch(:prune) do
1727-
visit(:each_option) do |sw0|
1728-
sw = sw0
1729-
sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg)
1730-
end
1731-
nonopt.call(arg)
1743+
catch(:prune) do
1744+
visit(:each_option) do |sw0|
1745+
sw = sw0
1746+
sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg)
17321747
end
1748+
nonopt.call(arg)
17331749
end
17341750
end
17351751

0 commit comments

Comments
 (0)