pry-moves 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -2
- data/README.md +22 -9
- data/bin/rspec +30 -0
- data/lib/commands/iterate.rb +7 -2
- data/lib/commands/next.rb +21 -16
- data/lib/commands/next_breakpoint.rb +8 -11
- data/lib/commands/step.rb +3 -2
- data/lib/commands/trace_command.rb +10 -6
- data/lib/pry-moves/backtrace.rb +23 -72
- data/lib/pry-moves/backtrace_builder.rb +92 -0
- data/lib/pry-moves/bindings_stack.rb +7 -6
- data/lib/pry-moves/code_reloader.rb +46 -0
- data/lib/pry-moves/commands.rb +18 -1
- data/lib/pry-moves/diff.rb +27 -0
- data/lib/pry-moves/formatter.rb +8 -2
- data/lib/pry-moves/pry_ext.rb +17 -7
- data/lib/pry-moves/pry_wrapper.rb +1 -1
- data/lib/pry-moves/restartable.rb +5 -1
- data/lib/pry-moves/tools.rb +22 -0
- data/lib/pry-moves/version.rb +1 -1
- data/lib/pry-moves.rb +61 -44
- data/lib/pry-stack_explorer/frame_helpers.rb +1 -0
- data/lib/requires.rb +38 -0
- data/lib/sugar/debug_of_missing.rb +36 -0
- data/lib/{debug_sugar.rb → sugar/debug_sugar.rb} +39 -14
- data/playground/Gemfile.lock +3 -3
- data/playground/playground.rb +7 -2
- data/pry-moves.gemspec +1 -0
- data/publish.sh +5 -2
- data/spec/backtrace_spec.rb +3 -0
- data/spec/commands_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -1
- metadata +27 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 311be09c5ffb0f48a6aae45f2cf138b4ac8f1c5b285335dd1b358ac5153ca6ab
|
4
|
+
data.tar.gz: 66b1eb2eea22582332db51580159ff3ad470dcdd26c2952b5b8846db4928cfb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55f69a03e9109a9f55c277242318475ef22cbf4776f885f4a2a3d8bab2ec66e83f6896ab305443dc7d5a6797db6bf7bc97644185e98ba18185792161d87dda8d
|
7
|
+
data.tar.gz: ec9e017b99cd33292fd49c5458a9fbe5abb3391a8966032cc9d7aa40f69051fddd83bffbe12b24e1f2e4724458b01893bf8a193934babb3b02e26c1f816b8e3f
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pry-moves (1.0.
|
4
|
+
pry-moves (1.0.4)
|
5
|
+
awesome_print (>= 1.8.0)
|
5
6
|
binding_of_caller (~> 0.7)
|
6
7
|
colorize (~> 0.8)
|
7
8
|
diffy (~> 3.4.0)
|
@@ -10,13 +11,14 @@ PATH
|
|
10
11
|
GEM
|
11
12
|
remote: https://rubygems.org/
|
12
13
|
specs:
|
14
|
+
awesome_print (1.9.2)
|
13
15
|
binding_of_caller (0.8.0)
|
14
16
|
debug_inspector (>= 0.0.1)
|
15
17
|
coderay (1.1.2)
|
16
18
|
colorize (0.8.1)
|
17
19
|
debug_inspector (1.1.0)
|
18
20
|
diff-lcs (1.3)
|
19
|
-
diffy (3.4.
|
21
|
+
diffy (3.4.2)
|
20
22
|
method_source (0.9.0)
|
21
23
|
pry (0.11.3)
|
22
24
|
coderay (~> 1.1.0)
|
data/README.md
CHANGED
@@ -18,16 +18,17 @@ Documentation for latest version. For [v0.1.12 see documentation here](https://g
|
|
18
18
|
* `s +` - step into function, including hidden frames
|
19
19
|
* `f` - **finish** execution of current frame (block or method) and stop at next line on higher level
|
20
20
|
* `c` - **continue**
|
21
|
-
* `b` - go to next breakpoint (
|
22
|
-
* `
|
21
|
+
* `b` - go to next breakpoint (methods marked with `pry_breakpoint = :some_scope` variable)
|
22
|
+
* `add-bp var_name [line_number]` - add to script in this place conditional breakpoint: `debug if var_name == <it's value>`
|
23
|
+
* `ir` - **iterate**, go to next iteration of current block
|
23
24
|
* `g 10` - **goto** line 10
|
24
25
|
* `bt` - show backtrace, excluding hidden frames
|
25
26
|
* `bt +` `bt hidden` - show backtrace including hidden frames
|
26
27
|
* `bt a` `bt all` - full backtrace with system and hidden frames
|
27
28
|
* `bt 10` - go to backtrace line 10
|
28
|
-
* `bt
|
29
|
-
* `bt diff` - diff with saved backtrace
|
29
|
+
* `bt diff` - diff of backtraces (`bt save` for persistent save of 1st backtrace)
|
30
30
|
* `bt > foo` - write backtrace to file `log/backtrace_foo.log`
|
31
|
+
* `bt ::ClassName` - list objects in backtrace which class name contains "ClassName"
|
31
32
|
* `up`/`down`/`top`/`bottom` (`bm`) - move over call stack
|
32
33
|
* `up +` - move up, including vapid frames (block callers, hidden frames)
|
33
34
|
* `up pattern` - move up till first frame which method name or file position in format `folder/script.rb:12` matches regexp pattern
|
@@ -36,7 +37,8 @@ Documentation for latest version. For [v0.1.12 see documentation here](https://g
|
|
36
37
|
* `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
|
37
38
|
* `.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`
|
38
39
|
* `watch variable` - display variable's value on each step
|
39
|
-
*
|
40
|
+
* `diff expression` - display difference between saved expression (on first run) and expression 2
|
41
|
+
* `@` - restart and reload scripts (in app/ & spec/ by default), reload rake tasks. Configurable.
|
40
42
|
* `#` - exit with code 3, can be wrapped in bash script to fully reload ruby scripts
|
41
43
|
* `!` - exit
|
42
44
|
|
@@ -79,12 +81,23 @@ end
|
|
79
81
|
## Configuration
|
80
82
|
|
81
83
|
Here is default configuration, you can reassign it:
|
82
|
-
|
83
84
|
```ruby
|
85
|
+
PryMoves.reload_ruby_scripts = {
|
86
|
+
monitor: %w(app spec),
|
87
|
+
except: %w(app/assets app/views)
|
88
|
+
}
|
89
|
+
PryMoves.reload_rake_tasks = true
|
84
90
|
PryMoves::Backtrace::filter =
|
85
91
|
/(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby\/|\/pry-moves\/)/
|
86
92
|
```
|
87
93
|
|
94
|
+
Turn off features with environment variables:
|
95
|
+
```bash
|
96
|
+
PRY_MOVES=off
|
97
|
+
PRY_MOVES_DEBUG_MISSING=off
|
98
|
+
PRY_MOVES_RELOADER=off
|
99
|
+
```
|
100
|
+
|
88
101
|
## Threads, helpers
|
89
102
|
|
90
103
|
To allow traveling to parent thread, use:
|
@@ -135,9 +148,10 @@ Please note that debugging functionality is implemented through
|
|
135
148
|
## Testing
|
136
149
|
|
137
150
|
```
|
138
|
-
|
151
|
+
bin/rspec
|
152
|
+
bin/rspec -f d # Output result of each spec example
|
139
153
|
|
140
|
-
DEBUG=true
|
154
|
+
DEBUG=true bin/rspec -e 'backtrace should backtrace'
|
141
155
|
```
|
142
156
|
|
143
157
|
## ToDo
|
@@ -168,7 +182,6 @@ file an [issue][issues].
|
|
168
182
|
[set_trace_func]: http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-set_trace_func
|
169
183
|
[pullrequests]: https://github.com/garmoshka-mo/pry-moves/pulls
|
170
184
|
[issues]: https://github.com/garmoshka-mo/pry-moves/issues
|
171
|
-
[changelog]: https://github.com/garmoshka-mo/pry-moves/blob/master/CHANGELOG.md
|
172
185
|
[debug.rb]: https://github.com/ruby/ruby/blob/trunk/lib/debug.rb
|
173
186
|
[Mon-Ouie]: https://github.com/Mon-Ouie
|
174
187
|
[pry_debug]: https://github.com/Mon-Ouie/pry_debug
|
data/bin/rspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'rspec/core'
|
5
|
+
|
6
|
+
RSpec::Core::Parser.class_eval do
|
7
|
+
|
8
|
+
alias original_parser parser
|
9
|
+
|
10
|
+
def parser(options)
|
11
|
+
parser = original_parser(options)
|
12
|
+
parser.on('-e', '--example STRING', "Run examples whose full nested names include STRING (may be",
|
13
|
+
" used more than once)") do |str|
|
14
|
+
|
15
|
+
str = str.split(" ").reject do |piece|
|
16
|
+
if (m = piece.match(/(\w+)=(.*)/))
|
17
|
+
ENV[m[1]] = m[2]
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end.join(" ")
|
21
|
+
|
22
|
+
r = Regexp.compile(Regexp.escape(str), Regexp::IGNORECASE)
|
23
|
+
(options[:full_description] ||= []) << r
|
24
|
+
end
|
25
|
+
parser
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
data/lib/commands/iterate.rb
CHANGED
@@ -3,20 +3,25 @@ class PryMoves::Iterate < PryMoves::TraceCommand
|
|
3
3
|
def init(binding_)
|
4
4
|
@iteration_start_line = binding_.eval('__LINE__')
|
5
5
|
@caller_digest = frame_digest(binding_)
|
6
|
+
@receiver = binding_.receiver
|
6
7
|
end
|
7
8
|
|
8
9
|
def trace(event, file, line, method, binding_)
|
9
10
|
return true if event == 'return' and
|
10
|
-
|
11
|
+
traced_method?(file, line, method, binding_)
|
11
12
|
|
12
13
|
# промотка итерации -
|
13
14
|
# попасть на ту же или предыдущую строку или выйти из дайджеста
|
14
15
|
# будучи в том же методе
|
15
16
|
event == 'line' and @call_depth == 0 and
|
16
|
-
|
17
|
+
traced_method?(file, line, method, binding_) and
|
17
18
|
(line <= @iteration_start_line or
|
18
19
|
@caller_digest != current_frame_digest
|
19
20
|
)
|
20
21
|
end
|
21
22
|
|
23
|
+
def traced_method?(file, line, method, binding_)
|
24
|
+
super and @receiver == binding_.receiver
|
25
|
+
end
|
26
|
+
|
22
27
|
end
|
data/lib/commands/next.rb
CHANGED
@@ -2,6 +2,7 @@ class PryMoves::Next < PryMoves::TraceCommand
|
|
2
2
|
|
3
3
|
def init(binding_)
|
4
4
|
@start_line = binding_.eval('__LINE__')
|
5
|
+
@receiver = binding_.receiver
|
5
6
|
@start_digest = frame_digest(binding_)
|
6
7
|
if @command[:param] == 'blockless'
|
7
8
|
@stay_at_frame = @start_digest
|
@@ -14,24 +15,28 @@ class PryMoves::Next < PryMoves::TraceCommand
|
|
14
15
|
|
15
16
|
return true if @call_depth < 0
|
16
17
|
|
17
|
-
return unless @call_depth == 0 and
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
18
|
+
return unless @call_depth == 0 and traced_method?(file, line, method, binding_)
|
19
|
+
|
20
|
+
if event == 'line'
|
21
|
+
if @stay_at_frame
|
22
|
+
return (
|
23
|
+
@stay_at_frame == current_frame_digest or
|
24
|
+
@c_stack_level < 0
|
25
|
+
)
|
26
|
+
elsif @start_line != line or (
|
27
|
+
@events_traced > 1 and # чтобы не застревало на while (vx = shift)
|
28
|
+
@start_digest == current_frame_digest # for correct iterating over one_line_in_block
|
29
|
+
)
|
30
|
+
return true
|
31
31
|
end
|
32
|
+
end
|
33
|
+
|
34
|
+
true if event == 'return' and
|
35
|
+
method == @method[:name] and @method.before_end?(line)
|
36
|
+
end
|
32
37
|
|
33
|
-
|
34
|
-
|
38
|
+
def traced_method?(file, line, method, binding_)
|
39
|
+
super and @receiver == binding_.receiver
|
35
40
|
end
|
36
41
|
|
37
42
|
end
|
@@ -1,22 +1,19 @@
|
|
1
1
|
class PryMoves::NextBreakpoint < PryMoves::TraceCommand
|
2
2
|
|
3
3
|
def init(binding_)
|
4
|
-
@reach_digest = frame_digest(binding_)
|
5
4
|
end
|
6
5
|
|
7
6
|
def trace(event, file, line, method, binding_)
|
8
|
-
if
|
9
|
-
|
10
|
-
|
11
|
-
else
|
12
|
-
return
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
if method.to_s.include? "debug"
|
17
|
-
@pry_start_options[:initial_frame] = 1
|
7
|
+
if binding_.local_variable_defined?(:pry_breakpoint) and
|
8
|
+
binding_.local_variable_get(:pry_breakpoint)
|
9
|
+
binding_.local_variable_set :pry_breakpoint, nil # reset breakpoint at visited method instance
|
18
10
|
true
|
19
11
|
end
|
12
|
+
|
13
|
+
# if method.to_s.include? "debug"
|
14
|
+
# @pry_start_options[:initial_frame] = 1
|
15
|
+
# true
|
16
|
+
# end
|
20
17
|
end
|
21
18
|
|
22
19
|
end
|
data/lib/commands/step.rb
CHANGED
@@ -7,7 +7,7 @@ class PryMoves::Step < PryMoves::TraceCommand
|
|
7
7
|
func = @command[:param]
|
8
8
|
redirect_step? binding_ # set @step_into_funcs from initial binding
|
9
9
|
if func == '+'
|
10
|
-
|
10
|
+
PryMoves.step_in_everywhere = true
|
11
11
|
elsif func
|
12
12
|
@find_straight_descendant = true
|
13
13
|
@step_into_funcs = [func]
|
@@ -18,6 +18,7 @@ class PryMoves::Step < PryMoves::TraceCommand
|
|
18
18
|
def trace(event, file, line, method, binding_)
|
19
19
|
if binding_.local_variable_defined? :pry_moves_skip
|
20
20
|
finish_cmd = {binding: binding_}
|
21
|
+
stop_tracing
|
21
22
|
PryMoves::Finish.new finish_cmd, @pry_start_options do |binding|
|
22
23
|
start_tracing
|
23
24
|
end
|
@@ -36,7 +37,7 @@ class PryMoves::Step < PryMoves::TraceCommand
|
|
36
37
|
|
37
38
|
return unless event == 'line'
|
38
39
|
|
39
|
-
if
|
40
|
+
if PryMoves.step_in_everywhere
|
40
41
|
return true
|
41
42
|
elsif @step_into_funcs
|
42
43
|
if @call_depth < 0
|
@@ -22,7 +22,7 @@ class TraceCommand
|
|
22
22
|
|
23
23
|
binding_ = @command[:binding] # =Command.target - more rich, contains required @iseq
|
24
24
|
unless binding_.instance_variable_get('@iseq')
|
25
|
-
binding_ = PryMoves::BindingsStack.new.initial_frame
|
25
|
+
binding_ = PryMoves::BindingsStack.new(@pry_start_options).initial_frame
|
26
26
|
end
|
27
27
|
@method = PryMoves::TracedMethod.new binding_
|
28
28
|
|
@@ -57,14 +57,14 @@ class TraceCommand
|
|
57
57
|
Thread.current : Kernel
|
58
58
|
end
|
59
59
|
|
60
|
-
def tracing_func(event, file, line,
|
60
|
+
def tracing_func(event, file, line, method, binding_, klass)
|
61
61
|
|
62
62
|
# Ignore traces inside pry-moves code
|
63
63
|
return if file && TRACE_IGNORE_FILES.include?(File.expand_path(file))
|
64
64
|
return unless binding_ # ignore strange cases
|
65
65
|
|
66
66
|
# for cases when currently traced method called more times recursively
|
67
|
-
if event == "call" and
|
67
|
+
if event == "call" and traced_method?(file, line, method, binding_)
|
68
68
|
@call_depth += 1
|
69
69
|
elsif %w(c-call c-return).include?(event)
|
70
70
|
# todo: может быть, c-return тоже правильнее делать после trace
|
@@ -72,16 +72,20 @@ class TraceCommand
|
|
72
72
|
@c_stack_level += delta
|
73
73
|
end
|
74
74
|
|
75
|
-
printf "👟 %8s %s:%-2d %10s %8s dep:#{@call_depth} c_st:#{@c_stack_level}\n", event, file, line,
|
75
|
+
printf "👟 %8s %s:%-2d %10s %8s dep:#{@call_depth} c_st:#{@c_stack_level}\n", event, file, line, method, klass if PryMoves.trace # TRACE_MOVES=1
|
76
76
|
|
77
|
-
if trace event, file, line,
|
77
|
+
if trace event, file, line, method, binding_
|
78
78
|
@pry_start_options[:exit_from_method] = true if event == 'return'
|
79
79
|
stop_tracing
|
80
80
|
@callback.call binding_
|
81
|
-
elsif event == "return" and
|
81
|
+
elsif event == "return" and traced_method?(file, line, method, binding_)
|
82
82
|
@call_depth -= 1
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
def traced_method?(file, line, method, binding_)
|
87
|
+
@method.within?(file, line, method)
|
88
|
+
end
|
89
|
+
|
86
90
|
end
|
87
91
|
end
|
data/lib/pry-moves/backtrace.rb
CHANGED
@@ -3,8 +3,10 @@ require 'fileutils'
|
|
3
3
|
class PryMoves::Backtrace
|
4
4
|
|
5
5
|
FILTERS = %w[/gems/ /rubygems/ /bin/ /lib/ruby/]
|
6
|
+
@@backtrace = nil
|
6
7
|
|
7
8
|
class << self
|
9
|
+
attr_accessor :trim_path
|
8
10
|
|
9
11
|
def filter
|
10
12
|
@filter ||= Regexp.new FILTERS.join("|")
|
@@ -25,21 +27,27 @@ class PryMoves::Backtrace
|
|
25
27
|
|
26
28
|
def initialize(pry)
|
27
29
|
@pry = pry
|
28
|
-
@
|
30
|
+
@builder = PryMoves::BacktraceBuilder.new frame_manager
|
29
31
|
end
|
30
32
|
|
31
33
|
def run_command(param, param2)
|
32
|
-
if param == 'save'
|
33
|
-
|
34
|
-
|
34
|
+
if param == 'save' || param == 'diff' && @@backtrace.nil?
|
35
|
+
@@hard_saved = param == 'save'
|
36
|
+
@builder.filter = 'hidden'
|
37
|
+
@builder.lines_numbers = false
|
38
|
+
@@backtrace = @builder.build_backtrace
|
35
39
|
@pry.output.puts "💾 Backtrace saved (#{@@backtrace.count} lines)"
|
36
40
|
elsif param == 'diff'
|
37
|
-
@filter = 'hidden'
|
41
|
+
@builder.filter = 'hidden'
|
42
|
+
@builder.lines_numbers = false
|
38
43
|
diff
|
44
|
+
@@backtrace = nil unless @@hard_saved
|
45
|
+
elsif param and (match = param.match /^::(\w*)/)
|
46
|
+
@builder.colorize = true
|
47
|
+
@pry.output.puts @builder.objects_of_class match[1]
|
39
48
|
elsif param.is_a?(String) and (match = param.match /^>(.*)/)
|
40
49
|
suffix = match[1].size > 0 ? match[1] : param2
|
41
|
-
@
|
42
|
-
write_to_file build_backtrace, suffix
|
50
|
+
write_to_file @builder.build_backtrace, suffix
|
43
51
|
elsif param and param.match /\d+/
|
44
52
|
index = param.to_i
|
45
53
|
frame_manager.goto_index index
|
@@ -51,68 +59,9 @@ class PryMoves::Backtrace
|
|
51
59
|
private
|
52
60
|
|
53
61
|
def print_backtrace filter
|
54
|
-
@colorize = true
|
55
|
-
@
|
56
|
-
@
|
57
|
-
@pry.output.puts build_backtrace
|
58
|
-
end
|
59
|
-
|
60
|
-
def build_backtrace
|
61
|
-
show_all = %w(a all).include?(@filter)
|
62
|
-
show_vapid = %w(+ hidden vapid).include?(@filter) || show_all
|
63
|
-
result = []
|
64
|
-
current_object, vapid_count = nil, 0
|
65
|
-
|
66
|
-
recursion = PryMoves::Recursion::Holder.new
|
67
|
-
|
68
|
-
frame_manager.bindings.reverse.each do |binding|
|
69
|
-
next if !show_all and binding.eval('__FILE__').match self.class::filter
|
70
|
-
|
71
|
-
if !show_vapid and binding.hidden
|
72
|
-
vapid_count += 1
|
73
|
-
next
|
74
|
-
end
|
75
|
-
|
76
|
-
if vapid_count > 0
|
77
|
-
result << "👽 frames hidden: #{vapid_count}"
|
78
|
-
vapid_count = 0
|
79
|
-
end
|
80
|
-
|
81
|
-
obj, debug_snapshot = binding.eval '[self, (debug_snapshot rescue nil)]'
|
82
|
-
# Comparison of objects directly may raise exception
|
83
|
-
if current_object.object_id != obj.object_id
|
84
|
-
result << "#{debug_snapshot || @formatter.format_obj(obj)}"
|
85
|
-
current_object = obj
|
86
|
-
end
|
87
|
-
|
88
|
-
file, line = binding.eval('[__FILE__, __LINE__]')
|
89
|
-
recursion.track file, line, result.count, binding.index unless show_vapid
|
90
|
-
result << build_line(binding, file, line)
|
91
|
-
end
|
92
|
-
|
93
|
-
# recursion.each { |t| t.apply result }
|
94
|
-
|
95
|
-
result << "👽 frames hidden: #{vapid_count}" if vapid_count > 0
|
96
|
-
|
97
|
-
result
|
98
|
-
end
|
99
|
-
|
100
|
-
def build_line(binding, file, line)
|
101
|
-
file = @formatter.shorten_path "#{file}"
|
102
|
-
|
103
|
-
signature = @formatter.method_signature binding
|
104
|
-
signature = ":#{binding.frame_type}" if !signature or signature.length < 1
|
105
|
-
|
106
|
-
indent = if frame_manager.current_frame == binding
|
107
|
-
'==> '
|
108
|
-
elsif true #@lines_numbers
|
109
|
-
s = "#{binding.index}:".ljust(4, ' ')
|
110
|
-
@colorize ? "\e[2;49;90m#{s}\e[0m" : s
|
111
|
-
else
|
112
|
-
' '
|
113
|
-
end
|
114
|
-
|
115
|
-
"#{indent}#{file}:#{line} #{signature}"
|
62
|
+
@builder.colorize = true
|
63
|
+
@builder.filter = filter if filter.is_a? String
|
64
|
+
@pry.output.puts @builder.build_backtrace
|
116
65
|
end
|
117
66
|
|
118
67
|
def frame_manager
|
@@ -135,9 +84,10 @@ class PryMoves::Backtrace
|
|
135
84
|
def diff
|
136
85
|
return STDERR.puts "No backtrace saved. Use `bt save` first".yellow unless defined? @@backtrace
|
137
86
|
|
138
|
-
|
139
|
-
|
140
|
-
|
87
|
+
@pry.output.puts Diffy.diff(
|
88
|
+
@@backtrace.join("\n"),
|
89
|
+
@builder.build_backtrace.join("\n")
|
90
|
+
)
|
141
91
|
end
|
142
92
|
|
143
93
|
end
|
@@ -164,4 +114,5 @@ Pry.config.exception_handler = proc do |output, exception, _|
|
|
164
114
|
end
|
165
115
|
end
|
166
116
|
end
|
117
|
+
|
167
118
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class PryMoves::BacktraceBuilder
|
2
|
+
|
3
|
+
attr_writer :lines_numbers, :filter, :colorize
|
4
|
+
|
5
|
+
def initialize frame_manager
|
6
|
+
@frame_manager = frame_manager
|
7
|
+
@filter = nil
|
8
|
+
@colorize = false
|
9
|
+
@lines_numbers = true
|
10
|
+
@formatter = PryMoves::Formatter.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_backtrace
|
14
|
+
show_all = %w(a all).include?(@filter)
|
15
|
+
show_vapid = %w(+ hidden vapid).include?(@filter) || show_all
|
16
|
+
result = []
|
17
|
+
current_object, vapid_count = nil, 0
|
18
|
+
|
19
|
+
recursion = PryMoves::Recursion::Holder.new
|
20
|
+
|
21
|
+
@frame_manager.bindings.reverse.each do |binding|
|
22
|
+
next if !show_all and binding.eval('__FILE__').match PryMoves::Backtrace::filter
|
23
|
+
|
24
|
+
if !show_vapid and binding.hidden
|
25
|
+
vapid_count += 1
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
if vapid_count > 0
|
30
|
+
result << "👽 frames hidden: #{vapid_count}"
|
31
|
+
vapid_count = 0
|
32
|
+
end
|
33
|
+
|
34
|
+
obj, debug_snapshot = binding.eval '[self, (debug_snapshot rescue nil)]'
|
35
|
+
# Comparison of objects directly may raise exception
|
36
|
+
if current_object.object_id != obj.object_id
|
37
|
+
result << "#{debug_snapshot || @formatter.format_obj(obj)}"
|
38
|
+
current_object = obj
|
39
|
+
end
|
40
|
+
|
41
|
+
file, line = binding.eval('[__FILE__, __LINE__]')
|
42
|
+
recursion.track file, line, result.count, binding.index unless show_vapid
|
43
|
+
result << build_line(binding, file, line)
|
44
|
+
end
|
45
|
+
|
46
|
+
# recursion.each { |t| t.apply result }
|
47
|
+
|
48
|
+
result << "👽 frames hidden: #{vapid_count}" if vapid_count > 0
|
49
|
+
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
def objects_of_class class_pattern
|
54
|
+
result = []
|
55
|
+
last_object = nil
|
56
|
+
class_pattern.downcase!
|
57
|
+
@frame_manager.bindings.reverse.each do |binding|
|
58
|
+
obj = binding.eval 'self'
|
59
|
+
next if !obj.class.to_s.downcase.include?(class_pattern) ||
|
60
|
+
last_object.object_id == obj.object_id
|
61
|
+
|
62
|
+
result << "#{line_num binding}#{@formatter.format_obj(obj)}"
|
63
|
+
last_object = obj
|
64
|
+
end
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def line_num binding
|
71
|
+
num = "#{binding.index}:".ljust(4, ' ')
|
72
|
+
@colorize ? "\e[2;49;90m#{num}\e[0m" : num
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_line(binding, file, line)
|
76
|
+
file = @formatter.shorten_path "#{file}"
|
77
|
+
|
78
|
+
signature = @formatter.method_signature binding
|
79
|
+
signature = ":#{binding.frame_type}" if !signature or signature.length < 1
|
80
|
+
|
81
|
+
indent = if @frame_manager.current_frame == binding
|
82
|
+
'==> '
|
83
|
+
elsif @lines_numbers
|
84
|
+
line_num binding
|
85
|
+
else
|
86
|
+
' '
|
87
|
+
end
|
88
|
+
|
89
|
+
"#{indent}#{file}:#{line} #{signature}"
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -14,16 +14,17 @@ class PryMoves::BindingsStack < Array
|
|
14
14
|
def suggest_initial_frame_index
|
15
15
|
m = PryMoves::TracedMethod.last
|
16
16
|
return 0 if m and m.binding_inside?(first)
|
17
|
-
index {|b|
|
17
|
+
index {|b| fits_for_initial_frame b} || 0
|
18
18
|
end
|
19
19
|
def initial_frame
|
20
|
-
find {|b|
|
20
|
+
find {|b| fits_for_initial_frame b}
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def fits_for_initial_frame b
|
24
|
+
PryMoves.step_in_everywhere or
|
25
|
+
not b.hidden and (
|
26
|
+
@options[:is_error] or b.eval("__method__") != :initialize
|
27
|
+
)
|
27
28
|
end
|
28
29
|
|
29
30
|
private
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class CodeReloader
|
2
|
+
|
3
|
+
def initialize
|
4
|
+
@timestamps = {}
|
5
|
+
traverse_files do |path|
|
6
|
+
@timestamps[path] = File.mtime(path)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def reload
|
11
|
+
traverse_files do |path|
|
12
|
+
if @timestamps[path] != File.mtime(path)
|
13
|
+
if reload_file path
|
14
|
+
@timestamps[path] = File.mtime(path)
|
15
|
+
# Log.info "⚡️ file reloaded #{path}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def reload_file path
|
24
|
+
hide_from_stack = true
|
25
|
+
load path
|
26
|
+
true
|
27
|
+
rescue SyntaxError => e
|
28
|
+
PryMoves.debug_error ["🛠 Syntax error:".red, e.message].join "\n"
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def traverse_files
|
33
|
+
paths = PryMoves.reload_ruby_scripts[:monitor]
|
34
|
+
except = PryMoves.reload_ruby_scripts[:except]
|
35
|
+
paths.each do |root|
|
36
|
+
files = Dir.glob("#{root}/**/*")
|
37
|
+
files.each do |path|
|
38
|
+
if path.end_with? '.rb' and
|
39
|
+
not except.any? {|_| path.start_with? _}
|
40
|
+
yield path
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/lib/pry-moves/commands.rb
CHANGED
@@ -26,9 +26,15 @@ module PryMoves
|
|
26
26
|
end
|
27
27
|
alias_command 'b', 'next_breakpoint'
|
28
28
|
|
29
|
+
block_command 'add-bp', 'Add conditional breakpoint to script' do |var_name, line_number|
|
30
|
+
PryMoves::Tools.new(_pry_).add_breakpoint var_name, line_number&.to_i, target
|
31
|
+
run 'restart'
|
32
|
+
end
|
33
|
+
|
29
34
|
block_command 'iterate', 'Go to next iteration of current block' do |param|
|
30
35
|
breakout_navigation :iterate, param
|
31
36
|
end
|
37
|
+
alias_command 'ir', 'iterate'
|
32
38
|
|
33
39
|
block_command 'goto', 'goto line' do |param|
|
34
40
|
breakout_navigation :goto, param
|
@@ -45,6 +51,11 @@ module PryMoves
|
|
45
51
|
PryMoves::Watch.instance.process_cmd param, target
|
46
52
|
end
|
47
53
|
|
54
|
+
block_command 'diff', 'Display difference' do
|
55
|
+
cmd = arg_string.gsub(/^diff/, '').strip
|
56
|
+
PryMoves::Diff.new(_pry_, target).run_command cmd
|
57
|
+
end
|
58
|
+
|
48
59
|
block_command 'bt', 'Backtrace' do |param, param2|
|
49
60
|
PryMoves::Backtrace.new(_pry_).run_command param, param2
|
50
61
|
end
|
@@ -101,8 +112,14 @@ module PryMoves
|
|
101
112
|
return
|
102
113
|
end
|
103
114
|
|
104
|
-
input = Pry.config.original_user_input || action
|
115
|
+
input = Pry.config.original_user_input || action.to_s
|
116
|
+
return if input == 'next' # ruby keyword
|
105
117
|
binding_value = target.eval(input) rescue nil
|
118
|
+
# begin # for debug
|
119
|
+
# binding_value = target.eval(input)
|
120
|
+
# rescue => e
|
121
|
+
# puts (e.backtrace.reverse + ["var_precedence exception:".red, "#{e}".red]).join "\n"
|
122
|
+
# end
|
106
123
|
unless binding_value.nil?
|
107
124
|
puts "ℹ️️ Variable \"#{input}\" found. To execute command type its alias or \\#{input}"
|
108
125
|
puts PryMoves::Painter.colorize binding_value
|