thor 0.12.0 → 0.13.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/CHANGELOG.rdoc +5 -5
- data/README.rdoc +65 -2
- data/Thorfile +15 -9
- data/bin/thor +1 -0
- data/lib/thor/actions/create_file.rb +2 -2
- data/lib/thor/actions/directory.rb +2 -4
- data/lib/thor/actions/file_manipulation.rb +10 -6
- data/lib/thor/actions/inject_into_file.rb +10 -7
- data/lib/thor/actions.rb +6 -5
- data/lib/thor/base.rb +45 -32
- data/lib/thor/core_ext/file_binary_read.rb +9 -0
- data/lib/thor/group.rb +46 -37
- data/lib/thor/runner.rb +49 -42
- data/lib/thor/shell/basic.rb +49 -29
- data/lib/thor/shell/color.rb +1 -1
- data/lib/thor/shell.rb +1 -1
- data/lib/thor/task.rb +27 -38
- data/lib/thor/util.rb +4 -22
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +43 -45
- data/spec/actions/create_file_spec.rb +7 -7
- data/spec/actions/directory_spec.rb +5 -4
- data/spec/actions/file_manipulation_spec.rb +29 -16
- data/spec/actions/inject_into_file_spec.rb +29 -0
- data/spec/actions_spec.rb +14 -13
- data/spec/base_spec.rb +16 -1
- data/spec/fixtures/bundle/main.thor +1 -0
- data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
- data/spec/fixtures/doc/README +3 -0
- data/spec/fixtures/group.thor +83 -0
- data/spec/fixtures/invoke.thor +112 -0
- data/spec/fixtures/script.thor +134 -0
- data/spec/fixtures/task.thor +10 -0
- data/spec/group_spec.rb +1 -7
- data/spec/runner_spec.rb +35 -39
- data/spec/shell/basic_spec.rb +56 -62
- data/spec/shell/color_spec.rb +6 -6
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +5 -4
- data/spec/task_spec.rb +14 -32
- data/spec/thor_spec.rb +21 -22
- data/spec/util_spec.rb +7 -31
- metadata +28 -19
data/CHANGELOG.rdoc
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
==
|
|
2
|
-
|
|
3
|
-
* Improve spec coverage for Thor::Runner
|
|
4
|
-
|
|
5
|
-
== 0.12, released 2009-11-06
|
|
1
|
+
== 0.12, released 2010-01-02
|
|
6
2
|
|
|
3
|
+
* Methods generated by attr_* are automatically not marked as tasks
|
|
4
|
+
* inject_into_file does not add the same content twice, unless :force is set
|
|
5
|
+
* Removed rr in favor to rspec mock framework
|
|
6
|
+
* Improved output for thor -T
|
|
7
7
|
* [#7] Do not force white color on status
|
|
8
8
|
* [#8] Yield a block with the filename on directory
|
|
9
9
|
|
data/README.rdoc
CHANGED
|
@@ -145,7 +145,7 @@ When invoking the task one:
|
|
|
145
145
|
|
|
146
146
|
The output is "1 2 3", which means that the three task was invoked only once.
|
|
147
147
|
You can even invoke tasks from another class, so be sure to check the
|
|
148
|
-
documentation.
|
|
148
|
+
documentation[http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor.html].
|
|
149
149
|
|
|
150
150
|
== Thor::Group
|
|
151
151
|
|
|
@@ -227,7 +227,70 @@ To use them, you just need to include Thor::Actions in your Thor classes:
|
|
|
227
227
|
|
|
228
228
|
Some actions like copy file requires that a class method called source_root is
|
|
229
229
|
defined in your class. This is the directory where your templates should be
|
|
230
|
-
placed. Be sure to check the documentation.
|
|
230
|
+
placed. Be sure to check the documentation on actions[http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor/Actions.html].
|
|
231
|
+
|
|
232
|
+
== Generators
|
|
233
|
+
|
|
234
|
+
A great use for Thor is creating custom generators. Combining Thor::Group,
|
|
235
|
+
Thor::Actions and ERB templates makes this very easy. Here is an example:
|
|
236
|
+
|
|
237
|
+
class Newgem < Thor::Group
|
|
238
|
+
include Thor::Actions
|
|
239
|
+
|
|
240
|
+
# Define arguments and options
|
|
241
|
+
argument :name
|
|
242
|
+
class_option :test_framework, :default => :test_unit
|
|
243
|
+
|
|
244
|
+
def self.source_root
|
|
245
|
+
File.dirname(__FILE__)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def create_lib_file
|
|
249
|
+
template('templates/newgem.tt', "#{name}/lib/#{name}.rb")
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def create_test_file
|
|
253
|
+
test = options[:test_framework] == "rspec" ? :spec : :test
|
|
254
|
+
create_file "#{name}/#{test}/#{name}_#{test}.rb"
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def copy_licence
|
|
258
|
+
if yes?("Use MIT license?")
|
|
259
|
+
# Make a copy of the MITLICENSE file at the source root
|
|
260
|
+
copy_file "MITLICENSE", "#{name}/MITLICENSE"
|
|
261
|
+
else
|
|
262
|
+
say "Shame on you…", :red
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
Doing a <tt>thor -T</tt> will show how to run our generator. It should read:
|
|
268
|
+
<tt>thor newgem NAME</tt>. This shows that we have to supply a NAME
|
|
269
|
+
argument for our generator to run.
|
|
270
|
+
|
|
271
|
+
The <tt>create_lib_file</tt> uses an ERB template. This is what it looks like:
|
|
272
|
+
|
|
273
|
+
class <%= name.camelize %>
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
The arguments that you set in your generator will automatically be passed in
|
|
277
|
+
when <tt>template</tt> gets called. Be sure to read the documentation[http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor/Actions.html] for
|
|
278
|
+
more options.
|
|
279
|
+
|
|
280
|
+
Running the generator with <tt>thor newgem devise</tt> will
|
|
281
|
+
create two files: "devise/lib/devise.rb",
|
|
282
|
+
"devise/test/devise_test.rb". The user will then be prompt (with the
|
|
283
|
+
use of the method <tt>yes?</tt>) if he wants to copy the MITLICENSE. If you
|
|
284
|
+
want to change the test framework, you can add the option:
|
|
285
|
+
<tt>thor newgem devise --test-framework=rspec</tt>
|
|
286
|
+
This will generate: "devise/lib/devise.rb" and
|
|
287
|
+
"devise/spec/devise_spec.rb".
|
|
288
|
+
|
|
289
|
+
== Further Reading
|
|
290
|
+
|
|
291
|
+
Thor has many scripting possibilities beyond these examples. Be sure to read
|
|
292
|
+
through the documentation[http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor.html] and specs[http://github.com/wycats/thor/tree/master/spec/] to get a better understanding of all the
|
|
293
|
+
options Thor offers.
|
|
231
294
|
|
|
232
295
|
== License
|
|
233
296
|
|
data/Thorfile
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# enconding: utf-8
|
|
2
2
|
|
|
3
3
|
require File.join(File.dirname(__FILE__), "lib", "thor", "version")
|
|
4
|
+
require 'rubygems'
|
|
4
5
|
require 'thor/rake_compat'
|
|
5
6
|
require 'spec/rake/spectask'
|
|
6
|
-
|
|
7
|
+
begin
|
|
8
|
+
require 'rdoc/task'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
end
|
|
7
11
|
|
|
8
12
|
GEM_NAME = 'thor'
|
|
9
13
|
EXTRA_RDOC_FILES = ["README.rdoc", "LICENSE", "CHANGELOG.rdoc", "VERSION", "Thorfile"]
|
|
@@ -25,13 +29,15 @@ class Default < Thor
|
|
|
25
29
|
t.rcov_dir = "rcov"
|
|
26
30
|
end
|
|
27
31
|
|
|
28
|
-
RDoc
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
if defined?(RDoc)
|
|
33
|
+
RDoc::Task.new do |rdoc|
|
|
34
|
+
rdoc.main = "README.rdoc"
|
|
35
|
+
rdoc.rdoc_dir = "rdoc"
|
|
36
|
+
rdoc.title = GEM_NAME
|
|
37
|
+
rdoc.rdoc_files.include(*EXTRA_RDOC_FILES)
|
|
38
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
39
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
40
|
+
end
|
|
35
41
|
end
|
|
36
42
|
|
|
37
43
|
begin
|
|
@@ -52,7 +58,7 @@ class Default < Thor
|
|
|
52
58
|
s.bindir = "bin"
|
|
53
59
|
s.executables = %w( thor rake2thor )
|
|
54
60
|
s.files = s.extra_rdoc_files + Dir.glob("{bin,lib}/**/*")
|
|
55
|
-
s.
|
|
61
|
+
s.test_files.include 'spec/**/*'
|
|
56
62
|
s.test_files.exclude 'spec/sandbox/**/*'
|
|
57
63
|
end
|
|
58
64
|
|
data/bin/thor
CHANGED
|
@@ -42,7 +42,7 @@ class Thor
|
|
|
42
42
|
# Boolean:: true if it is identical, false otherwise.
|
|
43
43
|
#
|
|
44
44
|
def identical?
|
|
45
|
-
exists? && File.
|
|
45
|
+
exists? && File.binread(destination) == render
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# Holds the content to be added to the file.
|
|
@@ -58,7 +58,7 @@ class Thor
|
|
|
58
58
|
def invoke!
|
|
59
59
|
invoke_with_conflict_check do
|
|
60
60
|
FileUtils.mkdir_p(File.dirname(destination))
|
|
61
|
-
File.open(destination, '
|
|
61
|
+
File.open(destination, 'wb') { |f| f.write render }
|
|
62
62
|
end
|
|
63
63
|
given_destination
|
|
64
64
|
end
|
|
@@ -79,11 +79,9 @@ class Thor
|
|
|
79
79
|
next if dirname == given_destination
|
|
80
80
|
base.empty_directory(dirname, config)
|
|
81
81
|
when /\.tt$/
|
|
82
|
-
destination = base.template(file_source, file_destination[0..-4], config)
|
|
83
|
-
@block.call(destination) if @block
|
|
82
|
+
destination = base.template(file_source, file_destination[0..-4], config, &@block)
|
|
84
83
|
else
|
|
85
|
-
destination = base.copy_file(file_source, file_destination, config)
|
|
86
|
-
@block.call(destination) if @block
|
|
84
|
+
destination = base.copy_file(file_source, file_destination, config, &@block)
|
|
87
85
|
end
|
|
88
86
|
end
|
|
89
87
|
end
|
|
@@ -18,12 +18,14 @@ class Thor
|
|
|
18
18
|
#
|
|
19
19
|
# copy_file "doc/README"
|
|
20
20
|
#
|
|
21
|
-
def copy_file(source, destination=nil, config={})
|
|
21
|
+
def copy_file(source, destination=nil, config={}, &block)
|
|
22
22
|
destination ||= source
|
|
23
23
|
source = File.expand_path(find_in_source_paths(source.to_s))
|
|
24
24
|
|
|
25
25
|
create_file destination, nil, config do
|
|
26
|
-
File.
|
|
26
|
+
content = File.binread(source)
|
|
27
|
+
content = block.call(content) if block
|
|
28
|
+
content
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
|
@@ -46,7 +48,7 @@ class Thor
|
|
|
46
48
|
#
|
|
47
49
|
def get(source, destination=nil, config={}, &block)
|
|
48
50
|
source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\//
|
|
49
|
-
render =
|
|
51
|
+
render = File.binread(source)
|
|
50
52
|
|
|
51
53
|
destination ||= if block_given?
|
|
52
54
|
block.arity == 1 ? block.call(render) : block.call
|
|
@@ -72,13 +74,15 @@ class Thor
|
|
|
72
74
|
#
|
|
73
75
|
# template "doc/README"
|
|
74
76
|
#
|
|
75
|
-
def template(source, destination=nil, config={})
|
|
77
|
+
def template(source, destination=nil, config={}, &block)
|
|
76
78
|
destination ||= source
|
|
77
79
|
source = File.expand_path(find_in_source_paths(source.to_s))
|
|
78
80
|
context = instance_eval('binding')
|
|
79
81
|
|
|
80
82
|
create_file destination, nil, config do
|
|
81
|
-
ERB.new(::File.
|
|
83
|
+
content = ERB.new(::File.binread(source), nil, '-').result(context)
|
|
84
|
+
content = block.call(content) if block
|
|
85
|
+
content
|
|
82
86
|
end
|
|
83
87
|
end
|
|
84
88
|
|
|
@@ -189,7 +193,7 @@ class Thor
|
|
|
189
193
|
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
|
|
190
194
|
|
|
191
195
|
unless options[:pretend]
|
|
192
|
-
content = File.
|
|
196
|
+
content = File.binread(path)
|
|
193
197
|
content.gsub!(flag, *args, &block)
|
|
194
198
|
File.open(path, 'wb') { |file| file.write(content) }
|
|
195
199
|
end
|
|
@@ -10,7 +10,8 @@ class Thor
|
|
|
10
10
|
# destination<String>:: Relative path to the destination root
|
|
11
11
|
# data<String>:: Data to add to the file. Can be given as a block.
|
|
12
12
|
# config<Hash>:: give :verbose => false to not log the status and the flag
|
|
13
|
-
# for injection (:after or :before)
|
|
13
|
+
# for injection (:after or :before) or :force => true for
|
|
14
|
+
# insert two or more times the same content.
|
|
14
15
|
#
|
|
15
16
|
# ==== Examples
|
|
16
17
|
#
|
|
@@ -55,7 +56,7 @@ class Thor
|
|
|
55
56
|
replacement + '\0'
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
replace!(/#{flag}/, content)
|
|
59
|
+
replace!(/#{flag}/, content, config[:force])
|
|
59
60
|
end
|
|
60
61
|
|
|
61
62
|
def revoke!
|
|
@@ -69,7 +70,7 @@ class Thor
|
|
|
69
70
|
/(#{Regexp.escape(replacement)})(.*)(#{flag})/m
|
|
70
71
|
end
|
|
71
72
|
|
|
72
|
-
replace!(regexp, content)
|
|
73
|
+
replace!(regexp, content, true)
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
protected
|
|
@@ -88,11 +89,13 @@ class Thor
|
|
|
88
89
|
|
|
89
90
|
# Adds the content to the file.
|
|
90
91
|
#
|
|
91
|
-
def replace!(regexp, string)
|
|
92
|
+
def replace!(regexp, string, force)
|
|
92
93
|
unless base.options[:pretend]
|
|
93
|
-
content = File.
|
|
94
|
-
content.
|
|
95
|
-
|
|
94
|
+
content = File.binread(destination)
|
|
95
|
+
if force || !content.include?(replacement)
|
|
96
|
+
content.gsub!(regexp, string)
|
|
97
|
+
File.open(destination, 'wb') { |file| file.write(content) }
|
|
98
|
+
end
|
|
96
99
|
end
|
|
97
100
|
end
|
|
98
101
|
|
data/lib/thor/actions.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'fileutils'
|
|
2
|
+
require 'thor/core_ext/file_binary_read'
|
|
2
3
|
|
|
3
4
|
Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action|
|
|
4
5
|
require action
|
|
@@ -38,17 +39,17 @@ class Thor
|
|
|
38
39
|
# Add runtime options that help actions execution.
|
|
39
40
|
#
|
|
40
41
|
def add_runtime_options!
|
|
41
|
-
class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
|
|
42
|
-
:desc => "Run but do not make any changes"
|
|
43
|
-
|
|
44
42
|
class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime,
|
|
45
43
|
:desc => "Overwrite files that already exist"
|
|
46
44
|
|
|
47
|
-
class_option :
|
|
48
|
-
|
|
45
|
+
class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
|
|
46
|
+
:desc => "Run but do not make any changes"
|
|
49
47
|
|
|
50
48
|
class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime,
|
|
51
49
|
:desc => "Supress status output"
|
|
50
|
+
|
|
51
|
+
class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime,
|
|
52
|
+
:desc => "Skip files that already exist"
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
|
data/lib/thor/base.rb
CHANGED
|
@@ -8,6 +8,9 @@ require 'thor/task'
|
|
|
8
8
|
require 'thor/util'
|
|
9
9
|
|
|
10
10
|
class Thor
|
|
11
|
+
autoload :Actions, 'thor/actions'
|
|
12
|
+
autoload :RakeCompat, 'thor/rake_compat'
|
|
13
|
+
|
|
11
14
|
# Shortcuts for help.
|
|
12
15
|
HELP_MAPPINGS = %w(-h -? --help -D)
|
|
13
16
|
|
|
@@ -92,6 +95,20 @@ class Thor
|
|
|
92
95
|
end
|
|
93
96
|
|
|
94
97
|
module ClassMethods
|
|
98
|
+
attr_accessor :debugging
|
|
99
|
+
|
|
100
|
+
def attr_reader(*) #:nodoc:
|
|
101
|
+
no_tasks { super }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def attr_writer(*) #:nodoc:
|
|
105
|
+
no_tasks { super }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def attr_accessor(*) #:nodoc:
|
|
109
|
+
no_tasks { super }
|
|
110
|
+
end
|
|
111
|
+
|
|
95
112
|
# Adds an argument to the class and creates an attr_accessor for it.
|
|
96
113
|
#
|
|
97
114
|
# Arguments are different from options in several aspects. The first one
|
|
@@ -347,10 +364,11 @@ class Thor
|
|
|
347
364
|
# Default way to start generators from the command line.
|
|
348
365
|
#
|
|
349
366
|
def start(given_args=ARGV, config={})
|
|
367
|
+
self.debugging = given_args.include?("--debug")
|
|
350
368
|
config[:shell] ||= Thor::Base.shell.new
|
|
351
369
|
yield
|
|
352
370
|
rescue Thor::Error => e
|
|
353
|
-
if
|
|
371
|
+
if debugging
|
|
354
372
|
raise e
|
|
355
373
|
else
|
|
356
374
|
config[:shell].error e.message
|
|
@@ -361,48 +379,43 @@ class Thor
|
|
|
361
379
|
protected
|
|
362
380
|
|
|
363
381
|
# Prints the class options per group. If an option does not belong to
|
|
364
|
-
# any group, it
|
|
365
|
-
# hooks to add extra options, one of them if the third argument called
|
|
366
|
-
# extra_group that should be a hash in the format :group => Array[Options].
|
|
367
|
-
#
|
|
368
|
-
# The second is by returning a lambda used to print values. The lambda
|
|
369
|
-
# requires two options: the group name and the array of options.
|
|
382
|
+
# any group, it's printed as Class option.
|
|
370
383
|
#
|
|
371
|
-
def class_options_help(shell,
|
|
372
|
-
|
|
373
|
-
|
|
384
|
+
def class_options_help(shell, groups={}) #:nodoc:
|
|
385
|
+
# Group options by group
|
|
374
386
|
class_options.each do |_, value|
|
|
375
387
|
groups[value.group] ||= []
|
|
376
388
|
groups[value.group] << value
|
|
377
389
|
end
|
|
378
390
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
391
|
+
# Deal with default group
|
|
392
|
+
global_options = groups.delete(nil) || []
|
|
393
|
+
print_options(shell, global_options)
|
|
382
394
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
395
|
+
# Print all others
|
|
396
|
+
groups.each do |group_name, options|
|
|
397
|
+
print_options(shell, options, group_name)
|
|
398
|
+
end
|
|
399
|
+
end
|
|
386
400
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
401
|
+
# Receives a set of options and print them.
|
|
402
|
+
def print_options(shell, options, group_name=nil)
|
|
403
|
+
return if options.empty?
|
|
390
404
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
shell.print_table(list, :ident => 2)
|
|
394
|
-
shell.say ""
|
|
395
|
-
end
|
|
396
|
-
end
|
|
405
|
+
list = []
|
|
406
|
+
padding = options.collect{ |o| o.aliases.size }.max.to_i * 4
|
|
397
407
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
408
|
+
options.each do |option|
|
|
409
|
+
item = [ option.usage(padding) ]
|
|
410
|
+
item.push(option.description ? "# #{option.description}" : "")
|
|
401
411
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
412
|
+
list << item
|
|
413
|
+
list << [ "", "# Default: #{option.default}" ] if option.show_default?
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
shell.say(group_name ? "#{group_name} options:" : "Options:")
|
|
417
|
+
shell.print_table(list, :ident => 2)
|
|
418
|
+
shell.say ""
|
|
406
419
|
end
|
|
407
420
|
|
|
408
421
|
# Raises an error if the word given is a Thor reserved word.
|
data/lib/thor/group.rb
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
require 'thor/base'
|
|
2
|
+
|
|
1
3
|
# Thor has a special class called Thor::Group. The main difference to Thor class
|
|
2
4
|
# is that it invokes all tasks at once. It also include some methods that allows
|
|
3
5
|
# invocations to be done at the class method, which are not available to Thor
|
|
4
6
|
# tasks.
|
|
5
|
-
#
|
|
6
7
|
class Thor::Group
|
|
7
8
|
class << self
|
|
8
9
|
# The descrition for this Thor::Group. If none is provided, but a source root
|
|
@@ -41,16 +42,12 @@ class Thor::Group
|
|
|
41
42
|
# ==== Options
|
|
42
43
|
# short:: When true, shows only usage.
|
|
43
44
|
#
|
|
44
|
-
def help(shell
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
shell.say
|
|
51
|
-
class_options_help(shell)
|
|
52
|
-
shell.say self.desc if self.desc
|
|
53
|
-
end
|
|
45
|
+
def help(shell)
|
|
46
|
+
shell.say "Usage:"
|
|
47
|
+
shell.say " #{banner}\n"
|
|
48
|
+
shell.say
|
|
49
|
+
class_options_help(shell)
|
|
50
|
+
shell.say self.desc if self.desc
|
|
54
51
|
end
|
|
55
52
|
|
|
56
53
|
# Stores invocations for this class merging with superclass values.
|
|
@@ -177,15 +174,11 @@ class Thor::Group
|
|
|
177
174
|
# Overwrite class options help to allow invoked generators options to be
|
|
178
175
|
# shown recursively when invoking a generator.
|
|
179
176
|
#
|
|
180
|
-
def class_options_help(shell,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
get_options_from_invocations(group_options, class_options) do |klass|
|
|
184
|
-
klass.send(:get_options_from_invocations, group_options, class_options)
|
|
177
|
+
def class_options_help(shell, groups={}) #:nodoc:
|
|
178
|
+
get_options_from_invocations(groups, class_options) do |klass|
|
|
179
|
+
klass.send(:get_options_from_invocations, groups, class_options)
|
|
185
180
|
end
|
|
186
|
-
|
|
187
|
-
group_options.merge!(extra_group) if extra_group
|
|
188
|
-
super(shell, ungrouped_name, group_options)
|
|
181
|
+
super(shell, groups)
|
|
189
182
|
end
|
|
190
183
|
|
|
191
184
|
# Get invocations array and merge options from invocations. Those
|
|
@@ -218,13 +211,27 @@ class Thor::Group
|
|
|
218
211
|
end
|
|
219
212
|
end
|
|
220
213
|
|
|
214
|
+
# Returns tasks ready to be printed.
|
|
215
|
+
def printable_tasks(*)
|
|
216
|
+
item = []
|
|
217
|
+
item << banner
|
|
218
|
+
item << (desc ? "# #{desc.gsub(/\s+/m,' ')}" : "")
|
|
219
|
+
[item]
|
|
220
|
+
end
|
|
221
|
+
|
|
221
222
|
protected
|
|
222
223
|
|
|
223
224
|
# The banner for this class. You can customize it if you are invoking the
|
|
224
225
|
# thor class by another ways which is not the Thor::Runner.
|
|
225
226
|
#
|
|
226
227
|
def banner
|
|
227
|
-
|
|
228
|
+
base = $thor_runner ? "thor" : File.basename($0.split(" ").first)
|
|
229
|
+
"#{base} #{self_task.formatted_usage(self, false)}"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Represents the whole class as a task.
|
|
233
|
+
def self_task #:nodoc:
|
|
234
|
+
Thor::Task::Dynamic.new(self.namespace, class_options)
|
|
228
235
|
end
|
|
229
236
|
|
|
230
237
|
def baseclass #:nodoc:
|
|
@@ -241,23 +248,25 @@ class Thor::Group
|
|
|
241
248
|
|
|
242
249
|
protected
|
|
243
250
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
invoke klass, task, *args
|
|
251
|
+
# Shortcut to invoke with padding and block handling. Use internally by
|
|
252
|
+
# invoke and invoke_from_option class methods.
|
|
253
|
+
def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc:
|
|
254
|
+
shell.padding += 1
|
|
255
|
+
|
|
256
|
+
result = if block_given?
|
|
257
|
+
case block.arity
|
|
258
|
+
when 3
|
|
259
|
+
block.call(self, klass, task)
|
|
260
|
+
when 2
|
|
261
|
+
block.call(self, klass)
|
|
262
|
+
when 1
|
|
263
|
+
instance_exec(klass, &block)
|
|
258
264
|
end
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
result
|
|
265
|
+
else
|
|
266
|
+
invoke klass, task, *args
|
|
262
267
|
end
|
|
268
|
+
|
|
269
|
+
shell.padding -= 1
|
|
270
|
+
result
|
|
271
|
+
end
|
|
263
272
|
end
|