@@ -461,6 +461,10 @@ def self.candidate(key, icase = false, pat = nil, &block)
461461 candidates
462462 end
463463
464+ def self . completable? ( key )
465+ String . try_convert ( key ) or defined? ( key . id2name )
466+ end
467+
464468 def candidate ( key , icase = false , pat = nil , &_ )
465469 Completion . candidate ( key , icase , pat , &method ( :each ) )
466470 end
@@ -544,11 +548,11 @@ def self.pattern
544548
545549 def initialize ( pattern = nil , conv = nil ,
546550 short = nil , long = nil , arg = nil ,
547- desc = ( [ ] if short or long ) , block = nil , &_block )
551+ desc = ( [ ] if short or long ) , block = nil , values = nil , &_block )
548552 raise if Array === pattern
549553 block ||= _block
550- @pattern , @conv , @short , @long , @arg , @desc , @block =
551- pattern , conv , short , long , arg , desc , block
554+ @pattern , @conv , @short , @long , @arg , @desc , @block , @values =
555+ pattern , conv , short , long , arg , desc , block , values
552556 end
553557
554558 #
@@ -581,11 +585,15 @@ def parse_arg(arg) # :nodoc:
581585 # exception.
582586 #
583587 def conv_arg ( arg , val = [ ] ) # :nodoc:
588+ v , = *val
584589 if conv
585590 val = conv . call ( *val )
586591 else
587592 val = proc { |v | v } . call ( *val )
588593 end
594+ if @values
595+ @values . include? ( val ) or raise InvalidArgument , v
596+ end
589597 return arg , block , val
590598 end
591599 private :conv_arg
@@ -780,7 +788,7 @@ class PlacedArgument < self
780788 # Returns nil if argument is not present or begins with '-' and is not '-'.
781789 #
782790 def parse ( arg , argv , &error )
783- if !( val = arg ) and ! ( val = argv [ 0 ] ) &. match? ( /\A (?!-.)/ )
791+ if !( val = arg ) and ( argv . empty? or /\A -./ =~ ( val = argv [ 0 ] ) )
784792 return nil , block
785793 end
786794 opt = ( val = parse_arg ( val , &error ) ) [ 1 ]
@@ -1464,6 +1472,7 @@ def make_switch(opts, block = nil)
14641472 klass = nil
14651473 q , a = nil
14661474 has_arg = false
1475+ values = nil
14671476
14681477 opts . each do |o |
14691478 # argument class
@@ -1477,7 +1486,7 @@ def make_switch(opts, block = nil)
14771486 end
14781487
14791488 # directly specified pattern(any object possible to match)
1480- if ( ! ( String === o || Symbol === o ) ) and o . respond_to? ( :match )
1489+ if ! Completion . completable? ( o ) and o . respond_to? ( :match )
14811490 pattern = notwice ( o , pattern , 'pattern' )
14821491 if pattern . respond_to? ( :convert )
14831492 conv = pattern . method ( :convert ) . to_proc
@@ -1492,6 +1501,11 @@ def make_switch(opts, block = nil)
14921501 when Proc , Method
14931502 block = notwice ( o , block , 'block' )
14941503 when Array , Hash
1504+ if Array === o
1505+ o , v = o . partition { |v | Completion . completable? ( v ) }
1506+ values = notwice ( v , values , 'values' ) unless v . empty?
1507+ next if o . empty?
1508+ end
14951509 case pattern
14961510 when CompletingHash
14971511 when nil
@@ -1500,7 +1514,9 @@ def make_switch(opts, block = nil)
15001514 else
15011515 raise ArgumentError , "argument pattern given twice"
15021516 end
1503- o . each { |pat , *v | pattern [ pat . to_s ] = v . fetch ( 0 ) { pat } }
1517+ o . each { |pat , *v | pattern [ pat ] = v . fetch ( 0 ) { pat } }
1518+ when Range
1519+ values = notwice ( o , values , 'values' )
15041520 when Module
15051521 raise ArgumentError , "unsupported argument type: #{ o } " , ParseError . filter_backtrace ( caller ( 4 ) )
15061522 when *ArgumentStyle . keys
@@ -1568,12 +1584,18 @@ def make_switch(opts, block = nil)
15681584 end
15691585
15701586 default_pattern , conv = search ( :atype , default_style . pattern ) unless default_pattern
1587+ if Range === values and klass
1588+ unless ( !values . begin or klass === values . begin ) and
1589+ ( !values . end or klass === values . end )
1590+ raise ArgumentError , "range does not match class"
1591+ end
1592+ end
15711593 if !( short . empty? and long . empty? )
15721594 if has_arg and default_style == Switch ::NoArgument
15731595 default_style = Switch ::RequiredArgument
15741596 end
15751597 s = ( style || default_style ) . new ( pattern || default_pattern ,
1576- conv , sdesc , ldesc , arg , desc , block )
1598+ conv , sdesc , ldesc , arg , desc , block , values )
15771599 elsif !block
15781600 if style or pattern
15791601 raise ArgumentError , "no switch given" , ParseError . filter_backtrace ( caller )
@@ -1582,7 +1604,7 @@ def make_switch(opts, block = nil)
15821604 else
15831605 short << pattern
15841606 s = ( style || default_style ) . new ( pattern ,
1585- conv , nil , nil , arg , desc , block )
1607+ conv , nil , nil , arg , desc , block , values )
15861608 end
15871609 return s , short , long ,
15881610 ( not_style . new ( not_pattern , not_conv , sdesc , ldesc , nil , desc , block ) if not_style ) ,
0 commit comments