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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +7 -5
  4. data/README.md +18 -8
  5. data/lib/commands/debug.rb +17 -0
  6. data/lib/commands/finish.rb +26 -0
  7. data/lib/commands/goto.rb +19 -0
  8. data/lib/commands/iterate.rb +22 -0
  9. data/lib/commands/next.rb +37 -0
  10. data/lib/commands/next_breakpoint.rb +22 -0
  11. data/lib/commands/step.rb +83 -0
  12. data/lib/commands/trace_command.rb +87 -0
  13. data/lib/commands/trace_helpers.rb +49 -0
  14. data/lib/commands/traced_method.rb +71 -0
  15. data/lib/debug_sugar.rb +72 -0
  16. data/lib/pry-moves/add_suffix.rb +87 -0
  17. data/lib/pry-moves/backtrace.rb +81 -50
  18. data/lib/pry-moves/bindings_stack.rb +97 -0
  19. data/lib/pry-moves/commands.rb +50 -7
  20. data/lib/pry-moves/formatter.rb +75 -0
  21. data/lib/pry-moves/painter.rb +5 -1
  22. data/lib/pry-moves/pry_ext.rb +64 -16
  23. data/lib/pry-moves/pry_wrapper.rb +30 -17
  24. data/lib/pry-moves/recursion_tracker.rb +94 -0
  25. data/lib/pry-moves/restartable.rb +38 -0
  26. data/lib/pry-moves/version.rb +1 -1
  27. data/lib/pry-moves/watch.rb +3 -0
  28. data/lib/pry-moves.rb +66 -4
  29. data/lib/pry-stack_explorer/VERSION +2 -0
  30. data/lib/pry-stack_explorer/frame_manager.rb +6 -9
  31. data/lib/pry-stack_explorer/pry-stack_explorer.rb +3 -17
  32. data/lib/pry-stack_explorer/{commands.rb → stack_commands.rb} +10 -6
  33. data/lib/pry-stack_explorer/when_started_hook.rb +17 -63
  34. data/playground/Gemfile.lock +9 -9
  35. data/playground/README.md +1 -0
  36. data/playground/playground.rb +94 -9
  37. data/playground/sand.rb +45 -12
  38. data/playground/test.rb +5 -1
  39. data/playground/test.sh +1 -0
  40. data/pry-moves.gemspec +3 -2
  41. data/publish.sh +3 -0
  42. data/spec/backtrace_spec.rb +11 -13
  43. data/spec/blocks_spec.rb +41 -8
  44. data/spec/commands_spec.rb +26 -25
  45. data/spec/pry_debugger.rb +5 -1
  46. data/spec/redirection_spec.rb +7 -0
  47. data/spec/spec_helper.rb +9 -4
  48. data/spec/step_spec.rb +51 -0
  49. metadata +44 -10
  50. data/lib/pry-moves/helpers.rb +0 -50
  51. data/lib/pry-moves/trace_commands.rb +0 -105
  52. 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
@@ -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 || /(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby\/)/
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(binding, pry)
26
- @binding, @pry = binding, pry
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
- @colorize = true
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
- show_vapid = %w(+ all hidden vapid).include? @lines_count
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
- build_result stack, result
59
- end
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
- def build_result(stack, result)
62
- current_object = nil
63
- stack.each do |binding|
64
- obj = binding.eval 'self'
65
- if current_object != obj
66
- result << "#{format_obj(obj)}:"
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
- result << build_line(binding)
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
- def format_obj(obj)
76
- if @colorize
77
- PryMoves::Painter.colorize obj
78
- else
79
- obj.inspect
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 = "#{binding.eval('__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 = PryMoves::Helpers.method_signature binding
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
@@ -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(target, _pry_).run_command param, param2
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
@@ -14,11 +14,15 @@ 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
+ 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
@@ -1,31 +1,31 @@
1
1
  class << Pry
2
- alias_method :start_without_pry_nav, :start
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
- PryMoves::PryWrapper.new(target, options).run do
10
- start_without_pry_nav(target, old_options)
11
- end
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
- start_without_pry_nav(target, old_options)
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
- unless Pry.config.disable_breakpoints
27
- PryMoves.synchronize_threads ||
28
- return # Don't start binding.pry when semaphore locked by current thread
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
- lines << "#{text.bold('From:')} #{location}"
61
- lines << PryMoves::Watch.instance.output(target) unless PryMoves::Watch.instance.empty?
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