pry-byebug 2.0.0 → 3.0.0
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/.rubocop.yml +10 -0
- data/.travis.yml +2 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -1
- data/README.md +45 -9
- data/lib/{pry-byebug/processor.rb → byebug/processors/pry_processor.rb} +32 -28
- data/lib/pry-byebug.rb +2 -1
- data/lib/pry-byebug/base.rb +14 -2
- data/lib/pry-byebug/pry_ext.rb +5 -8
- data/lib/pry-byebug/pry_remote_ext.rb +3 -1
- data/lib/pry-byebug/version.rb +4 -1
- data/lib/pry/byebug/breakpoints.rb +157 -0
- data/lib/{pry-byebug/commands.rb → pry/commands/breakpoint.rb} +52 -125
- data/lib/pry/commands/stepping.rb +90 -0
- data/test/base_test.rb +2 -2
- data/test/breakpoints_test.rb +16 -12
- data/test/examples/deep_stepping.rb +9 -0
- data/test/processor_test.rb +13 -0
- metadata +9 -6
- data/lib/pry-byebug/breakpoints.rb +0 -154
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c42e1d5a58d90aa640bcd1e79be383d78286fc66
|
4
|
+
data.tar.gz: 32cf706c69453f75a70729fa4caf95b023642379
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4e5826a3e0d91869ff79953c45e475d0ecb5252e50171a5ad18f8a667625558690af3b00e09d0b8ccb68c55257e5bc0f285edb85334388fd7a4b8ea9c6ce826
|
7
|
+
data.tar.gz: e87f0c3fe28da82b42e2146c108ae73b0832b4bc10d1f1b54baaefccf639580d8874cc5c7a1149fbd46500969ce3b55bd4e13b81531f1d05913735ad389fd193
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 3.0.0 (Unreleased)
|
2
|
+
|
3
|
+
- Improvements:
|
4
|
+
* Adds RuboCop to enforce a consistent code style.
|
5
|
+
* Several refactorings to keep code simpler.
|
6
|
+
|
7
|
+
- Bugfixes:
|
8
|
+
* `binding.pry` would not stop at the correct place when called at the last
|
9
|
+
line of a method/block.
|
10
|
+
|
11
|
+
- Removals:
|
12
|
+
* Stepping aliases for `next` (`n`), `step` (`s`), `finish` (`f`) and
|
13
|
+
`continue` (`c`). See #34.
|
14
|
+
|
15
|
+
|
1
16
|
## 2.0.0 (2014-01-09)
|
2
17
|
|
3
18
|
- Improvements:
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# pry-byebug
|
2
2
|
[![Version][VersionBadge]][VersionURL]
|
3
3
|
[![Build][TravisBadge]][TravisURL]
|
4
|
+
[![Inline docs][InchCIBadge]](InchCIURL)
|
4
5
|
[![Gittip][GittipBadge]][GittipURL]
|
5
6
|
|
6
7
|
_Fast execution control in Pry_
|
@@ -9,12 +10,16 @@ Adds **step**, **next**, **finish** and **continue** commands and
|
|
9
10
|
**breakpoints** to [Pry][pry] using [byebug][byebug].
|
10
11
|
|
11
12
|
To use, invoke pry normally. No need to start your script or app differently.
|
13
|
+
Execution will stop in the first statement after your `binding.pry`.
|
12
14
|
|
13
15
|
```ruby
|
14
16
|
def some_method
|
15
|
-
|
16
|
-
puts 'Hello World' # Run 'step' or 'next' in the console to move here.
|
17
|
+
puts 'Hello World' # Run 'step' in the console to move here
|
17
18
|
end
|
19
|
+
|
20
|
+
binding.pry
|
21
|
+
some_method # Execution will stop here.
|
22
|
+
puts 'Goodbye World' # Run 'next' in the console to move here.
|
18
23
|
```
|
19
24
|
|
20
25
|
|
@@ -37,14 +42,43 @@ to use it to debug your tests!_
|
|
37
42
|
## Execution Commands
|
38
43
|
|
39
44
|
**step:** Step execution into the next line or method. Takes an optional numeric
|
40
|
-
argument to step multiple times.
|
45
|
+
argument to step multiple times.
|
41
46
|
|
42
47
|
**next:** Step over to the next line within the same frame. Also takes an
|
43
|
-
optional numeric argument to step multiple lines.
|
48
|
+
optional numeric argument to step multiple lines.
|
49
|
+
|
50
|
+
**finish:** Execute until current stack frame returns.
|
51
|
+
|
52
|
+
**continue:** Continue program execution and end the Pry session.
|
53
|
+
|
44
54
|
|
45
|
-
|
55
|
+
## Matching Byebug Behaviour
|
46
56
|
|
47
|
-
|
57
|
+
If you're coming from Byebug or from Pry-Byebug versions previous to 3.0, you
|
58
|
+
may be lacking the 'n', 's', 'c' and 'f' aliases for the stepping commands.
|
59
|
+
These aliases were removed by default because they usually conflict with
|
60
|
+
scratch variable names. But it's very easy to reenable them if you still want
|
61
|
+
them, just add the following shortcuts to your `~/.pryrc` file:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
if defined?(PryByebug)
|
65
|
+
Pry.commands.alias_command 'c', 'continue'
|
66
|
+
Pry.commands.alias_command 's', 'step'
|
67
|
+
Pry.commands.alias_command 'n', 'next'
|
68
|
+
Pry.commands.alias_command 'f', 'finish'
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
Also, you might find useful as well the repeat the last command by just hitting
|
73
|
+
the `Enter` key (e.g., with `step` or `next`). To achieve that, add this to
|
74
|
+
your `~/.pryrc` file:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
# Hit Enter to repeat last command
|
78
|
+
Pry::Commands.command /^$/, "repeat last command" do
|
79
|
+
_pry_.run_command Pry.history.to_a.last
|
80
|
+
end
|
81
|
+
```
|
48
82
|
|
49
83
|
|
50
84
|
## Breakpoints
|
@@ -70,7 +104,7 @@ break --condition 3 # Remove the condition on breakpoint #3.
|
|
70
104
|
break --delete 5 # Delete breakpoint #5.
|
71
105
|
break --disable-all # Disable all breakpoints.
|
72
106
|
|
73
|
-
|
107
|
+
breaks # List all breakpoints. (Same as `breakpoints`)
|
74
108
|
break --show 2 # Show details about breakpoint #2.
|
75
109
|
```
|
76
110
|
|
@@ -99,9 +133,11 @@ Patches and bug reports are welcome.
|
|
99
133
|
[byebug]: https://github.com/deivid-rodriguez/byebug
|
100
134
|
[pry-debugger]: https://github.com/nixme/pry-debugger
|
101
135
|
[pry-stack_explorer]: https://github.com/pry/pry-stack_explorer
|
102
|
-
[VersionBadge]: https://badge.fury.io/rb/pry-byebug.
|
136
|
+
[VersionBadge]: https://badge.fury.io/rb/pry-byebug.svg
|
103
137
|
[VersionURL]: http://badge.fury.io/rb/pry-byebug
|
104
|
-
[TravisBadge]: https://secure.travis-ci.org/deivid-rodriguez/pry-byebug.
|
138
|
+
[TravisBadge]: https://secure.travis-ci.org/deivid-rodriguez/pry-byebug.svg
|
105
139
|
[TravisURL]: http://travis-ci.org/deivid-rodriguez/pry-byebug
|
140
|
+
[InchCIBadge]: http://inch-ci.org/github/deivid-rodriguez/pry-byebug.svg?branch=master
|
141
|
+
[InchCIURL]: http://inch-ci.org/github/deivid-rodriguez/pry-byebug
|
106
142
|
[GittipBadge]: http://img.shields.io/gittip/deivid-rodriguez.svg
|
107
143
|
[GittipURL]: https://www.gittip.com/deivid-rodriguez
|
@@ -1,51 +1,55 @@
|
|
1
1
|
require 'pry'
|
2
2
|
require 'byebug'
|
3
3
|
|
4
|
-
module
|
4
|
+
module Byebug
|
5
5
|
#
|
6
6
|
# Extends raw byebug's processor.
|
7
7
|
#
|
8
|
-
class
|
8
|
+
class PryProcessor < Processor
|
9
9
|
attr_accessor :pry
|
10
10
|
|
11
|
-
def initialize(interface =
|
11
|
+
def initialize(interface = LocalInterface.new)
|
12
12
|
super(interface)
|
13
13
|
|
14
14
|
Byebug.handler = self
|
15
15
|
end
|
16
16
|
|
17
|
+
def start
|
18
|
+
Byebug.start
|
19
|
+
Byebug.current_context.step_out(3, true)
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
17
23
|
# Wrap a Pry REPL to catch navigational commands and act on them.
|
18
|
-
|
24
|
+
#
|
25
|
+
def run(&_block)
|
19
26
|
return_value = nil
|
20
27
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
command = catch(:breakout_nav) do # Throws from PryByebug::Commands
|
26
|
-
return_value = yield
|
27
|
-
{} # Nothing thrown == no navigational command
|
28
|
-
end
|
29
|
-
|
30
|
-
times = (command[:times] || 1).to_i # Command argument
|
31
|
-
times = 1 if times <= 0
|
28
|
+
command = catch(:breakout_nav) do # Throws from PryByebug::Commands
|
29
|
+
return_value = yield
|
30
|
+
{} # Nothing thrown == no navigational command
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
# Pry instance to resume after stepping
|
34
|
+
@pry = command[:pry]
|
35
35
|
|
36
|
-
|
37
|
-
Byebug.current_context.step_over(times, 0)
|
36
|
+
perform(command[:action], (command[:times] || '1').to_i)
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
return_value
|
39
|
+
end
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
#
|
42
|
+
# Set up a number of navigational commands to be performed by Byebug.
|
43
|
+
#
|
44
|
+
def perform(action, times)
|
45
|
+
case action
|
46
|
+
when :next
|
47
|
+
Byebug.current_context.step_over(times, 0)
|
48
|
+
when :step
|
49
|
+
Byebug.current_context.step_into(times)
|
50
|
+
when :finish
|
51
|
+
Byebug.current_context.step_out(times)
|
46
52
|
end
|
47
|
-
|
48
|
-
return_value
|
49
53
|
end
|
50
54
|
|
51
55
|
# --- Callbacks from byebug C extension ---
|
@@ -93,7 +97,7 @@ module PryByebug
|
|
93
97
|
def resume_pry(context)
|
94
98
|
new_binding = context.frame_binding(0)
|
95
99
|
|
96
|
-
run
|
100
|
+
run do
|
97
101
|
if @pry
|
98
102
|
@pry.repl(new_binding)
|
99
103
|
else
|
data/lib/pry-byebug.rb
CHANGED
data/lib/pry-byebug/base.rb
CHANGED
@@ -1,11 +1,23 @@
|
|
1
|
+
#
|
2
|
+
# Main container module for Pry-Byebug functionality
|
3
|
+
#
|
1
4
|
module PryByebug
|
2
5
|
#
|
3
|
-
# Checks that a binding is in a local file context.
|
6
|
+
# Checks that a target binding is in a local file context.
|
4
7
|
#
|
5
|
-
def
|
8
|
+
def file_context?(target)
|
6
9
|
file = target.eval('__FILE__')
|
7
10
|
file == Pry.eval_path || !Pry::Helpers::BaseHelpers.not_a_real_file?(file)
|
8
11
|
end
|
12
|
+
module_function :file_context?
|
13
|
+
|
14
|
+
#
|
15
|
+
# Ensures that a command is executed in a local file context.
|
16
|
+
#
|
17
|
+
def check_file_context(target, e = nil)
|
18
|
+
e ||= 'Cannot find local context. Did you use `binding.pry`?'
|
19
|
+
fail(Pry::CommandError, e) unless file_context?(target)
|
20
|
+
end
|
9
21
|
module_function :check_file_context
|
10
22
|
|
11
23
|
# Reference to currently running pry-remote server. Used by the processor.
|
data/lib/pry-byebug/pry_ext.rb
CHANGED
@@ -1,19 +1,16 @@
|
|
1
1
|
require 'pry'
|
2
|
-
require '
|
2
|
+
require 'byebug/processors/pry_processor'
|
3
3
|
|
4
4
|
class << Pry
|
5
5
|
alias_method :start_without_pry_byebug, :start
|
6
6
|
attr_reader :processor
|
7
7
|
|
8
8
|
def start_with_pry_byebug(target = TOPLEVEL_BINDING, options = {})
|
9
|
-
@processor ||=
|
9
|
+
@processor ||= Byebug::PryProcessor.new
|
10
10
|
|
11
|
-
if target.is_a?(Binding) && PryByebug.
|
12
|
-
# Wrap
|
13
|
-
|
14
|
-
@processor.run(true) do
|
15
|
-
start_without_pry_byebug(target, options)
|
16
|
-
end
|
11
|
+
if target.is_a?(Binding) && PryByebug.file_context?(target)
|
12
|
+
# Wrap processor around the usual Pry.start to catch navigation commands
|
13
|
+
@processor.start
|
17
14
|
else
|
18
15
|
# No need for the tracer unless we have a file context to step through
|
19
16
|
start_without_pry_byebug(target, options)
|
@@ -19,7 +19,9 @@ module PryRemote
|
|
19
19
|
Pry.start @object, input: client.input_proxy, output: client.output
|
20
20
|
end
|
21
21
|
|
22
|
+
#
|
22
23
|
# Override to reset our saved global current server session.
|
24
|
+
#
|
23
25
|
alias_method :teardown_without_pry_byebug, :teardown
|
24
26
|
def teardown_with_pry_byebug
|
25
27
|
return if @torn
|
@@ -33,7 +35,7 @@ module PryRemote
|
|
33
35
|
end
|
34
36
|
|
35
37
|
# Ensure cleanup when a program finishes without another break. For example,
|
36
|
-
# 'next' on the last line of a program won't hit
|
38
|
+
# 'next' on the last line of a program won't hit Byebug::PryProcessor#run,
|
37
39
|
# which normally handles cleanup.
|
38
40
|
at_exit do
|
39
41
|
PryByebug.current_remote_server.teardown if PryByebug.current_remote_server
|
data/lib/pry-byebug/version.rb
CHANGED
@@ -0,0 +1,157 @@
|
|
1
|
+
class Pry
|
2
|
+
module Byebug
|
3
|
+
#
|
4
|
+
# Wrapper for Byebug.breakpoints that respects our Processor and has better
|
5
|
+
# failure behavior. Acts as an Enumerable.
|
6
|
+
#
|
7
|
+
module Breakpoints
|
8
|
+
extend Enumerable
|
9
|
+
extend self
|
10
|
+
|
11
|
+
#
|
12
|
+
# Breakpoint in a file:line location
|
13
|
+
#
|
14
|
+
class FileBreakpoint < SimpleDelegator
|
15
|
+
def source_code
|
16
|
+
Pry::Code.from_file(source).around(pos, 3).with_marker(pos)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{source} @ #{pos}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Breakpoint in a Class#method location
|
26
|
+
#
|
27
|
+
class MethodBreakpoint < SimpleDelegator
|
28
|
+
def initialize(byebug_bp, method)
|
29
|
+
__setobj__ byebug_bp
|
30
|
+
@method = method
|
31
|
+
end
|
32
|
+
|
33
|
+
def source_code
|
34
|
+
Pry::Code.from_method(Pry::Method.from_str(@method))
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
@method
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def breakpoints
|
43
|
+
@breakpoints ||= []
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Adds a method breakpoint.
|
48
|
+
#
|
49
|
+
def add_method(method, expression = nil)
|
50
|
+
validate_expression expression
|
51
|
+
owner, name = method.split(/[\.#]/)
|
52
|
+
byebug_bp = ::Byebug::Breakpoint.add(owner, name.to_sym, expression)
|
53
|
+
bp = MethodBreakpoint.new byebug_bp, method
|
54
|
+
breakpoints << bp
|
55
|
+
bp
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Adds a file breakpoint.
|
60
|
+
#
|
61
|
+
def add_file(file, line, expression = nil)
|
62
|
+
real_file = (file != Pry.eval_path)
|
63
|
+
fail(ArgumentError, 'Invalid file!') if real_file && !File.exist?(file)
|
64
|
+
validate_expression expression
|
65
|
+
|
66
|
+
path = (real_file ? File.expand_path(file) : file)
|
67
|
+
bp = FileBreakpoint.new ::Byebug::Breakpoint.add(path, line, expression)
|
68
|
+
breakpoints << bp
|
69
|
+
bp
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Changes the conditional expression for a breakpoint.
|
74
|
+
#
|
75
|
+
def change(id, expression = nil)
|
76
|
+
validate_expression expression
|
77
|
+
|
78
|
+
breakpoint = find_by_id(id)
|
79
|
+
breakpoint.expr = expression
|
80
|
+
breakpoint
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Deletes an existing breakpoint with the given ID.
|
85
|
+
#
|
86
|
+
def delete(id)
|
87
|
+
deleted = ::Byebug.started? &&
|
88
|
+
::Byebug::Breakpoint.remove(id) && breakpoints.delete(find_by_id(id))
|
89
|
+
fail(ArgumentError, "No breakpoint ##{id}") unless deleted
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Deletes all breakpoints.
|
94
|
+
#
|
95
|
+
def delete_all
|
96
|
+
@breakpoints = []
|
97
|
+
::Byebug.breakpoints.clear if ::Byebug.started?
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Enables a disabled breakpoint with the given ID.
|
102
|
+
#
|
103
|
+
def enable(id)
|
104
|
+
change_status id, true
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Disables a breakpoint with the given ID.
|
109
|
+
#
|
110
|
+
def disable(id)
|
111
|
+
change_status id, false
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Disables all breakpoints.
|
116
|
+
#
|
117
|
+
def disable_all
|
118
|
+
each do |breakpoint|
|
119
|
+
breakpoint.enabled = false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_a
|
124
|
+
breakpoints
|
125
|
+
end
|
126
|
+
|
127
|
+
def size
|
128
|
+
to_a.size
|
129
|
+
end
|
130
|
+
|
131
|
+
def each(&block)
|
132
|
+
to_a.each(&block)
|
133
|
+
end
|
134
|
+
|
135
|
+
def find_by_id(id)
|
136
|
+
breakpoint = find { |b| b.id == id }
|
137
|
+
fail(ArgumentError, "No breakpoint ##{id}!") unless breakpoint
|
138
|
+
breakpoint
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def change_status(id, enabled = true)
|
144
|
+
breakpoint = find_by_id(id)
|
145
|
+
breakpoint.enabled = enabled
|
146
|
+
breakpoint
|
147
|
+
end
|
148
|
+
|
149
|
+
def validate_expression(exp)
|
150
|
+
return unless exp &&
|
151
|
+
(exp.empty? || !Pry::Code.complete_expression?(exp))
|
152
|
+
|
153
|
+
fail("Invalid breakpoint conditional: #{expression}")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -1,86 +1,13 @@
|
|
1
1
|
require 'pry'
|
2
|
-
require 'pry
|
2
|
+
require 'pry/byebug/breakpoints'
|
3
3
|
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# Main Pry class.
|
6
6
|
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
banner <<-BANNER
|
13
|
-
Usage: step [TIMES]
|
14
|
-
Aliases: s
|
15
|
-
|
16
|
-
Step execution forward. By default, moves a single step.
|
17
|
-
|
18
|
-
Examples:
|
19
|
-
|
20
|
-
step Move a single step forward.
|
21
|
-
step 5 Execute the next 5 steps.
|
22
|
-
BANNER
|
23
|
-
|
24
|
-
def process
|
25
|
-
check_file_context
|
26
|
-
breakout_navigation :step, args.first
|
27
|
-
end
|
28
|
-
end
|
29
|
-
alias_command 's', 'step'
|
30
|
-
|
31
|
-
create_command 'next' do
|
32
|
-
description 'Execute the next line within the current stack frame.'
|
33
|
-
|
34
|
-
banner <<-BANNER
|
35
|
-
Usage: next [LINES]
|
36
|
-
Aliases: n
|
37
|
-
|
38
|
-
Step over within the same frame. By default, moves forward a single
|
39
|
-
line.
|
40
|
-
|
41
|
-
Examples:
|
42
|
-
|
43
|
-
next Move a single line forward.
|
44
|
-
next 4 Execute the next 4 lines.
|
45
|
-
BANNER
|
46
|
-
|
47
|
-
def process
|
48
|
-
check_file_context
|
49
|
-
breakout_navigation :next, args.first
|
50
|
-
end
|
51
|
-
end
|
52
|
-
alias_command 'n', 'next'
|
53
|
-
|
54
|
-
create_command 'finish' do
|
55
|
-
description 'Execute until current stack frame returns.'
|
56
|
-
|
57
|
-
banner <<-BANNER
|
58
|
-
Usage: finish
|
59
|
-
Aliases: f
|
60
|
-
BANNER
|
61
|
-
|
62
|
-
def process
|
63
|
-
check_file_context
|
64
|
-
breakout_navigation :finish
|
65
|
-
end
|
66
|
-
end
|
67
|
-
alias_command 'f', 'finish'
|
68
|
-
|
69
|
-
create_command 'continue' do
|
70
|
-
description 'Continue program execution and end the Pry session.'
|
71
|
-
|
72
|
-
banner <<-BANNER
|
73
|
-
Usage: continue
|
74
|
-
Aliases: c
|
75
|
-
BANNER
|
76
|
-
|
77
|
-
def process
|
78
|
-
check_file_context
|
79
|
-
breakout_navigation :continue
|
80
|
-
end
|
81
|
-
end
|
82
|
-
alias_command 'c', 'continue'
|
83
|
-
|
7
|
+
# We're going to add to it custom breakpoint commands for Pry-Byebug
|
8
|
+
#
|
9
|
+
class Pry
|
10
|
+
BreakpointCommands = CommandSet.new do
|
84
11
|
create_command 'break' do
|
85
12
|
description 'Set or edit a breakpoint.'
|
86
13
|
|
@@ -139,7 +66,7 @@ module PryByebug
|
|
139
66
|
|
140
67
|
%w(delete disable enable).each do |command|
|
141
68
|
define_method(:"process_#{command}") do
|
142
|
-
|
69
|
+
breakpoints.send(command, opts[command])
|
143
70
|
run 'breakpoints'
|
144
71
|
end
|
145
72
|
end
|
@@ -147,18 +74,18 @@ module PryByebug
|
|
147
74
|
%w(disable-all delete-all).each do |command|
|
148
75
|
method_name = command.gsub('-', '_')
|
149
76
|
define_method(:"process_#{method_name}") do
|
150
|
-
|
77
|
+
breakpoints.send(method_name)
|
151
78
|
run 'breakpoints'
|
152
79
|
end
|
153
80
|
end
|
154
81
|
|
155
82
|
def process_show
|
156
|
-
print_full_breakpoint(
|
83
|
+
print_full_breakpoint(breakpoints.find_by_id(opts[:show]))
|
157
84
|
end
|
158
85
|
|
159
86
|
def process_condition
|
160
87
|
expr = args.empty? ? nil : args.join(' ')
|
161
|
-
|
88
|
+
breakpoints.change(opts[:condition], expr)
|
162
89
|
end
|
163
90
|
|
164
91
|
def new_breakpoint
|
@@ -168,21 +95,21 @@ module PryByebug
|
|
168
95
|
bp =
|
169
96
|
case place
|
170
97
|
when /^(\d+)$/
|
171
|
-
line = Regexp.last_match[1]
|
172
98
|
errmsg = 'Line number declaration valid only in a file context.'
|
173
|
-
check_file_context(errmsg)
|
99
|
+
PryByebug.check_file_context(target, errmsg)
|
174
100
|
|
175
|
-
|
101
|
+
file, lineno = target.eval('__FILE__'), Regexp.last_match[1].to_i
|
102
|
+
breakpoints.add_file(file, lineno, condition)
|
176
103
|
when /^(.+):(\d+)$/
|
177
104
|
file, lineno = Regexp.last_match[1], Regexp.last_match[2].to_i
|
178
|
-
|
105
|
+
breakpoints.add_file(file, lineno, condition)
|
179
106
|
when /^(.*)[.#].+$/ # Method or class name
|
180
107
|
if Regexp.last_match[1].strip.empty?
|
181
108
|
errmsg = 'Method name declaration valid only in a file context.'
|
182
|
-
check_file_context(errmsg)
|
109
|
+
PryByebug.check_file_context(target, errmsg)
|
183
110
|
place = target.eval('self.class.to_s') + place
|
184
111
|
end
|
185
|
-
|
112
|
+
breakpoints.add_method(place, condition)
|
186
113
|
else
|
187
114
|
fail(ArgumentError, 'Cannot identify arguments as breakpoint')
|
188
115
|
end
|
@@ -207,33 +134,33 @@ module PryByebug
|
|
207
134
|
end
|
208
135
|
|
209
136
|
def process
|
210
|
-
|
211
|
-
|
137
|
+
if breakpoints.count == 0
|
138
|
+
return output.puts(text.bold('No breakpoints defined.'))
|
139
|
+
end
|
212
140
|
|
213
141
|
if opts.verbose?
|
214
|
-
|
142
|
+
breakpoints.each { |b| print_full_breakpoint(b) }
|
215
143
|
else
|
216
|
-
output.puts
|
217
144
|
print_breakpoints_header
|
218
|
-
|
219
|
-
output.puts
|
145
|
+
breakpoints.each { |b| print_short_breakpoint(b) }
|
220
146
|
end
|
221
147
|
end
|
222
148
|
end
|
223
149
|
alias_command 'breaks', 'breakpoints'
|
224
150
|
|
225
151
|
helpers do
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
152
|
+
#
|
153
|
+
# Byebug's array of breakpoints.
|
154
|
+
#
|
155
|
+
def breakpoints
|
156
|
+
Byebug::Breakpoints
|
231
157
|
end
|
232
158
|
|
233
|
-
#
|
234
|
-
|
235
|
-
|
236
|
-
|
159
|
+
#
|
160
|
+
# Prints a message with bold font.
|
161
|
+
#
|
162
|
+
def bold_puts(msg)
|
163
|
+
output.puts(text.bold(msg))
|
237
164
|
end
|
238
165
|
|
239
166
|
#
|
@@ -241,28 +168,24 @@ module PryByebug
|
|
241
168
|
#
|
242
169
|
# Includes surrounding code at that point.
|
243
170
|
#
|
244
|
-
def print_full_breakpoint(
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
end
|
252
|
-
output.puts
|
253
|
-
output.puts breakpoint.source_code.with_line_numbers.to_s
|
254
|
-
output.puts
|
171
|
+
def print_full_breakpoint(br)
|
172
|
+
header = text.bold("Breakpoint #{br.id}:")
|
173
|
+
status = br.enabled? ? '(Enabled)' : '(Disabled)'
|
174
|
+
code = br.source_code.with_line_numbers.to_s
|
175
|
+
condition = br.expr ? "#{text.bold('Condition:')} #{br.expr}\n" : ''
|
176
|
+
|
177
|
+
output.puts("#{header} #{br} #{status} :\n#{condition}#{code}\n")
|
255
178
|
end
|
256
179
|
|
257
180
|
#
|
258
181
|
# Print out concise information about a breakpoint.
|
259
182
|
#
|
260
183
|
def print_short_breakpoint(breakpoint)
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
output.puts
|
184
|
+
id = sprintf('%*d ', max_width, breakpoint.id)
|
185
|
+
status = breakpoint.enabled? ? 'Yes' : 'No'
|
186
|
+
expr = breakpoint.expr ? breakpoint.expr : ''
|
187
|
+
|
188
|
+
output.puts("#{id} #{status} #{breakpoint} #{expr}")
|
266
189
|
end
|
267
190
|
|
268
191
|
#
|
@@ -271,18 +194,22 @@ module PryByebug
|
|
271
194
|
def print_breakpoints_header
|
272
195
|
header = "#{' ' * (max_width - 1)}# Enabled At "
|
273
196
|
|
274
|
-
output.puts
|
275
|
-
|
197
|
+
output.puts <<-EOP
|
198
|
+
|
199
|
+
#{text.bold(header)}
|
200
|
+
#{text.bold('-' * header.size)}
|
201
|
+
|
202
|
+
EOP
|
276
203
|
end
|
277
204
|
|
278
205
|
#
|
279
206
|
# Max width of breakpoints id column
|
280
207
|
#
|
281
208
|
def max_width
|
282
|
-
[Math.log10(
|
209
|
+
[Math.log10(breakpoints.count).ceil, 1].max
|
283
210
|
end
|
284
211
|
end
|
285
212
|
end
|
286
|
-
end
|
287
213
|
|
288
|
-
Pry.commands.import
|
214
|
+
Pry.commands.import(BreakpointCommands)
|
215
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Main Pry class.
|
5
|
+
#
|
6
|
+
# We're going to add to it custom stepping commands for Pry-Byebug
|
7
|
+
#
|
8
|
+
class Pry
|
9
|
+
SteppingCommands = CommandSet.new do
|
10
|
+
create_command 'step' do
|
11
|
+
description 'Step execution into the next line or method.'
|
12
|
+
|
13
|
+
banner <<-BANNER
|
14
|
+
Usage: step [TIMES]
|
15
|
+
|
16
|
+
Step execution forward. By default, moves a single step.
|
17
|
+
|
18
|
+
Examples:
|
19
|
+
step #=> Move a single step forward.
|
20
|
+
step 5 #=> Execute the next 5 steps.
|
21
|
+
BANNER
|
22
|
+
|
23
|
+
def process
|
24
|
+
PryByebug.check_file_context(target)
|
25
|
+
|
26
|
+
breakout_navigation :step, args.first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
create_command 'next' do
|
31
|
+
description 'Execute the next line within the current stack frame.'
|
32
|
+
|
33
|
+
banner <<-BANNER
|
34
|
+
Usage: next [LINES]
|
35
|
+
|
36
|
+
Step over within the same frame. By default, moves forward a single
|
37
|
+
line.
|
38
|
+
|
39
|
+
Examples:
|
40
|
+
next #=> Move a single line forward.
|
41
|
+
next 4 #=> Execute the next 4 lines.
|
42
|
+
BANNER
|
43
|
+
|
44
|
+
def process
|
45
|
+
PryByebug.check_file_context(target)
|
46
|
+
|
47
|
+
breakout_navigation :next, args.first
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
create_command 'finish' do
|
52
|
+
description 'Execute until current stack frame returns.'
|
53
|
+
|
54
|
+
banner <<-BANNER
|
55
|
+
Usage: finish
|
56
|
+
BANNER
|
57
|
+
|
58
|
+
def process
|
59
|
+
PryByebug.check_file_context(target)
|
60
|
+
|
61
|
+
breakout_navigation :finish
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
create_command 'continue' do
|
66
|
+
description 'Continue program execution and end the Pry session.'
|
67
|
+
|
68
|
+
banner <<-BANNER
|
69
|
+
Usage: continue
|
70
|
+
BANNER
|
71
|
+
|
72
|
+
def process
|
73
|
+
PryByebug.check_file_context(target)
|
74
|
+
|
75
|
+
breakout_navigation :continue
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
helpers do
|
80
|
+
def breakout_navigation(action, times = nil)
|
81
|
+
_pry_.binding_stack.clear # Clear the binding stack.
|
82
|
+
|
83
|
+
# Break out of the REPL loop and signal tracer
|
84
|
+
throw :breakout_nav, action: action, times: times, pry: _pry_
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Pry.commands.import(SteppingCommands)
|
90
|
+
end
|
data/test/base_test.rb
CHANGED
@@ -6,11 +6,11 @@ require 'test_helper'
|
|
6
6
|
class BaseTest < MiniTest::Spec
|
7
7
|
def test_main_file_context
|
8
8
|
Pry.stubs eval_path: '<main>'
|
9
|
-
assert PryByebug.
|
9
|
+
assert PryByebug.file_context?(TOPLEVEL_BINDING)
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_other_file_context
|
13
13
|
Pry.stubs eval_path: 'something'
|
14
|
-
refute PryByebug.
|
14
|
+
refute PryByebug.file_context?(TOPLEVEL_BINDING)
|
15
15
|
end
|
16
16
|
end
|
data/test/breakpoints_test.rb
CHANGED
@@ -4,14 +4,6 @@ require 'test_helper'
|
|
4
4
|
# Tests for pry-byebug breakpoints.
|
5
5
|
#
|
6
6
|
class BreakpointsTestGeneral < MiniTest::Spec
|
7
|
-
def test_add_file_raises_argument_error
|
8
|
-
Pry.stubs eval_path: 'something'
|
9
|
-
File.stubs :exist?
|
10
|
-
assert_raises(ArgumentError) do
|
11
|
-
PryByebug::Breakpoints.add_file('file', 1)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
7
|
#
|
16
8
|
# Minimal dummy example class.
|
17
9
|
#
|
@@ -20,9 +12,21 @@ class BreakpointsTestGeneral < MiniTest::Spec
|
|
20
12
|
def instance_method; end
|
21
13
|
end
|
22
14
|
|
15
|
+
def breakpoints_class
|
16
|
+
Pry::Byebug::Breakpoints
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_add_file_raises_argument_error
|
20
|
+
Pry.stubs eval_path: 'something'
|
21
|
+
File.stubs :exist?
|
22
|
+
assert_raises(ArgumentError) do
|
23
|
+
breakpoints_class.add_file('file', 1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
23
27
|
def test_add_method_adds_instance_method_breakpoint
|
24
|
-
Pry.stub :processor,
|
25
|
-
|
28
|
+
Pry.stub :processor, Byebug::PryProcessor.new do
|
29
|
+
breakpoints_class.add_method 'BreakpointsTest::Tester#instance_method'
|
26
30
|
bp = Byebug.breakpoints.last
|
27
31
|
assert_equal 'BreakpointsTest::Tester', bp.source
|
28
32
|
assert_equal 'instance_method', bp.pos
|
@@ -30,8 +34,8 @@ class BreakpointsTestGeneral < MiniTest::Spec
|
|
30
34
|
end
|
31
35
|
|
32
36
|
def test_add_method_adds_class_method_breakpoint
|
33
|
-
Pry.stub :processor,
|
34
|
-
|
37
|
+
Pry.stub :processor, Byebug::PryProcessor.new do
|
38
|
+
breakpoints_class.add_method 'BreakpointsTest::Tester.class_method'
|
35
39
|
bp = Byebug.breakpoints.last
|
36
40
|
assert_equal 'BreakpointsTest::Tester', bp.source
|
37
41
|
assert_equal 'class_method', bp.pos
|
data/test/processor_test.rb
CHANGED
@@ -23,4 +23,17 @@ class ProcessorTest < Minitest::Spec
|
|
23
23
|
@output.string.must_match(/\=> 6:/)
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
describe 'Initialization at the end of block/method call' do
|
28
|
+
let(:step_file) { test_file('deep_stepping') }
|
29
|
+
|
30
|
+
before do
|
31
|
+
@input, @output = InputTester.new, StringIO.new
|
32
|
+
redirect_pry_io(@input, @output) { load step_file }
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'stops execution at the first line after binding.pry' do
|
36
|
+
@output.string.must_match(/\=> 7:/)
|
37
|
+
end
|
38
|
+
end
|
26
39
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pry-byebug
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Rodríguez
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-02-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pry
|
@@ -55,21 +55,23 @@ files:
|
|
55
55
|
- LICENSE
|
56
56
|
- README.md
|
57
57
|
- Rakefile
|
58
|
+
- lib/byebug/processors/pry_processor.rb
|
58
59
|
- lib/pry-byebug.rb
|
59
60
|
- lib/pry-byebug/base.rb
|
60
|
-
- lib/pry-byebug/breakpoints.rb
|
61
61
|
- lib/pry-byebug/cli.rb
|
62
|
-
- lib/pry-byebug/commands.rb
|
63
|
-
- lib/pry-byebug/processor.rb
|
64
62
|
- lib/pry-byebug/pry_ext.rb
|
65
63
|
- lib/pry-byebug/pry_remote_ext.rb
|
66
64
|
- lib/pry-byebug/version.rb
|
65
|
+
- lib/pry/byebug/breakpoints.rb
|
66
|
+
- lib/pry/commands/breakpoint.rb
|
67
|
+
- lib/pry/commands/stepping.rb
|
67
68
|
- pry-byebug.gemspec
|
68
69
|
- test/base_test.rb
|
69
70
|
- test/breakpoints_test.rb
|
70
71
|
- test/commands_test.rb
|
71
72
|
- test/examples/break1.rb
|
72
73
|
- test/examples/break2.rb
|
74
|
+
- test/examples/deep_stepping.rb
|
73
75
|
- test/examples/stepping.rb
|
74
76
|
- test/processor_test.rb
|
75
77
|
- test/pry_ext_test.rb
|
@@ -95,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
97
|
version: '0'
|
96
98
|
requirements: []
|
97
99
|
rubyforge_project:
|
98
|
-
rubygems_version: 2.4.
|
100
|
+
rubygems_version: 2.4.5
|
99
101
|
signing_key:
|
100
102
|
specification_version: 4
|
101
103
|
summary: Fast debugging with Pry.
|
@@ -105,6 +107,7 @@ test_files:
|
|
105
107
|
- test/commands_test.rb
|
106
108
|
- test/examples/break1.rb
|
107
109
|
- test/examples/break2.rb
|
110
|
+
- test/examples/deep_stepping.rb
|
108
111
|
- test/examples/stepping.rb
|
109
112
|
- test/processor_test.rb
|
110
113
|
- test/pry_ext_test.rb
|
@@ -1,154 +0,0 @@
|
|
1
|
-
module PryByebug
|
2
|
-
#
|
3
|
-
# Wrapper for Byebug.breakpoints that respects our Processor and has better
|
4
|
-
# failure behavior. Acts as an Enumerable.
|
5
|
-
#
|
6
|
-
module Breakpoints
|
7
|
-
extend Enumerable
|
8
|
-
extend self
|
9
|
-
|
10
|
-
#
|
11
|
-
# Breakpoint in a file:line location
|
12
|
-
#
|
13
|
-
class FileBreakpoint < SimpleDelegator
|
14
|
-
def source_code
|
15
|
-
Pry::Code.from_file(source).around(pos, 3).with_marker(pos)
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_s
|
19
|
-
"#{source} @ #{pos}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
#
|
24
|
-
# Breakpoint in a Class#method location
|
25
|
-
#
|
26
|
-
class MethodBreakpoint < SimpleDelegator
|
27
|
-
def initialize(byebug_bp, method)
|
28
|
-
__setobj__ byebug_bp
|
29
|
-
@method = method
|
30
|
-
end
|
31
|
-
|
32
|
-
def source_code
|
33
|
-
Pry::Code.from_method(Pry::Method.from_str(@method))
|
34
|
-
end
|
35
|
-
|
36
|
-
def to_s
|
37
|
-
@method
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def breakpoints
|
42
|
-
@breakpoints ||= []
|
43
|
-
end
|
44
|
-
|
45
|
-
#
|
46
|
-
# Adds a method breakpoint.
|
47
|
-
#
|
48
|
-
def add_method(method, expression = nil)
|
49
|
-
validate_expression expression
|
50
|
-
owner, name = method.split(/[\.#]/)
|
51
|
-
byebug_bp = Byebug::Breakpoint.add(owner, name.to_sym, expression)
|
52
|
-
bp = MethodBreakpoint.new byebug_bp, method
|
53
|
-
breakpoints << bp
|
54
|
-
bp
|
55
|
-
end
|
56
|
-
|
57
|
-
#
|
58
|
-
# Adds a file breakpoint.
|
59
|
-
#
|
60
|
-
def add_file(file, line, expression = nil)
|
61
|
-
real_file = (file != Pry.eval_path)
|
62
|
-
fail(ArgumentError, 'Invalid file!') if real_file && !File.exist?(file)
|
63
|
-
validate_expression expression
|
64
|
-
|
65
|
-
path = (real_file ? File.expand_path(file) : file)
|
66
|
-
bp = FileBreakpoint.new Byebug::Breakpoint.add(path, line, expression)
|
67
|
-
breakpoints << bp
|
68
|
-
bp
|
69
|
-
end
|
70
|
-
|
71
|
-
#
|
72
|
-
# Changes the conditional expression for a breakpoint.
|
73
|
-
#
|
74
|
-
def change(id, expression = nil)
|
75
|
-
validate_expression expression
|
76
|
-
|
77
|
-
breakpoint = find_by_id(id)
|
78
|
-
breakpoint.expr = expression
|
79
|
-
breakpoint
|
80
|
-
end
|
81
|
-
|
82
|
-
#
|
83
|
-
# Deletes an existing breakpoint with the given ID.
|
84
|
-
#
|
85
|
-
def delete(id)
|
86
|
-
deleted = Byebug.started? &&
|
87
|
-
Byebug::Breakpoint.remove(id) && breakpoints.delete(find_by_id(id))
|
88
|
-
fail(ArgumentError, "No breakpoint ##{id}") unless deleted
|
89
|
-
end
|
90
|
-
|
91
|
-
#
|
92
|
-
# Deletes all breakpoints.
|
93
|
-
#
|
94
|
-
def delete_all
|
95
|
-
@breakpoints = []
|
96
|
-
Byebug.breakpoints.clear if Byebug.started?
|
97
|
-
end
|
98
|
-
|
99
|
-
#
|
100
|
-
# Enables a disabled breakpoint with the given ID.
|
101
|
-
#
|
102
|
-
def enable(id)
|
103
|
-
change_status id, true
|
104
|
-
end
|
105
|
-
|
106
|
-
#
|
107
|
-
# Disables a breakpoint with the given ID.
|
108
|
-
#
|
109
|
-
def disable(id)
|
110
|
-
change_status id, false
|
111
|
-
end
|
112
|
-
|
113
|
-
#
|
114
|
-
# Disables all breakpoints.
|
115
|
-
#
|
116
|
-
def disable_all
|
117
|
-
each do |breakpoint|
|
118
|
-
breakpoint.enabled = false
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def to_a
|
123
|
-
breakpoints
|
124
|
-
end
|
125
|
-
|
126
|
-
def size
|
127
|
-
to_a.size
|
128
|
-
end
|
129
|
-
|
130
|
-
def each(&block)
|
131
|
-
to_a.each(&block)
|
132
|
-
end
|
133
|
-
|
134
|
-
def find_by_id(id)
|
135
|
-
breakpoint = find { |b| b.id == id }
|
136
|
-
fail(ArgumentError, "No breakpoint ##{id}!") unless breakpoint
|
137
|
-
breakpoint
|
138
|
-
end
|
139
|
-
|
140
|
-
private
|
141
|
-
|
142
|
-
def change_status(id, enabled = true)
|
143
|
-
breakpoint = find_by_id(id)
|
144
|
-
breakpoint.enabled = enabled
|
145
|
-
breakpoint
|
146
|
-
end
|
147
|
-
|
148
|
-
def validate_expression(exp)
|
149
|
-
return unless exp && (exp.empty? || !Pry::Code.complete_expression?(exp))
|
150
|
-
|
151
|
-
fail("Invalid breakpoint conditional: #{expression}")
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|