@@ -1148,6 +1148,7 @@ def initialize(banner = nil, width = 32, indent = ' ' * 4)
1148
1148
@summary_indent = indent
1149
1149
@default_argv = ARGV
1150
1150
@require_exact = false
1151
+ @subparsers = nil
1151
1152
add_officious
1152
1153
yield self if block_given?
1153
1154
end
@@ -1170,6 +1171,12 @@ def self.terminate(arg = nil)
1170
1171
throw :terminate , arg
1171
1172
end
1172
1173
1174
+ def subparser ( name , *rest , &block )
1175
+ parser = self . class . new ( *rest )
1176
+ ( @subparsers ||= CompletingHash . new ) [ name ] = [ parser , block ]
1177
+ parser
1178
+ end
1179
+
1173
1180
@stack = [ DefaultList ]
1174
1181
def self . top ( ) DefaultList end
1175
1182
@@ -1622,12 +1629,17 @@ def order(*argv, into: nil, &nonopt)
1622
1629
# Non-option arguments remain in +argv+.
1623
1630
#
1624
1631
def order! ( argv = default_argv , into : nil , &nonopt )
1625
- setter = -> ( name , val ) { into [ name . to_sym ] = val } if into
1632
+ setter = into . extend ( SymSetter ) . method ( :sym_set ) if into
1626
1633
parse_in_order ( argv , setter , &nonopt )
1627
1634
end
1628
1635
1636
+ module SymSetter
1637
+ def sym_set ( name , val )
1638
+ self [ name . to_sym ] = val
1639
+ end
1640
+ end
1629
1641
def parse_in_order ( argv = default_argv , setter = nil , &nonopt ) # :nodoc:
1630
- opt , arg , val , rest = nil
1642
+ opt , arg , val , rest , sub = nil
1631
1643
nonopt ||= proc { |a | throw :terminate , a }
1632
1644
argv . unshift ( arg ) if arg = catch ( :terminate ) {
1633
1645
while arg = argv . shift
@@ -1692,6 +1704,17 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
1692
1704
1693
1705
# non-option argument
1694
1706
else
1707
+ # sub-command
1708
+ if ( key , ( sub , block ) = @subparsers &.complete ( arg ) )
1709
+ block . call if block
1710
+ if setter
1711
+ into = setter . receiver . class . new . extend ( SymSetter )
1712
+ setter . call ( key , into )
1713
+ setter = into . method ( :sym_set )
1714
+ end
1715
+ return sub . parse_in_order ( argv , setter , &nonopt )
1716
+ end
1717
+
1695
1718
catch ( :prune ) do
1696
1719
visit ( :each_option ) do |sw0 |
1697
1720
sw = sw0
@@ -1709,7 +1732,7 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
1709
1732
1710
1733
argv
1711
1734
end
1712
- private :parse_in_order
1735
+ protected :parse_in_order
1713
1736
1714
1737
#
1715
1738
# Parses command line arguments +argv+ in permutation mode and returns
@@ -1728,6 +1751,9 @@ def permute(*argv, into: nil)
1728
1751
# Non-option arguments remain in +argv+.
1729
1752
#
1730
1753
def permute! ( argv = default_argv , into : nil )
1754
+ if @subparsers
1755
+ raise "cannot parse in permutation mode with subparsers"
1756
+ end
1731
1757
nonopts = [ ]
1732
1758
order! ( argv , into : into , &nonopts . method ( :<< ) )
1733
1759
argv [ 0 , 0 ] = nonopts
@@ -1751,7 +1777,7 @@ def parse(*argv, into: nil)
1751
1777
# Non-option arguments remain in +argv+.
1752
1778
#
1753
1779
def parse! ( argv = default_argv , into : nil )
1754
- if ENV . include? ( 'POSIXLY_CORRECT' )
1780
+ if @subparsers or ENV . include? ( 'POSIXLY_CORRECT' )
1755
1781
order! ( argv , into : into )
1756
1782
else
1757
1783
permute! ( argv , into : into )
0 commit comments