thor 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +1 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.rdoc +8 -0
- data/Gemfile +12 -8
- data/lib/thor.rb +79 -10
- data/lib/thor/actions.rb +13 -13
- data/lib/thor/actions/directory.rb +29 -10
- data/lib/thor/actions/file_manipulation.rb +8 -2
- data/lib/thor/base.rb +24 -11
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +5 -0
- data/lib/thor/group.rb +5 -5
- data/lib/thor/parser/options.rb +63 -25
- data/lib/thor/rake_compat.rb +3 -2
- data/lib/thor/runner.rb +1 -1
- data/lib/thor/shell/basic.rb +16 -16
- data/lib/thor/shell/color.rb +9 -9
- data/lib/thor/shell/html.rb +9 -9
- data/lib/thor/task.rb +2 -2
- data/lib/thor/version.rb +1 -1
- data/spec/actions/create_file_spec.rb +30 -30
- data/spec/actions/create_link_spec.rb +12 -12
- data/spec/actions/directory_spec.rb +34 -27
- data/spec/actions/empty_directory_spec.rb +16 -16
- data/spec/actions/file_manipulation_spec.rb +62 -50
- data/spec/actions/inject_into_file_spec.rb +18 -18
- data/spec/actions_spec.rb +56 -56
- data/spec/base_spec.rb +69 -69
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +19 -14
- data/spec/core_ext/ordered_hash_spec.rb +29 -29
- data/spec/exit_condition_spec.rb +3 -3
- data/spec/fixtures/preserve/script.sh +3 -0
- data/spec/fixtures/script.thor +5 -0
- data/spec/group_spec.rb +55 -55
- data/spec/invocation_spec.rb +26 -26
- data/spec/parser/argument_spec.rb +12 -12
- data/spec/parser/arguments_spec.rb +12 -12
- data/spec/parser/option_spec.rb +47 -47
- data/spec/parser/options_spec.rb +137 -72
- data/spec/rake_compat_spec.rb +11 -11
- data/spec/register_spec.rb +70 -8
- data/spec/runner_spec.rb +38 -38
- data/spec/shell/basic_spec.rb +49 -37
- data/spec/shell/color_spec.rb +13 -13
- data/spec/shell/html_spec.rb +3 -3
- data/spec/shell_spec.rb +7 -7
- data/spec/spec_helper.rb +4 -0
- data/spec/task_spec.rb +11 -11
- data/spec/thor_spec.rb +161 -91
- data/spec/util_spec.rb +42 -42
- data/thor.gemspec +1 -7
- metadata +8 -118
- data/lib/thor/core_ext/dir_escape.rb +0 -0
data/.rspec
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 0.17.0, release 2013-01-24
|
2
|
+
* Add better support for tasks that accept arbitrary additional arguments (e.g. things like `bundle exec`)
|
3
|
+
* Add #stop_on_unknown_option!
|
4
|
+
* Only strip from stdin.gets if it wasn't ended with EOF
|
5
|
+
* Allow "send" as a task name
|
6
|
+
* Allow passing options as arguments after "--"
|
7
|
+
* Autoload Thor::Group
|
8
|
+
|
1
9
|
== 0.16.0, release 2012-08-14
|
2
10
|
* Add enum to string arguments
|
3
11
|
|
data/Gemfile
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
source
|
1
|
+
source :rubygems
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
platforms :mri_19 do
|
10
|
-
gem 'ruby-debug19'
|
11
|
-
end
|
5
|
+
gem 'rake', '~> 0.9'
|
6
|
+
gem 'rdoc', '~> 3.9'
|
12
7
|
|
13
8
|
group :development do
|
14
9
|
gem 'pry'
|
10
|
+
gem 'pry-debugger', :platforms => :mri_19
|
11
|
+
end
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem 'childlabor'
|
15
|
+
gem 'fakeweb', '~> 1.3'
|
16
|
+
gem 'rspec', '~> 2.11'
|
17
|
+
gem 'rspec-mocks', :git => 'git://github.com/rspec/rspec-mocks.git'
|
18
|
+
gem 'simplecov'
|
15
19
|
end
|
data/lib/thor.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'set'
|
1
2
|
require 'thor/base'
|
2
3
|
|
3
4
|
class Thor
|
@@ -8,13 +9,13 @@ class Thor
|
|
8
9
|
# meth<Symbol>:: name of the default task
|
9
10
|
#
|
10
11
|
def default_task(meth=nil)
|
11
|
-
case meth
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
@default_task = case meth
|
13
|
+
when :none
|
14
|
+
'help'
|
15
|
+
when nil
|
16
|
+
@default_task || from_superclass(:default_task, 'help')
|
17
|
+
else
|
18
|
+
meth.to_s
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -210,7 +211,7 @@ class Thor
|
|
210
211
|
|
211
212
|
define_method(subcommand) do |*args|
|
212
213
|
args, opts = Thor::Arguments.split(args)
|
213
|
-
invoke subcommand_class, args, opts
|
214
|
+
invoke subcommand_class, args, opts, :invoked_via_subcommand => true
|
214
215
|
end
|
215
216
|
end
|
216
217
|
|
@@ -251,15 +252,83 @@ class Thor
|
|
251
252
|
end
|
252
253
|
end
|
253
254
|
|
255
|
+
# Stop parsing of options as soon as an unknown option or a regular
|
256
|
+
# argument is encountered. All remaining arguments are passed to the task.
|
257
|
+
# This is useful if you have a task that can receive arbitrary additional
|
258
|
+
# options, and where those additional options should not be handled by
|
259
|
+
# Thor.
|
260
|
+
#
|
261
|
+
# ==== Example
|
262
|
+
#
|
263
|
+
# To better understand how this is useful, let's consider a task that calls
|
264
|
+
# an external command. A user may want to pass arbitrary options and
|
265
|
+
# arguments to that command. The task itself also accepts some options,
|
266
|
+
# which should be handled by Thor.
|
267
|
+
#
|
268
|
+
# class_option "verbose", :type => :boolean
|
269
|
+
# stop_on_unknown_option! :exec
|
270
|
+
# check_unknown_options! :except => :exec
|
271
|
+
#
|
272
|
+
# desc "exec", "Run a shell command"
|
273
|
+
# def exec(*args)
|
274
|
+
# puts "diagnostic output" if options[:verbose]
|
275
|
+
# Kernel.exec(*args)
|
276
|
+
# end
|
277
|
+
#
|
278
|
+
# Here +exec+ can be called with +--verbose+ to get diagnostic output,
|
279
|
+
# e.g.:
|
280
|
+
#
|
281
|
+
# $ thor exec --verbose echo foo
|
282
|
+
# diagnostic output
|
283
|
+
# foo
|
284
|
+
#
|
285
|
+
# But if +--verbose+ is given after +echo+, it is passed to +echo+ instead:
|
286
|
+
#
|
287
|
+
# $ thor exec echo --verbose foo
|
288
|
+
# --verbose foo
|
289
|
+
#
|
290
|
+
# ==== Parameters
|
291
|
+
# Symbol ...:: A list of tasks that should be affected.
|
292
|
+
def stop_on_unknown_option!(*task_names)
|
293
|
+
@stop_on_unknown_option ||= Set.new
|
294
|
+
@stop_on_unknown_option.merge(task_names)
|
295
|
+
end
|
296
|
+
|
297
|
+
def stop_on_unknown_option?(task) #:nodoc:
|
298
|
+
!!@stop_on_unknown_option && @stop_on_unknown_option.include?(task.name.to_sym)
|
299
|
+
end
|
300
|
+
|
254
301
|
protected
|
255
302
|
|
256
303
|
# The method responsible for dispatching given the args.
|
257
304
|
def dispatch(meth, given_args, given_opts, config) #:nodoc:
|
258
|
-
|
259
|
-
task
|
305
|
+
# There is an edge case when dispatching from a subcommand.
|
306
|
+
# A problem occurs invoking the default task. This case occurs
|
307
|
+
# when arguments are passed and a default task is defined, and
|
308
|
+
# the first given_args does not match the default task.
|
309
|
+
# Thor use "help" by default so we skip that case.
|
310
|
+
# Note the call to retrieve_task_name. It's called with
|
311
|
+
# given_args.dup since that method calls args.shift. Then lookup
|
312
|
+
# the task normally. If the first item in given_args is not
|
313
|
+
# a task then use the default task. The given_args will be
|
314
|
+
# intact later since dup was used.
|
315
|
+
if config[:invoked_via_subcommand] && given_args.size >= 1 && default_task != "help" && given_args.first != default_task
|
316
|
+
meth ||= retrieve_task_name(given_args.dup)
|
317
|
+
task = all_tasks[normalize_task_name(meth)]
|
318
|
+
task ||= all_tasks[normalize_task_name(default_task)]
|
319
|
+
else
|
320
|
+
meth ||= retrieve_task_name(given_args)
|
321
|
+
task = all_tasks[normalize_task_name(meth)]
|
322
|
+
end
|
260
323
|
|
261
324
|
if task
|
262
325
|
args, opts = Thor::Options.split(given_args)
|
326
|
+
if stop_on_unknown_option?(task) && !args.empty?
|
327
|
+
# given_args starts with a non-option, so we treat everything as
|
328
|
+
# ordinary arguments
|
329
|
+
args.concat opts
|
330
|
+
opts.clear
|
331
|
+
end
|
263
332
|
else
|
264
333
|
args, opts = given_args, nil
|
265
334
|
task = Thor::DynamicTask.new(meth)
|
data/lib/thor/actions.rb
CHANGED
@@ -73,13 +73,13 @@ class Thor
|
|
73
73
|
#
|
74
74
|
def initialize(args=[], options={}, config={})
|
75
75
|
self.behavior = case config[:behavior].to_s
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
76
|
+
when "force", "skip"
|
77
|
+
_cleanup_options_and_set(options, config[:behavior])
|
78
|
+
:invoke
|
79
|
+
when "revoke"
|
80
|
+
:revoke
|
81
|
+
else
|
82
|
+
:invoke
|
83
83
|
end
|
84
84
|
|
85
85
|
super
|
@@ -305,12 +305,12 @@ class Thor
|
|
305
305
|
|
306
306
|
def _cleanup_options_and_set(options, key) #:nodoc:
|
307
307
|
case options
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
308
|
+
when Array
|
309
|
+
%w(--force -f --skip -s).each { |i| options.delete(i) }
|
310
|
+
options << "--#{key}"
|
311
|
+
when Hash
|
312
|
+
[:force, :skip, "force", "skip"].each { |i| options.delete(i) }
|
313
|
+
options.merge!(key => true)
|
314
314
|
end
|
315
315
|
end
|
316
316
|
|
@@ -38,6 +38,7 @@ class Thor
|
|
38
38
|
# destination<String>:: the relative path to the destination root.
|
39
39
|
# config<Hash>:: give :verbose => false to not log the status.
|
40
40
|
# If :recursive => false, does not look for paths recursively.
|
41
|
+
# If :mode => :preserve, preserve the file mode from the source.
|
41
42
|
#
|
42
43
|
# ==== Examples
|
43
44
|
#
|
@@ -73,26 +74,44 @@ class Thor
|
|
73
74
|
def execute!
|
74
75
|
lookup = Util.escape_globs(source)
|
75
76
|
lookup = config[:recursive] ? File.join(lookup, '**') : lookup
|
76
|
-
lookup =
|
77
|
+
lookup = file_level_lookup(lookup)
|
77
78
|
|
78
|
-
|
79
|
+
files(lookup).sort.each do |file_source|
|
79
80
|
next if File.directory?(file_source)
|
80
81
|
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
81
82
|
file_destination.gsub!('/./', '/')
|
82
83
|
|
83
84
|
case file_source
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
85
|
+
when /\.empty_directory$/
|
86
|
+
dirname = File.dirname(file_destination).gsub(/\/\.$/, '')
|
87
|
+
next if dirname == given_destination
|
88
|
+
base.empty_directory(dirname, config)
|
89
|
+
when /\.tt$/
|
90
|
+
destination = base.template(file_source, file_destination[0..-4], config, &@block)
|
91
|
+
else
|
92
|
+
destination = base.copy_file(file_source, file_destination, config, &@block)
|
92
93
|
end
|
93
94
|
end
|
94
95
|
end
|
95
96
|
|
97
|
+
if RUBY_VERSION < '2.0'
|
98
|
+
def file_level_lookup(previous_lookup)
|
99
|
+
File.join(previous_lookup, '{*,.[a-z]*}')
|
100
|
+
end
|
101
|
+
|
102
|
+
def files(lookup)
|
103
|
+
Dir[lookup]
|
104
|
+
end
|
105
|
+
else
|
106
|
+
def file_level_lookup(previous_lookup)
|
107
|
+
File.join(previous_lookup, '*')
|
108
|
+
end
|
109
|
+
|
110
|
+
def files(lookup)
|
111
|
+
Dir.glob(lookup, File::FNM_DOTMATCH)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
96
115
|
end
|
97
116
|
end
|
98
117
|
end
|
@@ -10,7 +10,9 @@ class Thor
|
|
10
10
|
# ==== Parameters
|
11
11
|
# source<String>:: the relative path to the source root.
|
12
12
|
# destination<String>:: the relative path to the destination root.
|
13
|
-
# config<Hash>:: give :verbose => false to not log the status
|
13
|
+
# config<Hash>:: give :verbose => false to not log the status, and
|
14
|
+
# :mode => :preserve, to preserve the file mode from the source.
|
15
|
+
|
14
16
|
#
|
15
17
|
# ==== Examples
|
16
18
|
#
|
@@ -28,6 +30,10 @@ class Thor
|
|
28
30
|
content = block.call(content) if block
|
29
31
|
content
|
30
32
|
end
|
33
|
+
if config[:mode] == :preserve
|
34
|
+
mode = File.stat(source).mode
|
35
|
+
chmod(destination, mode, config)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
# Links the file from the relative source to the relative destination. If
|
@@ -245,7 +251,7 @@ class Thor
|
|
245
251
|
def uncomment_lines(path, flag, *args)
|
246
252
|
flag = flag.respond_to?(:source) ? flag.source : flag
|
247
253
|
|
248
|
-
gsub_file(path, /^(\s*)
|
254
|
+
gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args)
|
249
255
|
end
|
250
256
|
|
251
257
|
# Comment all lines matching a given regex. It will leave the space
|
data/lib/thor/base.rb
CHANGED
@@ -10,6 +10,7 @@ require 'thor/util'
|
|
10
10
|
class Thor
|
11
11
|
autoload :Actions, 'thor/actions'
|
12
12
|
autoload :RakeCompat, 'thor/rake_compat'
|
13
|
+
autoload :Group, 'thor/group'
|
13
14
|
|
14
15
|
# Shortcuts for help.
|
15
16
|
HELP_MAPPINGS = %w(-h -? --help -D)
|
@@ -58,7 +59,8 @@ class Thor
|
|
58
59
|
# Let Thor::Options parse the options first, so it can remove
|
59
60
|
# declared options from the array. This will leave us with
|
60
61
|
# a list of arguments that weren't declared.
|
61
|
-
|
62
|
+
stop_on_unknown = self.class.stop_on_unknown_option? config[:current_task]
|
63
|
+
opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown)
|
62
64
|
self.options = opts.parse(array_options)
|
63
65
|
|
64
66
|
# If unknown options are disallowed, make sure that none of the
|
@@ -74,7 +76,7 @@ class Thor
|
|
74
76
|
to_parse += opts.remaining unless self.class.strict_args_position?(config)
|
75
77
|
|
76
78
|
thor_args = Thor::Arguments.new(self.class.arguments)
|
77
|
-
thor_args.parse(to_parse).each { |k,v|
|
79
|
+
thor_args.parse(to_parse).each { |k,v| __send__("#{k}=", v) }
|
78
80
|
@args = thor_args.remaining
|
79
81
|
end
|
80
82
|
|
@@ -142,6 +144,13 @@ class Thor
|
|
142
144
|
!!check_unknown_options
|
143
145
|
end
|
144
146
|
|
147
|
+
# If true, option parsing is suspended as soon as an unknown option or a
|
148
|
+
# regular argument is encountered. All remaining arguments are passed to
|
149
|
+
# the task as regular arguments.
|
150
|
+
def stop_on_unknown_option?(task_name) #:nodoc:
|
151
|
+
false
|
152
|
+
end
|
153
|
+
|
145
154
|
# If you want only strict string args (useful when cascading thor classes),
|
146
155
|
# call strict_args_position! This is disabled by default to allow dynamic
|
147
156
|
# invocations.
|
@@ -304,11 +313,11 @@ class Thor
|
|
304
313
|
# name<String|Symbol>
|
305
314
|
#
|
306
315
|
def group(name=nil)
|
307
|
-
case name
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
316
|
+
@group = case name
|
317
|
+
when nil
|
318
|
+
@group || from_superclass(:group, 'standard')
|
319
|
+
else
|
320
|
+
name.to_s
|
312
321
|
end
|
313
322
|
end
|
314
323
|
|
@@ -404,9 +413,9 @@ class Thor
|
|
404
413
|
# thor :my_task
|
405
414
|
#
|
406
415
|
def namespace(name=nil)
|
407
|
-
case name
|
416
|
+
@namespace = case name
|
408
417
|
when nil
|
409
|
-
@namespace
|
418
|
+
@namespace || Thor::Util.namespace_from_thor_class(self)
|
410
419
|
else
|
411
420
|
@namespace = name.to_s
|
412
421
|
end
|
@@ -462,8 +471,12 @@ class Thor
|
|
462
471
|
msg = "#{basename} #{task.name}"
|
463
472
|
if arity
|
464
473
|
required = arity < 0 ? (-1 - arity) : arity
|
465
|
-
|
466
|
-
|
474
|
+
if required == 0
|
475
|
+
msg << " should have no arguments"
|
476
|
+
else
|
477
|
+
msg << " requires at least #{required} argument"
|
478
|
+
msg << "s" if required > 1
|
479
|
+
end
|
467
480
|
else
|
468
481
|
msg = "call #{msg} as"
|
469
482
|
end
|
data/lib/thor/group.rb
CHANGED
@@ -14,11 +14,11 @@ class Thor::Group
|
|
14
14
|
# description<String>:: The description for this Thor::Group.
|
15
15
|
#
|
16
16
|
def desc(description=nil)
|
17
|
-
case description
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
@desc = case description
|
18
|
+
when nil
|
19
|
+
@desc || from_superclass(:desc, nil)
|
20
|
+
else
|
21
|
+
description
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/lib/thor/parser/options.rb
CHANGED
@@ -5,27 +5,32 @@ class Thor
|
|
5
5
|
EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i
|
6
6
|
SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args
|
7
7
|
SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i
|
8
|
+
OPTS_END = '--'.freeze
|
8
9
|
|
9
10
|
# Receives a hash and makes it switches.
|
10
11
|
def self.to_switches(options)
|
11
12
|
options.map do |key, value|
|
12
13
|
case value
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
when true
|
15
|
+
"--#{key}"
|
16
|
+
when Array
|
17
|
+
"--#{key} #{value.map{ |v| v.inspect }.join(' ')}"
|
18
|
+
when Hash
|
19
|
+
"--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}"
|
20
|
+
when nil, false
|
21
|
+
""
|
22
|
+
else
|
23
|
+
"--#{key} #{value.inspect}"
|
23
24
|
end
|
24
25
|
end.join(" ")
|
25
26
|
end
|
26
27
|
|
27
28
|
# Takes a hash of Thor::Option and a hash with defaults.
|
28
|
-
|
29
|
+
#
|
30
|
+
# If +stop_on_unknown+ is true, #parse will stop as soon as it encounters
|
31
|
+
# an unknown option or a regular argument.
|
32
|
+
def initialize(hash_options={}, defaults={}, stop_on_unknown=false)
|
33
|
+
@stop_on_unknown = stop_on_unknown
|
29
34
|
options = hash_options.values
|
30
35
|
super(options)
|
31
36
|
|
@@ -50,15 +55,30 @@ class Thor
|
|
50
55
|
@extra
|
51
56
|
end
|
52
57
|
|
58
|
+
def peek
|
59
|
+
return super unless @parsing_options
|
60
|
+
|
61
|
+
result = super
|
62
|
+
if result == OPTS_END
|
63
|
+
shift
|
64
|
+
@parsing_options = false
|
65
|
+
super
|
66
|
+
else
|
67
|
+
result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
53
71
|
def parse(args)
|
54
72
|
@pile = args.dup
|
73
|
+
@parsing_options = true
|
55
74
|
|
56
75
|
while peek
|
57
|
-
|
58
|
-
|
76
|
+
if parsing_options?
|
77
|
+
match, is_switch = current_is_switch?
|
78
|
+
shifted = shift
|
59
79
|
|
60
|
-
|
61
|
-
|
80
|
+
if is_switch
|
81
|
+
case shifted
|
62
82
|
when SHORT_SQ_RE
|
63
83
|
unshift($1.split('').map { |f| "-#{f}" })
|
64
84
|
next
|
@@ -67,16 +87,23 @@ class Thor
|
|
67
87
|
switch = $1
|
68
88
|
when LONG_RE, SHORT_RE
|
69
89
|
switch = $1
|
90
|
+
end
|
91
|
+
|
92
|
+
switch = normalize_switch(switch)
|
93
|
+
option = switch_option(switch)
|
94
|
+
@assigns[option.human_name] = parse_peek(switch, option)
|
95
|
+
elsif @stop_on_unknown
|
96
|
+
@extra << shifted
|
97
|
+
@extra << shift while peek
|
98
|
+
break
|
99
|
+
elsif match
|
100
|
+
@extra << shifted
|
101
|
+
@extra << shift while peek && peek !~ /^-/
|
102
|
+
else
|
103
|
+
@extra << shifted
|
70
104
|
end
|
71
|
-
|
72
|
-
switch = normalize_switch(switch)
|
73
|
-
option = switch_option(switch)
|
74
|
-
@assigns[option.human_name] = parse_peek(switch, option)
|
75
|
-
elsif match
|
76
|
-
@extra << shifted
|
77
|
-
@extra << shift while peek && peek !~ /^-/
|
78
105
|
else
|
79
|
-
@extra <<
|
106
|
+
@extra << shift
|
80
107
|
end
|
81
108
|
end
|
82
109
|
|
@@ -95,8 +122,10 @@ class Thor
|
|
95
122
|
|
96
123
|
protected
|
97
124
|
|
98
|
-
#
|
125
|
+
# Check if the current value in peek is a registered switch.
|
99
126
|
#
|
127
|
+
# Two booleans are returned. The first is true if the current value
|
128
|
+
# starts with a hyphen; the second is true if it is a registered switch.
|
100
129
|
def current_is_switch?
|
101
130
|
case peek
|
102
131
|
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
|
@@ -117,6 +146,10 @@ class Thor
|
|
117
146
|
end
|
118
147
|
end
|
119
148
|
|
149
|
+
def current_is_value?
|
150
|
+
peek && (!parsing_options? || super)
|
151
|
+
end
|
152
|
+
|
120
153
|
def switch?(arg)
|
121
154
|
switch_option(normalize_switch(arg))
|
122
155
|
end
|
@@ -135,6 +168,11 @@ class Thor
|
|
135
168
|
(@shorts[arg] || arg).tr('_', '-')
|
136
169
|
end
|
137
170
|
|
171
|
+
def parsing_options?
|
172
|
+
peek
|
173
|
+
@parsing_options
|
174
|
+
end
|
175
|
+
|
138
176
|
# Parse boolean values which can be given as --foo=true, --foo or --no-foo.
|
139
177
|
#
|
140
178
|
def parse_boolean(switch)
|
@@ -156,7 +194,7 @@ class Thor
|
|
156
194
|
# Parse the value at the peek analyzing if it requires an input or not.
|
157
195
|
#
|
158
196
|
def parse_peek(switch, option)
|
159
|
-
if current_is_switch_formatted? || last?
|
197
|
+
if parsing_options? && (current_is_switch_formatted? || last?)
|
160
198
|
if option.boolean?
|
161
199
|
# No problem for boolean types
|
162
200
|
elsif no_or_skip?(switch)
|