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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8123f22dc42ff24f284f47d77bdf74679b8025c2
4
- data.tar.gz: 1803eaf3cc4e019e64ce84835bb0a288cef8cebe
3
+ metadata.gz: c42e1d5a58d90aa640bcd1e79be383d78286fc66
4
+ data.tar.gz: 32cf706c69453f75a70729fa4caf95b023642379
5
5
  SHA512:
6
- metadata.gz: eecedab14af1c1eddfc82d5828a4418a239691b6ef27f67e4340458054e0646edd049ded5cde2dc1ef10efe72bf2abb70b4c759a1145710c2e25b9e59b3faeec
7
- data.tar.gz: 33135d020dc22bf50e1a8f57b39a5dce8f5e8c1373cd8f380500a210b8199bf05a5c90084f286c2d003b2379703e025fe63d80465b2007dfa3d10b68849a0495
6
+ metadata.gz: d4e5826a3e0d91869ff79953c45e475d0ecb5252e50171a5ad18f8a667625558690af3b00e09d0b8ccb68c55257e5bc0f285edb85334388fd7a4b8ea9c6ce826
7
+ data.tar.gz: e87f0c3fe28da82b42e2146c108ae73b0832b4bc10d1f1b54baaefccf639580d8874cc5c7a1149fbd46500969ce3b55bd4e13b81531f1d05913735ad389fd193
@@ -1,2 +1,12 @@
1
1
  Lint/Debugger:
2
+ Exclude:
3
+ - test/examples/*.rb
4
+
5
+ Style/FileName:
6
+ Exclude:
7
+ - lib/pry-byebug.rb
8
+ - lib/pry-byebug/cli.rb
9
+ - test/test_helper.rb
10
+
11
+ Style/ModuleFunction:
2
12
  Enabled: false
@@ -1,7 +1,9 @@
1
1
  rvm:
2
2
  - 2.0.0
3
3
  - 2.1
4
+ - 2.2
4
5
  - ruby-head
6
+
5
7
  matrix:
6
8
  allow_failures:
7
9
  - rvm: ruby-head
@@ -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
@@ -5,7 +5,7 @@ gemspec
5
5
  gem 'rake', '~> 10.3'
6
6
 
7
7
  group :development do
8
- gem 'rubocop', '~> 0.25'
8
+ gem 'rubocop', '~> 0.26'
9
9
  end
10
10
 
11
11
  group :test do
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
- binding.pry # Execution will stop here.
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. Aliased to `s`
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. Aliased to `n`
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
- **finish:** Execute until current stack frame returns. Aliased to `f`
55
+ ## Matching Byebug Behaviour
46
56
 
47
- **continue:** Continue program execution and end the Pry session. Aliased to `c`
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
- break # List all breakpoints. (Same as `breakpoints`)
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.png
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.png
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 PryByebug
4
+ module Byebug
5
5
  #
6
6
  # Extends raw byebug's processor.
7
7
  #
8
- class Processor < Byebug::Processor
8
+ class PryProcessor < Processor
9
9
  attr_accessor :pry
10
10
 
11
- def initialize(interface = Byebug::LocalInterface.new)
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
- def run(initial = false, &_block)
24
+ #
25
+ def run(&_block)
19
26
  return_value = nil
20
27
 
21
- if initial
22
- Byebug.start
23
- Byebug.current_context.step_out(3)
24
- else
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
- if [:step, :next, :finish].include? command[:action]
34
- @pry = command[:pry] # Pry instance to resume after stepping
33
+ # Pry instance to resume after stepping
34
+ @pry = command[:pry]
35
35
 
36
- if :next == command[:action]
37
- Byebug.current_context.step_over(times, 0)
36
+ perform(command[:action], (command[:times] || '1').to_i)
38
37
 
39
- elsif :step == command[:action]
40
- Byebug.current_context.step_into(times)
38
+ return_value
39
+ end
41
40
 
42
- elsif :finish == command[:action]
43
- Byebug.current_context.step_out(times)
44
- end
45
- end
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(false) do
100
+ run do
97
101
  if @pry
98
102
  @pry.repl(new_binding)
99
103
  else
@@ -1,3 +1,4 @@
1
1
  require 'pry-byebug/base'
2
2
  require 'pry-byebug/pry_ext'
3
- require 'pry-byebug/commands'
3
+ require 'pry/commands/stepping'
4
+ require 'pry/commands/breakpoint'
@@ -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. Extracted from
6
+ # Checks that a target binding is in a local file context.
4
7
  #
5
- def check_file_context(target)
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.
@@ -1,19 +1,16 @@
1
1
  require 'pry'
2
- require 'pry-byebug/processor'
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 ||= PryByebug::Processor.new
9
+ @processor ||= Byebug::PryProcessor.new
10
10
 
11
- if target.is_a?(Binding) && PryByebug.check_file_context(target)
12
- # Wrap the processor around the usual Pry.start to catch navigation
13
- # commands.
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 PryByebug::Processor#run,
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
@@ -1,3 +1,6 @@
1
+ #
2
+ # Main container module for Pry-Byebug functionality
3
+ #
1
4
  module PryByebug
2
- VERSION = '2.0.0'
5
+ VERSION = '3.0.0'
3
6
  end
@@ -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-byebug/breakpoints'
2
+ require 'pry/byebug/breakpoints'
3
3
 
4
4
  #
5
- # Container for all of pry-byebug's functionality
5
+ # Main Pry class.
6
6
  #
7
- module PryByebug
8
- Commands = Pry::CommandSet.new do
9
- create_command 'step' do
10
- description 'Step execution into the next line or method.'
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
- Breakpoints.send(command, opts[command])
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
- Breakpoints.send(method_name)
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(Breakpoints.find_by_id(opts[:show]))
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
- Breakpoints.change(opts[:condition], expr)
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
- Breakpoints.add_file(target.eval('__FILE__'), line.to_i, condition)
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
- Breakpoints.add_file(file, lineno, condition)
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
- Breakpoints.add_method(place, condition)
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
- errmsg = 'No breakpoints defined.'
211
- return output.puts text.bold(errmsg) unless Breakpoints.count > 0
137
+ if breakpoints.count == 0
138
+ return output.puts(text.bold('No breakpoints defined.'))
139
+ end
212
140
 
213
141
  if opts.verbose?
214
- Breakpoints.each { |b| print_full_breakpoint(b) }
142
+ breakpoints.each { |b| print_full_breakpoint(b) }
215
143
  else
216
- output.puts
217
144
  print_breakpoints_header
218
- Breakpoints.each { |b| print_short_breakpoint(b) }
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
- def breakout_navigation(action, times = nil)
227
- _pry_.binding_stack.clear # Clear the binding stack.
228
-
229
- # Break out of the REPL loop and signal tracer
230
- throw :breakout_nav, action: action, times: times, pry: _pry_
152
+ #
153
+ # Byebug's array of breakpoints.
154
+ #
155
+ def breakpoints
156
+ Byebug::Breakpoints
231
157
  end
232
158
 
233
- # Ensures that a command is executed in a local file context.
234
- def check_file_context(e = nil)
235
- e ||= 'Cannot find local context. Did you use `binding.pry`?'
236
- fail(Pry::CommandError, e) unless PryByebug.check_file_context(target)
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(breakpoint)
245
- output.print text.bold("Breakpoint #{breakpoint.id}: ")
246
- output.print "#{breakpoint} "
247
- output.print breakpoint.enabled? ? '(Enabled)' : '(Disabled)'
248
- output.puts ' :'
249
- if (expr = breakpoint.expr)
250
- output.puts "#{text.bold('Condition:')} #{expr}"
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
- output.printf "%#{max_width}d ", breakpoint.id
262
- output.print breakpoint.enabled? ? 'Yes ' : 'No '
263
- output.print breakpoint.to_s
264
- output.print " (if #{breakpoint.expr})" if breakpoint.expr
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 text.bold(header)
275
- output.puts text.bold('-' * header.size)
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(Breakpoints.count).ceil, 1].max
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 PryByebug::Commands
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
@@ -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.check_file_context(TOPLEVEL_BINDING)
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.check_file_context(TOPLEVEL_BINDING)
14
+ refute PryByebug.file_context?(TOPLEVEL_BINDING)
15
15
  end
16
16
  end
@@ -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, PryByebug::Processor.new do
25
- PryByebug::Breakpoints.add_method 'BreakpointsTest::Tester#instance_method'
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, PryByebug::Processor.new do
34
- PryByebug::Breakpoints.add_method 'BreakpointsTest::Tester.class_method'
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
@@ -0,0 +1,9 @@
1
+ #
2
+ # Toy program for testing binding.pry initialization
3
+ #
4
+
5
+ new_str = 'string'.gsub!(/str/) do |_|
6
+ binding.pry
7
+ end
8
+
9
+ new_str
@@ -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: 2.0.0
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: 2014-09-01 00:00:00.000000000 Z
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.1
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