thor 0.19.1 → 0.19.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/CONTRIBUTING.md +15 -0
- data/README.md +7 -1
- data/lib/thor.rb +31 -23
- data/lib/thor/actions.rb +21 -22
- data/lib/thor/actions/create_file.rb +1 -1
- data/lib/thor/actions/create_link.rb +1 -1
- data/lib/thor/actions/directory.rb +2 -2
- data/lib/thor/actions/empty_directory.rb +8 -8
- data/lib/thor/actions/file_manipulation.rb +23 -12
- data/lib/thor/actions/inject_into_file.rb +10 -14
- data/lib/thor/base.rb +33 -33
- data/lib/thor/command.rb +9 -9
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +9 -1
- data/lib/thor/core_ext/io_binary_read.rb +7 -5
- data/lib/thor/core_ext/ordered_hash.rb +94 -63
- data/lib/thor/error.rb +3 -3
- data/lib/thor/group.rb +12 -12
- data/lib/thor/invocation.rb +4 -5
- data/lib/thor/parser/argument.rb +4 -7
- data/lib/thor/parser/arguments.rb +16 -16
- data/lib/thor/parser/option.rb +39 -19
- data/lib/thor/parser/options.rb +7 -5
- data/lib/thor/runner.rb +25 -25
- data/lib/thor/shell.rb +1 -1
- data/lib/thor/shell/basic.rb +41 -26
- data/lib/thor/shell/color.rb +1 -1
- data/lib/thor/shell/html.rb +4 -4
- data/lib/thor/util.rb +8 -7
- data/lib/thor/version.rb +1 -1
- data/thor.gemspec +6 -9
- metadata +6 -148
- data/Thorfile +0 -29
- data/spec/actions/create_file_spec.rb +0 -168
- data/spec/actions/create_link_spec.rb +0 -96
- data/spec/actions/directory_spec.rb +0 -169
- data/spec/actions/empty_directory_spec.rb +0 -129
- data/spec/actions/file_manipulation_spec.rb +0 -392
- data/spec/actions/inject_into_file_spec.rb +0 -135
- data/spec/actions_spec.rb +0 -331
- data/spec/base_spec.rb +0 -298
- data/spec/command_spec.rb +0 -79
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +0 -48
- data/spec/core_ext/ordered_hash_spec.rb +0 -115
- data/spec/exit_condition_spec.rb +0 -19
- data/spec/fixtures/application.rb +0 -2
- data/spec/fixtures/app{1}/README +0 -3
- data/spec/fixtures/bundle/execute.rb +0 -6
- data/spec/fixtures/bundle/main.thor +0 -1
- data/spec/fixtures/command.thor +0 -10
- data/spec/fixtures/doc/%file_name%.rb.tt +0 -1
- data/spec/fixtures/doc/COMMENTER +0 -11
- data/spec/fixtures/doc/README +0 -3
- data/spec/fixtures/doc/block_helper.rb +0 -3
- data/spec/fixtures/doc/config.rb +0 -1
- data/spec/fixtures/doc/config.yaml.tt +0 -1
- data/spec/fixtures/doc/excluding/%file_name%.rb.tt +0 -1
- data/spec/fixtures/enum.thor +0 -10
- data/spec/fixtures/group.thor +0 -128
- data/spec/fixtures/invoke.thor +0 -131
- data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
- data/spec/fixtures/preserve/script.sh +0 -3
- data/spec/fixtures/script.thor +0 -220
- data/spec/fixtures/subcommand.thor +0 -17
- data/spec/group_spec.rb +0 -222
- data/spec/helper.rb +0 -80
- data/spec/invocation_spec.rb +0 -120
- data/spec/line_editor/basic_spec.rb +0 -28
- data/spec/line_editor/readline_spec.rb +0 -69
- data/spec/line_editor_spec.rb +0 -43
- data/spec/parser/argument_spec.rb +0 -53
- data/spec/parser/arguments_spec.rb +0 -66
- data/spec/parser/option_spec.rb +0 -210
- data/spec/parser/options_spec.rb +0 -414
- data/spec/quality_spec.rb +0 -75
- data/spec/rake_compat_spec.rb +0 -72
- data/spec/register_spec.rb +0 -227
- data/spec/runner_spec.rb +0 -246
- data/spec/sandbox/application.rb +0 -2
- data/spec/sandbox/app{1}/README +0 -3
- data/spec/sandbox/bundle/execute.rb +0 -6
- data/spec/sandbox/bundle/main.thor +0 -1
- data/spec/sandbox/command.thor +0 -10
- data/spec/sandbox/doc/%file_name%.rb.tt +0 -1
- data/spec/sandbox/doc/COMMENTER +0 -11
- data/spec/sandbox/doc/README +0 -3
- data/spec/sandbox/doc/block_helper.rb +0 -3
- data/spec/sandbox/doc/config.rb +0 -1
- data/spec/sandbox/doc/config.yaml.tt +0 -1
- data/spec/sandbox/doc/excluding/%file_name%.rb.tt +0 -1
- data/spec/sandbox/enum.thor +0 -10
- data/spec/sandbox/group.thor +0 -128
- data/spec/sandbox/invoke.thor +0 -131
- data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
- data/spec/sandbox/preserve/script.sh +0 -3
- data/spec/sandbox/script.thor +0 -220
- data/spec/sandbox/subcommand.thor +0 -17
- data/spec/shell/basic_spec.rb +0 -337
- data/spec/shell/color_spec.rb +0 -119
- data/spec/shell/html_spec.rb +0 -31
- data/spec/shell_spec.rb +0 -47
- data/spec/subcommand_spec.rb +0 -48
- data/spec/thor_spec.rb +0 -505
- data/spec/util_spec.rb +0 -196
@@ -22,11 +22,8 @@ class Thor
|
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
def insert_into_file(destination, *args, &block)
|
25
|
-
|
26
|
-
|
27
|
-
else
|
28
|
-
data, config = args.shift, args.shift
|
29
|
-
end
|
25
|
+
data = block_given? ? block : args.shift
|
26
|
+
config = args.shift
|
30
27
|
action InjectIntoFile.new(self, destination, data, config)
|
31
28
|
end
|
32
29
|
alias_method :inject_into_file, :insert_into_file
|
@@ -39,9 +36,9 @@ class Thor
|
|
39
36
|
|
40
37
|
@behavior, @flag = if @config.key?(:after)
|
41
38
|
[:after, @config.delete(:after)]
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
else
|
40
|
+
[:before, @config.delete(:before)]
|
41
|
+
end
|
45
42
|
|
46
43
|
@replacement = data.is_a?(Proc) ? data.call : data
|
47
44
|
@flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp)
|
@@ -94,12 +91,11 @@ class Thor
|
|
94
91
|
# Adds the content to the file.
|
95
92
|
#
|
96
93
|
def replace!(regexp, string, force)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
94
|
+
return if base.options[:pretend]
|
95
|
+
content = File.binread(destination)
|
96
|
+
if force || !content.include?(replacement)
|
97
|
+
content.gsub!(regexp, string)
|
98
|
+
File.open(destination, "wb") { |file| file.write(content) }
|
103
99
|
end
|
104
100
|
end
|
105
101
|
end
|
data/lib/thor/base.rb
CHANGED
@@ -14,11 +14,11 @@ class Thor
|
|
14
14
|
autoload :Group, "thor/group"
|
15
15
|
|
16
16
|
# Shortcuts for help.
|
17
|
-
HELP_MAPPINGS = %w
|
17
|
+
HELP_MAPPINGS = %w(-h -? --help -D)
|
18
18
|
|
19
19
|
# Thor methods that should not be overwritten by the user.
|
20
|
-
THOR_RESERVED_WORDS = %w
|
21
|
-
action add_file create_file in_root inside run run_ruby_script
|
20
|
+
THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root
|
21
|
+
action add_file create_file in_root inside run run_ruby_script)
|
22
22
|
|
23
23
|
TEMPLATE_EXTNAME = ".tt"
|
24
24
|
|
@@ -41,8 +41,8 @@ class Thor
|
|
41
41
|
#
|
42
42
|
# config<Hash>:: Configuration for this Thor class.
|
43
43
|
#
|
44
|
-
def initialize(args = [], local_options = {}, config = {})
|
45
|
-
parse_options = self.class.class_options
|
44
|
+
def initialize(args = [], local_options = {}, config = {})
|
45
|
+
parse_options = config[:current_command] && config[:current_command].disable_class_options ? {} : self.class.class_options
|
46
46
|
|
47
47
|
# The start method splits inbound arguments at the first argument
|
48
48
|
# that looks like an option (starts with - or --). It then calls
|
@@ -52,11 +52,13 @@ class Thor
|
|
52
52
|
command_options = config.delete(:command_options) # hook for start
|
53
53
|
parse_options = parse_options.merge(command_options) if command_options
|
54
54
|
if local_options.is_a?(Array)
|
55
|
-
array_options
|
55
|
+
array_options = local_options
|
56
|
+
hash_options = {}
|
56
57
|
else
|
57
58
|
# Handle the case where the class was explicitly instantiated
|
58
59
|
# with pre-parsed options.
|
59
|
-
array_options
|
60
|
+
array_options = []
|
61
|
+
hash_options = local_options
|
60
62
|
end
|
61
63
|
|
62
64
|
# Let Thor::Options parse the options first, so it can remove
|
@@ -205,8 +207,8 @@ class Thor
|
|
205
207
|
# ==== Errors
|
206
208
|
# ArgumentError:: Raised if you supply a required argument after a non required one.
|
207
209
|
#
|
208
|
-
def argument(name, options = {})
|
209
|
-
|
210
|
+
def argument(name, options = {})
|
211
|
+
thor_reserved_word?(name, :argument)
|
210
212
|
no_commands { attr_accessor name }
|
211
213
|
|
212
214
|
required = if options.key?(:optional)
|
@@ -219,11 +221,13 @@ class Thor
|
|
219
221
|
|
220
222
|
remove_argument name
|
221
223
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
224
|
+
if required
|
225
|
+
arguments.each do |argument|
|
226
|
+
next if argument.required?
|
227
|
+
raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " \
|
228
|
+
"the non-required argument #{argument.human_name.inspect}."
|
229
|
+
end
|
230
|
+
end
|
227
231
|
|
228
232
|
options[:required] = required
|
229
233
|
|
@@ -343,7 +347,7 @@ class Thor
|
|
343
347
|
#
|
344
348
|
def all_commands
|
345
349
|
@all_commands ||= from_superclass(:all_commands, Thor::CoreExt::OrderedHash.new)
|
346
|
-
@all_commands.merge(commands)
|
350
|
+
@all_commands.merge!(commands)
|
347
351
|
end
|
348
352
|
alias_method :all_tasks, :all_commands
|
349
353
|
|
@@ -467,11 +471,8 @@ class Thor
|
|
467
471
|
alias_method :public_task, :public_command
|
468
472
|
|
469
473
|
def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
|
470
|
-
if has_namespace
|
471
|
-
|
472
|
-
else
|
473
|
-
fail UndefinedCommandError, "Could not find command #{command.inspect}."
|
474
|
-
end
|
474
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace." if has_namespace
|
475
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect}."
|
475
476
|
end
|
476
477
|
alias_method :handle_no_task_error, :handle_no_command_error
|
477
478
|
|
@@ -480,7 +481,7 @@ class Thor
|
|
480
481
|
msg << "no arguments" if args.empty?
|
481
482
|
msg << "arguments " << args.inspect unless args.empty?
|
482
483
|
msg << "\nUsage: #{banner(command).inspect}"
|
483
|
-
|
484
|
+
raise InvocationError, msg
|
484
485
|
end
|
485
486
|
|
486
487
|
protected
|
@@ -513,14 +514,13 @@ class Thor
|
|
513
514
|
padding = options.map { |o| o.aliases.size }.max.to_i * 4
|
514
515
|
|
515
516
|
options.each do |option|
|
516
|
-
|
517
|
-
|
518
|
-
|
517
|
+
next if option.hide
|
518
|
+
item = [option.usage(padding)]
|
519
|
+
item.push(option.description ? "# #{option.description}" : "")
|
519
520
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
end
|
521
|
+
list << item
|
522
|
+
list << ["", "# Default: #{option.default}"] if option.show_default?
|
523
|
+
list << ["", "# Possible values: #{option.enum.join(', ')}"] if option.enum
|
524
524
|
end
|
525
525
|
|
526
526
|
shell.say(group_name ? "#{group_name} options:" : "Options:")
|
@@ -529,9 +529,9 @@ class Thor
|
|
529
529
|
end
|
530
530
|
|
531
531
|
# Raises an error if the word given is a Thor reserved word.
|
532
|
-
def
|
532
|
+
def thor_reserved_word?(word, type) #:nodoc:
|
533
533
|
return false unless THOR_RESERVED_WORDS.include?(word.to_s)
|
534
|
-
|
534
|
+
raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}"
|
535
535
|
end
|
536
536
|
|
537
537
|
# Build an option and adds it to the given scope.
|
@@ -566,7 +566,7 @@ class Thor
|
|
566
566
|
elsif command = all_commands[name.to_s] # rubocop:disable AssignmentInCondition
|
567
567
|
commands[name.to_s] = command.clone
|
568
568
|
else
|
569
|
-
|
569
|
+
raise ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found."
|
570
570
|
end
|
571
571
|
end
|
572
572
|
alias_method :find_and_refresh_task, :find_and_refresh_command
|
@@ -594,7 +594,7 @@ class Thor
|
|
594
594
|
@no_commands ||= false
|
595
595
|
return if @no_commands || !create_command(meth)
|
596
596
|
|
597
|
-
|
597
|
+
thor_reserved_word?(meth, :command)
|
598
598
|
Thor::Base.register_klass_file(self)
|
599
599
|
end
|
600
600
|
|
@@ -649,7 +649,7 @@ class Thor
|
|
649
649
|
|
650
650
|
# SIGNATURE: The hook invoked by start.
|
651
651
|
def dispatch(command, given_args, given_opts, config) #:nodoc:
|
652
|
-
|
652
|
+
raise NotImplementedError
|
653
653
|
end
|
654
654
|
end
|
655
655
|
end
|
data/lib/thor/command.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
class Thor
|
2
|
-
class Command < Struct.new(:name, :description, :long_description, :usage, :options)
|
2
|
+
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :disable_class_options)
|
3
3
|
FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
|
4
4
|
|
5
|
-
def initialize(name, description, long_description, usage, options = nil)
|
6
|
-
super(name.to_s, description, long_description, usage, options || {})
|
5
|
+
def initialize(name, description, long_description, usage, options = nil, disable_class_options = false)
|
6
|
+
super(name.to_s, description, long_description, usage, options || {}, disable_class_options)
|
7
7
|
end
|
8
8
|
|
9
9
|
def initialize_copy(other) #:nodoc:
|
@@ -33,7 +33,7 @@ class Thor
|
|
33
33
|
rescue ArgumentError => e
|
34
34
|
handle_argument_error?(instance, e, caller) ? instance.class.handle_argument_error(self, e, args, arity) : (raise e)
|
35
35
|
rescue NoMethodError => e
|
36
|
-
handle_no_method_error?(instance, e, caller) ? instance.class.handle_no_command_error(name) : (
|
36
|
+
handle_no_method_error?(instance, e, caller) ? instance.class.handle_no_command_error(name) : (raise e)
|
37
37
|
end
|
38
38
|
|
39
39
|
# Returns the formatted usage by injecting given required arguments
|
@@ -50,7 +50,7 @@ class Thor
|
|
50
50
|
# Add usage with required arguments
|
51
51
|
formatted << if klass && !klass.arguments.empty?
|
52
52
|
usage.to_s.gsub(/^#{name}/) do |match|
|
53
|
-
match << " " << klass.arguments.map
|
53
|
+
match << " " << klass.arguments.map(&:usage).compact.join(" ")
|
54
54
|
end
|
55
55
|
else
|
56
56
|
usage.to_s
|
@@ -88,7 +88,7 @@ class Thor
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def sans_backtrace(backtrace, caller) #:nodoc:
|
91
|
-
saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) || (frame =~
|
91
|
+
saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) || (frame =~ %r{^kernel/} && RUBY_ENGINE =~ /rbx/) }
|
92
92
|
saned - caller
|
93
93
|
end
|
94
94
|
|
@@ -105,7 +105,7 @@ class Thor
|
|
105
105
|
error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
|
106
106
|
end
|
107
107
|
end
|
108
|
-
Task = Command
|
108
|
+
Task = Command
|
109
109
|
|
110
110
|
# A command that is hidden in help messages but still invocable.
|
111
111
|
class HiddenCommand < Command
|
@@ -113,7 +113,7 @@ class Thor
|
|
113
113
|
true
|
114
114
|
end
|
115
115
|
end
|
116
|
-
HiddenTask = HiddenCommand
|
116
|
+
HiddenTask = HiddenCommand
|
117
117
|
|
118
118
|
# A dynamic command that handles method missing scenarios.
|
119
119
|
class DynamicCommand < Command
|
@@ -129,5 +129,5 @@ class Thor
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
132
|
-
DynamicTask = DynamicCommand
|
132
|
+
DynamicTask = DynamicCommand
|
133
133
|
end
|
@@ -28,6 +28,14 @@ class Thor
|
|
28
28
|
super(convert_key(key))
|
29
29
|
end
|
30
30
|
|
31
|
+
def fetch(key, *args)
|
32
|
+
super(convert_key(key), *args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def key?(key)
|
36
|
+
super(convert_key(key))
|
37
|
+
end
|
38
|
+
|
31
39
|
def values_at(*indices)
|
32
40
|
indices.map { |key| self[convert_key(key)] }
|
33
41
|
end
|
@@ -60,7 +68,7 @@ class Thor
|
|
60
68
|
# options.shebang # => "/usr/lib/local/ruby"
|
61
69
|
# options.test_framework?(:rspec) # => options[:test_framework] == :rspec
|
62
70
|
#
|
63
|
-
def method_missing(method, *args
|
71
|
+
def method_missing(method, *args)
|
64
72
|
method = method.to_s
|
65
73
|
if method =~ /^(\w+)\?$/
|
66
74
|
if args.empty?
|
@@ -1,10 +1,12 @@
|
|
1
1
|
class IO #:nodoc:
|
2
2
|
class << self
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
7
9
|
end
|
8
|
-
end
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
@@ -1,96 +1,127 @@
|
|
1
1
|
class Thor
|
2
|
-
module CoreExt
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
# It keeps the semantics and most of the efficiency of normal hashes
|
10
|
-
# while also keeping track of the order in which elements were set.
|
11
|
-
#
|
12
|
-
class OrderedHash #:nodoc:
|
13
|
-
include Enumerable
|
14
|
-
|
15
|
-
Node = Struct.new(:key, :value, :next, :prev)
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
@hash = {}
|
2
|
+
module CoreExt
|
3
|
+
class OrderedHash < ::Hash
|
4
|
+
if RUBY_VERSION < "1.9"
|
5
|
+
def initialize(*args, &block)
|
6
|
+
super
|
7
|
+
@keys = []
|
19
8
|
end
|
20
9
|
|
21
|
-
def
|
22
|
-
|
10
|
+
def initialize_copy(other)
|
11
|
+
super
|
12
|
+
# make a deep copy of keys
|
13
|
+
@keys = other.keys
|
23
14
|
end
|
24
15
|
|
25
16
|
def []=(key, value)
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
node = Node.new(key, value)
|
30
|
-
|
31
|
-
if !defined?(@first) || @first.nil?
|
32
|
-
@first = @last = node
|
33
|
-
else
|
34
|
-
node.prev = @last
|
35
|
-
@last.next = node
|
36
|
-
@last = node
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
@hash[key] = node
|
41
|
-
value
|
17
|
+
@keys << key unless key?(key)
|
18
|
+
super
|
42
19
|
end
|
43
20
|
|
44
21
|
def delete(key)
|
45
|
-
if
|
46
|
-
|
47
|
-
|
22
|
+
if key? key
|
23
|
+
index = @keys.index(key)
|
24
|
+
@keys.delete_at index
|
25
|
+
end
|
26
|
+
super
|
27
|
+
end
|
48
28
|
|
49
|
-
|
50
|
-
|
29
|
+
def delete_if
|
30
|
+
super
|
31
|
+
sync_keys!
|
32
|
+
self
|
33
|
+
end
|
51
34
|
|
52
|
-
|
53
|
-
@last = prev_node if @last == node
|
35
|
+
alias_method :reject!, :delete_if
|
54
36
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@hash.delete(key)
|
59
|
-
value
|
37
|
+
def reject(&block)
|
38
|
+
dup.reject!(&block)
|
60
39
|
end
|
61
40
|
|
62
41
|
def keys
|
63
|
-
|
42
|
+
@keys.dup
|
64
43
|
end
|
65
44
|
|
66
45
|
def values
|
67
|
-
map { |
|
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
|
68
67
|
end
|
69
68
|
|
70
69
|
def each
|
71
|
-
return
|
72
|
-
|
73
|
-
node = @first
|
74
|
-
yield [node.key, node.value] while node = node.next # rubocop:disable AssignmentInCondition
|
70
|
+
return to_enum(:each) unless block_given?
|
71
|
+
@keys.each { |key| yield([key, self[key]]) }
|
75
72
|
self
|
76
73
|
end
|
77
74
|
|
78
|
-
def
|
79
|
-
|
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
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
84
94
|
|
85
|
-
|
86
|
-
|
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 }
|
87
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
|
88
109
|
|
89
|
-
|
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
|
90
115
|
end
|
91
116
|
|
92
|
-
def
|
93
|
-
|
117
|
+
def inspect
|
118
|
+
"#<#{self.class} #{super}>"
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def sync_keys!
|
124
|
+
@keys.delete_if { |k| !key?(k) }
|
94
125
|
end
|
95
126
|
end
|
96
127
|
end
|