pry-moves 0.1.10 → 1.0.1
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 +1 -1
- data/Gemfile.lock +7 -5
- data/README.md +18 -8
- data/lib/commands/debug.rb +17 -0
- data/lib/commands/finish.rb +26 -0
- data/lib/commands/goto.rb +19 -0
- data/lib/commands/iterate.rb +22 -0
- data/lib/commands/next.rb +37 -0
- data/lib/commands/next_breakpoint.rb +22 -0
- data/lib/commands/step.rb +83 -0
- data/lib/commands/trace_command.rb +87 -0
- data/lib/commands/trace_helpers.rb +49 -0
- data/lib/commands/traced_method.rb +71 -0
- data/lib/debug_sugar.rb +72 -0
- data/lib/pry-moves/add_suffix.rb +87 -0
- data/lib/pry-moves/backtrace.rb +81 -50
- data/lib/pry-moves/bindings_stack.rb +97 -0
- data/lib/pry-moves/commands.rb +50 -7
- data/lib/pry-moves/formatter.rb +75 -0
- data/lib/pry-moves/painter.rb +5 -1
- data/lib/pry-moves/pry_ext.rb +64 -16
- data/lib/pry-moves/pry_wrapper.rb +30 -17
- data/lib/pry-moves/recursion_tracker.rb +94 -0
- data/lib/pry-moves/restartable.rb +38 -0
- data/lib/pry-moves/version.rb +1 -1
- data/lib/pry-moves/watch.rb +3 -0
- data/lib/pry-moves.rb +66 -4
- data/lib/pry-stack_explorer/VERSION +2 -0
- data/lib/pry-stack_explorer/frame_manager.rb +6 -9
- data/lib/pry-stack_explorer/pry-stack_explorer.rb +3 -17
- data/lib/pry-stack_explorer/{commands.rb → stack_commands.rb} +10 -6
- data/lib/pry-stack_explorer/when_started_hook.rb +17 -63
- data/playground/Gemfile.lock +9 -9
- data/playground/README.md +1 -0
- data/playground/playground.rb +94 -9
- data/playground/sand.rb +45 -12
- data/playground/test.rb +5 -1
- data/playground/test.sh +1 -0
- data/pry-moves.gemspec +3 -2
- data/publish.sh +3 -0
- data/spec/backtrace_spec.rb +11 -13
- data/spec/blocks_spec.rb +41 -8
- data/spec/commands_spec.rb +26 -25
- data/spec/pry_debugger.rb +5 -1
- data/spec/redirection_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -4
- data/spec/step_spec.rb +51 -0
- metadata +44 -10
- data/lib/pry-moves/helpers.rb +0 -50
- data/lib/pry-moves/trace_commands.rb +0 -105
- data/lib/pry-moves/tracer.rb +0 -169
@@ -0,0 +1,87 @@
|
|
1
|
+
module PryMoves
|
2
|
+
|
3
|
+
class AddSuffix < 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_suffix(cmd)}"
|
19
|
+
_pry_.pager.page " > #{cmd}\n"
|
20
|
+
_pry_.eval cmd
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def wrap_suffix(cmd)
|
26
|
+
cmd
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class Method < AddSuffix
|
32
|
+
match(/^\.(.+)$/) # when \. moved into group - match doesn't work because it overlaps with pry internal command
|
33
|
+
|
34
|
+
def wrap_suffix(cmd)
|
35
|
+
".#{cmd}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class ArgumentCall < AddSuffix
|
40
|
+
match(/^(\(.*\).*)/)
|
41
|
+
end
|
42
|
+
|
43
|
+
class ArrayIndex < AddSuffix
|
44
|
+
match(/^(\d+)$/)
|
45
|
+
|
46
|
+
def wrap_suffix(cmd)
|
47
|
+
"[#{cmd}]"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ArrayCall < AddSuffix
|
52
|
+
match(/^(\[\d+\].*)/)
|
53
|
+
end
|
54
|
+
|
55
|
+
class HashKey < AddSuffix
|
56
|
+
match(/^(:\w+)$/)
|
57
|
+
|
58
|
+
def wrap_suffix(cmd)
|
59
|
+
"[#{cmd}]"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
SUFFIX_COMMANDS = [
|
67
|
+
PryMoves::Method,
|
68
|
+
PryMoves::ArrayIndex,
|
69
|
+
PryMoves::ArrayCall,
|
70
|
+
PryMoves::HashKey
|
71
|
+
]
|
72
|
+
|
73
|
+
SUFFIX_COMMANDS.each do |cmd|
|
74
|
+
Pry::Commands.add_command(cmd)
|
75
|
+
end
|
76
|
+
|
77
|
+
Pry::History.class_eval do
|
78
|
+
|
79
|
+
def <<(line)
|
80
|
+
return if ["!"].include? line
|
81
|
+
return if SUFFIX_COMMANDS.any? do |cls|
|
82
|
+
line.match(cls.match)
|
83
|
+
end
|
84
|
+
push line
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
data/lib/pry-moves/backtrace.rb
CHANGED
@@ -2,12 +2,12 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
class PryMoves::Backtrace
|
4
4
|
|
5
|
+
FILTERS = %w[/gems/ /rubygems/ /bin/ /lib/ruby/]
|
6
|
+
|
5
7
|
class << self
|
6
|
-
def lines_count; @lines_count || 5; end
|
7
|
-
def lines_count=(f); @lines_count = f; end
|
8
8
|
|
9
9
|
def filter
|
10
|
-
@filter
|
10
|
+
@filter ||= Regexp.new FILTERS.join("|")
|
11
11
|
end
|
12
12
|
def filter=(f); @filter = f; end
|
13
13
|
|
@@ -20,77 +20,91 @@ class PryMoves::Backtrace
|
|
20
20
|
# not used
|
21
21
|
end
|
22
22
|
end
|
23
|
+
|
23
24
|
end
|
24
25
|
|
25
|
-
def initialize(
|
26
|
-
|
26
|
+
def initialize(pry)
|
27
|
+
@pry = pry
|
28
|
+
@formatter = PryMoves::Formatter.new
|
27
29
|
end
|
28
30
|
|
29
31
|
def run_command(param, param2)
|
30
32
|
if param.is_a?(String) and (match = param.match /^>(.*)/)
|
31
33
|
suffix = match[1].size > 0 ? match[1] : param2
|
34
|
+
@formatter.colorize = false
|
32
35
|
write_to_file build, suffix
|
36
|
+
elsif param and param.match /\d+/
|
37
|
+
index = param.to_i
|
38
|
+
frame_manager.goto_index index
|
33
39
|
else
|
34
|
-
|
35
|
-
if param.is_a? String and param.match /\d+/
|
36
|
-
param = param.to_i
|
37
|
-
end
|
38
|
-
@lines_count = param || PryMoves::Backtrace::lines_count
|
39
|
-
@pry.output.puts build
|
40
|
+
print_backtrace param
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
44
|
private
|
44
45
|
|
46
|
+
def print_backtrace filter
|
47
|
+
@colorize = true
|
48
|
+
@lines_numbers = true
|
49
|
+
@filter = filter if filter.is_a? String
|
50
|
+
@pry.output.puts build
|
51
|
+
end
|
52
|
+
|
45
53
|
def build
|
54
|
+
show_all = %w(a all).include?(@filter)
|
55
|
+
show_vapid = %w(+ hidden vapid).include?(@filter) || show_all
|
46
56
|
result = []
|
47
|
-
|
48
|
-
stack = stack_bindings(show_vapid)
|
49
|
-
.reverse.reject do |binding|
|
50
|
-
binding.eval('__FILE__').match self.class::filter
|
51
|
-
end
|
52
|
-
|
53
|
-
if @lines_count.is_a?(Numeric) and stack.count > @lines_count
|
54
|
-
result << "Latest #{@lines_count} lines: (`bt all` for full tracing)"
|
55
|
-
stack = stack.last(@lines_count)
|
56
|
-
end
|
57
|
+
current_object, vapid_count = nil, 0
|
57
58
|
|
58
|
-
|
59
|
-
|
59
|
+
recursion = PryMoves::Recursion::Holder.new
|
60
|
+
|
61
|
+
frame_manager.bindings.each_with_details do |binding, vapid|
|
62
|
+
next if !show_all and binding.eval('__FILE__').match self.class::filter
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
if !show_vapid and vapid
|
65
|
+
vapid_count += 1
|
66
|
+
next
|
67
|
+
end
|
68
|
+
|
69
|
+
if vapid_count > 0
|
70
|
+
result << "👽 frames hidden: #{vapid_count}"
|
71
|
+
vapid_count = 0
|
72
|
+
end
|
73
|
+
|
74
|
+
obj, debug_snapshot = binding.eval '[self, (debug_snapshot rescue nil)]'
|
75
|
+
# Comparison of objects directly may raise exception
|
76
|
+
if current_object.object_id != obj.object_id
|
77
|
+
result << "#{debug_snapshot || @formatter.format_obj(obj)}"
|
67
78
|
current_object = obj
|
68
79
|
end
|
69
80
|
|
70
|
-
|
81
|
+
file, line = binding.eval('[__FILE__, __LINE__]')
|
82
|
+
recursion.track file, line, result.count, binding.index unless show_vapid
|
83
|
+
result << build_line(binding, file, line)
|
71
84
|
end
|
72
|
-
result
|
73
|
-
end
|
74
85
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
86
|
+
recursion.each { |t| t.apply result }
|
87
|
+
|
88
|
+
result << "👽 frames hidden: #{vapid_count}" if vapid_count > 0
|
89
|
+
|
90
|
+
result
|
81
91
|
end
|
82
92
|
|
83
|
-
def build_line(binding)
|
84
|
-
file = "#{
|
85
|
-
file.gsub!( /^#{Rails.root.to_s}/, '') if defined? Rails
|
93
|
+
def build_line(binding, file, line)
|
94
|
+
file = @formatter.shorten_path "#{file}"
|
86
95
|
|
87
|
-
signature =
|
96
|
+
signature = @formatter.method_signature binding
|
88
97
|
signature = ":#{binding.frame_type}" if !signature or signature.length < 1
|
89
98
|
|
90
|
-
indent = frame_manager.current_frame == binding
|
91
|
-
|
99
|
+
indent = if frame_manager.current_frame == binding
|
100
|
+
'==> '
|
101
|
+
elsif true #@lines_numbers
|
102
|
+
s = "#{binding.index}:".ljust(4, ' ')
|
103
|
+
@colorize ? "\e[2;49;90m#{s}\e[0m" : s
|
104
|
+
else
|
105
|
+
' '
|
106
|
+
end
|
92
107
|
|
93
|
-
line = binding.eval('__LINE__')
|
94
108
|
"#{indent}#{file}:#{line} #{signature}"
|
95
109
|
end
|
96
110
|
|
@@ -98,10 +112,6 @@ class PryMoves::Backtrace
|
|
98
112
|
PryStackExplorer.frame_manager(@pry)
|
99
113
|
end
|
100
114
|
|
101
|
-
def stack_bindings(vapid_frames)
|
102
|
-
frame_manager.filter_bindings vapid_frames: vapid_frames
|
103
|
-
end
|
104
|
-
|
105
115
|
def write_to_file(lines, file_suffix)
|
106
116
|
log_path = log_path file_suffix
|
107
117
|
File.write log_path, lines.join("\n")
|
@@ -115,4 +125,25 @@ class PryMoves::Backtrace
|
|
115
125
|
"#{root}/backtrace_#{file_suffix}.log"
|
116
126
|
end
|
117
127
|
|
118
|
-
end
|
128
|
+
end
|
129
|
+
|
130
|
+
Pry.config.exception_handler = proc do |output, exception, _|
|
131
|
+
if Pry::UserError === exception && SyntaxError === exception
|
132
|
+
output.puts "SyntaxError: #{exception.message.sub(/.*syntax error, */m, '')}"
|
133
|
+
else
|
134
|
+
|
135
|
+
output.puts "#{exception.class}: #{exception.message}"
|
136
|
+
exception.backtrace.reject! {|l| l.match /sugar\.rb/}
|
137
|
+
output.puts "from #{exception.backtrace.first}"
|
138
|
+
|
139
|
+
if exception.respond_to? :cause
|
140
|
+
cause = exception.cause
|
141
|
+
while cause
|
142
|
+
output.puts "Caused by #{cause.class}: #{cause}\n"
|
143
|
+
cause.backtrace.reject! {|l| l.match /sugar\.rb/}
|
144
|
+
output.puts "from #{cause.backtrace.first}"
|
145
|
+
cause = cause.cause
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
class PryMoves::BindingsStack < Array
|
2
|
+
|
3
|
+
def initialize
|
4
|
+
@vapid_bindings = []
|
5
|
+
bindings = binding.callers # binding_of_caller has bug and always returns callers of current binding,
|
6
|
+
# no matter at which binding method is called. So no need to pass here binding
|
7
|
+
pre_callers = Thread.current[:pre_callers]
|
8
|
+
bindings = bindings + pre_callers if pre_callers
|
9
|
+
concat remove_internal_frames(bindings)
|
10
|
+
set_indices
|
11
|
+
mark_vapid_frames
|
12
|
+
end
|
13
|
+
|
14
|
+
def suggest_initial_frame_index
|
15
|
+
m = PryMoves::TracedMethod.last
|
16
|
+
return 0 if m and m.binding_inside?(first)
|
17
|
+
index{|b| not vapid? b} || 0
|
18
|
+
end
|
19
|
+
def initial_frame
|
20
|
+
find{|b| not vapid? b}
|
21
|
+
end
|
22
|
+
|
23
|
+
def each_with_details
|
24
|
+
self.reverse.each do |binding|
|
25
|
+
yield binding, vapid?(binding)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def vapid?(binding)
|
30
|
+
@vapid_bindings.include? binding
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def set_indices
|
36
|
+
reverse.each_with_index do |binding, index|
|
37
|
+
binding.index = index
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def mark_vapid_frames
|
42
|
+
stepped_out = false
|
43
|
+
actual_file, actual_method = nil, nil
|
44
|
+
|
45
|
+
# here calls checked in reverse order - from latest to parent:
|
46
|
+
each do |binding|
|
47
|
+
file, method, obj = binding.eval("[__FILE__, __method__, self]")
|
48
|
+
|
49
|
+
if file.match PryMoves::Backtrace::filter
|
50
|
+
@vapid_bindings << binding
|
51
|
+
elsif stepped_out
|
52
|
+
if actual_file == file and actual_method == method or
|
53
|
+
binding.local_variable_defined? :pry_moves_deferred_call
|
54
|
+
stepped_out = false
|
55
|
+
else
|
56
|
+
@vapid_bindings << binding
|
57
|
+
end
|
58
|
+
elsif binding.frame_type == :block
|
59
|
+
stepped_out = true
|
60
|
+
actual_file = file
|
61
|
+
actual_method = method
|
62
|
+
elsif obj and method and obj.method(method).source.strip.match /^delegate\s/
|
63
|
+
@vapid_bindings << binding
|
64
|
+
end
|
65
|
+
|
66
|
+
if binding.local_variable_defined? :hide_from_stack
|
67
|
+
@vapid_bindings << binding
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# remove internal frames related to setting up the session
|
73
|
+
def remove_internal_frames(bindings)
|
74
|
+
i = top_internal_frame_index(bindings)
|
75
|
+
# DEBUG:
|
76
|
+
#bindings.each_with_index do |b, index|
|
77
|
+
# puts "#{index}: #{b.eval("self.class")} #{b.eval("__method__")}"
|
78
|
+
#end
|
79
|
+
# puts "FOUND top internal frame in #{bindings.size} frames: [#{i}] #{bindings[i].ai}"
|
80
|
+
|
81
|
+
bindings.drop i+1
|
82
|
+
end
|
83
|
+
|
84
|
+
def top_internal_frame_index(bindings)
|
85
|
+
bindings.rindex do |b|
|
86
|
+
if b.frame_type == :method
|
87
|
+
method, self_ = b.eval("[__method__, self]")
|
88
|
+
|
89
|
+
self_.equal?(Pry) && method == :start ||
|
90
|
+
self_.class == Binding && method == :pry ||
|
91
|
+
self_.is_a?(PryMoves::TraceCommand) && method == :tracing_func ||
|
92
|
+
b.local_variable_defined?(:pry_moves_stack_root)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
data/lib/pry-moves/commands.rb
CHANGED
@@ -5,39 +5,48 @@ 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
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
20
|
block_command 'nn', 'Execute the next line skipping blocks' do |param|
|
18
21
|
breakout_navigation :next, 'blockless'
|
19
22
|
end
|
20
23
|
|
24
|
+
block_command 'next_breakpoint', 'Go to next breakpoint' do |param|
|
25
|
+
breakout_navigation :next_breakpoint, param
|
26
|
+
end
|
27
|
+
alias_command 'b', 'next_breakpoint'
|
28
|
+
|
21
29
|
block_command 'iterate', 'Go to next iteration of current block' do |param|
|
22
30
|
breakout_navigation :iterate, param
|
23
31
|
end
|
24
32
|
|
33
|
+
block_command 'goto', 'goto line' do |param|
|
34
|
+
breakout_navigation :goto, param
|
35
|
+
end
|
36
|
+
alias_command 'g', 'goto'
|
37
|
+
|
25
38
|
block_command 'continue', 'Continue program execution and end the Pry session' do
|
26
39
|
check_file_context
|
27
40
|
run 'exit-all'
|
28
41
|
end
|
29
|
-
|
30
42
|
alias_command 'c', 'continue'
|
31
|
-
alias_command 's', 'step'
|
32
|
-
alias_command 'n', 'next'
|
33
|
-
alias_command 'f', 'finish'
|
34
43
|
|
35
44
|
block_command 'watch', 'Display value of expression on every move' do |param|
|
36
45
|
PryMoves::Watch.instance.process_cmd param, target
|
37
46
|
end
|
38
47
|
|
39
48
|
block_command 'bt', 'Backtrace' do |param, param2|
|
40
|
-
PryMoves::Backtrace.new(
|
49
|
+
PryMoves::Backtrace.new(_pry_).run_command param, param2
|
41
50
|
end
|
42
51
|
|
43
52
|
block_command 'debug', '' do
|
@@ -45,6 +54,23 @@ module PryMoves
|
|
45
54
|
breakout_navigation :debug, cmd
|
46
55
|
end
|
47
56
|
|
57
|
+
block_command :restart, '' do
|
58
|
+
PryMoves.restart_requested = true
|
59
|
+
run 'continue'
|
60
|
+
end
|
61
|
+
alias_command '@', 'restart'
|
62
|
+
|
63
|
+
block_command :reload, '' do
|
64
|
+
PryMoves.reload_requested = true
|
65
|
+
run 'continue'
|
66
|
+
end
|
67
|
+
alias_command '#', 'reload'
|
68
|
+
|
69
|
+
block_command /^\\(\w+)$/, 'Execute command explicitly' do |param|
|
70
|
+
Pry.config.ignore_once_var_precedence = true
|
71
|
+
run param
|
72
|
+
end
|
73
|
+
|
48
74
|
block_command '!', 'exit' do
|
49
75
|
PryMoves.unlock
|
50
76
|
Pry.config.exit_requested = true
|
@@ -58,16 +84,32 @@ module PryMoves
|
|
58
84
|
|
59
85
|
helpers do
|
60
86
|
def breakout_navigation(action, param)
|
87
|
+
return if var_precedence action
|
88
|
+
|
61
89
|
check_file_context
|
62
90
|
_pry_.binding_stack.clear # Clear the binding stack.
|
63
91
|
throw :breakout_nav, { # Break out of the REPL loop and
|
64
92
|
action: action, # signal the tracer.
|
65
93
|
param: param,
|
66
|
-
binding: target
|
67
|
-
pry: _pry_
|
94
|
+
binding: target
|
68
95
|
}
|
69
96
|
end
|
70
97
|
|
98
|
+
def var_precedence action
|
99
|
+
if Pry.config.ignore_once_var_precedence
|
100
|
+
Pry.config.ignore_once_var_precedence = false
|
101
|
+
return
|
102
|
+
end
|
103
|
+
|
104
|
+
input = Pry.config.original_user_input || action
|
105
|
+
binding_value = target.eval(input) rescue nil
|
106
|
+
unless binding_value.nil?
|
107
|
+
puts "ℹ️️ Variable \"#{input}\" found. To execute command type its alias or \\#{input}"
|
108
|
+
puts PryMoves::Painter.colorize binding_value
|
109
|
+
true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
71
113
|
# Ensures that a command is executed in a local file context.
|
72
114
|
def check_file_context
|
73
115
|
unless PryMoves.check_file_context(target)
|
@@ -75,6 +117,7 @@ module PryMoves
|
|
75
117
|
end
|
76
118
|
end
|
77
119
|
end
|
120
|
+
|
78
121
|
end
|
79
122
|
end
|
80
123
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class PryMoves::Formatter
|
2
|
+
|
3
|
+
attr_accessor :colorize
|
4
|
+
|
5
|
+
def initialize colorize = true
|
6
|
+
@colorize = colorize
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_signature(binding)
|
10
|
+
meth = binding.eval('__method__')
|
11
|
+
meth_obj = meth ? Pry::Method.from_binding(binding) : nil
|
12
|
+
if !meth_obj
|
13
|
+
""
|
14
|
+
elsif meth_obj.undefined?
|
15
|
+
"#{meth_obj.name}(UNKNOWN) (undefined method)"
|
16
|
+
else
|
17
|
+
args = meth_obj.parameters.map.with_index do |(type, name), i|
|
18
|
+
if name
|
19
|
+
value = format_arg binding, name.to_s
|
20
|
+
show_value = true
|
21
|
+
else
|
22
|
+
name = (type == :block ? 'block' : "arg#{i + 1}")
|
23
|
+
end
|
24
|
+
name = case type
|
25
|
+
when :req then "#{name} ="
|
26
|
+
when :key then "#{name}:"
|
27
|
+
when :opt then "#{name}=?"
|
28
|
+
when :rest then "*#{name}"
|
29
|
+
when :block then "&#{name}"
|
30
|
+
else '?'
|
31
|
+
end
|
32
|
+
show_value ? "#{name} #{value}" : name
|
33
|
+
end
|
34
|
+
"#{meth_obj.name}(#{args.join(', ')})"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def format_arg binding, arg_name
|
39
|
+
arg = binding.eval(arg_name.to_s)
|
40
|
+
format_obj arg
|
41
|
+
end
|
42
|
+
|
43
|
+
def first_line str
|
44
|
+
str.split("\n").first
|
45
|
+
end
|
46
|
+
|
47
|
+
def cut_string str
|
48
|
+
return str unless str
|
49
|
+
str.length > 50 ? "#{str.first 50}..." : str
|
50
|
+
end
|
51
|
+
|
52
|
+
PATH_TRASH = defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
53
|
+
|
54
|
+
def shorten_path(path)
|
55
|
+
path.gsub( /^#{PATH_TRASH}\//, '')
|
56
|
+
end
|
57
|
+
|
58
|
+
def format_obj(obj)
|
59
|
+
if obj.is_a? String
|
60
|
+
format_obj2 cut_string first_line obj
|
61
|
+
else
|
62
|
+
first_line format_obj2 obj
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def format_obj2(obj)
|
67
|
+
if @colorize
|
68
|
+
PryMoves::Painter.colorize obj
|
69
|
+
else
|
70
|
+
i = obj.inspect
|
71
|
+
i.start_with?('#<') ? obj.class.to_s : i
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/lib/pry-moves/painter.rb
CHANGED
@@ -14,11 +14,15 @@ module PryMoves::Painter
|
|
14
14
|
|
15
15
|
def self.colorize(obj)
|
16
16
|
colored_str = Canvas.new
|
17
|
-
|
17
|
+
i = obj.inspect
|
18
|
+
obj = obj.class if i.is_a?(String) && i.start_with?("#<")
|
18
19
|
catch (:cut) do
|
19
20
|
Pry::ColorPrinter.pp obj, colored_str
|
20
21
|
end
|
21
22
|
colored_str.chomp
|
23
|
+
rescue => e
|
24
|
+
"⛔️ Inspect error: #{e}\n" +
|
25
|
+
"#{e.backtrace.first(3).join("\n")}"
|
22
26
|
end
|
23
27
|
|
24
28
|
end
|
data/lib/pry-moves/pry_ext.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
class << Pry
|
2
|
-
|
3
|
-
|
4
|
-
def start_with_pry_nav(target = TOPLEVEL_BINDING, options = {})
|
5
|
-
old_options = options.reject { |k, _| k == :pry_remote }
|
2
|
+
alias pry_moves_origin_start start
|
6
3
|
|
4
|
+
def start(target = TOPLEVEL_BINDING, options = {})
|
7
5
|
if target.is_a?(Binding) && PryMoves.check_file_context(target)
|
8
6
|
# Wrap the tracer around the usual Pry.start
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
original_verbosity = $VERBOSE
|
8
|
+
$VERBOSE = nil # Disable warnings for pry-moves
|
9
|
+
PryMoves::PryWrapper.new(target, options, self).run
|
10
|
+
$VERBOSE = original_verbosity
|
12
11
|
else
|
13
12
|
# No need for the tracer unless we have a file context to step through
|
14
|
-
|
13
|
+
pry_moves_origin_start(target, options)
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
18
|
-
alias_method :start, :start_with_pry_nav
|
19
17
|
end
|
20
18
|
|
21
19
|
Binding.class_eval do
|
22
20
|
|
21
|
+
attr_accessor :index
|
22
|
+
|
23
23
|
alias pry_forced pry
|
24
24
|
|
25
25
|
def pry
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
if !Pry.config.disable_breakpoints and
|
27
|
+
# Don't start binding.pry when semaphore locked by current thread
|
28
|
+
PryMoves.synchronize_threads
|
29
29
|
pry_forced
|
30
30
|
end
|
31
31
|
end
|
@@ -34,6 +34,32 @@ end
|
|
34
34
|
|
35
35
|
Pry.config.pager = false
|
36
36
|
|
37
|
+
Pry::Command.class_eval do
|
38
|
+
class << self
|
39
|
+
attr_accessor :original_user_input
|
40
|
+
end
|
41
|
+
|
42
|
+
alias run_origin_for_pry_moves run
|
43
|
+
def run(command_string, *args)
|
44
|
+
Pry.config.original_user_input = self.class.original_user_input
|
45
|
+
result = run_origin_for_pry_moves command_string, *args
|
46
|
+
Pry.config.original_user_input = nil
|
47
|
+
result
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Pry::CommandSet.class_eval do
|
52
|
+
|
53
|
+
alias alias_command_origin_for_pry_moves alias_command
|
54
|
+
|
55
|
+
def alias_command(match, action, options = {})
|
56
|
+
cmd = alias_command_origin_for_pry_moves match, action, options
|
57
|
+
cmd.original_user_input = match
|
58
|
+
cmd
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
37
63
|
Pry::Command::Whereami.class_eval do
|
38
64
|
# Negligent function from Pry - evidently poor output format
|
39
65
|
# would be wanted to be changed often by developers,
|
@@ -56,11 +82,19 @@ Pry::Command::Whereami.class_eval do
|
|
56
82
|
end
|
57
83
|
|
58
84
|
def build_output
|
59
|
-
lines = []
|
60
|
-
|
61
|
-
|
85
|
+
lines = ['']
|
86
|
+
|
87
|
+
formatter = PryMoves::Formatter.new
|
88
|
+
prefix = Thread.current[:pry_moves_debug] ? "👾 " : ""
|
89
|
+
lines << "#{prefix}#{formatter.shorten_path location}"
|
90
|
+
lines << " ." + formatter.method_signature(target)
|
62
91
|
lines << ''
|
63
92
|
lines << "#{code.with_line_numbers(use_line_numbers?).with_marker(marker).highlighted}"
|
93
|
+
|
94
|
+
lines << PryMoves::Watch.instance.output(target) unless PryMoves::Watch.instance.empty?
|
95
|
+
lines.concat PryMoves.messages
|
96
|
+
PryMoves.messages.clear
|
97
|
+
|
64
98
|
lines << ''
|
65
99
|
lines.join "\n"
|
66
100
|
end
|
@@ -82,4 +116,18 @@ Pry::Code::LOC.class_eval do
|
|
82
116
|
tuple[0] = " #{marker} #{ line }"
|
83
117
|
end
|
84
118
|
|
85
|
-
end
|
119
|
+
end
|
120
|
+
|
121
|
+
Pry::Output.class_eval do
|
122
|
+
|
123
|
+
alias pry_moves_origin_for_puts puts
|
124
|
+
|
125
|
+
def puts *args
|
126
|
+
first = args[0]
|
127
|
+
if first.is_a? String and first.start_with? "(pry) output error"
|
128
|
+
first.slice! 400..-1
|
129
|
+
end
|
130
|
+
pry_moves_origin_for_puts *args
|
131
|
+
end
|
132
|
+
|
133
|
+
end if defined? Pry::Output
|