pry-moves 0.1.4 → 0.1.5
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/.gitignore +0 -1
- data/Gemfile +5 -0
- data/Gemfile.lock +52 -0
- data/README.md +13 -5
- data/lib/pry-moves/backtrace.rb +36 -28
- data/lib/pry-moves/commands.rb +6 -5
- data/lib/pry-moves/helpers.rb +22 -0
- data/lib/pry-moves/painter.rb +23 -0
- data/lib/pry-moves/pry_ext.rb +12 -5
- data/lib/pry-moves/pry_wrapper.rb +12 -0
- data/lib/pry-moves/tracer.rb +36 -7
- data/lib/pry-moves/version.rb +1 -1
- data/lib/pry-moves.rb +8 -1
- data/lib/pry-stack_explorer/when_started_hook.rb +18 -41
- data/playground/Gemfile.lock +29 -0
- data/playground/playground.rb +90 -0
- data/playground/sand.rb +7 -11
- data/playground/threads.rb +18 -15
- data/pry-moves.gemspec +1 -1
- data/spec/backtrace_spec.rb +34 -0
- data/spec/blocks_spec.rb +52 -0
- data/spec/commands_spec.rb +73 -0
- data/spec/pry_debugger.rb +89 -0
- data/spec/spec_helper.rb +54 -0
- metadata +19 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c2844477b6ebf360fce390c440ac602b73dc287c
         | 
| 4 | 
            +
              data.tar.gz: 102a4fee351cb6dcbc078b2d22fe6b6829ba314d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: aa98bf11ad2de420aa25795cc53cab6be2d8ff13401a2d0dad69c96932ea613002b04f0f64303c1b6e520ddabd897d3d095791a52dba021319745435e4ffa0af
         | 
| 7 | 
            +
              data.tar.gz: fcabf21cb1742f44406cbd9d5391959d4a24eca3ff99e745b9298ba76dd7d98282992aaa9674f0963845c01b6059663e981797655b4cee203232d0658b0dd151
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            PATH
         | 
| 2 | 
            +
              remote: ../pry
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                pry (0.10.4)
         | 
| 5 | 
            +
                  coderay (~> 1.1.0)
         | 
| 6 | 
            +
                  method_source (~> 0.8.1)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            PATH
         | 
| 9 | 
            +
              remote: .
         | 
| 10 | 
            +
              specs:
         | 
| 11 | 
            +
                pry-moves (0.1.5)
         | 
| 12 | 
            +
                  binding_of_caller (~> 0.7)
         | 
| 13 | 
            +
                  pry (>= 0.9.10, < 0.11.0)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            GEM
         | 
| 16 | 
            +
              remote: https://rubygems.org/
         | 
| 17 | 
            +
              specs:
         | 
| 18 | 
            +
                binding_of_caller (0.7.2)
         | 
| 19 | 
            +
                  debug_inspector (>= 0.0.1)
         | 
| 20 | 
            +
                coderay (1.1.1)
         | 
| 21 | 
            +
                debug_inspector (0.0.3)
         | 
| 22 | 
            +
                diff-lcs (1.3)
         | 
| 23 | 
            +
                method_source (0.8.2)
         | 
| 24 | 
            +
                pry-remote (0.1.8)
         | 
| 25 | 
            +
                  pry (~> 0.9)
         | 
| 26 | 
            +
                  slop (~> 3.0)
         | 
| 27 | 
            +
                rspec (3.6.0)
         | 
| 28 | 
            +
                  rspec-core (~> 3.6.0)
         | 
| 29 | 
            +
                  rspec-expectations (~> 3.6.0)
         | 
| 30 | 
            +
                  rspec-mocks (~> 3.6.0)
         | 
| 31 | 
            +
                rspec-core (3.6.0)
         | 
| 32 | 
            +
                  rspec-support (~> 3.6.0)
         | 
| 33 | 
            +
                rspec-expectations (3.6.0)
         | 
| 34 | 
            +
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 35 | 
            +
                  rspec-support (~> 3.6.0)
         | 
| 36 | 
            +
                rspec-mocks (3.6.0)
         | 
| 37 | 
            +
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 38 | 
            +
                  rspec-support (~> 3.6.0)
         | 
| 39 | 
            +
                rspec-support (3.6.0)
         | 
| 40 | 
            +
                slop (3.6.0)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            PLATFORMS
         | 
| 43 | 
            +
              ruby
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            DEPENDENCIES
         | 
| 46 | 
            +
              pry!
         | 
| 47 | 
            +
              pry-moves!
         | 
| 48 | 
            +
              pry-remote (~> 0.1.6)
         | 
| 49 | 
            +
              rspec
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            BUNDLED WITH
         | 
| 52 | 
            +
               1.14.5
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,5 +1,3 @@ | |
| 1 | 
            -
            ### Using [**pry-byebug**][pry-byebug] and not happy with commands behavior? We recommend this project instead
         | 
| 2 | 
            -
             | 
| 3 1 | 
             
            # pry-moves
         | 
| 4 2 |  | 
| 5 3 | 
             
            _An execution control add-on for [Pry][pry]._
         | 
| @@ -17,11 +15,12 @@ _An execution control add-on for [Pry][pry]._ | |
| 17 15 | 
             
            * `bt` - show latest 5 lines from backtrace
         | 
| 18 16 | 
             
              * `bt 10` - latest 10 lines
         | 
| 19 17 | 
             
              * `bt all` - full backtrace
         | 
| 20 | 
            -
              * `bt >foo` - write backtrace to file `log/backtrace_foo.log`
         | 
| 18 | 
            +
              * `bt > foo` - write backtrace to file `log/backtrace_foo.log`
         | 
| 21 19 | 
             
            * `up`/`down`/`top`/`bottom` - move over call stack
         | 
| 22 20 | 
             
              * `up +` - move up, including vapid frames (block callers, hidden frames)
         | 
| 23 21 | 
             
              * `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( | 
| 22 | 
            +
            * `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
         | 
| 23 | 
            +
            * `watch variable` - display variable's value on each step
         | 
| 25 24 | 
             
            * `!` - exit
         | 
| 26 25 |  | 
| 27 26 |  | 
| @@ -96,7 +95,16 @@ gem 'pry-moves' | |
| 96 95 | 
             
            ## Performance
         | 
| 97 96 |  | 
| 98 97 | 
             
            Please note that debugging functionality is implemented through
         | 
| 99 | 
            -
            [`set_trace_func`][set_trace_func], which imposes  | 
| 98 | 
            +
            [`set_trace_func`][set_trace_func], which imposes heavy performance penalty while tracing
         | 
| 99 | 
            +
            (while running code within `next`/`step`/`finish` commands).
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            # Development
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            ## Testing
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            ```
         | 
| 106 | 
            +
            bundle exec rspec
         | 
| 107 | 
            +
            ```
         | 
| 100 108 |  | 
| 101 109 | 
             
            ## Contributors
         | 
| 102 110 |  | 
    
        data/lib/pry-moves/backtrace.rb
    CHANGED
    
    | @@ -7,7 +7,7 @@ class PryMoves::Backtrace | |
| 7 7 | 
             
                def lines_count=(f); @lines_count = f; end
         | 
| 8 8 |  | 
| 9 9 | 
             
                def filter
         | 
| 10 | 
            -
                  @filter || /(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby | 
| 10 | 
            +
                  @filter || /(\/gems\/|\/rubygems\/|\/bin\/|\/lib\/ruby\/)/
         | 
| 11 11 | 
             
                end
         | 
| 12 12 | 
             
                def filter=(f); @filter = f; end
         | 
| 13 13 |  | 
| @@ -26,43 +26,44 @@ class PryMoves::Backtrace | |
| 26 26 | 
             
                 @binding, @pry = binding, pry
         | 
| 27 27 | 
             
              end
         | 
| 28 28 |  | 
| 29 | 
            -
              def  | 
| 29 | 
            +
              def run_command(param, param2)
         | 
| 30 | 
            +
                if param.is_a?(String) and (match = param.match /^>(.*)/)
         | 
| 31 | 
            +
                  suffix = match[1].size > 0 ? match[1] : param2
         | 
| 32 | 
            +
                  write_to_file build, suffix
         | 
| 33 | 
            +
                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 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              private
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def build
         | 
| 30 46 | 
             
                result = []
         | 
| 31 | 
            -
                show_vapid = lines_count == 'all'
         | 
| 47 | 
            +
                show_vapid = @lines_count == 'all'
         | 
| 32 48 | 
             
                stack = stack_bindings(show_vapid)
         | 
| 33 49 | 
             
                          .reverse.reject do |binding|
         | 
| 34 50 | 
             
                            binding.eval('__FILE__').match self.class::filter
         | 
| 35 51 | 
             
                          end
         | 
| 36 52 |  | 
| 37 | 
            -
                if lines_count.is_a?  | 
| 38 | 
            -
                  lines_count  | 
| 39 | 
            -
             | 
| 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)
         | 
| 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)
         | 
| 43 56 | 
             
                end
         | 
| 44 57 |  | 
| 45 58 | 
             
                build_result stack, result
         | 
| 46 59 | 
             
              end
         | 
| 47 60 |  | 
| 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 61 | 
             
              def build_result(stack, result)
         | 
| 59 62 | 
             
                current_object = nil
         | 
| 60 63 | 
             
                stack.each do |binding|
         | 
| 61 64 | 
             
                  obj = binding.eval 'self'
         | 
| 62 65 | 
             
                  if current_object != obj
         | 
| 63 | 
            -
                     | 
| 64 | 
            -
                    Pry::ColorPrinter.pp obj, colored_obj
         | 
| 65 | 
            -
                    result << "#{colored_obj.chomp}:"
         | 
| 66 | 
            +
                    result << "#{format_obj(obj)}:"
         | 
| 66 67 | 
             
                    current_object = obj
         | 
| 67 68 | 
             
                  end
         | 
| 68 69 |  | 
| @@ -71,17 +72,26 @@ class PryMoves::Backtrace | |
| 71 72 | 
             
                result
         | 
| 72 73 | 
             
              end
         | 
| 73 74 |  | 
| 75 | 
            +
              def format_obj(obj)
         | 
| 76 | 
            +
                if @colorize
         | 
| 77 | 
            +
                  PryMoves::Painter.colorize obj
         | 
| 78 | 
            +
                else
         | 
| 79 | 
            +
                  obj.inspect
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 74 83 | 
             
              def build_line(binding)
         | 
| 75 84 | 
             
                file = "#{binding.eval('__FILE__')}"
         | 
| 76 85 | 
             
                file.gsub!( /^#{Rails.root.to_s}/, '') if defined? Rails
         | 
| 77 86 |  | 
| 78 | 
            -
                signature = PryMoves::Helpers. | 
| 87 | 
            +
                signature = PryMoves::Helpers.method_signature binding
         | 
| 88 | 
            +
                signature = signature.presence || ":#{binding.frame_type}"
         | 
| 79 89 |  | 
| 80 90 | 
             
                indent = frame_manager.current_frame == binding ?
         | 
| 81 91 | 
             
                    ' => ': '    '
         | 
| 82 92 |  | 
| 83 | 
            -
                 | 
| 84 | 
            -
             | 
| 93 | 
            +
                line = binding.eval('__LINE__')
         | 
| 94 | 
            +
                "#{indent}#{file}:#{line} #{signature}"
         | 
| 85 95 | 
             
              end
         | 
| 86 96 |  | 
| 87 97 | 
             
              def frame_manager
         | 
| @@ -94,9 +104,7 @@ class PryMoves::Backtrace | |
| 94 104 |  | 
| 95 105 | 
             
              def write_to_file(lines, file_suffix)
         | 
| 96 106 | 
             
                log_path = log_path file_suffix
         | 
| 97 | 
            -
                File. | 
| 98 | 
            -
                  f.puts lines
         | 
| 99 | 
            -
                end
         | 
| 107 | 
            +
                File.write log_path, lines
         | 
| 100 108 | 
             
                puts "Backtrace logged to #{log_path}"
         | 
| 101 109 | 
             
              end
         | 
| 102 110 |  | 
    
        data/lib/pry-moves/commands.rb
    CHANGED
    
    | @@ -31,8 +31,8 @@ module PryMoves | |
| 31 31 | 
             
                  PryMoves::Watch.instance.process_cmd param, target
         | 
| 32 32 | 
             
                end
         | 
| 33 33 |  | 
| 34 | 
            -
                block_command 'bt', 'Backtrace' do |param|
         | 
| 35 | 
            -
                  PryMoves::Backtrace.new(target, _pry_).run_command param
         | 
| 34 | 
            +
                block_command 'bt', 'Backtrace' do |param, param2|
         | 
| 35 | 
            +
                  PryMoves::Backtrace.new(target, _pry_).run_command param, param2
         | 
| 36 36 | 
             
                end
         | 
| 37 37 |  | 
| 38 38 | 
             
                block_command 'debug', '' do
         | 
| @@ -53,9 +53,10 @@ module PryMoves | |
| 53 53 | 
             
                  def breakout_navigation(action, param)
         | 
| 54 54 | 
             
                    _pry_.binding_stack.clear     # Clear the binding stack.
         | 
| 55 55 | 
             
                    throw :breakout_nav, {        # Break out of the REPL loop and
         | 
| 56 | 
            -
                      : | 
| 57 | 
            -
                      : | 
| 58 | 
            -
                      : | 
| 56 | 
            +
                      action: action,          #   signal the tracer.
         | 
| 57 | 
            +
                      param:  param,
         | 
| 58 | 
            +
                      binding: target,
         | 
| 59 | 
            +
                      pry: _pry_
         | 
| 59 60 | 
             
                    }
         | 
| 60 61 | 
             
                  end
         | 
| 61 62 |  | 
    
        data/lib/pry-moves/helpers.rb
    CHANGED
    
    | @@ -25,4 +25,26 @@ module PryMoves::Helpers | |
| 25 25 | 
             
                end
         | 
| 26 26 | 
             
              end
         | 
| 27 27 |  | 
| 28 | 
            +
              def method_signature(binding)
         | 
| 29 | 
            +
                meth = binding.eval('__method__')
         | 
| 30 | 
            +
                meth_obj = meth ? Pry::Method.from_binding(binding) : nil
         | 
| 31 | 
            +
                if !meth_obj
         | 
| 32 | 
            +
                  ""
         | 
| 33 | 
            +
                elsif meth_obj.undefined?
         | 
| 34 | 
            +
                  "#{meth_obj.name}(UNKNOWN) (undefined method)"
         | 
| 35 | 
            +
                else
         | 
| 36 | 
            +
                  args = meth_obj.parameters.inject([]) do |arr, (type, name)|
         | 
| 37 | 
            +
                    name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
         | 
| 38 | 
            +
                    arr << case type
         | 
| 39 | 
            +
                           when :req   then name.to_s
         | 
| 40 | 
            +
                           when :opt   then "#{name}=?"
         | 
| 41 | 
            +
                           when :rest  then "*#{name}"
         | 
| 42 | 
            +
                           when :block then "&#{name}"
         | 
| 43 | 
            +
                           else '?'
         | 
| 44 | 
            +
                           end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                  "#{meth_obj.name}(#{args.join(', ')})"
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 28 50 | 
             
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            module PryMoves::Painter
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class Canvas < String
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def <<(text)
         | 
| 6 | 
            +
                  if length > 2000
         | 
| 7 | 
            +
                    super("... (cut)")
         | 
| 8 | 
            +
                    throw :cut
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                  super
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def self.colorize(obj)
         | 
| 16 | 
            +
                colored_str = Canvas.new
         | 
| 17 | 
            +
                catch (:cut) do
         | 
| 18 | 
            +
                  Pry::ColorPrinter.pp obj, colored_str
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
                colored_str.chomp
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            end
         | 
    
        data/lib/pry-moves/pry_ext.rb
    CHANGED
    
    | @@ -69,12 +69,19 @@ Pry::Command::Whereami.class_eval do | |
| 69 69 |  | 
| 70 70 | 
             
              def location
         | 
| 71 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
         | 
| 72 | 
            +
                me = PryMoves::Painter.colorize me if me
         | 
| 77 73 | 
             
                file = defined?(Rails) ? @file.gsub(Rails.root.to_s, '') : @file
         | 
| 78 74 | 
             
                "#{file}:#{@line} #{me}"
         | 
| 79 75 | 
             
              end
         | 
| 80 76 | 
             
            end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            Pry.config.marker = "=>"
         | 
| 79 | 
            +
            Pry::Code::LOC.class_eval do
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              def add_marker(marker_lineno)
         | 
| 82 | 
            +
                marker = lineno == marker_lineno ?
         | 
| 83 | 
            +
                   Pry.config.marker : "  "
         | 
| 84 | 
            +
                tuple[0] = " #{marker} #{ line }"
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            end
         | 
| @@ -10,6 +10,8 @@ class PryWrapper | |
| 10 10 | 
             
              def run(&block)
         | 
| 11 11 | 
             
                PryMoves.lock
         | 
| 12 12 |  | 
| 13 | 
            +
                Pry.config.marker = "⛔️ " if @pry_start_options[:exit_from_method]
         | 
| 14 | 
            +
             | 
| 13 15 | 
             
                return_value = nil
         | 
| 14 16 | 
             
                PryMoves.is_open = true
         | 
| 15 17 | 
             
                @command = catch(:breakout_nav) do      # Coordinates with PryMoves::Commands
         | 
| @@ -17,6 +19,7 @@ class PryWrapper | |
| 17 19 | 
             
                  nil    # Nothing thrown == no navigational command
         | 
| 18 20 | 
             
                end
         | 
| 19 21 | 
             
                PryMoves.is_open = false
         | 
| 22 | 
            +
                Pry.config.marker = "=>"
         | 
| 20 23 |  | 
| 21 24 | 
             
                if @command
         | 
| 22 25 | 
             
                  trace_command
         | 
| @@ -44,7 +47,16 @@ class PryWrapper | |
| 44 47 | 
             
                #puts "##wrap debug"
         | 
| 45 48 | 
             
                #puts "CALLER:\n#{caller.join "\n"}\n"
         | 
| 46 49 | 
             
                #      Thread.abort_on_exception=true
         | 
| 50 | 
            +
                parent_thread = Thread.current
         | 
| 47 51 | 
             
                Thread.new do
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  # copy non-pry thread's properties
         | 
| 54 | 
            +
                  parent_thread.keys.select do |k|
         | 
| 55 | 
            +
                    !k.to_s.include?('pry')
         | 
| 56 | 
            +
                  end.each do |k|
         | 
| 57 | 
            +
                    Thread.current[k] = parent_thread[k]
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 48 60 | 
             
                  Thread.current[:pry_moves_debug] = true
         | 
| 49 61 | 
             
                  #@command[:binding].eval 'puts "###########"'
         | 
| 50 62 | 
             
                  start_tracing
         | 
    
        data/lib/pry-moves/tracer.rb
    CHANGED
    
    | @@ -10,15 +10,19 @@ class Tracer | |
| 10 10 |  | 
| 11 11 | 
             
              def trace
         | 
| 12 12 | 
             
                @action = @command[:action]
         | 
| 13 | 
            +
                #puts "COMMAND: #{@action}"
         | 
| 13 14 | 
             
                binding_ = @command[:binding]
         | 
| 14 15 | 
             
                set_traced_method binding_
         | 
| 15 16 |  | 
| 17 | 
            +
                @recursion_level -= 1 if @pry_start_options.delete :exit_from_method
         | 
| 18 | 
            +
             | 
| 16 19 | 
             
                case @action
         | 
| 17 20 | 
             
                when :step
         | 
| 18 21 | 
             
                  @step_info_funcs = nil
         | 
| 19 22 | 
             
                  if (func = @command[:param])
         | 
| 20 23 | 
             
                    @step_info_funcs = [func]
         | 
| 21 24 | 
             
                    @step_info_funcs << 'initialize' if func == 'new'
         | 
| 25 | 
            +
                    @caller_digest = frame_digest(binding_)
         | 
| 22 26 | 
             
                  end
         | 
| 23 27 | 
             
                when :finish
         | 
| 24 28 | 
             
                  @method_to_finish = @method
         | 
| @@ -62,6 +66,7 @@ class Tracer | |
| 62 66 | 
             
                  set_method({
         | 
| 63 67 | 
             
                   file: source[0],
         | 
| 64 68 | 
             
                   start: source[1],
         | 
| 69 | 
            +
                   name: method.name,
         | 
| 65 70 | 
             
                   end: (source[1] + method.source.count("\n") - 1)
         | 
| 66 71 | 
             
                 })
         | 
| 67 72 | 
             
                else
         | 
| @@ -91,8 +96,11 @@ class Tracer | |
| 91 96 | 
             
                    Pry.start(binding_, @pry_start_options)
         | 
| 92 97 |  | 
| 93 98 | 
             
                  # for cases when currently traced method called more times recursively
         | 
| 94 | 
            -
                  elsif %w(call return).include?(event) and within_current_method?(file, line)
         | 
| 95 | 
            -
             | 
| 99 | 
            +
                  elsif %w(call return).include?(event) and within_current_method?(file, line) and
         | 
| 100 | 
            +
                      @method[:name] == id # fix for bug in traced_method: return for dynamic methods has line number inside of caller
         | 
| 101 | 
            +
                    delta = event == 'call' ? 1 : -1
         | 
| 102 | 
            +
                    #puts "recursion #{event}: #{delta}; changed: #{@recursion_level} => #{@recursion_level + delta}"
         | 
| 103 | 
            +
                    @recursion_level += delta
         | 
| 96 104 | 
             
                  end
         | 
| 97 105 | 
             
                end
         | 
| 98 106 | 
             
              end
         | 
| @@ -100,8 +108,13 @@ class Tracer | |
| 100 108 | 
             
              def trace_step(event, file, line, binding_)
         | 
| 101 109 | 
             
                return unless event == 'line'
         | 
| 102 110 | 
             
                if @step_info_funcs
         | 
| 111 | 
            +
                  if @recursion_level < 0
         | 
| 112 | 
            +
                    pry_puts "⚠️  Unable to find function with name #{@step_info_funcs.join(',')}"
         | 
| 113 | 
            +
                    return true
         | 
| 114 | 
            +
                  end
         | 
| 103 115 | 
             
                  method = binding_.eval('__callee__').to_s
         | 
| 104 | 
            -
                  @step_info_funcs.any? {|pattern| method.include? pattern}
         | 
| 116 | 
            +
                  @step_info_funcs.any? {|pattern| method.include? pattern} and
         | 
| 117 | 
            +
                    @caller_digest == frame_digest(binding_.of_caller(3 + 1))
         | 
| 105 118 | 
             
                else
         | 
| 106 119 | 
             
                  true
         | 
| 107 120 | 
             
                end
         | 
| @@ -115,9 +128,16 @@ class Tracer | |
| 115 128 | 
             
                  throw :skip if event == 'call'
         | 
| 116 129 | 
             
                end
         | 
| 117 130 |  | 
| 118 | 
            -
                 | 
| 119 | 
            -
                  @recursion_level == 0 and
         | 
| 131 | 
            +
                if @recursion_level == 0 and
         | 
| 120 132 | 
             
                  within_current_method?(file, line)
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  return true if event == 'line'
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                  if event == 'return' and before_end?(line)
         | 
| 137 | 
            +
                    @pry_start_options[:exit_from_method] = true
         | 
| 138 | 
            +
                    true
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                end
         | 
| 121 141 | 
             
              end
         | 
| 122 142 |  | 
| 123 143 | 
             
              def trace_finish(event, file, line, binding_)
         | 
| @@ -126,8 +146,9 @@ class Tracer | |
| 126 146 |  | 
| 127 147 | 
             
                # for finishing blocks inside current method
         | 
| 128 148 | 
             
                if @block_to_finish
         | 
| 129 | 
            -
                   | 
| 130 | 
            -
             | 
| 149 | 
            +
                  @recursion_level == 0 and
         | 
| 150 | 
            +
                    within_current_method?(file, line) and
         | 
| 151 | 
            +
                    @block_to_finish != frame_digest(binding_.of_caller(3))
         | 
| 131 152 | 
             
                end
         | 
| 132 153 | 
             
              end
         | 
| 133 154 |  | 
| @@ -153,5 +174,13 @@ class Tracer | |
| 153 174 | 
             
                )
         | 
| 154 175 | 
             
              end
         | 
| 155 176 |  | 
| 177 | 
            +
              def before_end?(line)
         | 
| 178 | 
            +
                @method[:end] and line < @method[:end]
         | 
| 179 | 
            +
              end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
              def pry_puts(text)
         | 
| 182 | 
            +
                @command[:pry].output.puts text
         | 
| 183 | 
            +
              end
         | 
| 184 | 
            +
             | 
| 156 185 | 
             
            end
         | 
| 157 186 | 
             
            end
         | 
    
        data/lib/pry-moves/version.rb
    CHANGED
    
    
    
        data/lib/pry-moves.rb
    CHANGED
    
    | @@ -6,6 +6,7 @@ require 'pry-moves/tracer' | |
| 6 6 | 
             
            require 'pry-moves/backtrace'
         | 
| 7 7 | 
             
            require 'pry-moves/watch'
         | 
| 8 8 | 
             
            require 'pry-moves/helpers'
         | 
| 9 | 
            +
            require 'pry-moves/painter'
         | 
| 9 10 |  | 
| 10 11 | 
             
            require 'pry-stack_explorer/pry-stack_explorer'
         | 
| 11 12 |  | 
| @@ -43,7 +44,13 @@ module PryMoves | |
| 43 44 | 
             
              end
         | 
| 44 45 |  | 
| 45 46 | 
             
              def synchronize_threads
         | 
| 46 | 
            -
                 | 
| 47 | 
            +
                return if Thread.current[:pry_moves_debug]
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                semaphore.synchronize {}
         | 
| 50 | 
            +
              rescue ThreadError => e
         | 
| 51 | 
            +
                puts e.backtrace.reverse
         | 
| 52 | 
            +
                puts e
         | 
| 53 | 
            +
                raise e
         | 
| 47 54 | 
             
              end
         | 
| 48 55 |  | 
| 49 56 | 
             
              # Reference to currently running pry-remote server. Used by the tracer.
         | 
| @@ -4,13 +4,10 @@ module PryStackExplorer | |
| 4 4 |  | 
| 5 5 | 
             
                def caller_bindings(target)
         | 
| 6 6 | 
             
                  bindings = binding.callers
         | 
| 7 | 
            -
             | 
| 7 | 
            +
                  pre_callers = Thread.current[:pre_callers]
         | 
| 8 | 
            +
                  bindings = bindings + pre_callers if pre_callers
         | 
| 8 9 | 
             
                  bindings = remove_internal_frames(bindings)
         | 
| 9 | 
            -
                  bindings = remove_debugger_frames(bindings)
         | 
| 10 | 
            -
                  bindings = bindings.drop(1) if pry_method_frame?(bindings.first)
         | 
| 11 | 
            -
             | 
| 12 10 | 
             
                  mark_vapid_frames(bindings)
         | 
| 13 | 
            -
             | 
| 14 11 | 
             
                  bindings
         | 
| 15 12 | 
             
                end
         | 
| 16 13 |  | 
| @@ -63,44 +60,24 @@ module PryStackExplorer | |
| 63 60 |  | 
| 64 61 | 
             
                # remove internal frames related to setting up the session
         | 
| 65 62 | 
             
                def remove_internal_frames(bindings)
         | 
| 66 | 
            -
                   | 
| 67 | 
            -
                   | 
| 68 | 
            -
             | 
| 69 | 
            -
                   | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
                   | 
| 74 | 
            -
             | 
| 75 | 
            -
                  bindings.drop(start_frame_index + 1)
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                # remove pry-nav / pry-debugger / pry-byebug frames
         | 
| 79 | 
            -
                def remove_debugger_frames(bindings)
         | 
| 80 | 
            -
                  bindings.drop_while { |b| b.eval("__FILE__") =~ /\/pry-/ }
         | 
| 81 | 
            -
                end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                # binding.pry frame
         | 
| 84 | 
            -
                # @return [Boolean]
         | 
| 85 | 
            -
                def pry_method_frame?(binding)
         | 
| 86 | 
            -
                  safe_send(binding.eval("__method__"), :==, :pry)
         | 
| 63 | 
            +
                  i = top_internal_frame_index(bindings)
         | 
| 64 | 
            +
                  # DEBUG:
         | 
| 65 | 
            +
                  #bindings.each_with_index do |b, index|
         | 
| 66 | 
            +
                  #  puts "#{index}: #{b.eval("self.class")} #{b.eval("__method__")}"
         | 
| 67 | 
            +
                  #end
         | 
| 68 | 
            +
                  #puts "FOUND top internal frame: #{bindings.size} => #{i}"
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  bindings.drop i+1
         | 
| 87 71 | 
             
                end
         | 
| 88 72 |  | 
| 89 | 
            -
                 | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
                # @return [Array<Array<Binding, Fixnum>>]
         | 
| 99 | 
            -
                def internal_frames_with_indices(bindings)
         | 
| 100 | 
            -
                  bindings.each_with_index.select do |b, i|
         | 
| 101 | 
            -
                    b.frame_type == :method &&
         | 
| 102 | 
            -
                      safe_send(b.eval("self"), :equal?, Pry) &&
         | 
| 103 | 
            -
                      safe_send(b.eval("__method__"), :==, :start)
         | 
| 73 | 
            +
                def top_internal_frame_index(bindings)
         | 
| 74 | 
            +
                  bindings.rindex do |b|
         | 
| 75 | 
            +
                    if b.frame_type == :method
         | 
| 76 | 
            +
                      self_, method = b.eval("self"), b.eval("__method__")
         | 
| 77 | 
            +
                      self_.equal?(Pry) && method == :start ||
         | 
| 78 | 
            +
                        self_.class == Binding && method == :pry ||
         | 
| 79 | 
            +
                        self_.class == PryMoves::Tracer && method == :tracing_func
         | 
| 80 | 
            +
                    end
         | 
| 104 81 | 
             
                  end
         | 
| 105 82 | 
             
                end
         | 
| 106 83 |  | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            PATH
         | 
| 2 | 
            +
              remote: ..
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                pry-moves (0.1.5)
         | 
| 5 | 
            +
                  binding_of_caller (>= 0.7)
         | 
| 6 | 
            +
                  pry (>= 0.9.10, < 0.11.0)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            GEM
         | 
| 9 | 
            +
              remote: https://rubygems.org/
         | 
| 10 | 
            +
              specs:
         | 
| 11 | 
            +
                binding_of_caller (0.7.2)
         | 
| 12 | 
            +
                  debug_inspector (>= 0.0.1)
         | 
| 13 | 
            +
                coderay (1.1.1)
         | 
| 14 | 
            +
                debug_inspector (0.0.3)
         | 
| 15 | 
            +
                method_source (0.8.2)
         | 
| 16 | 
            +
                pry (0.10.4)
         | 
| 17 | 
            +
                  coderay (~> 1.1.0)
         | 
| 18 | 
            +
                  method_source (~> 0.8.1)
         | 
| 19 | 
            +
                  slop (~> 3.4)
         | 
| 20 | 
            +
                slop (3.6.0)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            PLATFORMS
         | 
| 23 | 
            +
              ruby
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            DEPENDENCIES
         | 
| 26 | 
            +
              pry-moves!
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            BUNDLED WITH
         | 
| 29 | 
            +
               1.14.5
         | 
| @@ -0,0 +1,90 @@ | |
| 1 | 
            +
            # Rails has such type of definitions
         | 
| 2 | 
            +
            Fixnum.send(:alias_method, :to_default_s, :to_s)
         | 
| 3 | 
            +
            Fixnum.send(:define_method, :to_s) do |*args|
         | 
| 4 | 
            +
              to_default_s(*args)
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class Playground
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def basic_next
         | 
| 10 | 
            +
                dummy = :basic_1
         | 
| 11 | 
            +
                binding.pry # basic next stop
         | 
| 12 | 
            +
                :basic_2 # next step
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def step_into
         | 
| 16 | 
            +
                binding.pry # step_into stop
         | 
| 17 | 
            +
                something_inside # point to step inside
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def continue
         | 
| 21 | 
            +
                binding.pry # first stop
         | 
| 22 | 
            +
                dummy = :something
         | 
| 23 | 
            +
                binding.pry # second stop
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def recursion(depth = 0)
         | 
| 27 | 
            +
                str = 3.to_s # here fired event "return" if "to_s" patched
         | 
| 28 | 
            +
                binding.pry if depth == 0
         | 
| 29 | 
            +
                recursion depth + 1 if depth < 2 # next step
         | 
| 30 | 
            +
                :ok # should stop here after 2 next-s
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              def step_by_name
         | 
| 34 | 
            +
                binding.pry # stop in step_by_name
         | 
| 35 | 
            +
                level_a.level_c(:target)
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def step_by_name_wrap
         | 
| 39 | 
            +
                step_by_name
         | 
| 40 | 
            +
                :after_step_by_name # after_step_by_name
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def level_a
         | 
| 44 | 
            +
                level_b # inside of level_a
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def level_b
         | 
| 48 | 
            +
                hide_from_stack = true
         | 
| 49 | 
            +
                level_c
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              def level_c(param = nil)
         | 
| 53 | 
            +
                binding.pry # stop in level_c
         | 
| 54 | 
            +
                self
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              def with_simple_block
         | 
| 58 | 
            +
                binding.pry # stop in with_simple_block
         | 
| 59 | 
            +
                iterator do |i|
         | 
| 60 | 
            +
                  dummy = 1 # inside block
         | 
| 61 | 
            +
                  dummy = 2
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
                :after_block # after block
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              def zaloop(pass = :root)
         | 
| 67 | 
            +
                binding.pry if pass == :root # stop in zaloop
         | 
| 68 | 
            +
                iterator do |i|
         | 
| 69 | 
            +
                  dummy = 1 # inside block
         | 
| 70 | 
            +
                  zaloop i if pass == :root
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
                :after_block # after block
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              private
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              def iterator
         | 
| 78 | 
            +
                2.times do |i|
         | 
| 79 | 
            +
                  dummy = :pre_yield # pre_yield
         | 
| 80 | 
            +
                  yield i
         | 
| 81 | 
            +
                  :post_yield # post_yield
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              def something_inside
         | 
| 86 | 
            +
                :something # some internal line
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            end
         | 
| 90 | 
            +
             | 
    
        data/playground/sand.rb
    CHANGED
    
    | @@ -1,11 +1,6 @@ | |
| 1 1 | 
             
            require 'pry-moves'
         | 
| 2 | 
            -
            #require 'pry-nav'
         | 
| 3 2 | 
             
            require './tracer.rb'
         | 
| 4 3 |  | 
| 5 | 
            -
            def debucher?
         | 
| 6 | 
            -
              binding.pry
         | 
| 7 | 
            -
              true
         | 
| 8 | 
            -
            end
         | 
| 9 4 |  | 
| 10 5 | 
             
            def fi(param)
         | 
| 11 6 | 
             
              a = 2 + 1
         | 
| @@ -30,19 +25,20 @@ class A | |
| 30 25 | 
             
              end
         | 
| 31 26 |  | 
| 32 27 | 
             
              def cc
         | 
| 28 | 
            +
                koko = :love
         | 
| 33 29 | 
             
                binding.pry
         | 
| 30 | 
            +
                return if true
         | 
| 31 | 
            +
                puts :two
         | 
| 34 32 | 
             
              end
         | 
| 33 | 
            +
              alias cc_al cc
         | 
| 35 34 |  | 
| 36 35 | 
             
            end
         | 
| 37 36 |  | 
| 38 | 
            -
            #trace_events
         | 
| 39 | 
            -
             | 
| 40 | 
            -
            a = 1123
         | 
| 41 | 
            -
            b = binding
         | 
| 42 | 
            -
             | 
| 43 37 | 
             
            puts :prepare
         | 
| 44 38 |  | 
| 45 | 
            -
             | 
| 39 | 
            +
            A.new.cc_al
         | 
| 40 | 
            +
            A.new.cc_al
         | 
| 41 | 
            +
            A.new.cc_al
         | 
| 46 42 |  | 
| 47 43 | 
             
            a = A.new.aa.bb.cc
         | 
| 48 44 |  | 
    
        data/playground/threads.rb
    CHANGED
    
    | @@ -2,25 +2,28 @@ require 'pry-moves' | |
| 2 2 |  | 
| 3 3 | 
             
            Thread.current[:name] = 'main'
         | 
| 4 4 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
              sleep 0.2
         | 
| 8 | 
            -
              puts 'a'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            def inside_thread
         | 
| 9 7 | 
             
              binding.pry
         | 
| 10 | 
            -
              puts 'aaaa'
         | 
| 11 | 
            -
              sleep 1
         | 
| 12 8 | 
             
              puts 'aaa'
         | 
| 13 9 | 
             
            end
         | 
| 14 10 |  | 
| 15 | 
            -
             | 
| 16 | 
            -
               | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 11 | 
            +
            def aaa
         | 
| 12 | 
            +
              pre_callers = binding.callers +
         | 
| 13 | 
            +
                (Thread.current[:pre_callers] || [])
         | 
| 14 | 
            +
              a = Thread.new do
         | 
| 15 | 
            +
                # что можно сделать - записать в текущий тред ссылку на биндинг
         | 
| 16 | 
            +
                # предыдущего треда. А если цепочка тредов - то как? Можно прямо там собирать каллеров предыдущего треда... ??
         | 
| 17 | 
            +
                Thread.current[:pre_callers] = pre_callers
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                Thread.current[:name] = 'a'
         | 
| 20 | 
            +
                inside_thread
         | 
| 19 21 | 
             
              end
         | 
| 20 | 
            -
               | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 22 | 
            +
              a.join
         | 
| 23 | 
            +
            end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            def bbb
         | 
| 26 | 
            +
              aaa
         | 
| 23 27 | 
             
            end
         | 
| 24 28 |  | 
| 25 | 
            -
             | 
| 26 | 
            -
            b.join
         | 
| 29 | 
            +
            bbb
         | 
    
        data/pry-moves.gemspec
    CHANGED
    
    | @@ -20,6 +20,6 @@ Gem::Specification.new do |gem| | |
| 20 20 | 
             
              # Dependencies
         | 
| 21 21 | 
             
              gem.required_ruby_version = '>= 1.8.7'
         | 
| 22 22 | 
             
              gem.add_runtime_dependency 'pry', '>= 0.9.10', '< 0.11.0'
         | 
| 23 | 
            -
              gem.add_runtime_dependency 'binding_of_caller', ' | 
| 23 | 
            +
              gem.add_runtime_dependency 'binding_of_caller', '~> 0.7'
         | 
| 24 24 | 
             
              gem.add_development_dependency 'pry-remote', '~> 0.1.6'
         | 
| 25 25 | 
             
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            require_relative 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'PryMoves Commands' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              it 'should backtrace' do
         | 
| 6 | 
            +
                breakpoints [
         | 
| 7 | 
            +
                  [nil, 'stop in level_c'],
         | 
| 8 | 
            +
                  ['bt', lambda{|b, out|
         | 
| 9 | 
            +
                    lines = out.split("\n").reverse
         | 
| 10 | 
            +
                    expect(lines[0]).to end_with 'Playground#level_c(param=?) :method'
         | 
| 11 | 
            +
                    expect(lines[1]).to end_with 'Playground#level_a() :method'
         | 
| 12 | 
            +
                    expect(lines[2]).to include 'Playground:'
         | 
| 13 | 
            +
                    expect(lines[3]).to end_with ':block'
         | 
| 14 | 
            +
                    expect(lines[4]).to include 'RSpec::ExampleGroups'
         | 
| 15 | 
            +
                    expect(lines.count).to be 5
         | 
| 16 | 
            +
                  }],
         | 
| 17 | 
            +
                  ['bt all', lambda{|b, out|
         | 
| 18 | 
            +
                    lines = out.split("\n").reverse
         | 
| 19 | 
            +
                    # show hidden frame
         | 
| 20 | 
            +
                    expect(lines[1]).to end_with 'Playground#level_b() :method'
         | 
| 21 | 
            +
                    expect(lines.count).to be 6
         | 
| 22 | 
            +
                  }],
         | 
| 23 | 
            +
                  ['bt 2', lambda{|b, out|
         | 
| 24 | 
            +
                    lines = out.split("\n").reverse
         | 
| 25 | 
            +
                    expect(lines[0]).to end_with 'Playground#level_c(param=?) :method'
         | 
| 26 | 
            +
                    expect(lines[1]).to end_with 'Playground#level_a() :method'
         | 
| 27 | 
            +
                    expect(lines[3]).to start_with 'Latest 2 lines'
         | 
| 28 | 
            +
                    expect(lines.count).to be 4
         | 
| 29 | 
            +
                  }],
         | 
| 30 | 
            +
                ]
         | 
| 31 | 
            +
                Playground.new.level_a
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            end
         | 
    
        data/spec/blocks_spec.rb
    ADDED
    
    | @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            require_relative 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'PryMoves Commands' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
             | 
| 6 | 
            +
              it 'should go next over blocks' do
         | 
| 7 | 
            +
                breakpoints [
         | 
| 8 | 
            +
                  [nil, 'stop in zaloop'],
         | 
| 9 | 
            +
                  ['n', ''],
         | 
| 10 | 
            +
                  # repeat commands
         | 
| 11 | 
            +
                  ['', 'inside block'],
         | 
| 12 | 
            +
                  ['', nil],
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  ['s', 'stop in zaloop'],
         | 
| 15 | 
            +
                  ['n', nil],
         | 
| 16 | 
            +
                  ['', 'inside block'],
         | 
| 17 | 
            +
                  ['pass', {out: '=> 0'}],
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  ['f', 'after block'],
         | 
| 20 | 
            +
                  ['pass', {out: '=> 0'}],
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  ['f', 'post_yield'], # Тут хорошо бы, чтобы сразу шёл на "after block",
         | 
| 23 | 
            +
                  # но пока и не понятно, как это угадать
         | 
| 24 | 
            +
                  ['f', 'after block'],
         | 
| 25 | 
            +
                  ['pass', {out: '=> :root'}],
         | 
| 26 | 
            +
                ]
         | 
| 27 | 
            +
                Playground.new.zaloop
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              it 'should finish simple block' do
         | 
| 31 | 
            +
                breakpoints [
         | 
| 32 | 
            +
                  [nil, 'stop in with_simple_block'],
         | 
| 33 | 
            +
                  ['n', ''],
         | 
| 34 | 
            +
                  ['', 'inside block'],
         | 
| 35 | 
            +
                  ['f', 'after block']
         | 
| 36 | 
            +
                ]
         | 
| 37 | 
            +
                Playground.new.with_simple_block
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              it 'should finish block with sub-calls' do
         | 
| 41 | 
            +
                breakpoints [
         | 
| 42 | 
            +
                  [nil, 'stop in zaloop'],
         | 
| 43 | 
            +
                  ['n', ''],
         | 
| 44 | 
            +
                  ['', 'inside block'],
         | 
| 45 | 
            +
                  ['f', 'after block'],
         | 
| 46 | 
            +
                  ['pass', {out: '=> :root'}],
         | 
| 47 | 
            +
                ]
         | 
| 48 | 
            +
                Playground.new.zaloop
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
             | 
| 52 | 
            +
            end
         | 
| @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            require_relative 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'PryMoves Commands' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              it 'should make one step next' do
         | 
| 6 | 
            +
                breakpoints [
         | 
| 7 | 
            +
                  [nil, 'basic next stop'],
         | 
| 8 | 
            +
                  ['n', 'next step'],
         | 
| 9 | 
            +
                ]
         | 
| 10 | 
            +
                Playground.new.basic_next
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it 'should stop on second breakpoint' do
         | 
| 14 | 
            +
                breakpoints [
         | 
| 15 | 
            +
                  [nil, 'first stop'],
         | 
| 16 | 
            +
                  ['c', 'second stop'],
         | 
| 17 | 
            +
                ]
         | 
| 18 | 
            +
                Playground.new.continue
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              it 'should step into func and walk over stack' do
         | 
| 22 | 
            +
                breakpoints [
         | 
| 23 | 
            +
                  [nil, 'step_into stop'],
         | 
| 24 | 
            +
                  ['s', 'point to step inside'],
         | 
| 25 | 
            +
                  ['s', 'some internal line'],
         | 
| 26 | 
            +
                  ['up', 'point to step inside'],
         | 
| 27 | 
            +
                  ['up', nil ],
         | 
| 28 | 
            +
                  ['up', {out_includes: 'top of stack'} ],
         | 
| 29 | 
            +
                  ['down', nil ],
         | 
| 30 | 
            +
                  ['down', 'some internal line'],
         | 
| 31 | 
            +
                  ['down', {out_includes: 'bottom of stack'} ],
         | 
| 32 | 
            +
                ]
         | 
| 33 | 
            +
                Playground.new.step_into
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              it 'should step into func by name' do
         | 
| 37 | 
            +
                breakpoints [
         | 
| 38 | 
            +
                  [nil, 'stop in step_by_name'],
         | 
| 39 | 
            +
                  ['s level_c', 'stop in level_c'],
         | 
| 40 | 
            +
                  ['param', {out: '=> :target'}],
         | 
| 41 | 
            +
                  ['n', nil],
         | 
| 42 | 
            +
                ]
         | 
| 43 | 
            +
                Playground.new.step_by_name
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              it 'should stop after inability to step into func by name' do
         | 
| 47 | 
            +
                breakpoints [
         | 
| 48 | 
            +
                  [nil, 'stop in step_by_name'],
         | 
| 49 | 
            +
                  ['s absent_function', 'after_step_by_name'],
         | 
| 50 | 
            +
                ]
         | 
| 51 | 
            +
                Playground.new.step_by_name_wrap
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              it 'should go next over recursion calls' do
         | 
| 55 | 
            +
                breakpoints [
         | 
| 56 | 
            +
                  [nil, nil],
         | 
| 57 | 
            +
                  ['n', 'next step'],
         | 
| 58 | 
            +
                  ['n', 'should stop here after 2 next-s'],
         | 
| 59 | 
            +
                  ['depth', {out: '=> 0'}],
         | 
| 60 | 
            +
                ]
         | 
| 61 | 
            +
                Playground.new.recursion
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              it 'should debug' do
         | 
| 65 | 
            +
                breakpoints [
         | 
| 66 | 
            +
                  [nil, 'basic next stop'],
         | 
| 67 | 
            +
                  ['debug level_a', 'inside of level_a'],
         | 
| 68 | 
            +
                  ['n', 'basic next stop'],
         | 
| 69 | 
            +
                ]
         | 
| 70 | 
            +
                Playground.new.basic_next
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            end
         | 
| @@ -0,0 +1,89 @@ | |
| 1 | 
            +
            module PryDebugger
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              module Breakpoints
         | 
| 4 | 
            +
                def breakpoints(breakpoints)
         | 
| 5 | 
            +
                  breakpoints.each_with_index do |b, index|
         | 
| 6 | 
            +
                    next_b = breakpoints[index+1]
         | 
| 7 | 
            +
                    b[0] = next_b ? next_b[0] : nil
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  PryDebugger.breakpoints =
         | 
| 11 | 
            +
                      breakpoints.map do |b|
         | 
| 12 | 
            +
                        Proc.new do |label, binding_, output|
         | 
| 13 | 
            +
                          compare(b[1], label, binding_, output)
         | 
| 14 | 
            +
                          b[0]
         | 
| 15 | 
            +
                        end
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def compare(subj, label, binding_, output)
         | 
| 20 | 
            +
                  if subj.is_a? Proc
         | 
| 21 | 
            +
                    subj.call binding_, output
         | 
| 22 | 
            +
                  elsif subj.is_a? Hash
         | 
| 23 | 
            +
                    if subj[:out_includes]
         | 
| 24 | 
            +
                      expect(output).to include subj[:out_includes]
         | 
| 25 | 
            +
                    else
         | 
| 26 | 
            +
                      expect(output).to eq subj[:out]
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  elsif not subj.nil?
         | 
| 29 | 
            +
                    expect(label).to eq subj
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              class InputPipe
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def readline(*args)
         | 
| 37 | 
            +
                  repl_binding = binding.callers[1]
         | 
| 38 | 
            +
                  pry_ = repl_binding.eval('@pry')
         | 
| 39 | 
            +
                  binding_ = pry_.current_binding
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  next_cmd = PryDebugger.enter_breakpoint binding_
         | 
| 42 | 
            +
                  next_cmd || 'c'
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              class OutputPipe < StringIO
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def print(*args)
         | 
| 50 | 
            +
                  #STDOUT.print *args
         | 
| 51 | 
            +
                  super
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def take_away
         | 
| 55 | 
            +
                  result = string.clone
         | 
| 56 | 
            +
                  truncate(0)
         | 
| 57 | 
            +
                  rewind
         | 
| 58 | 
            +
                  result.gsub(/\e\[([;\d]+)?m/, '')
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              extend self
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              def inject
         | 
| 66 | 
            +
                Pry.config.input = InputPipe.new
         | 
| 67 | 
            +
                @output = OutputPipe.new
         | 
| 68 | 
            +
                Pry.config.output = @output
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              def breakpoints
         | 
| 72 | 
            +
                @breakpoints_procs
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              def breakpoints=(breakpoints)
         | 
| 76 | 
            +
                @breakpoints_procs = breakpoints
         | 
| 77 | 
            +
                @breakpoint_call = 0
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              def enter_breakpoint(binding_)
         | 
| 81 | 
            +
                raise 'Next breakpoint handler missing' if @breakpoints_procs.size == 0
         | 
| 82 | 
            +
                #puts (@breakpoint_call += 1)
         | 
| 83 | 
            +
                output = @output.take_away
         | 
| 84 | 
            +
                output.match(/^ => .*#(.*)/)
         | 
| 85 | 
            +
                label = ($1 || '').strip
         | 
| 86 | 
            +
                @breakpoints_procs.shift.call label, binding_, output.strip
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            require 'pry'
         | 
| 2 | 
            +
            require_relative 'pry_debugger'
         | 
| 3 | 
            +
            require_relative '../playground/playground.rb'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            PryDebugger.inject unless ENV['DEBUG']
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            RSpec.configure do |config|
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              config.include PryDebugger::Breakpoints
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              config.before(:example) do
         | 
| 12 | 
            +
                PryMoves.unlock if PryMoves.semaphore.locked?
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              config.after(:example) do |example|
         | 
| 16 | 
            +
                unless example.exception
         | 
| 17 | 
            +
                  expect(PryDebugger.breakpoints.count).to be(0), "not all breakpoints launched"
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            RSpec::Core::BacktraceFormatter.class_eval do
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              alias :native_backtrace_line :backtrace_line
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              def format_backtrace(backtrace, options={})
         | 
| 28 | 
            +
                return [] unless backtrace
         | 
| 29 | 
            +
                return backtrace if options[:full_backtrace] || backtrace.empty?
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                @lines = 0
         | 
| 32 | 
            +
                backtrace.map { |l| backtrace_line(l) }.compact
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              FILTER = /(\/gems\/|\/lib\/pry\/|spec\/pry_debugger\.rb)/
         | 
| 36 | 
            +
              def backtrace_line(line)
         | 
| 37 | 
            +
                return if @lines == 3 and not ENV['TRACE']
         | 
| 38 | 
            +
                #return if line.match FILTER
         | 
| 39 | 
            +
                return unless line.include? '/playground.rb'
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                result = native_backtrace_line(line)
         | 
| 42 | 
            +
                if result
         | 
| 43 | 
            +
                  @lines += 1 if @lines
         | 
| 44 | 
            +
                  result[0 .. 1] == './' ? result[2 .. -1] : result
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            Pry::REPL.class_eval do
         | 
| 51 | 
            +
              def handle_read_errors
         | 
| 52 | 
            +
                yield
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: pry-moves
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.5
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - garmoshka-mo
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2018-05-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: pry
         | 
| @@ -34,14 +34,14 @@ dependencies: | |
| 34 34 | 
             
              name: binding_of_caller
         | 
| 35 35 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 36 36 | 
             
                requirements:
         | 
| 37 | 
            -
                - - " | 
| 37 | 
            +
                - - "~>"
         | 
| 38 38 | 
             
                  - !ruby/object:Gem::Version
         | 
| 39 39 | 
             
                    version: '0.7'
         | 
| 40 40 | 
             
              type: :runtime
         | 
| 41 41 | 
             
              prerelease: false
         | 
| 42 42 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 43 43 | 
             
                requirements:
         | 
| 44 | 
            -
                - - " | 
| 44 | 
            +
                - - "~>"
         | 
| 45 45 | 
             
                  - !ruby/object:Gem::Version
         | 
| 46 46 | 
             
                    version: '0.7'
         | 
| 47 47 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -67,6 +67,7 @@ extra_rdoc_files: [] | |
| 67 67 | 
             
            files:
         | 
| 68 68 | 
             
            - ".gitignore"
         | 
| 69 69 | 
             
            - Gemfile
         | 
| 70 | 
            +
            - Gemfile.lock
         | 
| 70 71 | 
             
            - LICENSE
         | 
| 71 72 | 
             
            - README.md
         | 
| 72 73 | 
             
            - Rakefile
         | 
| @@ -76,6 +77,7 @@ files: | |
| 76 77 | 
             
            - lib/pry-moves/cli.rb
         | 
| 77 78 | 
             
            - lib/pry-moves/commands.rb
         | 
| 78 79 | 
             
            - lib/pry-moves/helpers.rb
         | 
| 80 | 
            +
            - lib/pry-moves/painter.rb
         | 
| 79 81 | 
             
            - lib/pry-moves/pry_ext.rb
         | 
| 80 82 | 
             
            - lib/pry-moves/pry_remote_ext.rb
         | 
| 81 83 | 
             
            - lib/pry-moves/pry_wrapper.rb
         | 
| @@ -87,13 +89,20 @@ files: | |
| 87 89 | 
             
            - lib/pry-stack_explorer/pry-stack_explorer.rb
         | 
| 88 90 | 
             
            - lib/pry-stack_explorer/when_started_hook.rb
         | 
| 89 91 | 
             
            - playground/Gemfile
         | 
| 92 | 
            +
            - playground/Gemfile.lock
         | 
| 90 93 | 
             
            - playground/README.md
         | 
| 91 94 | 
             
            - playground/demo.rb
         | 
| 95 | 
            +
            - playground/playground.rb
         | 
| 92 96 | 
             
            - playground/recursions.rb
         | 
| 93 97 | 
             
            - playground/sand.rb
         | 
| 94 98 | 
             
            - playground/threads.rb
         | 
| 95 99 | 
             
            - playground/tracer.rb
         | 
| 96 100 | 
             
            - pry-moves.gemspec
         | 
| 101 | 
            +
            - spec/backtrace_spec.rb
         | 
| 102 | 
            +
            - spec/blocks_spec.rb
         | 
| 103 | 
            +
            - spec/commands_spec.rb
         | 
| 104 | 
            +
            - spec/pry_debugger.rb
         | 
| 105 | 
            +
            - spec/spec_helper.rb
         | 
| 97 106 | 
             
            homepage: https://github.com/garmoshka-mo/pry-moves
         | 
| 98 107 | 
             
            licenses:
         | 
| 99 108 | 
             
            - MIT
         | 
| @@ -118,4 +127,9 @@ rubygems_version: 2.6.8 | |
| 118 127 | 
             
            signing_key: 
         | 
| 119 128 | 
             
            specification_version: 4
         | 
| 120 129 | 
             
            summary: Debugger for ruby
         | 
| 121 | 
            -
            test_files: | 
| 130 | 
            +
            test_files:
         | 
| 131 | 
            +
            - spec/backtrace_spec.rb
         | 
| 132 | 
            +
            - spec/blocks_spec.rb
         | 
| 133 | 
            +
            - spec/commands_spec.rb
         | 
| 134 | 
            +
            - spec/pry_debugger.rb
         | 
| 135 | 
            +
            - spec/spec_helper.rb
         |