pry-moves 0.1.7 → 0.1.13
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 +5 -5
- data/Gemfile.lock +19 -20
- data/README.md +20 -2
- data/lib/pry-moves.rb +9 -6
- data/lib/pry-moves/backtrace.rb +6 -6
- data/lib/pry-moves/commands.rb +13 -8
- data/lib/pry-moves/helpers.rb +6 -0
- data/lib/pry-moves/painter.rb +4 -0
- data/lib/pry-moves/pry_ext.rb +3 -2
- data/lib/pry-moves/pry_wrapper.rb +1 -2
- data/lib/pry-moves/trace_commands.rb +30 -17
- data/lib/pry-moves/traced_method.rb +61 -0
- data/lib/pry-moves/tracer.rb +19 -35
- data/lib/pry-moves/traversing.rb +69 -0
- data/lib/pry-moves/version.rb +1 -1
- data/lib/pry-stack_explorer/VERSION +2 -0
- data/lib/pry-stack_explorer/pry-stack_explorer.rb +5 -4
- data/lib/pry-stack_explorer/when_started_hook.rb +11 -2
- data/playground/Gemfile.lock +8 -10
- data/playground/playground.rb +13 -4
- data/playground/sand.rb +3 -15
- data/pry-moves.gemspec +1 -1
- data/publish.sh +2 -0
- data/spec/blocks_spec.rb +52 -3
- data/spec/pry_debugger.rb +25 -15
- metadata +14 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8826581b1684b35099d08f56064e2f3b38ccf3e0d24e3bf40779de9da58151f1
|
4
|
+
data.tar.gz: d73a5a0b30ac023416e901a3a965d95b4d232bdef5c0f44ab49ec4dfc7708585
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ade46c2440bcd4e14a296b9f3785ce0fff501abe953670ce19c9851d0b52488795113179717dffab6b57221c81839317236417bd1ce76380ceed96c3ed4a596
|
7
|
+
data.tar.gz: b5b959011051e252cb8a65c1b049f0cdfd8dcd6056b47b7cc7ba87052bb84ec5e1fd767d641385ab2ac1c162f0230d6a7bc760f77ac2699bc5fdbd5d6e812a05
|
data/Gemfile.lock
CHANGED
@@ -1,39 +1,38 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pry-moves (0.1.
|
4
|
+
pry-moves (0.1.13)
|
5
5
|
binding_of_caller (~> 0.7)
|
6
|
-
pry (>= 0.
|
6
|
+
pry (>= 0.10.4, < 0.12.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
binding_of_caller (0.
|
11
|
+
binding_of_caller (0.8.0)
|
12
12
|
debug_inspector (>= 0.0.1)
|
13
|
-
coderay (1.1.
|
13
|
+
coderay (1.1.2)
|
14
14
|
debug_inspector (0.0.3)
|
15
15
|
diff-lcs (1.3)
|
16
|
-
method_source (0.
|
17
|
-
pry (0.
|
16
|
+
method_source (0.9.0)
|
17
|
+
pry (0.11.3)
|
18
18
|
coderay (~> 1.1.0)
|
19
|
-
method_source (~> 0.
|
20
|
-
slop (~> 3.4)
|
19
|
+
method_source (~> 0.9.0)
|
21
20
|
pry-remote (0.1.8)
|
22
21
|
pry (~> 0.9)
|
23
22
|
slop (~> 3.0)
|
24
|
-
rspec (3.
|
25
|
-
rspec-core (~> 3.
|
26
|
-
rspec-expectations (~> 3.
|
27
|
-
rspec-mocks (~> 3.
|
28
|
-
rspec-core (3.
|
29
|
-
rspec-support (~> 3.
|
30
|
-
rspec-expectations (3.
|
23
|
+
rspec (3.8.0)
|
24
|
+
rspec-core (~> 3.8.0)
|
25
|
+
rspec-expectations (~> 3.8.0)
|
26
|
+
rspec-mocks (~> 3.8.0)
|
27
|
+
rspec-core (3.8.0)
|
28
|
+
rspec-support (~> 3.8.0)
|
29
|
+
rspec-expectations (3.8.1)
|
31
30
|
diff-lcs (>= 1.2.0, < 2.0)
|
32
|
-
rspec-support (~> 3.
|
33
|
-
rspec-mocks (3.
|
31
|
+
rspec-support (~> 3.8.0)
|
32
|
+
rspec-mocks (3.8.0)
|
34
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
-
rspec-support (~> 3.
|
36
|
-
rspec-support (3.
|
34
|
+
rspec-support (~> 3.8.0)
|
35
|
+
rspec-support (3.8.0)
|
37
36
|
slop (3.6.0)
|
38
37
|
|
39
38
|
PLATFORMS
|
@@ -46,4 +45,4 @@ DEPENDENCIES
|
|
46
45
|
rspec
|
47
46
|
|
48
47
|
BUNDLED WITH
|
49
|
-
1.
|
48
|
+
2.1.1
|
data/README.md
CHANGED
@@ -15,15 +15,19 @@ _An execution control add-on for [Pry][pry]._
|
|
15
15
|
* `s method_name` - step into method `method_name` (For example from `User.new.method_name`). Partial name match supported.
|
16
16
|
* `s +` - step into function, including hidden frames
|
17
17
|
* `f` - **finish** execution of current frame (block or method) and stop at next line on higher level
|
18
|
+
* `iterate` - go to next iteration of current block
|
18
19
|
* `c` - **continue**
|
20
|
+
* `g 10` - **goto** line 10
|
19
21
|
* `bt` - show latest 5 lines from backtrace
|
20
22
|
* `bt 10` - latest 10 lines
|
21
|
-
* `bt
|
23
|
+
* `bt full` - full backtrace
|
24
|
+
* `bt +` - full backtrace with hidden frames. Aliases: `bt hidden` `bt vapid` `bt all`
|
22
25
|
* `bt > foo` - write backtrace to file `log/backtrace_foo.log`
|
23
26
|
* `up`/`down`/`top`/`bottom` - move over call stack
|
24
27
|
* `up +` - move up, including vapid frames (block callers, hidden frames)
|
25
28
|
* `up pattern` - move up till first frame which method name or file position in format `folder/script.rb:12` matches regexp pattern
|
26
29
|
* `debug some_method(some_param)` - call `some_method(some_param)` and interactively step into it. This way you can virtually "step back" by executing previous pieces of code from current method
|
30
|
+
* `.method` or `123` or `:hash_key` - Continue traversing of last object in history. E.g. `orders` will list array, then `3` will enter `orders[3]`, then `.price` will enter `orders[3].price`
|
27
31
|
* `watch variable` - display variable's value on each step
|
28
32
|
* `!` - exit
|
29
33
|
|
@@ -69,6 +73,16 @@ PryMoves::Backtrace::filter =
|
|
69
73
|
|
70
74
|
## Threads, helpers
|
71
75
|
|
76
|
+
To allow traveling to parent thread, use:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
pre_callers = binding.callers
|
80
|
+
Thread.new do
|
81
|
+
Thread.current[:pre_callers] = pre_callers
|
82
|
+
#...
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
72
86
|
`pry-moves` can't stop other threads on `binding.pry`, so they will continue to run.
|
73
87
|
This makes `pry-moves` not always suitable for debugging of multi-thread projects.
|
74
88
|
|
@@ -110,6 +124,10 @@ Please note that debugging functionality is implemented through
|
|
110
124
|
bundle exec rspec
|
111
125
|
```
|
112
126
|
|
127
|
+
## ToDo
|
128
|
+
|
129
|
+
* `iterate` - steps in into child sub-block - should skip
|
130
|
+
|
113
131
|
## Contributors
|
114
132
|
|
115
133
|
* Gopal Patel ([@nixme](https://github.com/nixme))
|
@@ -120,7 +138,7 @@ bundle exec rspec
|
|
120
138
|
* Ivo Anjo ([@ivoanjo](https://github.com/ivoanjo))
|
121
139
|
|
122
140
|
Patches and bug reports are welcome. Just send a [pull request][pullrequests] or
|
123
|
-
file an [issue][issues].
|
141
|
+
file an [issue][issues].
|
124
142
|
|
125
143
|
## Acknowledgments
|
126
144
|
|
data/lib/pry-moves.rb
CHANGED
@@ -2,9 +2,11 @@ require 'pry' unless defined? Pry
|
|
2
2
|
|
3
3
|
require 'pry-moves/version'
|
4
4
|
require 'pry-moves/trace_commands'
|
5
|
+
require 'pry-moves/traced_method'
|
5
6
|
require 'pry-moves/tracer'
|
6
7
|
require 'pry-moves/pry_ext'
|
7
8
|
require 'pry-moves/commands'
|
9
|
+
require 'pry-moves/traversing'
|
8
10
|
require 'pry-moves/pry_wrapper'
|
9
11
|
require 'pry-moves/backtrace'
|
10
12
|
require 'pry-moves/watch'
|
@@ -34,6 +36,10 @@ module PryMoves
|
|
34
36
|
@semaphore ||= Mutex.new
|
35
37
|
end
|
36
38
|
|
39
|
+
def locked?
|
40
|
+
semaphore.locked?
|
41
|
+
end
|
42
|
+
|
37
43
|
def lock
|
38
44
|
semaphore.lock unless semaphore.locked?
|
39
45
|
end
|
@@ -47,13 +53,10 @@ module PryMoves
|
|
47
53
|
end
|
48
54
|
|
49
55
|
def synchronize_threads
|
50
|
-
return if Thread.current[:pry_moves_debug]
|
56
|
+
return true if Thread.current[:pry_moves_debug]
|
51
57
|
|
52
|
-
semaphore.synchronize {}
|
53
|
-
|
54
|
-
puts e.backtrace.reverse
|
55
|
-
puts e
|
56
|
-
raise e
|
58
|
+
semaphore.synchronize {} rescue return
|
59
|
+
true
|
57
60
|
end
|
58
61
|
|
59
62
|
# Reference to currently running pry-remote server. Used by the tracer.
|
data/lib/pry-moves/backtrace.rb
CHANGED
@@ -44,7 +44,7 @@ class PryMoves::Backtrace
|
|
44
44
|
|
45
45
|
def build
|
46
46
|
result = []
|
47
|
-
show_vapid = @lines_count
|
47
|
+
show_vapid = %w(+ all hidden vapid).include? @lines_count
|
48
48
|
stack = stack_bindings(show_vapid)
|
49
49
|
.reverse.reject do |binding|
|
50
50
|
binding.eval('__FILE__').match self.class::filter
|
@@ -61,9 +61,10 @@ class PryMoves::Backtrace
|
|
61
61
|
def build_result(stack, result)
|
62
62
|
current_object = nil
|
63
63
|
stack.each do |binding|
|
64
|
-
obj = binding.eval 'self'
|
65
|
-
|
66
|
-
|
64
|
+
obj, debug_snapshot = binding.eval '[self, (debug_snapshot rescue nil)]'
|
65
|
+
# Comparison of objects directly may raise exception
|
66
|
+
if current_object.object_id != obj.object_id
|
67
|
+
result << "#{debug_snapshot || format_obj(obj)}:"
|
67
68
|
current_object = obj
|
68
69
|
end
|
69
70
|
|
@@ -81,8 +82,7 @@ class PryMoves::Backtrace
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def build_line(binding)
|
84
|
-
file = "#{binding.eval('__FILE__')}"
|
85
|
-
file.gsub!( /^#{Rails.root.to_s}/, '') if defined? Rails
|
85
|
+
file = PryMoves::Helpers.shorten_path "#{binding.eval('__FILE__')}"
|
86
86
|
|
87
87
|
signature = PryMoves::Helpers.method_signature binding
|
88
88
|
signature = ":#{binding.frame_type}" if !signature or signature.length < 1
|
data/lib/pry-moves/commands.rb
CHANGED
@@ -5,32 +5,36 @@ module PryMoves
|
|
5
5
|
block_command 'step', 'Step execution into the next line or method.' do |param|
|
6
6
|
breakout_navigation :step, param
|
7
7
|
end
|
8
|
+
alias_command 's', 'step'
|
8
9
|
|
9
|
-
block_command 'finish', 'Finish - xule tut neponyatnogo
|
10
|
+
block_command 'finish', 'Finish - xule tut neponyatnogo' do |param|
|
10
11
|
breakout_navigation :finish, param
|
11
12
|
end
|
13
|
+
alias_command 'f', 'finish'
|
12
14
|
|
13
15
|
block_command 'next', 'Execute the next line stepping into blocks' do |param|
|
14
16
|
breakout_navigation :next, param
|
15
17
|
end
|
18
|
+
alias_command 'n', 'next'
|
16
19
|
|
17
|
-
block_command 'nn', 'Execute the next line skipping blocks
|
20
|
+
block_command 'nn', 'Execute the next line skipping blocks' do |param|
|
18
21
|
breakout_navigation :next, 'blockless'
|
19
22
|
end
|
20
23
|
|
21
|
-
block_command 'iterate', '
|
24
|
+
block_command 'iterate', 'Go to next iteration of current block' do |param|
|
22
25
|
breakout_navigation :iterate, param
|
23
26
|
end
|
24
27
|
|
25
|
-
block_command '
|
28
|
+
block_command 'goto', 'goto line' do |param|
|
29
|
+
breakout_navigation :goto, param
|
30
|
+
end
|
31
|
+
alias_command 'g', 'goto'
|
32
|
+
|
33
|
+
block_command 'continue', 'Continue program execution and end the Pry session' do
|
26
34
|
check_file_context
|
27
35
|
run 'exit-all'
|
28
36
|
end
|
29
|
-
|
30
37
|
alias_command 'c', 'continue'
|
31
|
-
alias_command 's', 'step'
|
32
|
-
alias_command 'n', 'next'
|
33
|
-
alias_command 'f', 'finish'
|
34
38
|
|
35
39
|
block_command 'watch', 'Display value of expression on every move' do |param|
|
36
40
|
PryMoves::Watch.instance.process_cmd param, target
|
@@ -46,6 +50,7 @@ module PryMoves
|
|
46
50
|
end
|
47
51
|
|
48
52
|
block_command '!', 'exit' do
|
53
|
+
PryMoves.unlock
|
49
54
|
Pry.config.exit_requested = true
|
50
55
|
run '!!!'
|
51
56
|
end
|
data/lib/pry-moves/helpers.rb
CHANGED
data/lib/pry-moves/painter.rb
CHANGED
@@ -14,10 +14,14 @@ module PryMoves::Painter
|
|
14
14
|
|
15
15
|
def self.colorize(obj)
|
16
16
|
colored_str = Canvas.new
|
17
|
+
obj = obj.class if obj.inspect.start_with? "#<"
|
17
18
|
catch (:cut) do
|
18
19
|
Pry::ColorPrinter.pp obj, colored_str
|
19
20
|
end
|
20
21
|
colored_str.chomp
|
22
|
+
rescue => e
|
23
|
+
"Inspect error: #{e}\n" +
|
24
|
+
"#{e.backtrace.first(3).join("\n")}"
|
21
25
|
end
|
22
26
|
|
23
27
|
end
|
data/lib/pry-moves/pry_ext.rb
CHANGED
@@ -24,7 +24,8 @@ Binding.class_eval do
|
|
24
24
|
|
25
25
|
def pry
|
26
26
|
unless Pry.config.disable_breakpoints
|
27
|
-
PryMoves.synchronize_threads
|
27
|
+
PryMoves.synchronize_threads ||
|
28
|
+
return # Don't start binding.pry when semaphore locked by current thread
|
28
29
|
pry_forced
|
29
30
|
end
|
30
31
|
end
|
@@ -56,7 +57,7 @@ Pry::Command::Whereami.class_eval do
|
|
56
57
|
|
57
58
|
def build_output
|
58
59
|
lines = []
|
59
|
-
lines << "#{text.bold('From:')} #{location}"
|
60
|
+
lines << "#{text.bold('From:')} #{PryMoves::Helpers.shorten_path location}"
|
60
61
|
lines << PryMoves::Watch.instance.output(target) unless PryMoves::Watch.instance.empty?
|
61
62
|
lines << ''
|
62
63
|
lines << "#{code.with_line_numbers(use_line_numbers?).with_marker(marker).highlighted}"
|
@@ -10,7 +10,7 @@ class PryWrapper
|
|
10
10
|
def run(&block)
|
11
11
|
PryMoves.lock
|
12
12
|
|
13
|
-
Pry.config.marker = "⛔️
|
13
|
+
Pry.config.marker = "⛔️" if @pry_start_options[:exit_from_method]
|
14
14
|
|
15
15
|
return_value = nil
|
16
16
|
PryMoves.is_open = true
|
@@ -58,7 +58,6 @@ class PryWrapper
|
|
58
58
|
end
|
59
59
|
|
60
60
|
Thread.current[:pry_moves_debug] = true
|
61
|
-
#@command[:binding].eval 'puts "###########"'
|
62
61
|
tracer = start_tracing
|
63
62
|
begin
|
64
63
|
@command[:binding].eval @command[:param]
|
@@ -2,7 +2,7 @@ module PryMoves::TraceCommands
|
|
2
2
|
|
3
3
|
private
|
4
4
|
|
5
|
-
def trace_step(event, file, line, binding_)
|
5
|
+
def trace_step(event, file, line, method, binding_)
|
6
6
|
return unless event == 'line'
|
7
7
|
|
8
8
|
if @step_in_everywhere
|
@@ -33,7 +33,7 @@ module PryMoves::TraceCommands
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def trace_next(event, file, line, binding_)
|
36
|
+
def trace_next(event, file, line, method, binding_)
|
37
37
|
traced_method_exit = (@recursion_level < 0 and %w(line call).include? event)
|
38
38
|
if traced_method_exit
|
39
39
|
# Set new traced method, because we left previous one
|
@@ -45,20 +45,22 @@ module PryMoves::TraceCommands
|
|
45
45
|
within_current_method?(file, line)
|
46
46
|
|
47
47
|
if event == 'line'
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
if @stay_at_frame
|
49
|
+
return (
|
50
|
+
@stay_at_frame == frame_digest(binding_.of_caller(3)) or
|
51
|
+
@c_stack_level < 0
|
52
|
+
)
|
53
|
+
else
|
54
|
+
return true
|
55
|
+
end
|
52
56
|
end
|
53
57
|
|
54
|
-
|
55
|
-
|
56
|
-
true
|
57
|
-
end
|
58
|
+
exit_from_method if event == 'return' and
|
59
|
+
method != :to_s and before_end?(line)
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
def trace_finish(event, file, line, binding_)
|
63
|
+
def trace_finish(event, file, line, method, binding_)
|
62
64
|
return unless event == 'line'
|
63
65
|
if @recursion_level < 0 or @method_to_finish != @method
|
64
66
|
if redirect_step_into?(binding_)
|
@@ -76,7 +78,7 @@ module PryMoves::TraceCommands
|
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
79
|
-
def trace_debug(event, file, line, binding_)
|
81
|
+
def trace_debug(event, file, line, method, binding_)
|
80
82
|
return unless event == 'line'
|
81
83
|
if @first_line_skipped
|
82
84
|
true
|
@@ -86,11 +88,22 @@ module PryMoves::TraceCommands
|
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
#
|
91
|
+
def trace_iterate(event, file, line, method, binding_)
|
92
|
+
return exit_from_method if event == 'return' and
|
93
|
+
within_current_method?(file, line)
|
94
|
+
|
95
|
+
# промотка итерации -
|
96
|
+
# попасть на ту же или предыдущую строку или выйти из дайджеста
|
97
|
+
# будучи в том же методе
|
98
|
+
event == 'line' and @recursion_level == 0 and
|
99
|
+
within_current_method?(file, line) and
|
100
|
+
(line <= @iteration_start_line or
|
101
|
+
@caller_digest != frame_digest(binding_.of_caller(3))
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
def trace_goto(event, file, line, method, binding_)
|
106
|
+
event == 'line' && @goto_line == line and @method[:file] == file
|
94
107
|
end
|
95
108
|
|
96
109
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module PryMoves::TracedMethod
|
2
|
+
|
3
|
+
private
|
4
|
+
|
5
|
+
def set_traced_method(binding)
|
6
|
+
@recursion_level = 0
|
7
|
+
@c_stack_level = 0
|
8
|
+
@stay_at_frame = nil # reset tracked digest
|
9
|
+
|
10
|
+
method = find_method_definition binding
|
11
|
+
if method
|
12
|
+
source = method.source_location
|
13
|
+
set_method({
|
14
|
+
file: source[0],
|
15
|
+
start: source[1],
|
16
|
+
name: method.name,
|
17
|
+
end: (source[1] + method.source.count("\n") - 1)
|
18
|
+
})
|
19
|
+
else
|
20
|
+
set_method({file: binding.eval('__FILE__')})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_method_definition(binding)
|
25
|
+
method_name, obj, line, file =
|
26
|
+
binding.eval '[__method__, self, __LINE__, __FILE__]'
|
27
|
+
return unless method_name
|
28
|
+
|
29
|
+
method = obj.method(method_name)
|
30
|
+
return method if method.source_location[0] == file
|
31
|
+
|
32
|
+
# If found file was different - search definition at superclasses:
|
33
|
+
obj.class.ancestors.each do |cls|
|
34
|
+
if cls.instance_methods(false).include? method_name
|
35
|
+
method = cls.instance_method method_name
|
36
|
+
return method if method.source_location[0] == file
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
pry_puts "⚠️ Unable to find definition for method #{method_name} in #{obj}"
|
41
|
+
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_method(method)
|
46
|
+
#puts "set_traced_method #{method}"
|
47
|
+
@method = method
|
48
|
+
end
|
49
|
+
|
50
|
+
def within_current_method?(file, line)
|
51
|
+
@method[:file] == file and (
|
52
|
+
@method[:start].nil? or
|
53
|
+
line.between?(@method[:start], @method[:end])
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def before_end?(line)
|
58
|
+
@method[:end] and line < @method[:end]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
data/lib/pry-moves/tracer.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
1
3
|
require 'pry' unless defined? Pry
|
2
4
|
|
3
5
|
module PryMoves
|
4
6
|
class Tracer
|
5
7
|
|
6
8
|
include PryMoves::TraceCommands
|
9
|
+
include PryMoves::TracedMethod
|
7
10
|
|
8
11
|
def initialize(command, pry_start_options)
|
9
12
|
@command = command
|
@@ -38,6 +41,11 @@ class Tracer
|
|
38
41
|
if @command[:param] == 'blockless'
|
39
42
|
@stay_at_frame = frame_digest(binding_)
|
40
43
|
end
|
44
|
+
when :iterate
|
45
|
+
@iteration_start_line = binding_.eval('__LINE__')
|
46
|
+
@caller_digest = frame_digest(binding_)
|
47
|
+
when :goto
|
48
|
+
@goto_line = @command[:param].to_i
|
41
49
|
end
|
42
50
|
|
43
51
|
start_tracing
|
@@ -66,41 +74,19 @@ class Tracer
|
|
66
74
|
Thread.current : Kernel
|
67
75
|
end
|
68
76
|
|
69
|
-
def set_traced_method(binding)
|
70
|
-
@recursion_level = 0
|
71
|
-
|
72
|
-
method = binding.eval 'method(__method__) if __method__'
|
73
|
-
if method
|
74
|
-
source = method.source_location
|
75
|
-
set_method({
|
76
|
-
file: source[0],
|
77
|
-
start: source[1],
|
78
|
-
name: method.name,
|
79
|
-
end: (source[1] + method.source.count("\n") - 1)
|
80
|
-
})
|
81
|
-
else
|
82
|
-
set_method({file: binding.eval('__FILE__')})
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def set_method(method)
|
87
|
-
#puts "set_traced_method #{method}"
|
88
|
-
@method = method
|
89
|
-
end
|
90
|
-
|
91
77
|
def frame_digest(binding_)
|
92
78
|
#puts "frame_digest for: #{binding_.eval '__callee__'}"
|
93
79
|
Digest::MD5.hexdigest binding_.instance_variable_get('@iseq').disasm
|
94
80
|
end
|
95
81
|
|
96
82
|
def tracing_func(event, file, line, id, binding_, klass)
|
97
|
-
#printf "
|
83
|
+
# printf ": %8s %s:%-2d %10s %8s rec:#{@recursion_level} st:#{@c_stack_level}\n", event, file, line, id, klass
|
98
84
|
|
99
85
|
# Ignore traces inside pry-moves code
|
100
86
|
return if file && TRACE_IGNORE_FILES.include?(File.expand_path(file))
|
101
87
|
|
102
88
|
catch (:skip) do
|
103
|
-
if send "trace_#{@action}", event, file, line, binding_
|
89
|
+
if send "trace_#{@action}", event, file, line, id, binding_
|
104
90
|
stop_tracing
|
105
91
|
Pry.start(binding_, @pry_start_options)
|
106
92
|
|
@@ -110,6 +96,9 @@ class Tracer
|
|
110
96
|
delta = event == 'call' ? 1 : -1
|
111
97
|
#puts "recursion #{event}: #{delta}; changed: #{@recursion_level} => #{@recursion_level + delta}"
|
112
98
|
@recursion_level += delta
|
99
|
+
elsif %w(c-call c-return).include?(event)
|
100
|
+
delta = event == 'c-call' ? 1 : -1
|
101
|
+
@c_stack_level += delta
|
113
102
|
end
|
114
103
|
end
|
115
104
|
end
|
@@ -137,20 +126,15 @@ class Tracer
|
|
137
126
|
puts "#{id} #{@method[:start]} > #{line} > #{@method[:end]}"
|
138
127
|
end
|
139
128
|
|
140
|
-
def within_current_method?(file, line)
|
141
|
-
@method[:file] == file and (
|
142
|
-
@method[:start].nil? or
|
143
|
-
line.between?(@method[:start], @method[:end])
|
144
|
-
)
|
145
|
-
end
|
146
|
-
|
147
|
-
def before_end?(line)
|
148
|
-
@method[:end] and line < @method[:end]
|
149
|
-
end
|
150
129
|
|
151
130
|
def pry_puts(text)
|
152
131
|
@command[:pry].output.puts text
|
153
132
|
end
|
154
133
|
|
134
|
+
def exit_from_method
|
135
|
+
@pry_start_options[:exit_from_method] = true
|
136
|
+
true
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
155
140
|
end
|
156
|
-
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module PryMoves
|
2
|
+
|
3
|
+
class Traversing < Pry::ClassCommand
|
4
|
+
|
5
|
+
group 'Input and Output'
|
6
|
+
description "Continue traversing of last object in history."
|
7
|
+
|
8
|
+
banner <<-'BANNER'
|
9
|
+
Usage: .method | 123 | :hash_key
|
10
|
+
|
11
|
+
Continue traversing of last object in history
|
12
|
+
|
13
|
+
E.g. `orders` will list array, then `3` will enter `orders[3]`, then `.price` will enter `orders[3].price`
|
14
|
+
BANNER
|
15
|
+
|
16
|
+
def process(cmd)
|
17
|
+
last_cmd = Pry.history.to_a[-1]
|
18
|
+
cmd = "#{last_cmd}#{wrap_command(cmd)}"
|
19
|
+
_pry_.pager.page " > #{cmd}\n"
|
20
|
+
_pry_.eval cmd
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class Method < Traversing
|
29
|
+
match(/^\.(.+)$/)
|
30
|
+
|
31
|
+
def wrap_command(cmd)
|
32
|
+
".#{cmd}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class ArrayIndex < Traversing
|
37
|
+
match(/^(\d+)$/)
|
38
|
+
|
39
|
+
def wrap_command(cmd)
|
40
|
+
"[#{cmd}]"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class HashKey < Traversing
|
45
|
+
match(/^(:\w+)$/)
|
46
|
+
|
47
|
+
def wrap_command(cmd)
|
48
|
+
"[#{cmd}]"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
Pry::Commands.add_command(PryMoves::Method)
|
53
|
+
Pry::Commands.add_command(PryMoves::ArrayIndex)
|
54
|
+
Pry::Commands.add_command(PryMoves::HashKey)
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
Pry::History.class_eval do
|
59
|
+
|
60
|
+
EXCLUDE = [PryMoves::Method, PryMoves::ArrayIndex, PryMoves::HashKey]
|
61
|
+
|
62
|
+
def <<(line)
|
63
|
+
return if EXCLUDE.any? do |cls|
|
64
|
+
line.match(cls.match)
|
65
|
+
end
|
66
|
+
push line
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/pry-moves/version.rb
CHANGED
@@ -108,7 +108,7 @@ module PryStackExplorer
|
|
108
108
|
(b1.eval('self').equal?(b2.eval('self'))) &&
|
109
109
|
(b1.eval('__method__') == b2.eval('__method__')) &&
|
110
110
|
(b1.eval('local_variables').map { |v| b1.eval("#{v}") }.equal?(
|
111
|
-
|
111
|
+
b2.eval('local_variables').map { |v| b2.eval("#{v}") }))
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
@@ -117,6 +117,7 @@ Pry.config.hooks.add_hook(:after_session, :delete_frame_manager) do |_, _, _pry_
|
|
117
117
|
PryStackExplorer.clear_frame_managers(_pry_)
|
118
118
|
end
|
119
119
|
|
120
|
+
# Can be moved to start_with_pry_nav to isolate from other use cases of Pry
|
120
121
|
Pry.config.hooks.add_hook(:when_started, :save_caller_bindings, PryStackExplorer::WhenStartedHook.new)
|
121
122
|
|
122
123
|
# Import the StackExplorer commands
|
@@ -124,14 +125,14 @@ Pry.config.commands.import PryStackExplorer::Commands
|
|
124
125
|
|
125
126
|
# monkey-patch the whereami command to show some frame information,
|
126
127
|
# useful for navigating stack.
|
127
|
-
Pry.config.
|
128
|
+
Pry.config.hooks.add_hook(:before_whereami, :stack_explorer) do
|
128
129
|
if PryStackExplorer.frame_manager(_pry_) && !internal_binding?(target)
|
129
130
|
bindings = PryStackExplorer.frame_manager(_pry_).bindings
|
130
131
|
binding_index = PryStackExplorer.frame_manager(_pry_).binding_index
|
131
132
|
|
132
133
|
info = "#{Pry::Helpers::Text.bold('Frame:')} "+
|
133
|
-
|
134
|
-
|
134
|
+
"#{binding_index}/#{bindings.size - 1} "+
|
135
|
+
"#{bindings[binding_index].frame_type}"
|
135
136
|
|
136
137
|
output.puts "\n"
|
137
138
|
output.puts info
|
@@ -12,6 +12,11 @@ module PryStackExplorer
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def call(target, options, _pry_)
|
15
|
+
start_from_console = target.eval('__callee__').nil? &&
|
16
|
+
target.eval('__FILE__') == '<main>' &&
|
17
|
+
target.eval('__LINE__') == 0
|
18
|
+
return if start_from_console
|
19
|
+
|
15
20
|
target ||= _pry_.binding_stack.first if _pry_
|
16
21
|
options = {
|
17
22
|
:call_stack => true,
|
@@ -23,14 +28,18 @@ module PryStackExplorer
|
|
23
28
|
if options[:call_stack].is_a?(Array)
|
24
29
|
bindings = options[:call_stack]
|
25
30
|
|
26
|
-
|
31
|
+
unless valid_call_stack?(bindings)
|
27
32
|
raise ArgumentError, ":call_stack must be an array of bindings"
|
28
33
|
end
|
29
34
|
else
|
30
35
|
bindings = caller_bindings(target)
|
36
|
+
initial_frame = bindings.find do |b|
|
37
|
+
not b.local_variable_defined?(:vapid_frame)
|
38
|
+
end
|
39
|
+
options[:initial_frame] = bindings.index initial_frame
|
31
40
|
end
|
32
41
|
|
33
|
-
PryStackExplorer.create_and_push_frame_manager bindings, _pry_, :
|
42
|
+
PryStackExplorer.create_and_push_frame_manager bindings, _pry_, initial_frame: options[:initial_frame]
|
34
43
|
end
|
35
44
|
|
36
45
|
private
|
data/playground/Gemfile.lock
CHANGED
@@ -1,23 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
pry-moves (0.1.
|
4
|
+
pry-moves (0.1.11)
|
5
5
|
binding_of_caller (~> 0.7)
|
6
|
-
pry (>= 0.
|
6
|
+
pry (>= 0.10.4, < 1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
binding_of_caller (0.
|
11
|
+
binding_of_caller (0.8.0)
|
12
12
|
debug_inspector (>= 0.0.1)
|
13
|
-
coderay (1.1.
|
13
|
+
coderay (1.1.2)
|
14
14
|
debug_inspector (0.0.3)
|
15
|
-
method_source (0.
|
16
|
-
pry (0.
|
15
|
+
method_source (0.9.2)
|
16
|
+
pry (0.12.2)
|
17
17
|
coderay (~> 1.1.0)
|
18
|
-
method_source (~> 0.
|
19
|
-
slop (~> 3.4)
|
20
|
-
slop (3.6.0)
|
18
|
+
method_source (~> 0.9.0)
|
21
19
|
|
22
20
|
PLATFORMS
|
23
21
|
ruby
|
@@ -26,4 +24,4 @@ DEPENDENCIES
|
|
26
24
|
pry-moves!
|
27
25
|
|
28
26
|
BUNDLED WITH
|
29
|
-
1.
|
27
|
+
1.17.0
|
data/playground/playground.rb
CHANGED
@@ -54,11 +54,20 @@ class Playground
|
|
54
54
|
self
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
58
|
-
binding.pry # stop in
|
59
|
-
iterator do |i|
|
57
|
+
def nested_block(early_return: false)
|
58
|
+
binding.pry # stop in nested_block
|
59
|
+
iterator do |i| # iterator line
|
60
|
+
dummy = 1 # inside block
|
61
|
+
return if early_return
|
62
|
+
end
|
63
|
+
:after_block # after block
|
64
|
+
end
|
65
|
+
|
66
|
+
def native_block(early_return: false)
|
67
|
+
binding.pry # stop in native_block
|
68
|
+
2.times do |i| # iterator line
|
60
69
|
dummy = 1 # inside block
|
61
|
-
|
70
|
+
return if early_return
|
62
71
|
end
|
63
72
|
:after_block # after block
|
64
73
|
end
|
data/playground/sand.rb
CHANGED
@@ -10,33 +10,25 @@ end
|
|
10
10
|
class A
|
11
11
|
|
12
12
|
def initialize
|
13
|
-
hide_from_stack = true
|
14
13
|
puts :xuilo
|
15
14
|
end
|
16
15
|
|
17
|
-
def kozi
|
18
|
-
puts 'aa2 1'
|
19
|
-
puts 'aa2 2'
|
20
|
-
end
|
21
|
-
|
22
16
|
def aa
|
23
|
-
debug_redirect = :kozi
|
24
17
|
puts 'aa: step 1'
|
25
18
|
puts 'aa: step 2'
|
26
|
-
kozi
|
27
19
|
end
|
28
20
|
|
29
21
|
def bb
|
30
|
-
|
22
|
+
debug_redirect = :aa
|
23
|
+
hide_from_stack = true
|
31
24
|
puts 'bb: step 1'
|
32
25
|
puts 'bb: step 2'
|
33
26
|
aa
|
34
27
|
end
|
35
28
|
|
36
29
|
def cc
|
37
|
-
#debug_redirect = :bb
|
38
|
-
hide_from_stack = true
|
39
30
|
koko = :love
|
31
|
+
binding.pry
|
40
32
|
bb
|
41
33
|
(2..4).each do |i|
|
42
34
|
puts i
|
@@ -47,12 +39,8 @@ class A
|
|
47
39
|
|
48
40
|
end
|
49
41
|
|
50
|
-
require './playground.rb'
|
51
|
-
Playground.new.basic_next
|
52
|
-
|
53
42
|
puts :prepare
|
54
43
|
|
55
|
-
binding.pry
|
56
44
|
A.new.cc_al
|
57
45
|
A.new.cc_al
|
58
46
|
|
data/pry-moves.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
# Dependencies
|
21
21
|
gem.required_ruby_version = '>= 1.8.7'
|
22
|
-
gem.add_runtime_dependency 'pry', '>= 0.
|
22
|
+
gem.add_runtime_dependency 'pry', '>= 0.10.4', '< 0.12.0'
|
23
23
|
gem.add_runtime_dependency 'binding_of_caller', '~> 0.7'
|
24
24
|
gem.add_development_dependency 'pry-remote', '~> 0.1.6'
|
25
25
|
end
|
data/publish.sh
ADDED
data/spec/blocks_spec.rb
CHANGED
@@ -28,12 +28,12 @@ describe 'blocks' do
|
|
28
28
|
|
29
29
|
it 'should finish simple block' do
|
30
30
|
breakpoints [
|
31
|
-
[nil, 'stop in
|
32
|
-
['n', ''],
|
31
|
+
[nil, 'stop in nested_block'],
|
32
|
+
['n', 'iterator line'],
|
33
33
|
['', 'inside block'],
|
34
34
|
['f', 'after block']
|
35
35
|
]
|
36
|
-
Playground.new.
|
36
|
+
Playground.new.nested_block
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'should finish block with sub-calls' do
|
@@ -47,5 +47,54 @@ describe 'blocks' do
|
|
47
47
|
Playground.new.zaloop
|
48
48
|
end
|
49
49
|
|
50
|
+
it 'should iterate over native block' do
|
51
|
+
breakpoints [
|
52
|
+
[nil, 'stop in native_block'],
|
53
|
+
['n', 'iterator line'],
|
54
|
+
['n', 'inside block'],
|
55
|
+
['i', {output: '=> 0'}],
|
56
|
+
['iterate', 'inside block'],
|
57
|
+
['i', {output: '=> 1'}],
|
58
|
+
['iterate', 'after block'],
|
59
|
+
]
|
60
|
+
Playground.new.native_block
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should iterate over nested block' do
|
64
|
+
breakpoints [
|
65
|
+
[nil, 'stop in nested_block'],
|
66
|
+
['n', 'iterator line'],
|
67
|
+
['n', 'inside block'],
|
68
|
+
['i', {output: '=> 0'}],
|
69
|
+
['iterate', 'inside block'],
|
70
|
+
['i', {output: '=> 1'}],
|
71
|
+
['iterate', 'after block'],
|
72
|
+
]
|
73
|
+
Playground.new.nested_block
|
74
|
+
end
|
50
75
|
|
76
|
+
it 'should return during iterating native block' do
|
77
|
+
breakpoints [
|
78
|
+
[nil, 'stop in native_block'],
|
79
|
+
['n', 'iterator line'],
|
80
|
+
['n', 'inside block'],
|
81
|
+
['iterate', 'iterator line'],
|
82
|
+
['n', 'exit'],
|
83
|
+
]
|
84
|
+
Playground.new.native_block early_return: true
|
85
|
+
:exit # exit
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should return during iterating nested block' do
|
89
|
+
breakpoints [
|
90
|
+
[nil, 'stop in nested_block'],
|
91
|
+
['n', 'iterator line'],
|
92
|
+
['n', 'inside block'],
|
93
|
+
['iterate', 'iterator line'],
|
94
|
+
['n', 'exit'],
|
95
|
+
]
|
96
|
+
Playground.new.nested_block early_return: true
|
97
|
+
:exit # exit
|
98
|
+
end
|
99
|
+
|
51
100
|
end
|
data/spec/pry_debugger.rb
CHANGED
@@ -2,31 +2,41 @@ module PryDebugger
|
|
2
2
|
|
3
3
|
module Breakpoints
|
4
4
|
def breakpoints(breakpoints)
|
5
|
+
steps = []
|
5
6
|
breakpoints.each_with_index do |b, index|
|
6
7
|
next_b = breakpoints[index+1]
|
7
|
-
|
8
|
+
steps << {
|
9
|
+
cmd: b[0],
|
10
|
+
expected: b[1],
|
11
|
+
next_cmd: next_b ? next_b[0] : nil,
|
12
|
+
index: index
|
13
|
+
}
|
8
14
|
end
|
9
15
|
|
10
16
|
PryDebugger.breakpoints =
|
11
|
-
|
17
|
+
steps.map do |step|
|
12
18
|
Proc.new do |label, binding_, output|
|
13
|
-
compare(
|
14
|
-
|
19
|
+
compare(step, label, binding_, output)
|
20
|
+
step[:next_cmd]
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
19
|
-
def compare(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
def compare(step, label, binding_, output)
|
26
|
+
exp = step[:expected]
|
27
|
+
if exp.is_a? Proc
|
28
|
+
exp.call binding_, output
|
29
|
+
elsif exp.is_a? Hash
|
30
|
+
if exp[:output_includes]
|
31
|
+
expect(output).to include exp[:output_includes]
|
25
32
|
else
|
26
|
-
expect(output).to eq
|
33
|
+
expect(output).to eq exp[:output]
|
27
34
|
end
|
28
|
-
elsif not
|
29
|
-
|
35
|
+
elsif not exp.nil?
|
36
|
+
err = <<-TEXT
|
37
|
+
[#{step[:index]}] #{step[:cmd]} => '#{exp}', got '#{label}'
|
38
|
+
TEXT
|
39
|
+
expect(label).to eq(exp), err
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
@@ -81,8 +91,8 @@ module PryDebugger
|
|
81
91
|
raise 'Next breakpoint handler missing' if @breakpoints_procs.size == 0
|
82
92
|
#puts (@breakpoint_call += 1)
|
83
93
|
output = @output.take_away
|
84
|
-
output.match(/^
|
85
|
-
label = ($
|
94
|
+
output.match(/^ (=>|⛔️) .*#(.*)/)
|
95
|
+
label = ($2 || '').strip
|
86
96
|
@breakpoints_procs.shift.call label, binding_, output.strip
|
87
97
|
end
|
88
98
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pry-moves
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- garmoshka-mo
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.10.4
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: 0.12.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.10.4
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
32
|
+
version: 0.12.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: binding_of_caller
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,9 +82,12 @@ files:
|
|
82
82
|
- lib/pry-moves/pry_remote_ext.rb
|
83
83
|
- lib/pry-moves/pry_wrapper.rb
|
84
84
|
- lib/pry-moves/trace_commands.rb
|
85
|
+
- lib/pry-moves/traced_method.rb
|
85
86
|
- lib/pry-moves/tracer.rb
|
87
|
+
- lib/pry-moves/traversing.rb
|
86
88
|
- lib/pry-moves/version.rb
|
87
89
|
- lib/pry-moves/watch.rb
|
90
|
+
- lib/pry-stack_explorer/VERSION
|
88
91
|
- lib/pry-stack_explorer/commands.rb
|
89
92
|
- lib/pry-stack_explorer/frame_manager.rb
|
90
93
|
- lib/pry-stack_explorer/pry-stack_explorer.rb
|
@@ -100,6 +103,7 @@ files:
|
|
100
103
|
- playground/threads.rb
|
101
104
|
- playground/tracer.rb
|
102
105
|
- pry-moves.gemspec
|
106
|
+
- publish.sh
|
103
107
|
- spec/backtrace_spec.rb
|
104
108
|
- spec/blocks_spec.rb
|
105
109
|
- spec/commands_spec.rb
|
@@ -110,7 +114,7 @@ homepage: https://github.com/garmoshka-mo/pry-moves
|
|
110
114
|
licenses:
|
111
115
|
- MIT
|
112
116
|
metadata: {}
|
113
|
-
post_install_message:
|
117
|
+
post_install_message:
|
114
118
|
rdoc_options: []
|
115
119
|
require_paths:
|
116
120
|
- lib
|
@@ -125,9 +129,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
129
|
- !ruby/object:Gem::Version
|
126
130
|
version: '0'
|
127
131
|
requirements: []
|
128
|
-
|
129
|
-
|
130
|
-
signing_key:
|
132
|
+
rubygems_version: 3.1.2
|
133
|
+
signing_key:
|
131
134
|
specification_version: 4
|
132
135
|
summary: Debugger for ruby
|
133
136
|
test_files:
|