thor 0.13.4 → 0.14.3
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/CHANGELOG.rdoc +5 -3
- data/{README.rdoc → README.md} +65 -55
- data/Thorfile +3 -2
- data/lib/thor/actions/create_file.rb +3 -1
- data/lib/thor/actions/directory.rb +4 -2
- data/lib/thor/actions/file_manipulation.rb +30 -7
- data/lib/thor/actions.rb +31 -9
- data/lib/thor/base.rb +38 -15
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +1 -1
- data/lib/thor/group.rb +22 -20
- data/lib/thor/invocation.rb +45 -57
- data/lib/thor/parser/argument.rb +15 -15
- data/lib/thor/parser/arguments.rb +14 -3
- data/lib/thor/parser/option.rb +38 -46
- data/lib/thor/parser/options.rb +26 -22
- data/lib/thor/runner.rb +11 -16
- data/lib/thor/shell/basic.rb +48 -12
- data/lib/thor/shell/html.rb +121 -0
- data/lib/thor/shell.rb +7 -2
- data/lib/thor/task.rb +63 -51
- data/lib/thor/util.rb +15 -16
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +118 -45
- data/spec/actions/directory_spec.rb +2 -2
- data/spec/actions/file_manipulation_spec.rb +7 -0
- data/spec/actions_spec.rb +21 -3
- data/spec/base_spec.rb +9 -3
- data/spec/fixtures/doc/block_helper.rb +3 -0
- data/spec/fixtures/doc/components/.empty_directory +0 -0
- data/spec/fixtures/group.thor +16 -4
- data/spec/fixtures/path with spaces +0 -0
- data/spec/fixtures/script.thor +48 -4
- data/spec/group_spec.rb +3 -3
- data/spec/invocation_spec.rb +1 -8
- data/spec/parser/option_spec.rb +2 -2
- data/spec/parser/options_spec.rb +27 -0
- data/spec/runner_spec.rb +16 -8
- data/spec/shell/basic_spec.rb +13 -4
- data/spec/shell/html_spec.rb +27 -0
- data/spec/shell_spec.rb +13 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/task_spec.rb +7 -7
- data/spec/thor_spec.rb +103 -6
- data/spec/util_spec.rb +3 -7
- metadata +63 -7
data/lib/thor/group.rb
CHANGED
|
@@ -6,7 +6,7 @@ require 'thor/base'
|
|
|
6
6
|
# tasks.
|
|
7
7
|
class Thor::Group
|
|
8
8
|
class << self
|
|
9
|
-
# The
|
|
9
|
+
# The description for this Thor::Group. If none is provided, but a source root
|
|
10
10
|
# exists, tries to find the USAGE one folder above it, otherwise searches
|
|
11
11
|
# in the superclass.
|
|
12
12
|
#
|
|
@@ -22,21 +22,6 @@ class Thor::Group
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
# Start works differently in Thor::Group, it simply invokes all tasks
|
|
26
|
-
# inside the class.
|
|
27
|
-
#
|
|
28
|
-
def start(original_args=ARGV, config={})
|
|
29
|
-
super do |given_args|
|
|
30
|
-
if Thor::HELP_MAPPINGS.include?(given_args.first)
|
|
31
|
-
help(config[:shell])
|
|
32
|
-
return
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
args, opts = Thor::Options.split(given_args)
|
|
36
|
-
new(args, opts, config).invoke
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
25
|
# Prints help information.
|
|
41
26
|
#
|
|
42
27
|
# ==== Options
|
|
@@ -129,7 +114,7 @@ class Thor::Group
|
|
|
129
114
|
|
|
130
115
|
names.each do |name|
|
|
131
116
|
unless class_options.key?(name)
|
|
132
|
-
raise ArgumentError, "You have to define the option #{name.inspect} " <<
|
|
117
|
+
raise ArgumentError, "You have to define the option #{name.inspect} " <<
|
|
133
118
|
"before setting invoke_from_option."
|
|
134
119
|
end
|
|
135
120
|
|
|
@@ -225,15 +210,32 @@ class Thor::Group
|
|
|
225
210
|
|
|
226
211
|
protected
|
|
227
212
|
|
|
213
|
+
# The method responsible for dispatching given the args.
|
|
214
|
+
def dispatch(task, given_args, given_opts, config) #:nodoc:
|
|
215
|
+
if Thor::HELP_MAPPINGS.include?(given_args.first)
|
|
216
|
+
help(config[:shell])
|
|
217
|
+
return
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
args, opts = Thor::Options.split(given_args)
|
|
221
|
+
opts = given_opts || opts
|
|
222
|
+
|
|
223
|
+
if task
|
|
224
|
+
new(args, opts, config).invoke_task(all_tasks[task])
|
|
225
|
+
else
|
|
226
|
+
new(args, opts, config).invoke_all
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
228
230
|
# The banner for this class. You can customize it if you are invoking the
|
|
229
231
|
# thor class by another ways which is not the Thor::Runner.
|
|
230
232
|
def banner
|
|
231
|
-
"#{
|
|
233
|
+
"#{basename} #{self_task.formatted_usage(self, false)}"
|
|
232
234
|
end
|
|
233
235
|
|
|
234
236
|
# Represents the whole class as a task.
|
|
235
237
|
def self_task #:nodoc:
|
|
236
|
-
Thor::
|
|
238
|
+
Thor::DynamicTask.new(self.namespace, class_options)
|
|
237
239
|
end
|
|
238
240
|
|
|
239
241
|
def baseclass #:nodoc:
|
|
@@ -241,7 +243,7 @@ class Thor::Group
|
|
|
241
243
|
end
|
|
242
244
|
|
|
243
245
|
def create_task(meth) #:nodoc:
|
|
244
|
-
tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil)
|
|
246
|
+
tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil, nil)
|
|
245
247
|
true
|
|
246
248
|
end
|
|
247
249
|
end
|
data/lib/thor/invocation.rb
CHANGED
|
@@ -10,10 +10,10 @@ class Thor
|
|
|
10
10
|
# available only in class methods invocations (i.e. in Thor::Group).
|
|
11
11
|
def prepare_for_invocation(key, name) #:nodoc:
|
|
12
12
|
case name
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
when Symbol, String
|
|
14
|
+
Thor::Util.find_class_and_task_by_namespace(name.to_s, !key)
|
|
15
|
+
else
|
|
16
|
+
name
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -94,29 +94,34 @@ class Thor
|
|
|
94
94
|
# invoke Rspec::RR, [], :style => :foo
|
|
95
95
|
#
|
|
96
96
|
def invoke(name=nil, *args)
|
|
97
|
+
if name.nil?
|
|
98
|
+
warn "[Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}"
|
|
99
|
+
return invoke_all
|
|
100
|
+
end
|
|
101
|
+
|
|
97
102
|
args.unshift(nil) if Array === args.first || NilClass === args.first
|
|
98
103
|
task, args, opts, config = args
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
klass, task = _retrieve_class_and_task(name, task)
|
|
106
|
+
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
|
|
107
|
+
|
|
108
|
+
args, opts, config = _parse_initialization_options(args, opts, config)
|
|
109
|
+
klass.send(:dispatch, task, args, opts, config)
|
|
110
|
+
end
|
|
102
111
|
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
# Invoke the given task if the given args.
|
|
113
|
+
def invoke_task(task, *args) #:nodoc:
|
|
114
|
+
current = @_invocations[self.class]
|
|
105
115
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
task.run(instance, method_args)
|
|
110
|
-
end
|
|
116
|
+
unless current.include?(task.name)
|
|
117
|
+
current << task.name
|
|
118
|
+
task.run(self, *args)
|
|
111
119
|
end
|
|
120
|
+
end
|
|
112
121
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
iterator.call(nil, task)
|
|
117
|
-
else
|
|
118
|
-
klass.all_tasks.map(&iterator)
|
|
119
|
-
end
|
|
122
|
+
# Invoke all tasks for the current instance.
|
|
123
|
+
def invoke_all #:nodoc:
|
|
124
|
+
self.class.all_tasks.map { |_, task| invoke_task(task) }
|
|
120
125
|
end
|
|
121
126
|
|
|
122
127
|
# Invokes using shell padding.
|
|
@@ -131,50 +136,33 @@ class Thor
|
|
|
131
136
|
{ :invocations => @_invocations }
|
|
132
137
|
end
|
|
133
138
|
|
|
134
|
-
# This method
|
|
135
|
-
#
|
|
136
|
-
#
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
# This method simply retrieves the class and task to be invoked.
|
|
140
|
+
# If the name is nil or the given name is a task in the current class,
|
|
141
|
+
# use the given name and return self as class. Otherwise, call
|
|
142
|
+
# prepare_for_invocation in the current class.
|
|
143
|
+
def _retrieve_class_and_task(name, sent_task=nil) #:nodoc:
|
|
144
|
+
case
|
|
145
|
+
when name.nil?
|
|
146
|
+
[self.class, nil]
|
|
147
|
+
when self.class.all_tasks[name.to_s]
|
|
148
|
+
[self.class, name.to_s]
|
|
142
149
|
else
|
|
143
|
-
|
|
144
|
-
task
|
|
150
|
+
klass, task = self.class.prepare_for_invocation(nil, name)
|
|
151
|
+
[klass, task || sent_task]
|
|
145
152
|
end
|
|
146
|
-
|
|
147
|
-
# If the object was not set, use self and use the name as task.
|
|
148
|
-
object, task = self, name unless object
|
|
149
|
-
return object, _validate_task(object, task)
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
# Check if the object given is a Thor class object and get a task object
|
|
153
|
-
# for it.
|
|
154
|
-
def _validate_task(object, task) #:nodoc:
|
|
155
|
-
klass = object.is_a?(Class) ? object : object.class
|
|
156
|
-
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
|
|
157
|
-
|
|
158
|
-
task ||= klass.default_task if klass.respond_to?(:default_task)
|
|
159
|
-
task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task)
|
|
160
|
-
task
|
|
161
153
|
end
|
|
162
154
|
|
|
163
155
|
# Initialize klass using values stored in the @_initializer.
|
|
164
|
-
def
|
|
165
|
-
|
|
166
|
-
klass = object
|
|
156
|
+
def _parse_initialization_options(args, opts, config) #:nodoc:
|
|
157
|
+
stored_args, stored_opts, stored_config = @_initializer
|
|
167
158
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
opts ||= stored_opts.dup
|
|
159
|
+
args ||= stored_args.dup
|
|
160
|
+
opts ||= stored_opts.dup
|
|
171
161
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
[ object.class, object ]
|
|
177
|
-
end
|
|
162
|
+
config ||= {}
|
|
163
|
+
config = stored_config.merge(_shared_configuration).merge!(config)
|
|
164
|
+
|
|
165
|
+
[ args, opts, config ]
|
|
178
166
|
end
|
|
179
167
|
end
|
|
180
168
|
end
|
data/lib/thor/parser/argument.rb
CHANGED
|
@@ -31,10 +31,10 @@ class Thor
|
|
|
31
31
|
|
|
32
32
|
def show_default?
|
|
33
33
|
case default
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
when Array, String, Hash
|
|
35
|
+
!default.empty?
|
|
36
|
+
else
|
|
37
|
+
default
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -45,21 +45,21 @@ class Thor
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def valid_type?(type)
|
|
48
|
-
VALID_TYPES.include?(type.to_sym)
|
|
48
|
+
self.class::VALID_TYPES.include?(type.to_sym)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def default_banner
|
|
52
52
|
case type
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
when :boolean
|
|
54
|
+
nil
|
|
55
|
+
when :string, :default
|
|
56
|
+
human_name.upcase
|
|
57
|
+
when :numeric
|
|
58
|
+
"N"
|
|
59
|
+
when :hash
|
|
60
|
+
"key:value"
|
|
61
|
+
when :array
|
|
62
|
+
"one two three"
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -51,6 +51,11 @@ class Thor
|
|
|
51
51
|
|
|
52
52
|
private
|
|
53
53
|
|
|
54
|
+
def no_or_skip?(arg)
|
|
55
|
+
arg =~ /^--(no|skip)-([-\w]+)$/
|
|
56
|
+
$2
|
|
57
|
+
end
|
|
58
|
+
|
|
54
59
|
def last?
|
|
55
60
|
@pile.empty?
|
|
56
61
|
end
|
|
@@ -114,7 +119,7 @@ class Thor
|
|
|
114
119
|
array
|
|
115
120
|
end
|
|
116
121
|
|
|
117
|
-
# Check if the
|
|
122
|
+
# Check if the peek is numeric format and return a Float or Integer.
|
|
118
123
|
# Otherwise raises an error.
|
|
119
124
|
#
|
|
120
125
|
def parse_numeric(name)
|
|
@@ -127,10 +132,16 @@ class Thor
|
|
|
127
132
|
$&.index('.') ? shift.to_f : shift.to_i
|
|
128
133
|
end
|
|
129
134
|
|
|
130
|
-
# Parse string
|
|
135
|
+
# Parse string:
|
|
136
|
+
# for --string-arg, just return the current value in the pile
|
|
137
|
+
# for --no-string-arg, nil
|
|
131
138
|
#
|
|
132
139
|
def parse_string(name)
|
|
133
|
-
|
|
140
|
+
if no_or_skip?(name)
|
|
141
|
+
nil
|
|
142
|
+
else
|
|
143
|
+
shift
|
|
144
|
+
end
|
|
134
145
|
end
|
|
135
146
|
|
|
136
147
|
# Raises an error if @non_assigned_required array is not empty.
|
data/lib/thor/parser/option.rb
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
class Thor
|
|
2
2
|
class Option < Argument #:nodoc:
|
|
3
|
-
attr_reader :aliases, :group
|
|
3
|
+
attr_reader :aliases, :group, :lazy_default
|
|
4
4
|
|
|
5
5
|
VALID_TYPES = [:boolean, :numeric, :hash, :array, :string]
|
|
6
6
|
|
|
7
|
-
def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, group=nil, aliases=nil)
|
|
7
|
+
def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, lazy_default=nil, group=nil, aliases=nil)
|
|
8
8
|
super(name, description, required, type, default, banner)
|
|
9
|
-
@
|
|
10
|
-
@group
|
|
9
|
+
@lazy_default = lazy_default
|
|
10
|
+
@group = group.to_s.capitalize if group
|
|
11
|
+
@aliases = [*aliases].compact
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
# This parse quick options given as method_options. It makes several
|
|
@@ -48,23 +49,22 @@ class Thor
|
|
|
48
49
|
default = value
|
|
49
50
|
|
|
50
51
|
type = case value
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
value.class.name.downcase.to_sym
|
|
52
|
+
when Symbol
|
|
53
|
+
default = nil
|
|
54
|
+
if VALID_TYPES.include?(value)
|
|
55
|
+
value
|
|
56
|
+
elsif required = (value == :required)
|
|
57
|
+
:string
|
|
58
|
+
end
|
|
59
|
+
when TrueClass, FalseClass
|
|
60
|
+
:boolean
|
|
61
|
+
when Numeric
|
|
62
|
+
:numeric
|
|
63
|
+
when Hash, Array, String
|
|
64
|
+
value.class.name.downcase.to_sym
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
self.new(name.to_s, nil, required, type, default, nil, nil, aliases)
|
|
67
|
+
self.new(name.to_s, nil, required, type, default, nil, nil, nil, aliases)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def switch_name
|
|
@@ -91,38 +91,30 @@ class Thor
|
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
else
|
|
101
|
-
super
|
|
102
|
-
end
|
|
94
|
+
VALID_TYPES.each do |type|
|
|
95
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
96
|
+
def #{type}?
|
|
97
|
+
self.type == #{type.inspect}
|
|
98
|
+
end
|
|
99
|
+
RUBY
|
|
103
100
|
end
|
|
104
101
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def validate!
|
|
108
|
-
raise ArgumentError, "An option cannot be boolean and required." if boolean? && required?
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def valid_type?(type)
|
|
112
|
-
VALID_TYPES.include?(type.to_sym)
|
|
113
|
-
end
|
|
102
|
+
protected
|
|
114
103
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
104
|
+
def validate!
|
|
105
|
+
raise ArgumentError, "An option cannot be boolean and required." if boolean? && required?
|
|
106
|
+
end
|
|
118
107
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
108
|
+
def dasherized?
|
|
109
|
+
name.index('-') == 0
|
|
110
|
+
end
|
|
122
111
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
112
|
+
def undasherize(str)
|
|
113
|
+
str.sub(/^-{1,2}/, '')
|
|
114
|
+
end
|
|
126
115
|
|
|
116
|
+
def dasherize(str)
|
|
117
|
+
(str.length > 1 ? "--" : "-") + str.gsub('_', '-')
|
|
118
|
+
end
|
|
127
119
|
end
|
|
128
120
|
end
|
data/lib/thor/parser/options.rb
CHANGED
|
@@ -53,7 +53,9 @@ class Thor
|
|
|
53
53
|
@pile = args.dup
|
|
54
54
|
|
|
55
55
|
while peek
|
|
56
|
-
|
|
56
|
+
match, is_switch = current_is_switch?
|
|
57
|
+
|
|
58
|
+
if is_switch
|
|
57
59
|
case shift
|
|
58
60
|
when SHORT_SQ_RE
|
|
59
61
|
unshift($1.split('').map { |f| "-#{f}" })
|
|
@@ -68,7 +70,7 @@ class Thor
|
|
|
68
70
|
switch = normalize_switch(switch)
|
|
69
71
|
option = switch_option(switch)
|
|
70
72
|
@assigns[option.human_name] = parse_peek(switch, option)
|
|
71
|
-
elsif
|
|
73
|
+
elsif match
|
|
72
74
|
@unknown << shift
|
|
73
75
|
else
|
|
74
76
|
shift
|
|
@@ -92,15 +94,17 @@ class Thor
|
|
|
92
94
|
#
|
|
93
95
|
def current_is_switch?
|
|
94
96
|
case peek
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
|
|
98
|
+
[true, switch?($1)]
|
|
99
|
+
when SHORT_SQ_RE
|
|
100
|
+
[true, $1.split('').any? { |f| switch?("-#{f}") }]
|
|
101
|
+
else
|
|
102
|
+
[false, false]
|
|
99
103
|
end
|
|
100
104
|
end
|
|
101
105
|
|
|
102
|
-
def
|
|
103
|
-
case
|
|
106
|
+
def current_is_switch_formatted?
|
|
107
|
+
case peek
|
|
104
108
|
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE
|
|
105
109
|
true
|
|
106
110
|
else
|
|
@@ -108,12 +112,8 @@ class Thor
|
|
|
108
112
|
end
|
|
109
113
|
end
|
|
110
114
|
|
|
111
|
-
def current_is_switch_formatted?
|
|
112
|
-
switch_formatted? peek
|
|
113
|
-
end
|
|
114
|
-
|
|
115
115
|
def switch?(arg)
|
|
116
|
-
switch_option(
|
|
116
|
+
switch_option(normalize_switch(arg))
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
def switch_option(arg)
|
|
@@ -124,22 +124,25 @@ class Thor
|
|
|
124
124
|
end
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
-
def no_or_skip?(arg)
|
|
128
|
-
arg =~ /^--(no|skip)-([-\w]+)$/
|
|
129
|
-
$2
|
|
130
|
-
end
|
|
131
|
-
|
|
132
127
|
# Check if the given argument is actually a shortcut.
|
|
133
128
|
#
|
|
134
129
|
def normalize_switch(arg)
|
|
135
|
-
|
|
130
|
+
(@shorts[arg] || arg).tr('_', '-')
|
|
136
131
|
end
|
|
137
132
|
|
|
138
133
|
# Parse boolean values which can be given as --foo=true, --foo or --no-foo.
|
|
139
134
|
#
|
|
140
135
|
def parse_boolean(switch)
|
|
141
136
|
if current_is_value?
|
|
142
|
-
["true", "TRUE", "t", "T", true].include?(
|
|
137
|
+
if ["true", "TRUE", "t", "T", true].include?(peek)
|
|
138
|
+
shift
|
|
139
|
+
true
|
|
140
|
+
elsif ["false", "FALSE", "f", "F", false].include?(peek)
|
|
141
|
+
shift
|
|
142
|
+
false
|
|
143
|
+
else
|
|
144
|
+
true
|
|
145
|
+
end
|
|
143
146
|
else
|
|
144
147
|
@switches.key?(switch) || !no_or_skip?(switch)
|
|
145
148
|
end
|
|
@@ -155,7 +158,9 @@ class Thor
|
|
|
155
158
|
return nil # User set value to nil
|
|
156
159
|
elsif option.string? && !option.required?
|
|
157
160
|
# Return the default if there is one, else the human name
|
|
158
|
-
return option.default || option.human_name
|
|
161
|
+
return option.lazy_default || option.default || option.human_name
|
|
162
|
+
elsif option.lazy_default
|
|
163
|
+
return option.lazy_default
|
|
159
164
|
else
|
|
160
165
|
raise MalformattedArgumentError, "No value provided for option '#{switch}'"
|
|
161
166
|
end
|
|
@@ -164,6 +169,5 @@ class Thor
|
|
|
164
169
|
@non_assigned_required.delete(option)
|
|
165
170
|
send(:"parse_#{option.type}", switch)
|
|
166
171
|
end
|
|
167
|
-
|
|
168
172
|
end
|
|
169
173
|
end
|
data/lib/thor/runner.rb
CHANGED
|
@@ -13,10 +13,10 @@ class Thor::Runner < Thor #:nodoc:
|
|
|
13
13
|
|
|
14
14
|
# Override Thor#help so it can give information about any class and any method.
|
|
15
15
|
#
|
|
16
|
-
def help(meth=nil)
|
|
16
|
+
def help(meth = nil)
|
|
17
17
|
if meth && !self.respond_to?(meth)
|
|
18
18
|
initialize_thorfiles(meth)
|
|
19
|
-
klass, task = Thor::Util.find_class_and_task_by_namespace
|
|
19
|
+
klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
|
|
20
20
|
klass.start(["-h", task].compact, :shell => self.shell)
|
|
21
21
|
else
|
|
22
22
|
super
|
|
@@ -29,7 +29,7 @@ class Thor::Runner < Thor #:nodoc:
|
|
|
29
29
|
def method_missing(meth, *args)
|
|
30
30
|
meth = meth.to_s
|
|
31
31
|
initialize_thorfiles(meth)
|
|
32
|
-
klass, task = Thor::Util.find_class_and_task_by_namespace
|
|
32
|
+
klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
|
|
33
33
|
args.unshift(task) if task
|
|
34
34
|
klass.start(args, :shell => self.shell)
|
|
35
35
|
end
|
|
@@ -39,15 +39,15 @@ class Thor::Runner < Thor #:nodoc:
|
|
|
39
39
|
def install(name)
|
|
40
40
|
initialize_thorfiles
|
|
41
41
|
|
|
42
|
-
# If a directory name is provided as the argument, look for a 'main.thor'
|
|
42
|
+
# If a directory name is provided as the argument, look for a 'main.thor'
|
|
43
43
|
# task in said directory.
|
|
44
44
|
begin
|
|
45
45
|
if File.directory?(File.expand_path(name))
|
|
46
46
|
base, package = File.join(name, "main.thor"), :directory
|
|
47
|
-
contents = open(base).read
|
|
47
|
+
contents = open(base) {|input| input.read }
|
|
48
48
|
else
|
|
49
49
|
base, package = name, :file
|
|
50
|
-
contents = open(name).read
|
|
50
|
+
contents = open(name) {|input| input.read }
|
|
51
51
|
end
|
|
52
52
|
rescue OpenURI::HTTPError
|
|
53
53
|
raise Error, "Error opening URI '#{name}'"
|
|
@@ -139,7 +139,7 @@ class Thor::Runner < Thor #:nodoc:
|
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)"
|
|
142
|
-
method_options :substring => :boolean, :group => :string, :all => :boolean
|
|
142
|
+
method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
|
|
143
143
|
def list(search="")
|
|
144
144
|
initialize_thorfiles
|
|
145
145
|
|
|
@@ -156,8 +156,8 @@ class Thor::Runner < Thor #:nodoc:
|
|
|
156
156
|
|
|
157
157
|
private
|
|
158
158
|
|
|
159
|
-
def self.banner(task)
|
|
160
|
-
"thor " + task.formatted_usage(self,
|
|
159
|
+
def self.banner(task, all = false, subcommand = false)
|
|
160
|
+
"thor " + task.formatted_usage(self, all, subcommand)
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
def thor_root
|
|
@@ -199,7 +199,7 @@ class Thor::Runner < Thor #:nodoc:
|
|
|
199
199
|
#
|
|
200
200
|
def initialize_thorfiles(relevant_to=nil, skip_lookup=false)
|
|
201
201
|
thorfiles(relevant_to, skip_lookup).each do |f|
|
|
202
|
-
Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
|
|
202
|
+
Thor::Util.load_thorfile(f, nil, options[:debug]) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
|
|
203
203
|
end
|
|
204
204
|
end
|
|
205
205
|
|
|
@@ -267,16 +267,11 @@ class Thor::Runner < Thor #:nodoc:
|
|
|
267
267
|
raise Error, "No Thor tasks available" if klasses.empty?
|
|
268
268
|
show_modules if with_modules && !thor_yaml.empty?
|
|
269
269
|
|
|
270
|
-
# Remove subclasses
|
|
271
|
-
klasses.dup.each do |klass|
|
|
272
|
-
klasses -= Thor::Util.thor_classes_in(klass)
|
|
273
|
-
end
|
|
274
|
-
|
|
275
270
|
list = Hash.new { |h,k| h[k] = [] }
|
|
276
271
|
groups = klasses.select { |k| k.ancestors.include?(Thor::Group) }
|
|
277
272
|
|
|
278
273
|
# Get classes which inherit from Thor
|
|
279
|
-
(klasses - groups).each { |k| list[k.namespace] += k.printable_tasks(false) }
|
|
274
|
+
(klasses - groups).each { |k| list[k.namespace.split(":").first] += k.printable_tasks(false) }
|
|
280
275
|
|
|
281
276
|
# Get classes which inherit from Thor::Base
|
|
282
277
|
groups.map! { |k| k.printable_tasks(false).first }
|