thor 0.20.3 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -1
- data/lib/thor.rb +12 -4
- data/lib/thor/actions.rb +17 -12
- data/lib/thor/actions/create_file.rb +1 -1
- data/lib/thor/actions/create_link.rb +3 -2
- 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 +59 -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 +9 -2
- metadata +19 -10
- 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: 2c23d1fdac6ea485b4cbfe91abad33a46e03c00baf2e7e0068c9f8d4ce41e607
|
4
|
+
data.tar.gz: 368fe9c87e8a426eaf38278acaba2b7a3171c96c99298ca5e2eddf3b1b466ff6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f2e3b52a657bc5318fed8a5e3f15368d734f62e7b8039a296add626ff6bdc415e6c8a85cea31bdd591a629960854f0d34e47ef81161c63acf4ef140457a7bdb
|
7
|
+
data.tar.gz: 8086cd52e16a12fb63dad7df484f0c079feed33d7aa6078d8683f895ddcd92da21be58d26a3b33f89e44d822ae9b01e73ef36672aa77a7befcfa3198523df253
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# 1.0.1
|
2
|
+
* Fix thor when `thor/base` and `thor/group` are required without `thor.rb`.
|
3
|
+
* Handle relative source path in `create_link`.
|
4
|
+
|
5
|
+
# 1.0.0
|
6
|
+
* Drop support to Ruby 1.8 and 1.9.
|
7
|
+
* Deprecate relying on default `exit_on_failure?`.
|
8
|
+
In preparation to make Thor commands exit when there is a failure we are deprecating
|
9
|
+
defining a command without defining what behavior is expected when there is a failure.
|
10
|
+
|
11
|
+
To fix the deprecation you need to define a class method called `exit_on_failure?` returning
|
12
|
+
|
13
|
+
`false` if you want the current behavior or `true` if you want the new behavior.
|
14
|
+
* Deprecate defining an option with the default value using a different type as defined in the option.
|
15
|
+
* Allow options to be repeatable. See #674.
|
16
|
+
|
1
17
|
# 0.20.3
|
2
18
|
* Support old versions of `did_you_mean`.
|
3
19
|
|
@@ -5,7 +21,7 @@
|
|
5
21
|
* Fix `did_you_mean` support.
|
6
22
|
|
7
23
|
# 0.20.1
|
8
|
-
* Support new versions
|
24
|
+
* Support new versions of ERB.
|
9
25
|
* 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
26
|
* Add `did_you_mean` support.
|
11
27
|
|
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
|
@@ -393,7 +398,10 @@ class Thor
|
|
393
398
|
# the namespace should be displayed as arguments.
|
394
399
|
#
|
395
400
|
def banner(command, namespace = nil, subcommand = false)
|
396
|
-
|
401
|
+
$thor_runner ||= false
|
402
|
+
command.formatted_usage(self, $thor_runner, subcommand).split("\n").map do |formatted_usage|
|
403
|
+
"#{basename} #{formatted_usage}"
|
404
|
+
end.join("\n")
|
397
405
|
end
|
398
406
|
|
399
407
|
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 "create_file"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -33,7 +33,8 @@ class Thor
|
|
33
33
|
# Boolean:: true if it is identical, false otherwise.
|
34
34
|
#
|
35
35
|
def identical?
|
36
|
-
|
36
|
+
source = File.expand_path(render, File.dirname(destination))
|
37
|
+
exists? && File.identical?(source, destination)
|
37
38
|
end
|
38
39
|
|
39
40
|
def invoke!
|
@@ -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)
|
@@ -22,6 +22,15 @@ class Thor
|
|
22
22
|
|
23
23
|
TEMPLATE_EXTNAME = ".tt"
|
24
24
|
|
25
|
+
class << self
|
26
|
+
def deprecation_warning(message) #:nodoc:
|
27
|
+
unless ENV['THOR_SILENCE_DEPRECATION']
|
28
|
+
warn "Deprecation warning: #{message}\n" +
|
29
|
+
'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
25
34
|
module Base
|
26
35
|
attr_accessor :options, :parent_options, :args
|
27
36
|
|
@@ -89,6 +98,7 @@ class Thor
|
|
89
98
|
|
90
99
|
class << self
|
91
100
|
def included(base) #:nodoc:
|
101
|
+
super(base)
|
92
102
|
base.extend ClassMethods
|
93
103
|
base.send :include, Invocation
|
94
104
|
base.send :include, Shell
|
@@ -153,17 +163,20 @@ class Thor
|
|
153
163
|
|
154
164
|
# If you want to raise an error when the default value of an option does not match
|
155
165
|
# the type call check_default_type!
|
156
|
-
# This
|
166
|
+
# This will be the default; for compatibility a deprecation warning is issued if necessary.
|
157
167
|
def check_default_type!
|
158
168
|
@check_default_type = true
|
159
169
|
end
|
160
170
|
|
161
|
-
|
162
|
-
|
171
|
+
# If you want to use defaults that don't match the type of an option,
|
172
|
+
# either specify `check_default_type: false` or call `allow_incompatible_default_type!`
|
173
|
+
def allow_incompatible_default_type!
|
174
|
+
@check_default_type = false
|
163
175
|
end
|
164
176
|
|
165
|
-
def check_default_type
|
166
|
-
|
177
|
+
def check_default_type #:nodoc:
|
178
|
+
@check_default_type = from_superclass(:check_default_type, nil) unless defined?(@check_default_type)
|
179
|
+
@check_default_type
|
167
180
|
end
|
168
181
|
|
169
182
|
# If true, option parsing is suspended as soon as an unknown option or a
|
@@ -353,22 +366,22 @@ class Thor
|
|
353
366
|
# Returns the commands for this Thor class.
|
354
367
|
#
|
355
368
|
# ==== Returns
|
356
|
-
#
|
357
|
-
#
|
369
|
+
# Hash:: An ordered hash with commands names as keys and Thor::Command
|
370
|
+
# objects as values.
|
358
371
|
#
|
359
372
|
def commands
|
360
|
-
@commands ||=
|
373
|
+
@commands ||= Hash.new
|
361
374
|
end
|
362
375
|
alias_method :tasks, :commands
|
363
376
|
|
364
377
|
# Returns the commands for this Thor class and all subclasses.
|
365
378
|
#
|
366
379
|
# ==== Returns
|
367
|
-
#
|
368
|
-
#
|
380
|
+
# Hash:: An ordered hash with commands names as keys and Thor::Command
|
381
|
+
# objects as values.
|
369
382
|
#
|
370
383
|
def all_commands
|
371
|
-
@all_commands ||= from_superclass(:all_commands,
|
384
|
+
@all_commands ||= from_superclass(:all_commands, Hash.new)
|
372
385
|
@all_commands.merge!(commands)
|
373
386
|
end
|
374
387
|
alias_method :all_tasks, :all_commands
|
@@ -415,14 +428,20 @@ class Thor
|
|
415
428
|
# remove_command :this_is_not_a_command
|
416
429
|
# end
|
417
430
|
#
|
418
|
-
def no_commands
|
419
|
-
|
420
|
-
yield
|
421
|
-
ensure
|
422
|
-
@no_commands = false
|
431
|
+
def no_commands(&block)
|
432
|
+
no_commands_context.enter(&block)
|
423
433
|
end
|
434
|
+
|
424
435
|
alias_method :no_tasks, :no_commands
|
425
436
|
|
437
|
+
def no_commands_context
|
438
|
+
@no_commands_context ||= NestedContext.new
|
439
|
+
end
|
440
|
+
|
441
|
+
def no_commands?
|
442
|
+
no_commands_context.entered?
|
443
|
+
end
|
444
|
+
|
426
445
|
# Sets the namespace for the Thor or Thor::Group class. By default the
|
427
446
|
# namespace is retrieved from the class name. If your Thor class is named
|
428
447
|
# Scripts::MyScript, the help method, for example, will be called as:
|
@@ -502,10 +521,16 @@ class Thor
|
|
502
521
|
msg = "ERROR: \"#{basename} #{name}\" was called with ".dup
|
503
522
|
msg << "no arguments" if args.empty?
|
504
523
|
msg << "arguments " << args.inspect unless args.empty?
|
505
|
-
msg << "\nUsage: #{banner(command).
|
524
|
+
msg << "\nUsage: \"#{banner(command).split("\n").join("\"\n \"")}\""
|
506
525
|
raise InvocationError, msg
|
507
526
|
end
|
508
527
|
|
528
|
+
# A flag that makes the process exit with status 1 if any error happens.
|
529
|
+
def exit_on_failure?
|
530
|
+
Thor.deprecation_warning "Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `#{self.name}`"
|
531
|
+
false
|
532
|
+
end
|
533
|
+
|
509
534
|
protected
|
510
535
|
|
511
536
|
# Prints the class options per group. If an option does not belong to
|
@@ -563,7 +588,7 @@ class Thor
|
|
563
588
|
# options<Hash>:: Described in both class_option and method_option.
|
564
589
|
# scope<Hash>:: Options hash that is being built up
|
565
590
|
def build_option(name, options, scope) #:nodoc:
|
566
|
-
scope[name] = Thor::Option.new(name,
|
591
|
+
scope[name] = Thor::Option.new(name, {:check_default_type => check_default_type}.merge!(options))
|
567
592
|
end
|
568
593
|
|
569
594
|
# Receives a hash of options, parse them and add to the scope. This is a
|
@@ -596,13 +621,15 @@ class Thor
|
|
596
621
|
# Everytime someone inherits from a Thor class, register the klass
|
597
622
|
# and file into baseclass.
|
598
623
|
def inherited(klass)
|
624
|
+
super(klass)
|
599
625
|
Thor::Base.register_klass_file(klass)
|
600
|
-
klass.instance_variable_set(:@no_commands,
|
626
|
+
klass.instance_variable_set(:@no_commands, 0)
|
601
627
|
end
|
602
628
|
|
603
629
|
# Fire this callback whenever a method is added. Added methods are
|
604
630
|
# tracked as commands by invoking the create_command method.
|
605
631
|
def method_added(meth)
|
632
|
+
super(meth)
|
606
633
|
meth = meth.to_s
|
607
634
|
|
608
635
|
if meth == "initialize"
|
@@ -613,8 +640,7 @@ class Thor
|
|
613
640
|
# Return if it's not a public instance method
|
614
641
|
return unless public_method_defined?(meth.to_sym)
|
615
642
|
|
616
|
-
|
617
|
-
return if @no_commands || !create_command(meth)
|
643
|
+
return if no_commands? || !create_command(meth)
|
618
644
|
|
619
645
|
is_thor_reserved_word?(meth, :command)
|
620
646
|
Thor::Base.register_klass_file(self)
|
@@ -641,11 +667,6 @@ class Thor
|
|
641
667
|
end
|
642
668
|
end
|
643
669
|
|
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
670
|
#
|
650
671
|
# The basename of the program invoking the thor class.
|
651
672
|
#
|
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"
|
@@ -13,8 +13,15 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "http://whatisthor.com/"
|
14
14
|
spec.licenses = %w(MIT)
|
15
15
|
spec.name = "thor"
|
16
|
+
spec.metadata = {
|
17
|
+
"bug_tracker_uri" => "https://github.com/erikhuda/thor/issues",
|
18
|
+
"changelog_uri" => "https://github.com/erikhuda/thor/blob/master/CHANGELOG.md",
|
19
|
+
"documentation_uri" => "http://whatisthor.com/",
|
20
|
+
"source_code_uri" => "https://github.com/erikhuda/thor/tree/v#{Thor::VERSION}",
|
21
|
+
"wiki_uri" => "https://github.com/erikhuda/thor/wiki"
|
22
|
+
}
|
16
23
|
spec.require_paths = %w(lib)
|
17
|
-
spec.required_ruby_version = ">=
|
24
|
+
spec.required_ruby_version = ">= 2.0.0"
|
18
25
|
spec.required_rubygems_version = ">= 1.3.5"
|
19
26
|
spec.summary = spec.description
|
20
27
|
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.1
|
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-17 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
|
@@ -74,7 +79,12 @@ files:
|
|
74
79
|
homepage: http://whatisthor.com/
|
75
80
|
licenses:
|
76
81
|
- MIT
|
77
|
-
metadata:
|
82
|
+
metadata:
|
83
|
+
bug_tracker_uri: https://github.com/erikhuda/thor/issues
|
84
|
+
changelog_uri: https://github.com/erikhuda/thor/blob/master/CHANGELOG.md
|
85
|
+
documentation_uri: http://whatisthor.com/
|
86
|
+
source_code_uri: https://github.com/erikhuda/thor/tree/v1.0.1
|
87
|
+
wiki_uri: https://github.com/erikhuda/thor/wiki
|
78
88
|
post_install_message:
|
79
89
|
rdoc_options: []
|
80
90
|
require_paths:
|
@@ -83,15 +93,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
93
|
requirements:
|
84
94
|
- - ">="
|
85
95
|
- !ruby/object:Gem::Version
|
86
|
-
version:
|
96
|
+
version: 2.0.0
|
87
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
98
|
requirements:
|
89
99
|
- - ">="
|
90
100
|
- !ruby/object:Gem::Version
|
91
101
|
version: 1.3.5
|
92
102
|
requirements: []
|
93
|
-
|
94
|
-
rubygems_version: 2.7.6
|
103
|
+
rubygems_version: 3.0.3
|
95
104
|
signing_key:
|
96
105
|
specification_version: 4
|
97
106
|
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
|