thor 0.17.0 → 0.18.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 → CHANGELOG.md} +30 -36
- data/README.md +10 -3
- data/lib/thor.rb +205 -180
- data/lib/thor/actions.rb +5 -5
- data/lib/thor/actions/create_link.rb +3 -0
- data/lib/thor/actions/directory.rb +2 -0
- data/lib/thor/actions/file_manipulation.rb +1 -1
- data/lib/thor/base.rb +84 -95
- data/lib/thor/{task.rb → command.rb} +17 -13
- data/lib/thor/core_ext/io_binary_read.rb +12 -0
- data/lib/thor/error.rb +4 -7
- data/lib/thor/group.rb +30 -33
- data/lib/thor/invocation.rb +28 -26
- data/lib/thor/parser/options.rb +3 -1
- data/lib/thor/runner.rb +21 -20
- data/lib/thor/shell/basic.rb +5 -1
- data/lib/thor/shell/color.rb +4 -0
- data/lib/thor/shell/html.rb +4 -0
- data/lib/thor/util.rb +214 -210
- data/lib/thor/version.rb +1 -1
- data/spec/actions/create_file_spec.rb +1 -1
- data/spec/actions/create_link_spec.rb +15 -1
- data/spec/actions/directory_spec.rb +18 -5
- data/spec/actions/empty_directory_spec.rb +1 -1
- data/spec/actions/file_manipulation_spec.rb +13 -13
- data/spec/actions/inject_into_file_spec.rb +1 -1
- data/spec/actions_spec.rb +1 -1
- data/spec/base_spec.rb +40 -24
- data/spec/command_spec.rb +80 -0
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +1 -1
- data/spec/core_ext/ordered_hash_spec.rb +1 -1
- data/spec/exit_condition_spec.rb +3 -3
- data/spec/fixtures/{task.thor → command.thor} +0 -0
- data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
- data/spec/fixtures/doc/COMMENTER +11 -0
- data/spec/fixtures/doc/README +3 -0
- data/spec/fixtures/doc/block_helper.rb +3 -0
- data/spec/fixtures/doc/config.rb +1 -0
- data/spec/fixtures/doc/config.yaml.tt +1 -0
- data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
- data/spec/fixtures/group.thor +24 -10
- data/spec/fixtures/invoke.thor +3 -3
- data/spec/fixtures/script.thor +40 -15
- data/spec/fixtures/subcommand.thor +17 -0
- data/spec/group_spec.rb +13 -13
- data/spec/{spec_helper.rb → helper.rb} +11 -7
- data/spec/invocation_spec.rb +16 -16
- data/spec/parser/argument_spec.rb +4 -4
- data/spec/parser/arguments_spec.rb +1 -1
- data/spec/parser/option_spec.rb +1 -1
- data/spec/parser/options_spec.rb +6 -1
- data/spec/rake_compat_spec.rb +1 -1
- data/spec/register_spec.rb +12 -12
- data/spec/runner_spec.rb +36 -36
- data/spec/shell/basic_spec.rb +9 -10
- data/spec/shell/color_spec.rb +16 -2
- data/spec/shell/html_spec.rb +1 -1
- data/spec/shell_spec.rb +1 -1
- data/spec/subcommand_spec.rb +30 -0
- data/spec/thor_spec.rb +81 -78
- data/spec/util_spec.rb +10 -10
- data/thor.gemspec +22 -18
- metadata +49 -38
- data/.gitignore +0 -44
- data/.rspec +0 -3
- data/.travis.yml +0 -8
- data/Gemfile +0 -19
- data/bin/rake2thor +0 -86
- data/lib/thor/core_ext/file_binary_read.rb +0 -9
- data/spec/task_spec.rb +0 -80
@@ -1,4 +1,13 @@
|
|
1
|
-
|
1
|
+
## 0.18.0, release 2013-03-26
|
2
|
+
* Remove rake2thor
|
3
|
+
* Only display colors if output medium supports colors
|
4
|
+
* Pass parent_options to subcommands
|
5
|
+
* Fix non-dash-prefixed aliases
|
6
|
+
* Make error messages more helpful
|
7
|
+
* Rename "task" to "command"
|
8
|
+
* Add the method to allow for custom package name
|
9
|
+
|
10
|
+
## 0.17.0, release 2013-01-24
|
2
11
|
* Add better support for tasks that accept arbitrary additional arguments (e.g. things like `bundle exec`)
|
3
12
|
* Add #stop_on_unknown_option!
|
4
13
|
* Only strip from stdin.gets if it wasn't ended with EOF
|
@@ -6,26 +15,26 @@
|
|
6
15
|
* Allow passing options as arguments after "--"
|
7
16
|
* Autoload Thor::Group
|
8
17
|
|
9
|
-
|
18
|
+
## 0.16.0, release 2012-08-14
|
10
19
|
* Add enum to string arguments
|
11
20
|
|
12
|
-
|
21
|
+
## 0.15.4, release 2012-06-29
|
13
22
|
* Fix regression when destination root contains reserved regexp characters
|
14
23
|
|
15
|
-
|
24
|
+
## 0.15.3, release 2012-06-18
|
16
25
|
* Support strict_args_position! for backwards compatibility
|
17
26
|
* Escape Dir glob characters in paths
|
18
27
|
|
19
|
-
|
28
|
+
## 0.15.2, released 2012-05-07
|
20
29
|
* Added print_in_columns
|
21
30
|
* Exposed terminal_width as a public API
|
22
31
|
|
23
|
-
|
32
|
+
## 0.15.1, release 2012-05-06
|
24
33
|
* Fix Ruby 1.8 truncation bug with unicode chars
|
25
34
|
* Fix shell delegate methods to pass their block
|
26
35
|
* Don't output trailing spaces when printing the last column in a table
|
27
36
|
|
28
|
-
|
37
|
+
## 0.15, released 2012-04-29
|
29
38
|
* Alias method_options to options
|
30
39
|
* Refactor say to allow multiple colors
|
31
40
|
* Exposed error as a public API
|
@@ -37,8 +46,7 @@
|
|
37
46
|
* Fix Errno::EPIPE when piping tasks to `head`
|
38
47
|
* More friendly error messages
|
39
48
|
|
40
|
-
|
41
|
-
|
49
|
+
## 0.14, released 2010-07-25
|
42
50
|
* Added CreateLink class and #link_file method
|
43
51
|
* Made Thor::Actions#run use system as default method for system calls
|
44
52
|
* Allow use of private methods from superclass as tasks
|
@@ -49,8 +57,7 @@
|
|
49
57
|
* Deprecated invoke() without arguments
|
50
58
|
* Added :only and :except to check_unknown_options
|
51
59
|
|
52
|
-
|
53
|
-
|
60
|
+
## 0.13, released 2010-02-03
|
54
61
|
* Added :lazy_default which is only triggered if a switch is given
|
55
62
|
* Added Thor::Shell::HTML
|
56
63
|
* Added subcommands
|
@@ -58,8 +65,7 @@
|
|
58
65
|
* Added check_unknown_options! in case you want error messages to be raised in valid switches
|
59
66
|
* run(command) should return the results of command
|
60
67
|
|
61
|
-
|
62
|
-
|
68
|
+
## 0.12, released 2010-01-02
|
63
69
|
* Methods generated by attr_* are automatically not marked as tasks
|
64
70
|
* inject_into_file does not add the same content twice, unless :force is set
|
65
71
|
* Removed rr in favor to rspec mock framework
|
@@ -67,40 +73,31 @@
|
|
67
73
|
* [#7] Do not force white color on status
|
68
74
|
* [#8] Yield a block with the filename on directory
|
69
75
|
|
70
|
-
|
71
|
-
|
76
|
+
## 0.11, released 2009-07-01
|
72
77
|
* Added a rake compatibility layer. It allows you to use spec and rdoc tasks on
|
73
78
|
Thor classes.
|
74
|
-
|
75
79
|
* BACKWARDS INCOMPATIBLE: aliases are not generated automatically anymore
|
76
80
|
since it may cause wrong behavior in the invocation system.
|
77
|
-
|
78
81
|
* thor help now show information about any class/task. All those calls are
|
79
82
|
possible:
|
80
83
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
+
thor help describe
|
85
|
+
thor help describe:amazing
|
84
86
|
Or even with default namespaces:
|
85
87
|
|
86
|
-
|
87
|
-
|
88
|
+
thor help :spec
|
88
89
|
* Thor::Runner now invokes the default task if none is supplied:
|
89
90
|
|
90
|
-
|
91
|
-
|
91
|
+
thor describe # invokes the default task, usually help
|
92
92
|
* Thor::Runner now works with mappings:
|
93
93
|
|
94
|
-
|
95
|
-
|
94
|
+
thor describe -h
|
96
95
|
* Added some documentation and code refactoring.
|
97
96
|
|
98
|
-
|
99
|
-
|
97
|
+
## 0.9.8, released 2008-10-20
|
100
98
|
* Fixed some tiny issues that were introduced lately.
|
101
99
|
|
102
|
-
|
103
|
-
|
100
|
+
## 0.9.7, released 2008-10-13
|
104
101
|
* Setting global method options on the initialize method works as expected:
|
105
102
|
All other tasks will accept these global options in addition to their own.
|
106
103
|
* Added 'group' notion to Thor task sets (class Thor); by default all tasks
|
@@ -108,12 +105,10 @@
|
|
108
105
|
tasks - adding --all will show all tasks. You can also filter on a specific
|
109
106
|
group using the --group option: thor -T --group advanced
|
110
107
|
|
111
|
-
|
112
|
-
|
108
|
+
## 0.9.6, released 2008-09-13
|
113
109
|
* Generic improvements
|
114
110
|
|
115
|
-
|
116
|
-
|
111
|
+
## 0.9.5, released 2008-08-27
|
117
112
|
* Improve Windows compatibility
|
118
113
|
* Update (incorrect) README and task.thor sample file
|
119
114
|
* Options hash is now frozen (once returned)
|
@@ -124,8 +119,7 @@
|
|
124
119
|
* Don't write options for nil or false values. This allows, for example, turning color off when running specs.
|
125
120
|
* Exit with the status of the spec command to help CI stuff out some.
|
126
121
|
|
127
|
-
|
128
|
-
|
122
|
+
## 0.9.4, released 2008-08-13
|
129
123
|
* Try to add Windows compatibility.
|
130
124
|
* BACKWARDS INCOMPATIBLE: options hash is now accessed as a property in your class and is not passed as last argument anymore
|
131
125
|
* Allow options at the beginning of the argument list as well as the end.
|
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
[](https://rubygems.org/gems/thor)
|
1
2
|
[](http://travis-ci.org/wycats/thor)
|
3
|
+
[](https://gemnasium.com/wycats/thor)
|
4
|
+
[](https://codeclimate.com/github/wycats/thor)
|
5
|
+
[](https://coveralls.io/r/wycats/thor)
|
2
6
|
|
3
7
|
Thor
|
4
8
|
====
|
@@ -19,10 +23,13 @@ Installation
|
|
19
23
|
|
20
24
|
Usage and documentation
|
21
25
|
-----------------------
|
22
|
-
Please see
|
26
|
+
Please see the [wiki][] for basic usage and other documentation on using Thor. You can also checkout the [official homepage][homepage].
|
27
|
+
|
28
|
+
[wiki]: https://github.com/wycats/thor/wiki
|
29
|
+
[homepage]: http://whatisthor.com/
|
23
30
|
|
24
31
|
License
|
25
32
|
-------
|
26
|
-
Released under the MIT License. See the [LICENSE][
|
33
|
+
Released under the MIT License. See the [LICENSE][] file for further details.
|
27
34
|
|
28
|
-
[license]:
|
35
|
+
[license]: LICENSE.md
|
data/lib/thor.rb
CHANGED
@@ -3,21 +3,32 @@ require 'thor/base'
|
|
3
3
|
|
4
4
|
class Thor
|
5
5
|
class << self
|
6
|
-
#
|
6
|
+
# Allows for custom "Command" package naming.
|
7
|
+
#
|
8
|
+
# === Parameters
|
9
|
+
# name<String>
|
10
|
+
# options<Hash>
|
11
|
+
#
|
12
|
+
def package_name(name, options={})
|
13
|
+
@package_name = name.nil? || name == '' ? nil : name
|
14
|
+
end
|
15
|
+
|
16
|
+
# Sets the default command when thor is executed without an explicit command to be called.
|
7
17
|
#
|
8
18
|
# ==== Parameters
|
9
|
-
# meth<Symbol>:: name of the default
|
19
|
+
# meth<Symbol>:: name of the default command
|
10
20
|
#
|
11
|
-
def
|
12
|
-
@
|
21
|
+
def default_command(meth=nil)
|
22
|
+
@default_command = case meth
|
13
23
|
when :none
|
14
24
|
'help'
|
15
25
|
when nil
|
16
|
-
@
|
26
|
+
@default_command || from_superclass(:default_command, 'help')
|
17
27
|
else
|
18
28
|
meth.to_s
|
19
29
|
end
|
20
30
|
end
|
31
|
+
alias default_task default_command
|
21
32
|
|
22
33
|
# Registers another Thor subclass as a command.
|
23
34
|
#
|
@@ -36,7 +47,7 @@ class Thor
|
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|
39
|
-
# Defines the usage and the description of the next
|
50
|
+
# Defines the usage and the description of the next command.
|
40
51
|
#
|
41
52
|
# ==== Parameters
|
42
53
|
# usage<String>
|
@@ -45,29 +56,29 @@ class Thor
|
|
45
56
|
#
|
46
57
|
def desc(usage, description, options={})
|
47
58
|
if options[:for]
|
48
|
-
|
49
|
-
|
50
|
-
|
59
|
+
command = find_and_refresh_command(options[:for])
|
60
|
+
command.usage = usage if usage
|
61
|
+
command.description = description if description
|
51
62
|
else
|
52
63
|
@usage, @desc, @hide = usage, description, options[:hide] || false
|
53
64
|
end
|
54
65
|
end
|
55
66
|
|
56
|
-
# Defines the long description of the next
|
67
|
+
# Defines the long description of the next command.
|
57
68
|
#
|
58
69
|
# ==== Parameters
|
59
70
|
# long description<String>
|
60
71
|
#
|
61
72
|
def long_desc(long_description, options={})
|
62
73
|
if options[:for]
|
63
|
-
|
64
|
-
|
74
|
+
command = find_and_refresh_command(options[:for])
|
75
|
+
command.long_description = long_description if long_description
|
65
76
|
else
|
66
77
|
@long_desc = long_description
|
67
78
|
end
|
68
79
|
end
|
69
80
|
|
70
|
-
# Maps an input to a
|
81
|
+
# Maps an input to a command. If you define:
|
71
82
|
#
|
72
83
|
# map "-T" => "list"
|
73
84
|
#
|
@@ -75,10 +86,10 @@ class Thor
|
|
75
86
|
#
|
76
87
|
# thor -T
|
77
88
|
#
|
78
|
-
# Will invoke the list
|
89
|
+
# Will invoke the list command.
|
79
90
|
#
|
80
91
|
# ==== Parameters
|
81
|
-
# Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given
|
92
|
+
# Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
|
82
93
|
#
|
83
94
|
def map(mappings=nil)
|
84
95
|
@map ||= from_superclass(:map, {})
|
@@ -96,7 +107,7 @@ class Thor
|
|
96
107
|
@map
|
97
108
|
end
|
98
109
|
|
99
|
-
# Declares the options for the next
|
110
|
+
# Declares the options for the next command to be declared.
|
100
111
|
#
|
101
112
|
# ==== Parameters
|
102
113
|
# Hash[Symbol => Object]:: The hash key is the name of the option and the value
|
@@ -112,15 +123,15 @@ class Thor
|
|
112
123
|
alias options method_options
|
113
124
|
|
114
125
|
# Adds an option to the set of method options. If :for is given as option,
|
115
|
-
# it allows you to change the options from a previous defined
|
126
|
+
# it allows you to change the options from a previous defined command.
|
116
127
|
#
|
117
|
-
# def
|
128
|
+
# def previous_command
|
118
129
|
# # magic
|
119
130
|
# end
|
120
131
|
#
|
121
|
-
# method_option :foo => :bar, :for => :
|
132
|
+
# method_option :foo => :bar, :for => :previous_command
|
122
133
|
#
|
123
|
-
# def
|
134
|
+
# def next_command
|
124
135
|
# # magic
|
125
136
|
# end
|
126
137
|
#
|
@@ -139,38 +150,38 @@ class Thor
|
|
139
150
|
#
|
140
151
|
def method_option(name, options={})
|
141
152
|
scope = if options[:for]
|
142
|
-
|
153
|
+
find_and_refresh_command(options[:for]).options
|
143
154
|
else
|
144
155
|
method_options
|
145
156
|
end
|
146
157
|
|
147
158
|
build_option(name, options, scope)
|
148
159
|
end
|
149
|
-
|
150
160
|
alias option method_option
|
151
161
|
|
152
|
-
# Prints help information for the given
|
162
|
+
# Prints help information for the given command.
|
153
163
|
#
|
154
164
|
# ==== Parameters
|
155
165
|
# shell<Thor::Shell>
|
156
|
-
#
|
166
|
+
# command_name<String>
|
157
167
|
#
|
158
|
-
def
|
159
|
-
meth =
|
160
|
-
|
161
|
-
|
168
|
+
def command_help(shell, command_name)
|
169
|
+
meth = normalize_command_name(command_name)
|
170
|
+
command = all_commands[meth]
|
171
|
+
handle_no_command_error(meth) unless command
|
162
172
|
|
163
173
|
shell.say "Usage:"
|
164
|
-
shell.say " #{banner(
|
174
|
+
shell.say " #{banner(command)}"
|
165
175
|
shell.say
|
166
|
-
class_options_help(shell, nil =>
|
167
|
-
if
|
176
|
+
class_options_help(shell, nil => command.options.map { |_, o| o })
|
177
|
+
if command.long_description
|
168
178
|
shell.say "Description:"
|
169
|
-
shell.print_wrapped(
|
179
|
+
shell.print_wrapped(command.long_description, :indent => 2)
|
170
180
|
else
|
171
|
-
shell.say
|
181
|
+
shell.say command.description
|
172
182
|
end
|
173
183
|
end
|
184
|
+
alias task_help command_help
|
174
185
|
|
175
186
|
# Prints help information for this class.
|
176
187
|
#
|
@@ -178,32 +189,39 @@ class Thor
|
|
178
189
|
# shell<Thor::Shell>
|
179
190
|
#
|
180
191
|
def help(shell, subcommand = false)
|
181
|
-
list =
|
192
|
+
list = printable_commands(true, subcommand)
|
182
193
|
Thor::Util.thor_classes_in(self).each do |klass|
|
183
|
-
list += klass.
|
194
|
+
list += klass.printable_commands(false)
|
184
195
|
end
|
185
196
|
list.sort!{ |a,b| a[0] <=> b[0] }
|
186
197
|
|
187
|
-
|
198
|
+
if @package_name
|
199
|
+
shell.say "#{@package_name} commands:"
|
200
|
+
else
|
201
|
+
shell.say "Commands:"
|
202
|
+
end
|
203
|
+
|
188
204
|
shell.print_table(list, :indent => 2, :truncate => true)
|
189
205
|
shell.say
|
190
206
|
class_options_help(shell)
|
191
207
|
end
|
192
208
|
|
193
|
-
# Returns
|
194
|
-
def
|
195
|
-
(all ?
|
196
|
-
next if
|
209
|
+
# Returns commands ready to be printed.
|
210
|
+
def printable_commands(all = true, subcommand = false)
|
211
|
+
(all ? all_commands : commands).map do |_, command|
|
212
|
+
next if command.hidden?
|
197
213
|
item = []
|
198
|
-
item << banner(
|
199
|
-
item << (
|
214
|
+
item << banner(command, false, subcommand)
|
215
|
+
item << (command.description ? "# #{command.description.gsub(/\s+/m,' ')}" : "")
|
200
216
|
item
|
201
217
|
end.compact
|
202
218
|
end
|
219
|
+
alias printable_tasks printable_commands
|
203
220
|
|
204
221
|
def subcommands
|
205
222
|
@subcommands ||= from_superclass(:subcommands, [])
|
206
223
|
end
|
224
|
+
alias subtasks subcommands
|
207
225
|
|
208
226
|
def subcommand(subcommand, subcommand_class)
|
209
227
|
self.subcommands << subcommand.to_s
|
@@ -211,9 +229,10 @@ class Thor
|
|
211
229
|
|
212
230
|
define_method(subcommand) do |*args|
|
213
231
|
args, opts = Thor::Arguments.split(args)
|
214
|
-
invoke subcommand_class, args, opts, :invoked_via_subcommand => true
|
232
|
+
invoke subcommand_class, args, opts, :invoked_via_subcommand => true, :class_options => options
|
215
233
|
end
|
216
234
|
end
|
235
|
+
alias subtask subcommand
|
217
236
|
|
218
237
|
# Extend check unknown options to accept a hash of conditions.
|
219
238
|
#
|
@@ -236,10 +255,10 @@ class Thor
|
|
236
255
|
options = check_unknown_options
|
237
256
|
return false unless options
|
238
257
|
|
239
|
-
|
240
|
-
return true unless
|
258
|
+
command = config[:current_command]
|
259
|
+
return true unless command
|
241
260
|
|
242
|
-
name =
|
261
|
+
name = command.name
|
243
262
|
|
244
263
|
if subcommands.include?(name)
|
245
264
|
false
|
@@ -253,16 +272,16 @@ class Thor
|
|
253
272
|
end
|
254
273
|
|
255
274
|
# Stop parsing of options as soon as an unknown option or a regular
|
256
|
-
# argument is encountered. All remaining arguments are passed to the
|
257
|
-
# This is useful if you have a
|
275
|
+
# argument is encountered. All remaining arguments are passed to the command.
|
276
|
+
# This is useful if you have a command that can receive arbitrary additional
|
258
277
|
# options, and where those additional options should not be handled by
|
259
278
|
# Thor.
|
260
279
|
#
|
261
280
|
# ==== Example
|
262
281
|
#
|
263
|
-
# To better understand how this is useful, let's consider a
|
282
|
+
# To better understand how this is useful, let's consider a command that calls
|
264
283
|
# an external command. A user may want to pass arbitrary options and
|
265
|
-
# arguments to that command. The
|
284
|
+
# arguments to that command. The command itself also accepts some options,
|
266
285
|
# which should be handled by Thor.
|
267
286
|
#
|
268
287
|
# class_option "verbose", :type => :boolean
|
@@ -288,161 +307,167 @@ class Thor
|
|
288
307
|
# --verbose foo
|
289
308
|
#
|
290
309
|
# ==== Parameters
|
291
|
-
# Symbol ...:: A list of
|
292
|
-
def stop_on_unknown_option!(*
|
310
|
+
# Symbol ...:: A list of commands that should be affected.
|
311
|
+
def stop_on_unknown_option!(*command_names)
|
293
312
|
@stop_on_unknown_option ||= Set.new
|
294
|
-
@stop_on_unknown_option.merge(
|
313
|
+
@stop_on_unknown_option.merge(command_names)
|
295
314
|
end
|
296
315
|
|
297
|
-
def stop_on_unknown_option?(
|
298
|
-
!!@stop_on_unknown_option && @stop_on_unknown_option.include?(
|
316
|
+
def stop_on_unknown_option?(command) #:nodoc:
|
317
|
+
!!@stop_on_unknown_option && @stop_on_unknown_option.include?(command.name.to_sym)
|
299
318
|
end
|
300
319
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
320
|
+
protected
|
321
|
+
|
322
|
+
# The method responsible for dispatching given the args.
|
323
|
+
def dispatch(meth, given_args, given_opts, config) #:nodoc:
|
324
|
+
# There is an edge case when dispatching from a subcommand.
|
325
|
+
# A problem occurs invoking the default command. This case occurs
|
326
|
+
# when arguments are passed and a default command is defined, and
|
327
|
+
# the first given_args does not match the default command.
|
328
|
+
# Thor use "help" by default so we skip that case.
|
329
|
+
# Note the call to retrieve_command_name. It's called with
|
330
|
+
# given_args.dup since that method calls args.shift. Then lookup
|
331
|
+
# the command normally. If the first item in given_args is not
|
332
|
+
# a command then use the default command. The given_args will be
|
333
|
+
# intact later since dup was used.
|
334
|
+
if config[:invoked_via_subcommand] && given_args.size >= 1 && default_command != "help" && given_args.first != default_command
|
335
|
+
meth ||= retrieve_command_name(given_args.dup)
|
336
|
+
command = all_commands[normalize_command_name(meth)]
|
337
|
+
command ||= all_commands[normalize_command_name(default_command)]
|
338
|
+
else
|
339
|
+
meth ||= retrieve_command_name(given_args)
|
340
|
+
command = all_commands[normalize_command_name(meth)]
|
341
|
+
end
|
323
342
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
end
|
332
|
-
else
|
333
|
-
args, opts = given_args, nil
|
334
|
-
task = Thor::DynamicTask.new(meth)
|
343
|
+
if command
|
344
|
+
args, opts = Thor::Options.split(given_args)
|
345
|
+
if stop_on_unknown_option?(command) && !args.empty?
|
346
|
+
# given_args starts with a non-option, so we treat everything as
|
347
|
+
# ordinary arguments
|
348
|
+
args.concat opts
|
349
|
+
opts.clear
|
335
350
|
end
|
336
|
-
|
337
|
-
opts =
|
338
|
-
|
339
|
-
|
340
|
-
instance = new(args, opts, config)
|
341
|
-
yield instance if block_given?
|
342
|
-
args = instance.args
|
343
|
-
trailing = args[Range.new(arguments.size, -1)]
|
344
|
-
instance.invoke_task(task, trailing || [])
|
351
|
+
else
|
352
|
+
args, opts = given_args, nil
|
353
|
+
command = Thor::DynamicCommand.new(meth)
|
345
354
|
end
|
346
355
|
|
347
|
-
|
348
|
-
|
349
|
-
# the task that is going to be invoked and a boolean which indicates if
|
350
|
-
# the namespace should be displayed as arguments.
|
351
|
-
#
|
352
|
-
def banner(task, namespace = nil, subcommand = false)
|
353
|
-
"#{basename} #{task.formatted_usage(self, $thor_runner, subcommand)}"
|
354
|
-
end
|
356
|
+
opts = given_opts || opts || []
|
357
|
+
config.merge!(:current_command => command, :command_options => command.options)
|
355
358
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
+
instance = new(args, opts, config)
|
360
|
+
yield instance if block_given?
|
361
|
+
args = instance.args
|
362
|
+
trailing = args[Range.new(arguments.size, -1)]
|
363
|
+
instance.invoke_command(command, trailing || [])
|
364
|
+
end
|
359
365
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
else
|
369
|
-
puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " <<
|
370
|
-
"Call desc if you want this method to be available as task or declare it inside a " <<
|
371
|
-
"no_tasks{} block. Invoked from #{caller[1].inspect}."
|
372
|
-
false
|
373
|
-
end
|
374
|
-
end
|
366
|
+
# The banner for this class. You can customize it if you are invoking the
|
367
|
+
# thor class by another ways which is not the Thor::Runner. It receives
|
368
|
+
# the command that is going to be invoked and a boolean which indicates if
|
369
|
+
# the namespace should be displayed as arguments.
|
370
|
+
#
|
371
|
+
def banner(command, namespace = nil, subcommand = false)
|
372
|
+
"#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
|
373
|
+
end
|
375
374
|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
end
|
375
|
+
def baseclass #:nodoc:
|
376
|
+
Thor
|
377
|
+
end
|
380
378
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
379
|
+
def create_command(meth) #:nodoc:
|
380
|
+
if @usage && @desc
|
381
|
+
base_class = @hide ? Thor::HiddenCommand : Thor::Command
|
382
|
+
commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
|
383
|
+
@usage, @desc, @long_desc, @method_options, @hide = nil
|
384
|
+
true
|
385
|
+
elsif self.all_commands[meth] || meth == "method_missing"
|
386
|
+
true
|
387
|
+
else
|
388
|
+
puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " <<
|
389
|
+
"Call desc if you want this method to be available as command or declare it inside a " <<
|
390
|
+
"no_commands{} block. Invoked from #{caller[1].inspect}."
|
391
|
+
false
|
389
392
|
end
|
393
|
+
end
|
394
|
+
alias create_task create_command
|
390
395
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
#
|
396
|
-
# +normalize_task_name+ also converts names like +animal-prison+
|
397
|
-
# into +animal_prison+.
|
398
|
-
def normalize_task_name(meth) #:nodoc:
|
399
|
-
return default_task.to_s.gsub('-', '_') unless meth
|
400
|
-
|
401
|
-
possibilities = find_task_possibilities(meth)
|
402
|
-
if possibilities.size > 1
|
403
|
-
raise ArgumentError, "Ambiguous task #{meth} matches [#{possibilities.join(', ')}]"
|
404
|
-
elsif possibilities.size < 1
|
405
|
-
meth = meth || default_task
|
406
|
-
elsif map[meth]
|
407
|
-
meth = map[meth]
|
408
|
-
else
|
409
|
-
meth = possibilities.first
|
410
|
-
end
|
396
|
+
def initialize_added #:nodoc:
|
397
|
+
class_options.merge!(method_options)
|
398
|
+
@method_options = nil
|
399
|
+
end
|
411
400
|
|
412
|
-
|
401
|
+
# Retrieve the command name from given args.
|
402
|
+
def retrieve_command_name(args) #:nodoc:
|
403
|
+
meth = args.first.to_s unless args.empty?
|
404
|
+
if meth && (map[meth] || meth !~ /^\-/)
|
405
|
+
args.shift
|
406
|
+
else
|
407
|
+
nil
|
413
408
|
end
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
409
|
+
end
|
410
|
+
alias retrieve_task_name retrieve_command_name
|
411
|
+
|
412
|
+
# receives a (possibly nil) command name and returns a name that is in
|
413
|
+
# the commands hash. In addition to normalizing aliases, this logic
|
414
|
+
# will determine if a shortened command is an unambiguous substring of
|
415
|
+
# a command or alias.
|
416
|
+
#
|
417
|
+
# +normalize_command_name+ also converts names like +animal-prison+
|
418
|
+
# into +animal_prison+.
|
419
|
+
def normalize_command_name(meth) #:nodoc:
|
420
|
+
return default_command.to_s.gsub('-', '_') unless meth
|
421
|
+
|
422
|
+
possibilities = find_command_possibilities(meth)
|
423
|
+
if possibilities.size > 1
|
424
|
+
raise ArgumentError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]"
|
425
|
+
elsif possibilities.size < 1
|
426
|
+
meth = meth || default_command
|
427
|
+
elsif map[meth]
|
428
|
+
meth = map[meth]
|
429
|
+
else
|
430
|
+
meth = possibilities.first
|
430
431
|
end
|
431
432
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
433
|
+
meth.to_s.gsub('-','_') # treat foo-bar as foo_bar
|
434
|
+
end
|
435
|
+
alias normalize_task_name normalize_command_name
|
436
|
+
|
437
|
+
# this is the logic that takes the command name passed in by the user
|
438
|
+
# and determines whether it is an unambiguous substrings of a command or
|
439
|
+
# alias name.
|
440
|
+
def find_command_possibilities(meth)
|
441
|
+
len = meth.to_s.length
|
442
|
+
possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort
|
443
|
+
unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
|
444
|
+
|
445
|
+
if possibilities.include?(meth)
|
446
|
+
[meth]
|
447
|
+
elsif unique_possibilities.size == 1
|
448
|
+
unique_possibilities
|
449
|
+
else
|
450
|
+
possibilities
|
437
451
|
end
|
452
|
+
end
|
453
|
+
alias find_task_possibilities find_command_possibilities
|
454
|
+
|
455
|
+
def subcommand_help(cmd)
|
456
|
+
desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
|
457
|
+
class_eval <<-RUBY
|
458
|
+
def help(command = nil, subcommand = true); super; end
|
459
|
+
RUBY
|
460
|
+
end
|
461
|
+
alias subtask_help subcommand_help
|
462
|
+
|
438
463
|
end
|
439
464
|
|
440
465
|
include Thor::Base
|
441
466
|
|
442
467
|
map HELP_MAPPINGS => :help
|
443
468
|
|
444
|
-
desc "help [
|
445
|
-
def help(
|
446
|
-
|
469
|
+
desc "help [COMMAND]", "Describe available commands or one specific command"
|
470
|
+
def help(command = nil, subcommand = false)
|
471
|
+
command ? self.class.command_help(shell, command) : self.class.help(shell, subcommand)
|
447
472
|
end
|
448
473
|
end
|