thor 0.20.3 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/lib/thor.rb +19 -4
- data/lib/thor/actions.rb +17 -12
- data/lib/thor/actions/create_file.rb +1 -1
- data/lib/thor/actions/create_link.rb +1 -1
- data/lib/thor/actions/directory.rb +7 -17
- data/lib/thor/actions/file_manipulation.rb +5 -5
- data/lib/thor/actions/inject_into_file.rb +19 -8
- data/lib/thor/base.rb +50 -38
- data/lib/thor/command.rb +21 -14
- data/lib/thor/error.rb +14 -18
- data/lib/thor/group.rb +1 -1
- data/lib/thor/invocation.rb +1 -0
- data/lib/thor/line_editor.rb +2 -2
- data/lib/thor/line_editor/basic.rb +1 -1
- data/lib/thor/line_editor/readline.rb +6 -6
- data/lib/thor/nested_context.rb +29 -0
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/parser/arguments.rb +2 -2
- data/lib/thor/parser/option.rb +20 -7
- data/lib/thor/parser/options.rb +13 -3
- data/lib/thor/rake_compat.rb +1 -0
- data/lib/thor/runner.rb +5 -4
- data/lib/thor/shell.rb +3 -3
- data/lib/thor/shell/basic.rb +10 -1
- data/lib/thor/shell/color.rb +6 -2
- data/lib/thor/shell/html.rb +3 -3
- data/lib/thor/util.rb +16 -0
- data/lib/thor/version.rb +1 -1
- data/thor.gemspec +2 -2
- metadata +13 -9
- data/lib/thor/core_ext/io_binary_read.rb +0 -12
- data/lib/thor/core_ext/ordered_hash.rb +0 -129
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0fc8dc6eec2f5a8963a04be9954614a50272049dc1ee40ac444a8de4961bc982
|
|
4
|
+
data.tar.gz: 0ea9eb9c0a1685ebf30a7c3b245d7f364dc03a1d3bd52a9af90135a561fd8e5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 88f22ea77e8939f637d5b01c7178ec0b4ce12c92dfeab0d747a5d4b00c5fef90caff0a95fef0ff3b7d80c360ac15afdc222f77322729ec1de55252cdf76fd644
|
|
7
|
+
data.tar.gz: 49364d76cf884f66a68bc12536668881bd144237017aad4d38bc5bd9d041672b9b68ce0642139d97e98990e39899c522b6d4c37eb6591f826d276a26a1bf5e11
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# 1.0.0
|
|
2
|
+
* Drop support to Ruby 1.8 and 1.9.
|
|
3
|
+
* Deprecate relying on default `exit_on_failure?`.
|
|
4
|
+
In preparation to make Thor commands exit when there is a failure we are deprecating
|
|
5
|
+
defining a command without defining what behavior is expected when there is a failure.
|
|
6
|
+
|
|
7
|
+
To fix the deprecation you need to define a class method called `exit_on_failure?` returning
|
|
8
|
+
|
|
9
|
+
`false` if you want the current behavior or `true` if you want the new behavior.
|
|
10
|
+
* Deprecate defining an option with the default value using a different type as defined in the option.
|
|
11
|
+
* Allow options to be repeatable. See #674.
|
|
12
|
+
|
|
1
13
|
# 0.20.3
|
|
2
14
|
* Support old versions of `did_you_mean`.
|
|
3
15
|
|
|
@@ -5,7 +17,7 @@
|
|
|
5
17
|
* Fix `did_you_mean` support.
|
|
6
18
|
|
|
7
19
|
# 0.20.1
|
|
8
|
-
* Support new versions
|
|
20
|
+
* Support new versions of ERB.
|
|
9
21
|
* Fix `check_unknown_options!` to not check the content that was not parsed, i.e. after a `--` or after the first unknown with `stop_on_unknown_option!`
|
|
10
22
|
* Add `did_you_mean` support.
|
|
11
23
|
|
data/lib/thor.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require "set"
|
|
2
|
-
|
|
2
|
+
require_relative "thor/base"
|
|
3
3
|
|
|
4
4
|
class Thor
|
|
5
5
|
class << self
|
|
@@ -90,9 +90,14 @@ class Thor
|
|
|
90
90
|
# ==== Parameters
|
|
91
91
|
# Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
|
|
92
92
|
#
|
|
93
|
-
def map(mappings = nil)
|
|
93
|
+
def map(mappings = nil, **kw)
|
|
94
94
|
@map ||= from_superclass(:map, {})
|
|
95
95
|
|
|
96
|
+
if mappings && !kw.empty?
|
|
97
|
+
mappings = kw.merge!(mappings)
|
|
98
|
+
else
|
|
99
|
+
mappings ||= kw
|
|
100
|
+
end
|
|
96
101
|
if mappings
|
|
97
102
|
mappings.each do |key, value|
|
|
98
103
|
if key.respond_to?(:each)
|
|
@@ -170,7 +175,7 @@ class Thor
|
|
|
170
175
|
handle_no_command_error(meth) unless command
|
|
171
176
|
|
|
172
177
|
shell.say "Usage:"
|
|
173
|
-
shell.say " #{banner(command)}"
|
|
178
|
+
shell.say " #{banner(command).split("\n").join("\n ")}"
|
|
174
179
|
shell.say
|
|
175
180
|
class_options_help(shell, nil => command.options.values)
|
|
176
181
|
if command.long_description
|
|
@@ -339,6 +344,13 @@ class Thor
|
|
|
339
344
|
command && disable_required_check.include?(command.name.to_sym)
|
|
340
345
|
end
|
|
341
346
|
|
|
347
|
+
def deprecation_warning(message) #:nodoc:
|
|
348
|
+
unless ENV['THOR_SILENCE_DEPRECATION']
|
|
349
|
+
warn "Deprecation warning: #{message}\n" +
|
|
350
|
+
'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.'
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
342
354
|
protected
|
|
343
355
|
|
|
344
356
|
def stop_on_unknown_option #:nodoc:
|
|
@@ -393,7 +405,10 @@ class Thor
|
|
|
393
405
|
# the namespace should be displayed as arguments.
|
|
394
406
|
#
|
|
395
407
|
def banner(command, namespace = nil, subcommand = false)
|
|
396
|
-
|
|
408
|
+
$thor_runner ||= false
|
|
409
|
+
command.formatted_usage(self, $thor_runner, subcommand).split("\n").map do |formatted_usage|
|
|
410
|
+
"#{basename} #{formatted_usage}"
|
|
411
|
+
end.join("\n")
|
|
397
412
|
end
|
|
398
413
|
|
|
399
414
|
def baseclass #:nodoc:
|
data/lib/thor/actions.rb
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
require "thor/actions/file_manipulation"
|
|
8
|
-
require "thor/actions/inject_into_file"
|
|
1
|
+
require_relative "actions/create_file"
|
|
2
|
+
require_relative "actions/create_link"
|
|
3
|
+
require_relative "actions/directory"
|
|
4
|
+
require_relative "actions/empty_directory"
|
|
5
|
+
require_relative "actions/file_manipulation"
|
|
6
|
+
require_relative "actions/inject_into_file"
|
|
9
7
|
|
|
10
8
|
class Thor
|
|
11
9
|
module Actions
|
|
12
10
|
attr_accessor :behavior
|
|
13
11
|
|
|
14
12
|
def self.included(base) #:nodoc:
|
|
13
|
+
super(base)
|
|
15
14
|
base.extend ClassMethods
|
|
16
15
|
end
|
|
17
16
|
|
|
@@ -257,13 +256,19 @@ class Thor
|
|
|
257
256
|
|
|
258
257
|
return if options[:pretend]
|
|
259
258
|
|
|
260
|
-
|
|
259
|
+
env_splat = [config[:env]] if config[:env]
|
|
261
260
|
|
|
262
|
-
if config[:
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
if config[:capture]
|
|
262
|
+
require "open3"
|
|
263
|
+
result, status = Open3.capture2e(*env_splat, command.to_s)
|
|
264
|
+
success = status.success?
|
|
265
|
+
else
|
|
266
|
+
result = system(*env_splat, command.to_s)
|
|
267
|
+
success = result
|
|
265
268
|
end
|
|
266
269
|
|
|
270
|
+
abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?)
|
|
271
|
+
|
|
267
272
|
result
|
|
268
273
|
end
|
|
269
274
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative "empty_directory"
|
|
2
2
|
|
|
3
3
|
class Thor
|
|
4
4
|
module Actions
|
|
@@ -56,7 +56,7 @@ class Thor
|
|
|
56
56
|
attr_reader :source
|
|
57
57
|
|
|
58
58
|
def initialize(base, source, destination = nil, config = {}, &block)
|
|
59
|
-
@source = File.expand_path(base.find_in_source_paths(source.to_s))
|
|
59
|
+
@source = File.expand_path(Dir[Util.escape_globs(base.find_in_source_paths(source.to_s))].first)
|
|
60
60
|
@block = block
|
|
61
61
|
super(base, destination, {:recursive => true}.merge(config))
|
|
62
62
|
end
|
|
@@ -96,22 +96,12 @@ class Thor
|
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def files(lookup)
|
|
105
|
-
Dir[lookup]
|
|
106
|
-
end
|
|
107
|
-
else
|
|
108
|
-
def file_level_lookup(previous_lookup)
|
|
109
|
-
File.join(previous_lookup, "*")
|
|
110
|
-
end
|
|
99
|
+
def file_level_lookup(previous_lookup)
|
|
100
|
+
File.join(previous_lookup, "*")
|
|
101
|
+
end
|
|
111
102
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
end
|
|
103
|
+
def files(lookup)
|
|
104
|
+
Dir.glob(lookup, File::FNM_DOTMATCH)
|
|
115
105
|
end
|
|
116
106
|
end
|
|
117
107
|
end
|
|
@@ -23,14 +23,14 @@ class Thor
|
|
|
23
23
|
destination = args.first || source
|
|
24
24
|
source = File.expand_path(find_in_source_paths(source.to_s))
|
|
25
25
|
|
|
26
|
-
create_file destination, nil, config do
|
|
26
|
+
resulting_destination = create_file destination, nil, config do
|
|
27
27
|
content = File.binread(source)
|
|
28
28
|
content = yield(content) if block
|
|
29
29
|
content
|
|
30
30
|
end
|
|
31
31
|
if config[:mode] == :preserve
|
|
32
32
|
mode = File.stat(source).mode
|
|
33
|
-
chmod(
|
|
33
|
+
chmod(resulting_destination, mode, config)
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -80,14 +80,14 @@ class Thor
|
|
|
80
80
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
|
81
81
|
destination = args.first
|
|
82
82
|
|
|
83
|
-
if source =~ %r{^https?\://}
|
|
83
|
+
render = if source =~ %r{^https?\://}
|
|
84
84
|
require "open-uri"
|
|
85
|
+
URI.send(:open, source) { |input| input.binmode.read }
|
|
85
86
|
else
|
|
86
87
|
source = File.expand_path(find_in_source_paths(source.to_s))
|
|
88
|
+
open(source) { |input| input.binmode.read }
|
|
87
89
|
end
|
|
88
90
|
|
|
89
|
-
render = open(source) { |input| input.binmode.read }
|
|
90
|
-
|
|
91
91
|
destination ||= if block_given?
|
|
92
92
|
block.arity == 1 ? yield(render) : yield
|
|
93
93
|
else
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative "empty_directory"
|
|
2
2
|
|
|
3
3
|
class Thor
|
|
4
4
|
module Actions
|
|
@@ -21,9 +21,14 @@ class Thor
|
|
|
21
21
|
# gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n")
|
|
22
22
|
# end
|
|
23
23
|
#
|
|
24
|
+
WARNINGS = { unchanged_no_flag: 'File unchanged! The supplied flag value not found!' }
|
|
25
|
+
|
|
24
26
|
def insert_into_file(destination, *args, &block)
|
|
25
27
|
data = block_given? ? block : args.shift
|
|
26
|
-
|
|
28
|
+
|
|
29
|
+
config = args.shift || {}
|
|
30
|
+
config[:after] = /\z/ unless config.key?(:before) || config.key?(:after)
|
|
31
|
+
|
|
27
32
|
action InjectIntoFile.new(self, destination, data, config)
|
|
28
33
|
end
|
|
29
34
|
alias_method :inject_into_file, :insert_into_file
|
|
@@ -45,8 +50,6 @@ class Thor
|
|
|
45
50
|
end
|
|
46
51
|
|
|
47
52
|
def invoke!
|
|
48
|
-
say_status :invoke
|
|
49
|
-
|
|
50
53
|
content = if @behavior == :after
|
|
51
54
|
'\0' + replacement
|
|
52
55
|
else
|
|
@@ -54,7 +57,11 @@ class Thor
|
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
if exists?
|
|
57
|
-
replace!(/#{flag}/, content, config[:force])
|
|
60
|
+
if replace!(/#{flag}/, content, config[:force])
|
|
61
|
+
say_status(:invoke)
|
|
62
|
+
else
|
|
63
|
+
say_status(:unchanged, warning: WARNINGS[:unchanged_no_flag], color: :red)
|
|
64
|
+
end
|
|
58
65
|
else
|
|
59
66
|
unless pretend?
|
|
60
67
|
raise Thor::Error, "The file #{ destination } does not appear to exist"
|
|
@@ -78,7 +85,7 @@ class Thor
|
|
|
78
85
|
|
|
79
86
|
protected
|
|
80
87
|
|
|
81
|
-
def say_status(behavior)
|
|
88
|
+
def say_status(behavior, warning: nil, color: nil)
|
|
82
89
|
status = if behavior == :invoke
|
|
83
90
|
if flag == /\A/
|
|
84
91
|
:prepend
|
|
@@ -87,11 +94,13 @@ class Thor
|
|
|
87
94
|
else
|
|
88
95
|
:insert
|
|
89
96
|
end
|
|
97
|
+
elsif warning
|
|
98
|
+
warning
|
|
90
99
|
else
|
|
91
100
|
:subtract
|
|
92
101
|
end
|
|
93
102
|
|
|
94
|
-
super(status, config[:verbose])
|
|
103
|
+
super(status, (color || config[:verbose]))
|
|
95
104
|
end
|
|
96
105
|
|
|
97
106
|
# Adds the content to the file.
|
|
@@ -100,8 +109,10 @@ class Thor
|
|
|
100
109
|
return if pretend?
|
|
101
110
|
content = File.read(destination)
|
|
102
111
|
if force || !content.include?(replacement)
|
|
103
|
-
content.gsub!(regexp, string)
|
|
112
|
+
success = content.gsub!(regexp, string)
|
|
113
|
+
|
|
104
114
|
File.open(destination, "wb") { |file| file.write(content) }
|
|
115
|
+
success
|
|
105
116
|
end
|
|
106
117
|
end
|
|
107
118
|
end
|
data/lib/thor/base.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
require_relative "command"
|
|
2
|
+
require_relative "core_ext/hash_with_indifferent_access"
|
|
3
|
+
require_relative "error"
|
|
4
|
+
require_relative "invocation"
|
|
5
|
+
require_relative "nested_context"
|
|
6
|
+
require_relative "parser"
|
|
7
|
+
require_relative "shell"
|
|
8
|
+
require_relative "line_editor"
|
|
9
|
+
require_relative "util"
|
|
10
10
|
|
|
11
11
|
class Thor
|
|
12
|
-
autoload :Actions, "
|
|
13
|
-
autoload :RakeCompat, "
|
|
14
|
-
autoload :Group, "
|
|
12
|
+
autoload :Actions, File.expand_path("actions", __dir__)
|
|
13
|
+
autoload :RakeCompat, File.expand_path("rake_compat", __dir__)
|
|
14
|
+
autoload :Group, File.expand_path("group", __dir__)
|
|
15
15
|
|
|
16
16
|
# Shortcuts for help.
|
|
17
17
|
HELP_MAPPINGS = %w(-h -? --help -D)
|
|
@@ -89,6 +89,7 @@ class Thor
|
|
|
89
89
|
|
|
90
90
|
class << self
|
|
91
91
|
def included(base) #:nodoc:
|
|
92
|
+
super(base)
|
|
92
93
|
base.extend ClassMethods
|
|
93
94
|
base.send :include, Invocation
|
|
94
95
|
base.send :include, Shell
|
|
@@ -153,17 +154,20 @@ class Thor
|
|
|
153
154
|
|
|
154
155
|
# If you want to raise an error when the default value of an option does not match
|
|
155
156
|
# the type call check_default_type!
|
|
156
|
-
# This
|
|
157
|
+
# This will be the default; for compatibility a deprecation warning is issued if necessary.
|
|
157
158
|
def check_default_type!
|
|
158
159
|
@check_default_type = true
|
|
159
160
|
end
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
# If you want to use defaults that don't match the type of an option,
|
|
163
|
+
# either specify `check_default_type: false` or call `allow_incompatible_default_type!`
|
|
164
|
+
def allow_incompatible_default_type!
|
|
165
|
+
@check_default_type = false
|
|
163
166
|
end
|
|
164
167
|
|
|
165
|
-
def check_default_type
|
|
166
|
-
|
|
168
|
+
def check_default_type #:nodoc:
|
|
169
|
+
@check_default_type = from_superclass(:check_default_type, nil) unless defined?(@check_default_type)
|
|
170
|
+
@check_default_type
|
|
167
171
|
end
|
|
168
172
|
|
|
169
173
|
# If true, option parsing is suspended as soon as an unknown option or a
|
|
@@ -353,22 +357,22 @@ class Thor
|
|
|
353
357
|
# Returns the commands for this Thor class.
|
|
354
358
|
#
|
|
355
359
|
# ==== Returns
|
|
356
|
-
#
|
|
357
|
-
#
|
|
360
|
+
# Hash:: An ordered hash with commands names as keys and Thor::Command
|
|
361
|
+
# objects as values.
|
|
358
362
|
#
|
|
359
363
|
def commands
|
|
360
|
-
@commands ||=
|
|
364
|
+
@commands ||= Hash.new
|
|
361
365
|
end
|
|
362
366
|
alias_method :tasks, :commands
|
|
363
367
|
|
|
364
368
|
# Returns the commands for this Thor class and all subclasses.
|
|
365
369
|
#
|
|
366
370
|
# ==== Returns
|
|
367
|
-
#
|
|
368
|
-
#
|
|
371
|
+
# Hash:: An ordered hash with commands names as keys and Thor::Command
|
|
372
|
+
# objects as values.
|
|
369
373
|
#
|
|
370
374
|
def all_commands
|
|
371
|
-
@all_commands ||= from_superclass(:all_commands,
|
|
375
|
+
@all_commands ||= from_superclass(:all_commands, Hash.new)
|
|
372
376
|
@all_commands.merge!(commands)
|
|
373
377
|
end
|
|
374
378
|
alias_method :all_tasks, :all_commands
|
|
@@ -415,14 +419,20 @@ class Thor
|
|
|
415
419
|
# remove_command :this_is_not_a_command
|
|
416
420
|
# end
|
|
417
421
|
#
|
|
418
|
-
def no_commands
|
|
419
|
-
|
|
420
|
-
yield
|
|
421
|
-
ensure
|
|
422
|
-
@no_commands = false
|
|
422
|
+
def no_commands(&block)
|
|
423
|
+
no_commands_context.enter(&block)
|
|
423
424
|
end
|
|
425
|
+
|
|
424
426
|
alias_method :no_tasks, :no_commands
|
|
425
427
|
|
|
428
|
+
def no_commands_context
|
|
429
|
+
@no_commands_context ||= NestedContext.new
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def no_commands?
|
|
433
|
+
no_commands_context.entered?
|
|
434
|
+
end
|
|
435
|
+
|
|
426
436
|
# Sets the namespace for the Thor or Thor::Group class. By default the
|
|
427
437
|
# namespace is retrieved from the class name. If your Thor class is named
|
|
428
438
|
# Scripts::MyScript, the help method, for example, will be called as:
|
|
@@ -502,10 +512,16 @@ class Thor
|
|
|
502
512
|
msg = "ERROR: \"#{basename} #{name}\" was called with ".dup
|
|
503
513
|
msg << "no arguments" if args.empty?
|
|
504
514
|
msg << "arguments " << args.inspect unless args.empty?
|
|
505
|
-
msg << "\nUsage: #{banner(command).
|
|
515
|
+
msg << "\nUsage: \"#{banner(command).split("\n").join("\"\n \"")}\""
|
|
506
516
|
raise InvocationError, msg
|
|
507
517
|
end
|
|
508
518
|
|
|
519
|
+
# A flag that makes the process exit with status 1 if any error happens.
|
|
520
|
+
def exit_on_failure?
|
|
521
|
+
Thor.deprecation_warning "Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `#{self.name}`"
|
|
522
|
+
false
|
|
523
|
+
end
|
|
524
|
+
|
|
509
525
|
protected
|
|
510
526
|
|
|
511
527
|
# Prints the class options per group. If an option does not belong to
|
|
@@ -563,7 +579,7 @@ class Thor
|
|
|
563
579
|
# options<Hash>:: Described in both class_option and method_option.
|
|
564
580
|
# scope<Hash>:: Options hash that is being built up
|
|
565
581
|
def build_option(name, options, scope) #:nodoc:
|
|
566
|
-
scope[name] = Thor::Option.new(name,
|
|
582
|
+
scope[name] = Thor::Option.new(name, {:check_default_type => check_default_type}.merge!(options))
|
|
567
583
|
end
|
|
568
584
|
|
|
569
585
|
# Receives a hash of options, parse them and add to the scope. This is a
|
|
@@ -596,13 +612,15 @@ class Thor
|
|
|
596
612
|
# Everytime someone inherits from a Thor class, register the klass
|
|
597
613
|
# and file into baseclass.
|
|
598
614
|
def inherited(klass)
|
|
615
|
+
super(klass)
|
|
599
616
|
Thor::Base.register_klass_file(klass)
|
|
600
|
-
klass.instance_variable_set(:@no_commands,
|
|
617
|
+
klass.instance_variable_set(:@no_commands, 0)
|
|
601
618
|
end
|
|
602
619
|
|
|
603
620
|
# Fire this callback whenever a method is added. Added methods are
|
|
604
621
|
# tracked as commands by invoking the create_command method.
|
|
605
622
|
def method_added(meth)
|
|
623
|
+
super(meth)
|
|
606
624
|
meth = meth.to_s
|
|
607
625
|
|
|
608
626
|
if meth == "initialize"
|
|
@@ -613,8 +631,7 @@ class Thor
|
|
|
613
631
|
# Return if it's not a public instance method
|
|
614
632
|
return unless public_method_defined?(meth.to_sym)
|
|
615
633
|
|
|
616
|
-
|
|
617
|
-
return if @no_commands || !create_command(meth)
|
|
634
|
+
return if no_commands? || !create_command(meth)
|
|
618
635
|
|
|
619
636
|
is_thor_reserved_word?(meth, :command)
|
|
620
637
|
Thor::Base.register_klass_file(self)
|
|
@@ -641,11 +658,6 @@ class Thor
|
|
|
641
658
|
end
|
|
642
659
|
end
|
|
643
660
|
|
|
644
|
-
# A flag that makes the process exit with status 1 if any error happens.
|
|
645
|
-
def exit_on_failure?
|
|
646
|
-
false
|
|
647
|
-
end
|
|
648
|
-
|
|
649
661
|
#
|
|
650
662
|
# The basename of the program invoking the thor class.
|
|
651
663
|
#
|
data/lib/thor/command.rb
CHANGED
|
@@ -49,24 +49,32 @@ class Thor
|
|
|
49
49
|
|
|
50
50
|
formatted ||= "".dup
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
usage.to_s.gsub(/^#{name}/) do |match|
|
|
55
|
-
match << " " << klass.arguments.map(&:usage).compact.join(" ")
|
|
56
|
-
end
|
|
57
|
-
else
|
|
58
|
-
usage.to_s
|
|
59
|
-
end
|
|
52
|
+
Array(usage).map do |specific_usage|
|
|
53
|
+
formatted_specific_usage = formatted
|
|
60
54
|
|
|
61
|
-
|
|
62
|
-
formatted << " #{required_options}"
|
|
55
|
+
formatted_specific_usage += required_arguments_for(klass, specific_usage)
|
|
63
56
|
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
# Add required options
|
|
58
|
+
formatted_specific_usage += " #{required_options}"
|
|
59
|
+
|
|
60
|
+
# Strip and go!
|
|
61
|
+
formatted_specific_usage.strip
|
|
62
|
+
end.join("\n")
|
|
66
63
|
end
|
|
67
64
|
|
|
68
65
|
protected
|
|
69
66
|
|
|
67
|
+
# Add usage with required arguments
|
|
68
|
+
def required_arguments_for(klass, usage)
|
|
69
|
+
if klass && !klass.arguments.empty?
|
|
70
|
+
usage.to_s.gsub(/^#{name}/) do |match|
|
|
71
|
+
match << " " << klass.arguments.map(&:usage).compact.join(" ")
|
|
72
|
+
end
|
|
73
|
+
else
|
|
74
|
+
usage.to_s
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
70
78
|
def not_debugging?(instance)
|
|
71
79
|
!(instance.class.respond_to?(:debugging) && instance.class.debugging)
|
|
72
80
|
end
|
|
@@ -97,8 +105,7 @@ class Thor
|
|
|
97
105
|
def handle_argument_error?(instance, error, caller)
|
|
98
106
|
not_debugging?(instance) && (error.message =~ /wrong number of arguments/ || error.message =~ /given \d*, expected \d*/) && begin
|
|
99
107
|
saned = sans_backtrace(error.backtrace, caller)
|
|
100
|
-
|
|
101
|
-
saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9")
|
|
108
|
+
saned.empty? || saned.size == 1
|
|
102
109
|
end
|
|
103
110
|
end
|
|
104
111
|
|
data/lib/thor/error.rb
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
class Thor
|
|
2
|
-
Correctable =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
DidYouMean::Correctable
|
|
18
|
-
rescue LoadError, NameError
|
|
19
|
-
end
|
|
2
|
+
Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable)
|
|
3
|
+
# In order to support versions of Ruby that don't have keyword
|
|
4
|
+
# arguments, we need our own spell checker class that doesn't take key
|
|
5
|
+
# words. Even though this code wouldn't be hit because of the check
|
|
6
|
+
# above, it's still necessary because the interpreter would otherwise be
|
|
7
|
+
# unable to parse the file.
|
|
8
|
+
class NoKwargSpellChecker < DidYouMean::SpellChecker # :nodoc:
|
|
9
|
+
def initialize(dictionary)
|
|
10
|
+
@dictionary = dictionary
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
DidYouMean::Correctable
|
|
15
|
+
end
|
|
20
16
|
|
|
21
17
|
# Thor::Error is raised when it's caused by wrong usage of thor classes. Those
|
|
22
18
|
# errors have their backtrace suppressed and are nicely shown to the user.
|
data/lib/thor/group.rb
CHANGED
data/lib/thor/invocation.rb
CHANGED
data/lib/thor/line_editor.rb
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
begin
|
|
2
|
-
require "readline"
|
|
3
|
-
rescue LoadError
|
|
4
|
-
end
|
|
5
|
-
|
|
6
1
|
class Thor
|
|
7
2
|
module LineEditor
|
|
8
3
|
class Readline < Basic
|
|
9
4
|
def self.available?
|
|
5
|
+
begin
|
|
6
|
+
require "readline"
|
|
7
|
+
rescue LoadError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
10
|
Object.const_defined?(:Readline)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def readline
|
|
14
14
|
if echo?
|
|
15
15
|
::Readline.completion_append_character = nil
|
|
16
|
-
#
|
|
16
|
+
# rb-readline does not allow Readline.completion_proc= to receive nil.
|
|
17
17
|
if complete = completion_proc
|
|
18
18
|
::Readline.completion_proc = complete
|
|
19
19
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class Thor
|
|
2
|
+
class NestedContext
|
|
3
|
+
def initialize
|
|
4
|
+
@depth = 0
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def enter
|
|
8
|
+
push
|
|
9
|
+
|
|
10
|
+
yield
|
|
11
|
+
ensure
|
|
12
|
+
pop
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def entered?
|
|
16
|
+
@depth > 0
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def push
|
|
22
|
+
@depth += 1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def pop
|
|
26
|
+
@depth -= 1
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/thor/parser.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
require_relative "parser/argument"
|
|
2
|
+
require_relative "parser/arguments"
|
|
3
|
+
require_relative "parser/option"
|
|
4
|
+
require_relative "parser/options"
|
|
@@ -9,7 +9,7 @@ class Thor
|
|
|
9
9
|
arguments = []
|
|
10
10
|
|
|
11
11
|
args.each do |item|
|
|
12
|
-
break if item =~ /^-/
|
|
12
|
+
break if item.is_a?(String) && item =~ /^-/
|
|
13
13
|
arguments << item
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -82,7 +82,7 @@ class Thor
|
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def current_is_value?
|
|
85
|
-
peek && peek.to_s !~
|
|
85
|
+
peek && peek.to_s !~ /^-{1,2}\S+/
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
# Runs through the argument array getting strings that contains ":" and
|
data/lib/thor/parser/option.rb
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
class Thor
|
|
2
2
|
class Option < Argument #:nodoc:
|
|
3
|
-
attr_reader :aliases, :group, :lazy_default, :hide
|
|
3
|
+
attr_reader :aliases, :group, :lazy_default, :hide, :repeatable
|
|
4
4
|
|
|
5
5
|
VALID_TYPES = [:boolean, :numeric, :hash, :array, :string]
|
|
6
6
|
|
|
7
7
|
def initialize(name, options = {})
|
|
8
8
|
@check_default_type = options[:check_default_type]
|
|
9
9
|
options[:required] = false unless options.key?(:required)
|
|
10
|
+
@repeatable = options.fetch(:repeatable, false)
|
|
10
11
|
super
|
|
11
|
-
@lazy_default
|
|
12
|
-
@group
|
|
13
|
-
@aliases
|
|
14
|
-
@hide
|
|
12
|
+
@lazy_default = options[:lazy_default]
|
|
13
|
+
@group = options[:group].to_s.capitalize if options[:group]
|
|
14
|
+
@aliases = Array(options[:aliases])
|
|
15
|
+
@hide = options[:hide]
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
# This parse quick options given as method_options. It makes several
|
|
@@ -111,7 +112,7 @@ class Thor
|
|
|
111
112
|
|
|
112
113
|
def validate!
|
|
113
114
|
raise ArgumentError, "An option cannot be boolean and required." if boolean? && required?
|
|
114
|
-
validate_default_type!
|
|
115
|
+
validate_default_type!
|
|
115
116
|
end
|
|
116
117
|
|
|
117
118
|
def validate_default_type!
|
|
@@ -128,7 +129,19 @@ class Thor
|
|
|
128
129
|
@default.class.name.downcase.to_sym
|
|
129
130
|
end
|
|
130
131
|
|
|
131
|
-
|
|
132
|
+
expected_type = (@repeatable && @type != :hash) ? :array : @type
|
|
133
|
+
|
|
134
|
+
if default_type != expected_type
|
|
135
|
+
err = "Expected #{expected_type} default value for '#{switch_name}'; got #{@default.inspect} (#{default_type})"
|
|
136
|
+
|
|
137
|
+
if @check_default_type
|
|
138
|
+
raise ArgumentError, err
|
|
139
|
+
elsif @check_default_type == nil
|
|
140
|
+
Thor.deprecation_warning "#{err}.\n" +
|
|
141
|
+
'This will be rejected in the future unless you explicitly pass the options `check_default_type: false`' +
|
|
142
|
+
' or call `allow_incompatible_default_type!` in your code'
|
|
143
|
+
end
|
|
144
|
+
end
|
|
132
145
|
end
|
|
133
146
|
|
|
134
147
|
def dasherized?
|
data/lib/thor/parser/options.rb
CHANGED
|
@@ -97,7 +97,8 @@ class Thor
|
|
|
97
97
|
|
|
98
98
|
switch = normalize_switch(switch)
|
|
99
99
|
option = switch_option(switch)
|
|
100
|
-
|
|
100
|
+
result = parse_peek(switch, option)
|
|
101
|
+
assign_result!(option, result)
|
|
101
102
|
elsif @stop_on_unknown
|
|
102
103
|
@parsing_options = false
|
|
103
104
|
@extra << shifted
|
|
@@ -132,6 +133,15 @@ class Thor
|
|
|
132
133
|
|
|
133
134
|
protected
|
|
134
135
|
|
|
136
|
+
def assign_result!(option, result)
|
|
137
|
+
if option.repeatable && option.type == :hash
|
|
138
|
+
(@assigns[option.human_name] ||= {}).merge!(result)
|
|
139
|
+
elsif option.repeatable
|
|
140
|
+
(@assigns[option.human_name] ||= []) << result
|
|
141
|
+
else
|
|
142
|
+
@assigns[option.human_name] = result
|
|
143
|
+
end
|
|
144
|
+
end
|
|
135
145
|
# Check if the current value in peek is a registered switch.
|
|
136
146
|
#
|
|
137
147
|
# Two booleans are returned. The first is true if the current value
|
|
@@ -161,7 +171,7 @@ class Thor
|
|
|
161
171
|
end
|
|
162
172
|
|
|
163
173
|
def switch?(arg)
|
|
164
|
-
switch_option(normalize_switch(arg))
|
|
174
|
+
!switch_option(normalize_switch(arg)).nil?
|
|
165
175
|
end
|
|
166
176
|
|
|
167
177
|
def switch_option(arg)
|
|
@@ -194,7 +204,7 @@ class Thor
|
|
|
194
204
|
shift
|
|
195
205
|
false
|
|
196
206
|
else
|
|
197
|
-
!no_or_skip?(switch)
|
|
207
|
+
@switches.key?(switch) || !no_or_skip?(switch)
|
|
198
208
|
end
|
|
199
209
|
else
|
|
200
210
|
@switches.key?(switch) || !no_or_skip?(switch)
|
data/lib/thor/rake_compat.rb
CHANGED
|
@@ -25,6 +25,7 @@ class Thor
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def self.included(base)
|
|
28
|
+
super(base)
|
|
28
29
|
# Hack. Make rakefile point to invoker, so rdoc task is generated properly.
|
|
29
30
|
rakefile = File.basename(caller[0].match(/(.*):\d+/)[1])
|
|
30
31
|
Rake.application.instance_variable_set(:@rakefile, rakefile)
|
data/lib/thor/runner.rb
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require "thor/core_ext/io_binary_read"
|
|
1
|
+
require_relative "../thor"
|
|
2
|
+
require_relative "group"
|
|
4
3
|
|
|
5
4
|
require "yaml"
|
|
6
5
|
require "digest/md5"
|
|
7
6
|
require "pathname"
|
|
8
7
|
|
|
9
8
|
class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
|
|
9
|
+
autoload :OpenURI, "open-uri"
|
|
10
|
+
|
|
10
11
|
map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
|
|
11
12
|
|
|
12
13
|
def self.banner(command, all = false, subcommand = false)
|
|
@@ -111,7 +112,7 @@ class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
|
|
|
111
112
|
|
|
112
113
|
desc "version", "Show Thor version"
|
|
113
114
|
def version
|
|
114
|
-
|
|
115
|
+
require_relative "version"
|
|
115
116
|
say "Thor #{Thor::VERSION}"
|
|
116
117
|
end
|
|
117
118
|
|
data/lib/thor/shell.rb
CHANGED
|
@@ -24,9 +24,9 @@ class Thor
|
|
|
24
24
|
SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
|
|
25
25
|
attr_writer :shell
|
|
26
26
|
|
|
27
|
-
autoload :Basic, "
|
|
28
|
-
autoload :Color, "
|
|
29
|
-
autoload :HTML, "
|
|
27
|
+
autoload :Basic, File.expand_path("shell/basic", __dir__)
|
|
28
|
+
autoload :Color, File.expand_path("shell/color", __dir__)
|
|
29
|
+
autoload :HTML, File.expand_path("shell/html", __dir__)
|
|
30
30
|
|
|
31
31
|
# Add shell to initialize config values.
|
|
32
32
|
#
|
data/lib/thor/shell/basic.rb
CHANGED
|
@@ -451,16 +451,25 @@ class Thor
|
|
|
451
451
|
|
|
452
452
|
def ask_filtered(statement, color, options)
|
|
453
453
|
answer_set = options[:limited_to]
|
|
454
|
+
case_insensitive = options.fetch(:case_insensitive, false)
|
|
454
455
|
correct_answer = nil
|
|
455
456
|
until correct_answer
|
|
456
457
|
answers = answer_set.join(", ")
|
|
457
458
|
answer = ask_simply("#{statement} [#{answers}]", color, options)
|
|
458
|
-
correct_answer = answer_set
|
|
459
|
+
correct_answer = answer_match(answer_set, answer, case_insensitive)
|
|
459
460
|
say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer
|
|
460
461
|
end
|
|
461
462
|
correct_answer
|
|
462
463
|
end
|
|
463
464
|
|
|
465
|
+
def answer_match(possibilities, answer, case_insensitive)
|
|
466
|
+
if case_insensitive
|
|
467
|
+
possibilities.detect{ |possibility| possibility.downcase == answer.downcase }
|
|
468
|
+
else
|
|
469
|
+
possibilities.detect{ |possibility| possibility == answer }
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
464
473
|
def merge(destination, content) #:nodoc:
|
|
465
474
|
require "tempfile"
|
|
466
475
|
Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
|
data/lib/thor/shell/color.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative "basic"
|
|
2
2
|
|
|
3
3
|
class Thor
|
|
4
4
|
module Shell
|
|
@@ -97,7 +97,11 @@ class Thor
|
|
|
97
97
|
protected
|
|
98
98
|
|
|
99
99
|
def can_display_colors?
|
|
100
|
-
stdout.tty?
|
|
100
|
+
stdout.tty? && !are_colors_disabled?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def are_colors_disabled?
|
|
104
|
+
!ENV['NO_COLOR'].nil?
|
|
101
105
|
end
|
|
102
106
|
|
|
103
107
|
# Overwrite show_diff to show diff with colors if Diff::LCS is
|
data/lib/thor/shell/html.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative "basic"
|
|
2
2
|
|
|
3
3
|
class Thor
|
|
4
4
|
module Shell
|
|
@@ -51,13 +51,13 @@ class Thor
|
|
|
51
51
|
def set_color(string, *colors)
|
|
52
52
|
if colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) }
|
|
53
53
|
html_colors = colors.map { |color| lookup_color(color) }
|
|
54
|
-
"<span style=\"#{html_colors.join('; ')};\">#{string}</span>"
|
|
54
|
+
"<span style=\"#{html_colors.join('; ')};\">#{Thor::Util.escape_html(string)}</span>"
|
|
55
55
|
else
|
|
56
56
|
color, bold = colors
|
|
57
57
|
html_color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
|
|
58
58
|
styles = [html_color]
|
|
59
59
|
styles << BOLD if bold
|
|
60
|
-
"<span style=\"#{styles.join('; ')};\">#{string}</span>"
|
|
60
|
+
"<span style=\"#{styles.join('; ')};\">#{Thor::Util.escape_html(string)}</span>"
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
data/lib/thor/util.rb
CHANGED
|
@@ -263,6 +263,22 @@ class Thor
|
|
|
263
263
|
def escape_globs(path)
|
|
264
264
|
path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&')
|
|
265
265
|
end
|
|
266
|
+
|
|
267
|
+
# Returns a string that has had any HTML characters escaped.
|
|
268
|
+
#
|
|
269
|
+
# ==== Examples
|
|
270
|
+
#
|
|
271
|
+
# Thor::Util.escape_html('<div>') # => "<div>"
|
|
272
|
+
#
|
|
273
|
+
# ==== Parameters
|
|
274
|
+
# String
|
|
275
|
+
#
|
|
276
|
+
# ==== Returns
|
|
277
|
+
# String
|
|
278
|
+
#
|
|
279
|
+
def escape_html(string)
|
|
280
|
+
CGI.escapeHTML(string)
|
|
281
|
+
end
|
|
266
282
|
end
|
|
267
283
|
end
|
|
268
284
|
end
|
data/lib/thor/version.rb
CHANGED
data/thor.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
require "thor/version"
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.add_development_dependency "bundler", "
|
|
7
|
+
spec.add_development_dependency "bundler", ">= 1.0", "< 3"
|
|
8
8
|
spec.authors = ["Yehuda Katz", "José Valim"]
|
|
9
9
|
spec.description = "Thor is a toolkit for building powerful command-line interfaces."
|
|
10
10
|
spec.email = "ruby-thor@googlegroups.com"
|
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
spec.licenses = %w(MIT)
|
|
15
15
|
spec.name = "thor"
|
|
16
16
|
spec.require_paths = %w(lib)
|
|
17
|
-
spec.required_ruby_version = ">=
|
|
17
|
+
spec.required_ruby_version = ">= 2.0.0"
|
|
18
18
|
spec.required_rubygems_version = ">= 1.3.5"
|
|
19
19
|
spec.summary = spec.description
|
|
20
20
|
spec.version = Thor::VERSION
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: thor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yehuda Katz
|
|
@@ -9,22 +9,28 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2019-12-13 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: bundler
|
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
|
17
17
|
requirements:
|
|
18
|
-
- - "
|
|
18
|
+
- - ">="
|
|
19
19
|
- !ruby/object:Gem::Version
|
|
20
20
|
version: '1.0'
|
|
21
|
+
- - "<"
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: '3'
|
|
21
24
|
type: :development
|
|
22
25
|
prerelease: false
|
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
|
24
27
|
requirements:
|
|
25
|
-
- - "
|
|
28
|
+
- - ">="
|
|
26
29
|
- !ruby/object:Gem::Version
|
|
27
30
|
version: '1.0'
|
|
31
|
+
- - "<"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '3'
|
|
28
34
|
description: Thor is a toolkit for building powerful command-line interfaces.
|
|
29
35
|
email: ruby-thor@googlegroups.com
|
|
30
36
|
executables:
|
|
@@ -49,14 +55,13 @@ files:
|
|
|
49
55
|
- lib/thor/base.rb
|
|
50
56
|
- lib/thor/command.rb
|
|
51
57
|
- lib/thor/core_ext/hash_with_indifferent_access.rb
|
|
52
|
-
- lib/thor/core_ext/io_binary_read.rb
|
|
53
|
-
- lib/thor/core_ext/ordered_hash.rb
|
|
54
58
|
- lib/thor/error.rb
|
|
55
59
|
- lib/thor/group.rb
|
|
56
60
|
- lib/thor/invocation.rb
|
|
57
61
|
- lib/thor/line_editor.rb
|
|
58
62
|
- lib/thor/line_editor/basic.rb
|
|
59
63
|
- lib/thor/line_editor/readline.rb
|
|
64
|
+
- lib/thor/nested_context.rb
|
|
60
65
|
- lib/thor/parser.rb
|
|
61
66
|
- lib/thor/parser/argument.rb
|
|
62
67
|
- lib/thor/parser/arguments.rb
|
|
@@ -83,15 +88,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
83
88
|
requirements:
|
|
84
89
|
- - ">="
|
|
85
90
|
- !ruby/object:Gem::Version
|
|
86
|
-
version:
|
|
91
|
+
version: 2.0.0
|
|
87
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
93
|
requirements:
|
|
89
94
|
- - ">="
|
|
90
95
|
- !ruby/object:Gem::Version
|
|
91
96
|
version: 1.3.5
|
|
92
97
|
requirements: []
|
|
93
|
-
|
|
94
|
-
rubygems_version: 2.7.6
|
|
98
|
+
rubygems_version: 3.0.3
|
|
95
99
|
signing_key:
|
|
96
100
|
specification_version: 4
|
|
97
101
|
summary: Thor is a toolkit for building powerful command-line interfaces.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
class IO #:nodoc:
|
|
2
|
-
class << self
|
|
3
|
-
unless method_defined? :binread
|
|
4
|
-
def binread(file, *args)
|
|
5
|
-
raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
|
|
6
|
-
File.open(file, "rb") do |f|
|
|
7
|
-
f.read(*args)
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
class Thor
|
|
2
|
-
module CoreExt
|
|
3
|
-
class OrderedHash < ::Hash
|
|
4
|
-
if RUBY_VERSION < "1.9"
|
|
5
|
-
def initialize(*args, &block)
|
|
6
|
-
super
|
|
7
|
-
@keys = []
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def initialize_copy(other)
|
|
11
|
-
super
|
|
12
|
-
# make a deep copy of keys
|
|
13
|
-
@keys = other.keys
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def []=(key, value)
|
|
17
|
-
@keys << key unless key?(key)
|
|
18
|
-
super
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def delete(key)
|
|
22
|
-
if key? key
|
|
23
|
-
index = @keys.index(key)
|
|
24
|
-
@keys.delete_at index
|
|
25
|
-
end
|
|
26
|
-
super
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def delete_if
|
|
30
|
-
super
|
|
31
|
-
sync_keys!
|
|
32
|
-
self
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
alias_method :reject!, :delete_if
|
|
36
|
-
|
|
37
|
-
def reject(&block)
|
|
38
|
-
dup.reject!(&block)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def keys
|
|
42
|
-
@keys.dup
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def values
|
|
46
|
-
@keys.map { |key| self[key] }
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def to_hash
|
|
50
|
-
self
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def to_a
|
|
54
|
-
@keys.map { |key| [key, self[key]] }
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def each_key
|
|
58
|
-
return to_enum(:each_key) unless block_given?
|
|
59
|
-
@keys.each { |key| yield(key) }
|
|
60
|
-
self
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def each_value
|
|
64
|
-
return to_enum(:each_value) unless block_given?
|
|
65
|
-
@keys.each { |key| yield(self[key]) }
|
|
66
|
-
self
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def each
|
|
70
|
-
return to_enum(:each) unless block_given?
|
|
71
|
-
@keys.each { |key| yield([key, self[key]]) }
|
|
72
|
-
self
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def each_pair
|
|
76
|
-
return to_enum(:each_pair) unless block_given?
|
|
77
|
-
@keys.each { |key| yield(key, self[key]) }
|
|
78
|
-
self
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
alias_method :select, :find_all
|
|
82
|
-
|
|
83
|
-
def clear
|
|
84
|
-
super
|
|
85
|
-
@keys.clear
|
|
86
|
-
self
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def shift
|
|
90
|
-
k = @keys.first
|
|
91
|
-
v = delete(k)
|
|
92
|
-
[k, v]
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def merge!(other_hash)
|
|
96
|
-
if block_given?
|
|
97
|
-
other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
|
|
98
|
-
else
|
|
99
|
-
other_hash.each { |k, v| self[k] = v }
|
|
100
|
-
end
|
|
101
|
-
self
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
alias_method :update, :merge!
|
|
105
|
-
|
|
106
|
-
def merge(other_hash, &block)
|
|
107
|
-
dup.merge!(other_hash, &block)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
|
|
111
|
-
def replace(other)
|
|
112
|
-
super
|
|
113
|
-
@keys = other.keys
|
|
114
|
-
self
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def inspect
|
|
118
|
-
"#<#{self.class} #{super}>"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
private
|
|
122
|
-
|
|
123
|
-
def sync_keys!
|
|
124
|
-
@keys.delete_if { |k| !key?(k) }
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|