@@ -401,67 +401,9 @@ class OptionParser
401401          break 
402402        end 
403403
404-         if  arg.starts_with?(" --"  )
405-           value_index =  arg.index('=' )
406-           if  value_index
407-             flag =  arg[0 ...value_index]
408-             value =  arg[value_index +  1 ..- 1 ]
409-           else 
410-             flag =  arg
411-             value =  nil 
412-           end 
413-         elsif  arg.starts_with?('-' )
414-           if  arg.size >  2 
415-             flag =  arg[0 ..1]
416-             value =  arg[2 ..- 1 ]
417-           else 
418-             flag =  arg
419-             value =  nil 
420-           end 
421-         else 
422-           flag =  arg
423-           value =  nil 
424-         end 
425- 
426-         #  Fetch handler of the flag.
427-         #  If value is given even though handler does not take value, it is invalid, then it is skipped.
428-         if  (handler =  @handlers [flag]?) &&  ! (handler.value_type.none? &&  value)
429-           handled_args <<  arg_index
430- 
431-           if  ! value
432-             case  handler.value_type
433-             in  FlagValue ::Required 
434-               value =  args[arg_index +  1 ]?
435-               if  value
436-                 handled_args <<  arg_index +  1 
437-                 arg_index +=  1 
438-               else 
439-                 @missing_option .call(flag)
440-               end 
441-             in  FlagValue ::Optional 
442-               unless  gnu_optional_args?
443-                 value =  args[arg_index +  1 ]?
444-                 if  value &&  ! @handlers .has_key?(value)
445-                   handled_args <<  arg_index +  1 
446-                   arg_index +=  1 
447-                 else 
448-                   value =  nil 
449-                 end 
450-               end 
451-             in  FlagValue ::None 
452-               #  do nothing
453-             end 
454-           end 
404+         flag, value =  parse_arg_to_flag_and_value(arg)
455405
456-           #  If this is a subcommand (flag not starting with -), delete all
457-           #  subcommands since they are no longer valid.
458-           unless  flag.starts_with?('-' )
459-             @handlers .select! { |k , _ | k.starts_with?('-' ) }
460-             @flags .select!(& .starts_with?("     -"  ))
461-           end 
462- 
463-           handler.block.call(value ||  " "  )
464-         end 
406+         arg_index =  handle_flag(flag, value, arg_index, args, handled_args)
465407
466408        arg_index +=  1 
467409      end 
@@ -476,20 +418,7 @@ class OptionParser
476418      end 
477419
478420      #  After argument parsing, delete handled arguments from args.
479-       #  We reverse so that we delete args from
480-       handled_args.reverse!
481-       i =  0 
482-       args.reject! do 
483-         #  handled_args is sorted in reverse so we know that i <= handled_args.last
484-         handled =  i ==  handled_args.last?
485- 
486-         #  Maintain the i <= handled_args.last invariant
487-         handled_args.pop if  handled
488- 
489-         i +=  1 
490- 
491-         handled
492-       end 
421+       remove_handled_args(args, handled_args)
493422
494423      #  Since we've deleted all handled arguments, `args` is all unknown arguments
495424      #  which we split by the index of any double dash argument
@@ -514,4 +443,92 @@ class OptionParser
514443      end 
515444    end 
516445  end 
446+ 
447+   #  Parses a command-line argument into a flag and optional inline value.
448+   private  def  parse_arg_to_flag_and_value (arg  : String ) : {String , String ?}
449+     if  arg.starts_with?(" --"  )
450+       value_index =  arg.index('=' )
451+       if  value_index
452+         flag =  arg[0 ...value_index]
453+         value =  arg[value_index +  1 ..- 1 ]
454+       else 
455+         flag =  arg
456+         value =  nil 
457+       end 
458+     elsif  arg.starts_with?('-' )
459+       if  arg.size >  2 
460+         flag =  arg[0 ..1]
461+         value =  arg[2 ..- 1 ]
462+       else 
463+         flag =  arg
464+         value =  nil 
465+       end 
466+     else 
467+       flag =  arg
468+       value =  nil 
469+     end 
470+     {flag, value}
471+   end 
472+ 
473+   #  Processes a single flag/subcommand. Matches original behaviour exactly.
474+   private  def  handle_flag (flag  : String , value  : String ?, arg_index  : Int32 , args  : Array (String ), handled_args : Array (Int32 )) : Int32 
475+     if  (handler =  @handlers [flag]?) &&  ! (handler.value_type.none? &&  value)
476+       handled_args <<  arg_index
477+ 
478+       if  ! value
479+         case  handler.value_type
480+         in  FlagValue ::Required 
481+           value =  args[arg_index +  1 ]?
482+           if  value
483+             handled_args <<  arg_index +  1 
484+             arg_index +=  1 
485+           else 
486+             @missing_option .call(flag)
487+           end 
488+         in  FlagValue ::Optional 
489+           unless  gnu_optional_args?
490+             value =  args[arg_index +  1 ]?
491+             if  value &&  ! @handlers .has_key?(value)
492+               handled_args <<  arg_index +  1 
493+               arg_index +=  1 
494+             else 
495+               value =  nil 
496+             end 
497+           end 
498+         in  FlagValue ::None 
499+           #  do nothing
500+         end 
501+       end 
502+ 
503+       #  If this is a subcommand (flag not starting with -), delete all
504+       #  subcommands since they are no longer valid.
505+       unless  flag.starts_with?('-' )
506+         @handlers .select! { |k , _ | k.starts_with?('-' ) }
507+         @flags .select!(& .starts_with?("     -"  ))
508+       end 
509+ 
510+       handler.block.call(value ||  " "  )
511+     end 
512+ 
513+     arg_index
514+   end 
515+ 
516+   #  Removes handled arguments from the args array based on handled_args indexes.
517+   private  def  remove_handled_args (args  : Array (String ), handled_args : Array (Int32 )) : Nil 
518+     #  After argument parsing, delete handled arguments from args.
519+     #  We reverse so that we delete args from the end
520+     handled_args.reverse!
521+     i =  0 
522+     args.reject! do 
523+       #  handled_args is sorted in reverse so we know that i <= handled_args.last
524+       handled =  i ==  handled_args.last?
525+ 
526+       #  Maintain the i <= handled_args.last invariant
527+       handled_args.pop if  handled
528+ 
529+       i +=  1 
530+ 
531+       handled
532+     end 
533+   end 
517534end 
0 commit comments