commander-rb / commander

The complete solution for Ruby command-line executables
MIT License
823 stars 74 forks source link

Options with arguments may not be properly removed before executing command #47

Closed JosephPecoraro closed 4 years ago

JosephPecoraro commented 7 years ago

Options with arguments may not be properly removed before executing command.

Test program:

require 'commander/import'

program :name, 'Name'
program :version, '0.1'
program :description, 'Issue with Global Option parsing.'

default_command :cmd

global_option('--target=STRING', String, 'Specify a target.') do |s|
  puts "Parsed Global Option: #{s}"
end

command :cmd do |c|
  c.action do
    puts 'Success'
  end
end

Example:

$ ruby test.rb --target 1
Parsed Global Option: 1
Success

$ ruby test.rb --target=1
Parsed Global Option: 1
invalid option: --target=1

Here it is clear that the Global Option handler for --target ran and received the expected argument 1. However this global option was not consumed before invoking the sub-command, and produced invalid option. Doing the same thing without an = sign works for both global option parsing and is removed before the sub-command.


Relevant code to look at is remove_global_option which I don't think correctly handles arguments that contains an =. In this case arg is --target=1 and the code tries to remove switches named --target with direct comparisons, which of course fails.

Specifically this part looks fishy:

  args.delete_if do |arg|
    if switches.any? { |s| s[0, arg.length] == arg }
      ...
    end
  end
JosephPecoraro commented 4 years ago

Awesome!!