Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Allow passing options as arguments after '--'. #260

Merged
merged 2 commits into from

2 participants

Brian Donovan Erik Michaels-Ober
Brian Donovan
Collaborator

This should allow the use case brought up by erikhuda/thor#259, namely that this command does not work:

foreman run ruby -Itest test/unit/a_test.rb

With this patch you could run it like so:

foreman run -- ruby -Itest test/unit/a_test.rb

Brian Donovan
Collaborator

@sferik, @wycats, thoughts?

Brian Donovan
Collaborator
Brian Donovan
Collaborator

Should be good to go now. I used this to test it:

$ foreman run -- ruby -e 'puts 1'
1
Erik Michaels-Ober sferik merged commit 7445a6d into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 84 additions and 22 deletions.
  1. +50 −22 lib/thor/parser/options.rb
  2. +34 −0 spec/parser/options_spec.rb
72 lib/thor/parser/options.rb
View
@@ -5,6 +5,7 @@ class Options < Arguments #:nodoc:
EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i
SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args
SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i
+ OPTS_END = '--'.freeze
# Receives a hash and makes it switches.
def self.to_switches(options)
@@ -50,33 +51,51 @@ def remaining
@extra
end
+ def peek
+ return super unless @parsing_options
+
+ result = super
+ if result == OPTS_END
+ shift
+ @parsing_options = false
+ super
+ else
+ result
+ end
+ end
+
def parse(args)
@pile = args.dup
+ @parsing_options = true
while peek
- match, is_switch = current_is_switch?
- shifted = shift
-
- if is_switch
- case shifted
- when SHORT_SQ_RE
- unshift($1.split('').map { |f| "-#{f}" })
- next
- when EQ_RE, SHORT_NUM
- unshift($2)
- switch = $1
- when LONG_RE, SHORT_RE
- switch = $1
+ if parsing_options?
+ match, is_switch = current_is_switch?
+ shifted = shift
+
+ if is_switch
+ case shifted
+ when SHORT_SQ_RE
+ unshift($1.split('').map { |f| "-#{f}" })
+ next
+ when EQ_RE, SHORT_NUM
+ unshift($2)
+ switch = $1
+ when LONG_RE, SHORT_RE
+ switch = $1
+ end
+
+ switch = normalize_switch(switch)
+ option = switch_option(switch)
+ @assigns[option.human_name] = parse_peek(switch, option)
+ elsif match
+ @extra << shifted
+ @extra << shift while peek && peek !~ /^-/
+ else
+ @extra << shifted
end
-
- switch = normalize_switch(switch)
- option = switch_option(switch)
- @assigns[option.human_name] = parse_peek(switch, option)
- elsif match
- @extra << shifted
- @extra << shift while peek && peek !~ /^-/
else
- @extra << shifted
+ @extra << shift
end
end
@@ -117,6 +136,10 @@ def current_is_switch_formatted?
end
end
+ def current_is_value?
+ peek && (!parsing_options? || super)
+ end
+
def switch?(arg)
switch_option(normalize_switch(arg))
end
@@ -135,6 +158,11 @@ def normalize_switch(arg)
(@shorts[arg] || arg).tr('_', '-')
end
+ def parsing_options?
+ peek
+ @parsing_options
+ end
+
# Parse boolean values which can be given as --foo=true, --foo or --no-foo.
#
def parse_boolean(switch)
@@ -156,7 +184,7 @@ def parse_boolean(switch)
# Parse the value at the peek analyzing if it requires an input or not.
#
def parse_peek(switch, option)
- if current_is_switch_formatted? || last?
+ if parsing_options? && (current_is_switch_formatted? || last?)
if option.boolean?
# No problem for boolean types
elsif no_or_skip?(switch)
34 spec/parser/options_spec.rb
View
@@ -18,6 +18,10 @@ def check_unknown!
@opt.check_unknown!
end
+ def remaining
+ @opt.remaining
+ end
+
describe "#to_switches" do
it "turns true values into a flag" do
Thor::Options.to_switches(:color => true).should == "--color"
@@ -133,6 +137,36 @@ def check_unknown!
parse("--baz_foo", "foo bar")["baz_foo"].should == "foo bar"
end
+ it "interprets everything after -- as args instead of options" do
+ create(:foo => :string, :bar => :required)
+ parse(%w[--bar abc moo -- --foo def -a]).should == {"bar" => "abc"}
+ remaining.should == %w[moo --foo def -a]
+ end
+
+ it "ignores -- when looking for single option values" do
+ create(:foo => :string, :bar => :required)
+ parse(%w[--bar -- --foo def -a]).should == {"bar" => "--foo"}
+ remaining.should == %w[def -a]
+ end
+
+ it "ignores -- when looking for array option values" do
+ create(:foo => :array)
+ parse(%w[--foo a b -- c d -e]).should == {"foo" => %w[a b c d -e]}
+ remaining.should == []
+ end
+
+ it "ignores -- when looking for hash option values" do
+ create(:foo => :hash)
+ parse(%w[--foo a:b -- c:d -e]).should == {"foo" => {'a' => 'b', 'c' => 'd'}}
+ remaining.should == %w[-e]
+ end
+
+ it "ignores trailing --" do
+ create(:foo => :string)
+ parse(%w[--foo --]).should == {"foo" => nil}
+ remaining.should == []
+ end
+
describe "with no input" do
it "and no switches returns an empty hash" do
create({})
Something went wrong with that request. Please try again.