pry-moves 0.1.13 → 1.0.2
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 +9 -5
- data/README.md +25 -9
- data/lib/commands/debug.rb +21 -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 +73 -0
- data/lib/pry-moves/add_suffix.rb +87 -0
- data/lib/pry-moves/backtrace.rb +99 -50
- data/lib/pry-moves/bindings_stack.rb +106 -0
- data/lib/pry-moves/commands.rb +42 -3
- data/lib/pry-moves/error_with_data.rb +10 -0
- data/lib/pry-moves/formatter.rb +79 -0
- data/lib/pry-moves/painter.rb +3 -2
- data/lib/pry-moves/pry_ext.rb +66 -18
- data/lib/pry-moves/pry_wrapper.rb +30 -17
- data/lib/pry-moves/recursion_tracker.rb +94 -0
- data/lib/pry-moves/restartable.rb +39 -0
- data/lib/pry-moves/version.rb +1 -1
- data/lib/pry-moves/watch.rb +3 -0
- data/lib/pry-moves.rb +77 -6
- data/lib/pry-stack_explorer/frame_helpers.rb +114 -0
- data/lib/pry-stack_explorer/frame_manager.rb +6 -9
- data/lib/pry-stack_explorer/pry-stack_explorer.rb +2 -17
- data/lib/pry-stack_explorer/{commands.rb → stack_commands.rb} +6 -109
- data/lib/pry-stack_explorer/when_started_hook.rb +10 -65
- data/playground/Gemfile.lock +9 -5
- data/playground/README.md +1 -0
- data/playground/playground.rb +94 -9
- data/playground/sand.rb +12 -10
- data/playground/test.rb +5 -1
- data/playground/test.sh +1 -0
- data/pry-moves.gemspec +4 -2
- data/publish.sh +2 -1
- 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 +60 -13
- data/lib/pry-moves/helpers.rb +0 -56
- data/lib/pry-moves/trace_commands.rb +0 -109
- data/lib/pry-moves/traced_method.rb +0 -61
- data/lib/pry-moves/tracer.rb +0 -140
- data/lib/pry-moves/traversing.rb +0 -69
@@ -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,98 @@ 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
|
-
if param
|
32
|
+
if param == 'save'
|
33
|
+
@filter = 'hidden'
|
34
|
+
@@backtrace = build_backtrace
|
35
|
+
@pry.output.puts "💾 Backtrace saved (#{@@backtrace.count} lines)"
|
36
|
+
elsif param == 'diff'
|
37
|
+
@filter = 'hidden'
|
38
|
+
diff
|
39
|
+
elsif param.is_a?(String) and (match = param.match /^>(.*)/)
|
31
40
|
suffix = match[1].size > 0 ? match[1] : param2
|
32
|
-
|
41
|
+
@formatter.colorize = false
|
42
|
+
write_to_file build_backtrace, suffix
|
43
|
+
elsif param and param.match /\d+/
|
44
|
+
index = param.to_i
|
45
|
+
frame_manager.goto_index index
|
33
46
|
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
|
47
|
+
print_backtrace param
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
43
51
|
private
|
44
52
|
|
45
|
-
def
|
53
|
+
def print_backtrace filter
|
54
|
+
@colorize = true
|
55
|
+
@lines_numbers = true
|
56
|
+
@filter = filter if filter.is_a? String
|
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
|
46
63
|
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
|
64
|
+
current_object, vapid_count = nil, 0
|
57
65
|
|
58
|
-
|
59
|
-
|
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
|
60
80
|
|
61
|
-
def build_result(stack, result)
|
62
|
-
current_object = nil
|
63
|
-
stack.each do |binding|
|
64
81
|
obj, debug_snapshot = binding.eval '[self, (debug_snapshot rescue nil)]'
|
65
82
|
# Comparison of objects directly may raise exception
|
66
83
|
if current_object.object_id != obj.object_id
|
67
|
-
result << "#{debug_snapshot || format_obj(obj)}
|
84
|
+
result << "#{debug_snapshot || @formatter.format_obj(obj)}"
|
68
85
|
current_object = obj
|
69
86
|
end
|
70
87
|
|
71
|
-
|
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)
|
72
91
|
end
|
73
|
-
result
|
74
|
-
end
|
75
92
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
93
|
+
# recursion.each { |t| t.apply result }
|
94
|
+
|
95
|
+
result << "👽 frames hidden: #{vapid_count}" if vapid_count > 0
|
96
|
+
|
97
|
+
result
|
82
98
|
end
|
83
99
|
|
84
|
-
def build_line(binding)
|
85
|
-
file =
|
100
|
+
def build_line(binding, file, line)
|
101
|
+
file = @formatter.shorten_path "#{file}"
|
86
102
|
|
87
|
-
signature =
|
103
|
+
signature = @formatter.method_signature binding
|
88
104
|
signature = ":#{binding.frame_type}" if !signature or signature.length < 1
|
89
105
|
|
90
|
-
indent = frame_manager.current_frame == binding
|
91
|
-
|
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
|
92
114
|
|
93
|
-
line = binding.eval('__LINE__')
|
94
115
|
"#{indent}#{file}:#{line} #{signature}"
|
95
116
|
end
|
96
117
|
|
@@ -98,10 +119,6 @@ class PryMoves::Backtrace
|
|
98
119
|
PryStackExplorer.frame_manager(@pry)
|
99
120
|
end
|
100
121
|
|
101
|
-
def stack_bindings(vapid_frames)
|
102
|
-
frame_manager.filter_bindings vapid_frames: vapid_frames
|
103
|
-
end
|
104
|
-
|
105
122
|
def write_to_file(lines, file_suffix)
|
106
123
|
log_path = log_path file_suffix
|
107
124
|
File.write log_path, lines.join("\n")
|
@@ -115,4 +132,36 @@ class PryMoves::Backtrace
|
|
115
132
|
"#{root}/backtrace_#{file_suffix}.log"
|
116
133
|
end
|
117
134
|
|
118
|
-
|
135
|
+
def diff
|
136
|
+
return STDERR.puts "No backtrace saved. Use `bt save` first".yellow unless defined? @@backtrace
|
137
|
+
|
138
|
+
diff = Diffy::Diff.new(@@backtrace.join("\n"), build_backtrace.join("\n")).to_s "color"
|
139
|
+
diff = 'Backtraces are equal' if diff.strip.empty?
|
140
|
+
@pry.output.puts diff
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
Pry.config.exception_handler = proc do |output, exception, _|
|
146
|
+
|
147
|
+
def print_error message, exception, output
|
148
|
+
output.puts message.red
|
149
|
+
exception.backtrace.reject! {|l| l.match /sugar\.rb/}
|
150
|
+
exception.backtrace.first(3).each { output.puts _1.white }
|
151
|
+
end
|
152
|
+
|
153
|
+
if Pry::UserError === exception && SyntaxError === exception
|
154
|
+
output.puts "SyntaxError: #{exception.message.sub(/.*syntax error, */m, '')}"
|
155
|
+
else
|
156
|
+
|
157
|
+
print_error "#{exception.class}: #{exception.message}", exception, output
|
158
|
+
|
159
|
+
if exception.respond_to? :cause
|
160
|
+
cause = exception.cause
|
161
|
+
while cause
|
162
|
+
print_error "Caused by #{cause.class}: #{cause}\n", exception, output
|
163
|
+
cause = cause.cause
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
class PryMoves::BindingsStack < Array
|
2
|
+
|
3
|
+
def initialize options
|
4
|
+
@options = options
|
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| for_for_initial_frame b} || 0
|
18
|
+
end
|
19
|
+
def initial_frame
|
20
|
+
find {|b| for_for_initial_frame b}
|
21
|
+
end
|
22
|
+
|
23
|
+
def for_for_initial_frame b
|
24
|
+
not b.hidden and (
|
25
|
+
@options[:is_error] or b.eval("__method__") != :initialize
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def set_indices
|
32
|
+
reverse.each_with_index do |binding, index|
|
33
|
+
binding.index = index
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def mark_vapid_frames
|
38
|
+
stepped_out = false
|
39
|
+
actual_file, actual_method = nil, nil
|
40
|
+
|
41
|
+
# here calls checked in reverse order - from latest to parent:
|
42
|
+
each do |binding|
|
43
|
+
file, method, obj = binding.eval("[__FILE__, __method__, self]")
|
44
|
+
|
45
|
+
if file.match PryMoves::Backtrace::filter
|
46
|
+
binding.hidden = true
|
47
|
+
elsif stepped_out
|
48
|
+
if actual_file == file and actual_method == method or
|
49
|
+
binding.local_variable_defined? :pry_moves_deferred_call
|
50
|
+
stepped_out = false
|
51
|
+
else
|
52
|
+
binding.hidden = true
|
53
|
+
end
|
54
|
+
elsif binding.frame_type == :block
|
55
|
+
stepped_out = true
|
56
|
+
actual_file = file
|
57
|
+
actual_method = method
|
58
|
+
elsif obj and method and obj.method(method).source.strip.match /^delegate\s/
|
59
|
+
binding.hidden = true
|
60
|
+
end
|
61
|
+
|
62
|
+
if binding.local_variable_defined? :hide_from_stack
|
63
|
+
binding.hidden = true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
stack_tip_met = false
|
68
|
+
stack_tips = PryMoves.stack_tips || []
|
69
|
+
reverse.each do |binding|
|
70
|
+
if binding.local_variable_defined?(:pry_moves_stack_tip) ||
|
71
|
+
stack_tips.include?(binding.eval("__method__"))
|
72
|
+
stack_tip_met = true
|
73
|
+
end
|
74
|
+
binding.hidden = true if stack_tip_met
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# remove internal frames related to setting up the session
|
79
|
+
def remove_internal_frames(bindings)
|
80
|
+
i = top_internal_frame_index(bindings)
|
81
|
+
# DEBUG:
|
82
|
+
#bindings.each_with_index do |b, index|
|
83
|
+
# puts "#{index}: #{b.eval("self.class")} #{b.eval("__method__")}"
|
84
|
+
#end
|
85
|
+
# puts "FOUND top internal frame in #{bindings.size} frames: [#{i}] #{bindings[i].ai}"
|
86
|
+
|
87
|
+
bindings.drop i+1
|
88
|
+
end
|
89
|
+
|
90
|
+
def top_internal_frame_index(bindings)
|
91
|
+
pry_moves_debug = Thread.current[:pry_moves_debug]
|
92
|
+
bindings.rindex do |b|
|
93
|
+
if not pry_moves_debug and b.frame_type == :eval
|
94
|
+
true
|
95
|
+
elsif b.frame_type == :method
|
96
|
+
method, self_ = b.eval("[__method__, self, __FILE__]")
|
97
|
+
|
98
|
+
self_.equal?(Pry) && method == :start ||
|
99
|
+
self_.class == Binding && method == :pry ||
|
100
|
+
self_.is_a?(PryMoves::TraceCommand) && method == :tracing_func ||
|
101
|
+
b.local_variable_defined?(:pry_moves_stack_end)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
data/lib/pry-moves/commands.rb
CHANGED
@@ -21,6 +21,11 @@ module PryMoves
|
|
21
21
|
breakout_navigation :next, 'blockless'
|
22
22
|
end
|
23
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
|
+
|
24
29
|
block_command 'iterate', 'Go to next iteration of current block' do |param|
|
25
30
|
breakout_navigation :iterate, param
|
26
31
|
end
|
@@ -41,7 +46,7 @@ module PryMoves
|
|
41
46
|
end
|
42
47
|
|
43
48
|
block_command 'bt', 'Backtrace' do |param, param2|
|
44
|
-
PryMoves::Backtrace.new(
|
49
|
+
PryMoves::Backtrace.new(_pry_).run_command param, param2
|
45
50
|
end
|
46
51
|
|
47
52
|
block_command 'debug', '' do
|
@@ -49,6 +54,23 @@ module PryMoves
|
|
49
54
|
breakout_navigation :debug, cmd
|
50
55
|
end
|
51
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
|
+
|
52
74
|
block_command '!', 'exit' do
|
53
75
|
PryMoves.unlock
|
54
76
|
Pry.config.exit_requested = true
|
@@ -62,16 +84,32 @@ module PryMoves
|
|
62
84
|
|
63
85
|
helpers do
|
64
86
|
def breakout_navigation(action, param)
|
87
|
+
return if var_precedence action
|
88
|
+
|
65
89
|
check_file_context
|
66
90
|
_pry_.binding_stack.clear # Clear the binding stack.
|
67
91
|
throw :breakout_nav, { # Break out of the REPL loop and
|
68
92
|
action: action, # signal the tracer.
|
69
93
|
param: param,
|
70
|
-
binding: target
|
71
|
-
pry: _pry_
|
94
|
+
binding: target
|
72
95
|
}
|
73
96
|
end
|
74
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
|
+
|
75
113
|
# Ensures that a command is executed in a local file context.
|
76
114
|
def check_file_context
|
77
115
|
unless PryMoves.check_file_context(target)
|
@@ -79,6 +117,7 @@ module PryMoves
|
|
79
117
|
end
|
80
118
|
end
|
81
119
|
end
|
120
|
+
|
82
121
|
end
|
83
122
|
end
|
84
123
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class PryMoves::Formatter
|
2
|
+
|
3
|
+
attr_accessor :colorize
|
4
|
+
|
5
|
+
def initialize colorize = true
|
6
|
+
@colorize = colorize
|
7
|
+
end
|
8
|
+
|
9
|
+
MAX_PARAMS = 5
|
10
|
+
def method_signature(binding)
|
11
|
+
meth = binding.eval('__method__')
|
12
|
+
meth_obj = meth ? Pry::Method.from_binding(binding) : nil
|
13
|
+
if !meth_obj
|
14
|
+
""
|
15
|
+
elsif meth_obj.undefined?
|
16
|
+
"#{meth_obj.name}(UNKNOWN) (undefined method)"
|
17
|
+
else
|
18
|
+
args = meth_obj.parameters.map.with_index do |(type, name), i|
|
19
|
+
if name
|
20
|
+
value = format_arg binding, name.to_s
|
21
|
+
show_value = true
|
22
|
+
else
|
23
|
+
name = (type == :block ? 'block' : "arg#{i + 1}")
|
24
|
+
end
|
25
|
+
name = case type
|
26
|
+
when :req then "#{name} ="
|
27
|
+
when :key then "#{name}:"
|
28
|
+
when :opt then "#{name}=?"
|
29
|
+
when :rest then "*#{name}"
|
30
|
+
when :block then "&#{name}"
|
31
|
+
else '?'
|
32
|
+
end
|
33
|
+
show_value ? "#{name} #{value}" : name
|
34
|
+
end
|
35
|
+
if args.count > MAX_PARAMS
|
36
|
+
args = args.first(MAX_PARAMS) + ["(#{args.count - MAX_PARAMS} more params)…"]
|
37
|
+
end
|
38
|
+
"#{meth_obj.name}(#{args.join(', ')})"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def format_arg binding, arg_name
|
43
|
+
arg = binding.eval(arg_name.to_s)
|
44
|
+
format_obj arg
|
45
|
+
end
|
46
|
+
|
47
|
+
def first_line str
|
48
|
+
str.split("\n").first
|
49
|
+
end
|
50
|
+
|
51
|
+
def cut_string str
|
52
|
+
return str unless str
|
53
|
+
str.length > 50 ? "#{str.first 50}..." : str
|
54
|
+
end
|
55
|
+
|
56
|
+
PATH_TRASH = defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
57
|
+
|
58
|
+
def shorten_path(path)
|
59
|
+
path.gsub( /^#{PATH_TRASH}\//, '')
|
60
|
+
end
|
61
|
+
|
62
|
+
def format_obj(obj)
|
63
|
+
if obj.is_a? String
|
64
|
+
format_obj2 cut_string first_line obj
|
65
|
+
else
|
66
|
+
first_line format_obj2 obj
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def format_obj2(obj)
|
71
|
+
if @colorize
|
72
|
+
PryMoves::Painter.colorize obj
|
73
|
+
else
|
74
|
+
i = obj.inspect
|
75
|
+
i.start_with?('#<') ? obj.class.to_s : i
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/lib/pry-moves/painter.rb
CHANGED
@@ -14,13 +14,14 @@ 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
|
22
23
|
rescue => e
|
23
|
-
"Inspect error: #{e}\n" +
|
24
|
+
"⛔️ Inspect error: #{e}\n" +
|
24
25
|
"#{e.backtrace.first(3).join("\n")}"
|
25
26
|
end
|
26
27
|
|