pry-moves 0.1.1 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f79cd377ce0604df7803f55544d00d04f2e8342
4
- data.tar.gz: fcff3fd9d786930d8468dc2f5d81912702cb1b70
3
+ metadata.gz: 9397716c77781c90d1a1130b30a780226ac44aac
4
+ data.tar.gz: 9f26eae9c3731f48c93c875f3af90c5e6025c749
5
5
  SHA512:
6
- metadata.gz: 0ccc6ebb0b80454c784cfb7ef9e27b22fb1f700f42c0abfdc2f7eeca89bfc9cf5796b6c809fc76e9dd3641ec333c4b1dd878e50aebf660f3ddc139355e22c924
7
- data.tar.gz: 92dbe779b01e9fdaee2f48291c37e0e22d5ed9e3197ae75e370d085a3ac11e3bd044a3167ac3fc7165c6b732bdf6bd4bccfce8d0f39fca739eb23ff308577517
6
+ metadata.gz: b2b54ca87a8935f49de7a9d016446db8dd1a065af3e98062db580afd0ef95de7597c15def6bfc9048cfca5e1ffaeb386c315ddaf2dbf79ab14f031122c81f4e0
7
+ data.tar.gz: 6b2039aadade2fb859e382edcb38080d33c3bf4d3b8d025d0a783f7029607445d05744372156462bc9de0c0045772266ae12a0039d597abafc200662362cc912
data/README.md CHANGED
@@ -11,13 +11,17 @@ _An execution control add-on for [Pry][pry]._
11
11
 
12
12
  * `n` - **next** line in current frame, including block lines (moving to next line goes as naturally expected)
13
13
  * `s` - **step** into function execution
14
- * `s func_name` - steps into first method called by name `func_name`
15
- * `f` - **finish** execution of current frame and stop at next line on higher level
14
+ * `s func_name` - step into first method called by name `func_name`
15
+ * `f` - **finish** execution of current frame (block or method) and stop at next line on higher level
16
16
  * `c` - **continue**
17
- * `bt` - shows latest 5 lines from backtrace
17
+ * `bt` - show latest 5 lines from backtrace
18
18
  * `bt 10` - latest 10 lines
19
- * `bt all`- full backtrace
20
- * `up`/`down` - move over call stack
19
+ * `bt all` - full backtrace
20
+ * `bt >foo` - write backtrace to file `log/backtrace_foo.log`
21
+ * `up`/`down`/`top`/`bottom` - move over call stack
22
+ * `up +` - move up, including vapid frames (block callers, hidden frames)
23
+ * `up pattern` - move up till first frame which method name or file position in format `folder/script.rb:12` matches regexp pattern
24
+ * `debug some_method(param, param2)` - call `some_method(param, param2)` and interactively step into it
21
25
  * `!` - exit
22
26
 
23
27
 
@@ -38,22 +42,46 @@ end
38
42
 
39
43
  _Demo class source [here](https://github.com/garmoshka-mo/pry-moves/issues/1)_
40
44
 
45
+ ## Backtrace and call stack
46
+
47
+ You can explicitly hide frames from backtrace and call stack by defining `hide_from_stack` variable:
48
+
49
+ ```ruby
50
+ def insignificant_method
51
+ hide_from_stack = true
52
+ something_insignificant
53
+ yield
54
+ end
55
+ ```
56
+
41
57
  ## Configuration
42
58
 
43
59
  Here is default configuration, you can override it:
44
60
 
45
61
  ```ruby
46
- PryMoves::Backtrace::filter =
62
+ PryMoves::Backtrace::lines_count = 5
63
+ PryMoves::Backtrace::filter =
47
64
  /(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby\/|\/pry-moves\/)/
48
-
49
- PryMoves::Backtrace::format do |line|
50
- defined?(Rails) : line.gsub( /^#{Rails.root.to_s}/, '') : line
51
- end
52
65
  ```
53
66
 
54
- ## Technical info
67
+ ## Threads, helpers
68
+
69
+ `pry-moves` can't stop other threads on `binding.pry`, so they will continue to run.
70
+ This makes `pry-moves` not always suitable for debugging of multi-thread projects.
71
+
72
+ Though you can pause other threads with helper which will suspend execution on current line,
73
+ until ongoing debug session will be finished with `continue`:
74
+
75
+ ```ruby
76
+ PryMoves.synchronize_threads
77
+ ```
78
+
79
+ _For example, you can put it into function which periodically reports status of thread (if you have such)_
80
+
81
+ Other helpers:
82
+ * `PryMoves.open?` - if pry input dialog active. Can be used to suppress output from ongoing parallel threads
55
83
 
56
- `pry-moves` is not yet thread-safe, so only use in single-threaded environments.
84
+ ## pry-remote
57
85
 
58
86
  Rudimentary support for [`pry-remote`][pry-remote] (>= 0.1.1) is also included.
59
87
  Ensure `pry-remote` is loaded or required before `pry-moves`. For example, in a
@@ -65,9 +93,10 @@ gem 'pry-remote'
65
93
  gem 'pry-moves'
66
94
  ```
67
95
 
96
+ ## Performance
97
+
68
98
  Please note that debugging functionality is implemented through
69
- [`set_trace_func`][set_trace_func], which imposes a large performance
70
- penalty.
99
+ [`set_trace_func`][set_trace_func], which imposes certain performance penalty.
71
100
 
72
101
  ## Contributors
73
102
 
@@ -0,0 +1,42 @@
1
+ if @command[:action] == :ababa
2
+ puts 'catch debug'
3
+
4
+
5
+ set_trace_func (
6
+ Proc.new { |event, file, line, id, binding_, classname|
7
+ #if file == '(pry)'
8
+ #unless file.match /\/gems\/|\/ruby\//
9
+ printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
10
+ if event=='line' and file == 'sand.rb' and line != 47
11
+ set_trace_func nil
12
+ Pry.start(binding_, @pry_start_options)
13
+ end
14
+ })
15
+
16
+ puts "CALLER:\n#{caller.join "\n"}\n"
17
+
18
+ #Pry.start(command[:binding], @pry_start_options)
19
+ return return_value
20
+ end
21
+
22
+ TracePoint.new(:line) {|tp|p [tp.lineno, tp.event]}.enable
23
+
24
+ set_trace_func proc { |event, file, line, id, binding, classname|
25
+ printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
26
+ }
27
+
28
+
29
+ set_trace_func proc { |event, file, line, id, binding, classname|
30
+ printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname unless file.match /\/gems\/|\/ruby\//
31
+ }
32
+
33
+
34
+ set_trace_func proc { |event, file, line, id, binding, classname|
35
+ printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname if file == '(pry)'
36
+ }
37
+
38
+
39
+
40
+
41
+
42
+
@@ -0,0 +1,110 @@
1
+ require 'fileutils'
2
+
3
+ class PryMoves::Backtrace
4
+
5
+ class << self
6
+ def lines_count; @lines_count || 5; end
7
+ def lines_count=(f); @lines_count = f; end
8
+
9
+ def filter
10
+ @filter || /(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby\/|\/pry-moves\/)/
11
+ end
12
+ def filter=(f); @filter = f; end
13
+
14
+ def format(&block)
15
+ @formatter = block
16
+ end
17
+
18
+ def formatter
19
+ @formatter || lambda do |line|
20
+ # not used
21
+ end
22
+ end
23
+ end
24
+
25
+ def initialize(binding, pry)
26
+ @binding, @pry = binding, pry
27
+ end
28
+
29
+ def build(lines_count = nil)
30
+ result = []
31
+ show_vapid = lines_count == 'all'
32
+ stack = stack_bindings(show_vapid)
33
+ .reverse.reject do |binding|
34
+ binding.eval('__FILE__').match self.class::filter
35
+ end
36
+
37
+ if lines_count.is_a? String and lines_count.match /\d+/
38
+ lines_count = lines_count.to_i
39
+ end
40
+ if lines_count.is_a?(Numeric) and stack.count > lines_count
41
+ result << "Latest #{lines_count} lines: (`bt all` for full tracing)"
42
+ stack = stack.last(lines_count)
43
+ end
44
+
45
+ build_result stack, result
46
+ end
47
+
48
+ def run_command(param)
49
+ if param.is_a?(String) and (match = param.match /^>(.*)/)
50
+ write_to_file build, match[1]
51
+ else
52
+ puts build(param || PryMoves::Backtrace::lines_count)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def build_result(stack, result)
59
+ current_object = nil
60
+ stack.each do |binding|
61
+ obj = binding.eval 'self'
62
+ if current_object != obj
63
+ colored_obj = ""
64
+ Pry::ColorPrinter.pp obj, colored_obj
65
+ result << "#{colored_obj.chomp}:"
66
+ current_object = obj
67
+ end
68
+
69
+ result << build_line(binding)
70
+ end
71
+ result
72
+ end
73
+
74
+ def build_line(binding)
75
+ file = "#{binding.eval('__FILE__')}"
76
+ file.gsub!( /^#{Rails.root.to_s}/, '') if defined? Rails
77
+
78
+ signature = PryMoves::Helpers.method_signature_with_owner binding
79
+
80
+ indent = frame_manager.current_frame == binding ?
81
+ ' => ': ' '
82
+
83
+ "#{indent}#{file}:#{binding.eval('__LINE__')} "+
84
+ " #{signature} :#{binding.frame_type}"
85
+ end
86
+
87
+ def frame_manager
88
+ PryStackExplorer.frame_manager(@pry)
89
+ end
90
+
91
+ def stack_bindings(vapid_frames)
92
+ frame_manager.filter_bindings vapid_frames: vapid_frames
93
+ end
94
+
95
+ def write_to_file(lines, file_suffix)
96
+ log_path = log_path file_suffix
97
+ File.open(log_path, "w") do |f|
98
+ f.puts lines
99
+ end
100
+ puts "Backtrace logged to #{log_path}"
101
+ end
102
+
103
+ def log_path(file_suffix)
104
+ root = defined?(Rails) ? Rails.root.to_s : '.'
105
+ root += '/log'
106
+ FileUtils.mkdir_p root
107
+ "#{root}/backtrace_#{file_suffix}.log"
108
+ end
109
+
110
+ end
@@ -22,15 +22,25 @@ module PryMoves
22
22
  run 'exit-all'
23
23
  end
24
24
 
25
- block_command 'bt', 'Backtrace' do |param|
26
- PryMoves::Backtrace.new(target).print param
27
- end
28
-
29
25
  alias_command 'c', 'continue'
30
26
  alias_command 's', 'step'
31
27
  alias_command 'n', 'next'
32
28
  alias_command 'f', 'finish'
33
29
 
30
+ block_command 'watch', 'Display value of expression on every move' do |param|
31
+ PryMoves::Watch.instance.process_cmd param, target
32
+ end
33
+
34
+ block_command 'bt', 'Backtrace' do |param|
35
+ PryMoves::Backtrace.new(target, _pry_).run_command param
36
+ end
37
+
38
+ block_command 'debug', '' do |*command_parts|
39
+ check_file_context
40
+ cmd = command_parts.join ' '
41
+ breakout_navigation :debug, cmd
42
+ end
43
+
34
44
  # Hit Enter to repeat last command
35
45
  command /^$/, "repeat last command" do
36
46
  _pry_.run_command Pry.history.to_a.last
@@ -0,0 +1,28 @@
1
+ module PryMoves::Helpers
2
+
3
+ extend self
4
+
5
+ # @return [String] Signature for the method object in Class#method format.
6
+ def method_signature_with_owner(binding)
7
+ meth = binding.eval('__method__')
8
+ meth_obj = meth ? Pry::Method.from_binding(binding) : nil
9
+ if !meth_obj
10
+ ""
11
+ elsif meth_obj.undefined?
12
+ "#{meth_obj.name_with_owner}(UNKNOWN) (undefined method)"
13
+ else
14
+ args = meth_obj.parameters.inject([]) do |arr, (type, name)|
15
+ name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
16
+ arr << case type
17
+ when :req then name.to_s
18
+ when :opt then "#{name}=?"
19
+ when :rest then "*#{name}"
20
+ when :block then "&#{name}"
21
+ else '?'
22
+ end
23
+ end
24
+ "#{meth_obj.name_with_owner}(#{args.join(', ')})"
25
+ end
26
+ end
27
+
28
+ end
@@ -9,7 +9,7 @@ class << Pry
9
9
 
10
10
  if target.is_a?(Binding) && PryMoves.check_file_context(target)
11
11
  # Wrap the tracer around the usual Pry.start
12
- PryMoves::Tracer.new(options).run do
12
+ PryMoves::PryWrapper.new(target, options).run do
13
13
  start_without_pry_nav(target, old_options)
14
14
  end
15
15
  else
@@ -23,20 +23,58 @@ end
23
23
 
24
24
  Binding.class_eval do
25
25
 
26
- alias original_pry pry
26
+ alias pry_forced pry
27
27
 
28
28
  def pry
29
- original_pry unless Pry.config.disable_breakpoints
29
+ unless Pry.config.disable_breakpoints
30
+ PryMoves.synchronize_threads
31
+ pry_forced
32
+ end
30
33
  end
31
34
 
32
35
  end
33
36
 
34
- require 'pry-stack_explorer'
37
+ Pry.config.pager = false
38
+
39
+ Pry::Command::Whereami.class_eval do
40
+ # Negligent function from Pry - evidently poor output format
41
+ # would be wanted to be changed often by developers,
42
+ # but definition so long... :(
43
+ def process
44
+ if bad_option_combination?
45
+ raise CommandError, "Only one of -m, -c, -f, and LINES may be specified."
46
+ end
47
+
48
+ if nothing_to_do?
49
+ return
50
+ elsif internal_binding?(target)
51
+ handle_internal_binding
52
+ return
53
+ end
35
54
 
36
- PryStackExplorer::WhenStartedHook.class_eval do
55
+ set_file_and_dir_locals(@file)
37
56
 
38
- def remove_debugger_frames(bindings)
39
- bindings.drop_while { |b| b.eval("__FILE__") =~ /\/pry-/ }
57
+ _pry_.pager.page build_output
40
58
  end
41
59
 
60
+ def build_output
61
+ lines = []
62
+ lines << "#{text.bold('From:')} #{location}"
63
+ lines << PryMoves::Watch.instance.output(target) unless PryMoves::Watch.instance.empty?
64
+ lines << ''
65
+ lines << "#{code.with_line_numbers(use_line_numbers?).with_marker(marker).highlighted}"
66
+ lines << ''
67
+ lines.join "\n"
68
+ end
69
+
70
+ def location
71
+ me = target.eval 'self' rescue nil
72
+ if me
73
+ colored_str = ''
74
+ Pry::ColorPrinter.pp me, colored_str
75
+ me = colored_str.chomp
76
+ end
77
+ file = defined?(Rails) ? @file.gsub(Rails.root.to_s, '') : @file
78
+ "#{file}:#{@line} #{me}"
79
+ end
42
80
  end
@@ -0,0 +1,69 @@
1
+ require 'pry' unless defined? Pry
2
+
3
+ module PryMoves
4
+ class PryWrapper
5
+ def initialize(binding_, pry_start_options = {})
6
+ @init_binding = binding_
7
+ @pry_start_options = pry_start_options # Options to use for Pry.start
8
+ end
9
+
10
+ def run(&block)
11
+ PryMoves.lock
12
+
13
+ return_value = nil
14
+ PryMoves.is_open = true
15
+ @command = catch(:breakout_nav) do # Coordinates with PryMoves::Commands
16
+ return_value = yield
17
+ nil # Nothing thrown == no navigational command
18
+ end
19
+ PryMoves.is_open = false
20
+
21
+ if @command
22
+ trace_command
23
+ else
24
+ PryMoves.unlock
25
+ if @pry_start_options[:pry_remote] && PryMoves.current_remote_server
26
+ PryMoves.current_remote_server.teardown
27
+ end
28
+ end
29
+
30
+ return_value
31
+ end
32
+
33
+ private
34
+
35
+ def trace_command
36
+ if @command[:action] == :debug
37
+ wrap_debug
38
+ else
39
+ start_tracing
40
+ end
41
+ end
42
+
43
+ def wrap_debug
44
+ #puts "##wrap debug"
45
+ #puts "CALLER:\n#{caller.join "\n"}\n"
46
+ # Thread.abort_on_exception=true
47
+ Thread.new do
48
+ Thread.current[:pry_moves_debug] = true
49
+ #@command[:binding].eval 'puts "###########"'
50
+ start_tracing
51
+ begin
52
+ @command[:binding].eval @command[:param]
53
+ rescue => e
54
+ Thread.current.set_trace_func nil
55
+ puts e
56
+ end
57
+ end.join
58
+ binding_ = @last_runtime_binding || @init_binding
59
+ Pry.start(binding_, @pry_start_options)
60
+ end
61
+
62
+ def start_tracing
63
+ @last_runtime_binding = @command[:binding]
64
+ @tracer = PryMoves::Tracer.new @command, @pry_start_options
65
+ @tracer.trace
66
+ end
67
+
68
+ end
69
+ end