Use a Pry before_session hook as described in the Pry wiki article on hooks.
A before_session hook is executed before dropping you into the REPL when binding.pry is called. Pry uses a before_session hook every time you invoke binding.pry to call whereami --quiet, like you have in your post:
From: /opt/hobbyonrails/spec/support/alias.rb:12 :
7:
8: rspec.before(:example, pry: true) do |_|
9: # rubocop:disable Lint/Debugger
10: binding.pry
11: # rubocop:enable Lint/Debugger
=> 12: end
13: end
The idea of using a before_session hook to solve your problem is to tell Pry that when it is invoked it should automatically call step 25. (or however many steps you need)
It gets a little bit tricky though because the step command from pry-byebug actually invokes a new Pry session. If you add a before_session hook that calls step, and step then invokes a new session, you'll get caught in a loop that steps through until the program finishes executing.
Another issue is that any invocation of binding.pry in your code that is executed after the hook is added will invoke step again, and you probably don't want it to step every time, just in one particular spot.
The fix for this is to add a hook that removes itself when executed:
Pry.hooks.add_hook(:before_session, 'step') do |output, binding, pry|
Pry.hooks.delete_hook(:before_session, 'step')
pry.run_command('step 1')
end
Now the flow should be:
- The hook above is added
binding.pry is invoked
- The hook above is executed, removing the hook and running
step 1
step invokes a new Pry session
- The hook above is no longer present and is not executed
- The REPL opens
- Any further
binding.pry invocations do not execute the hook
Here is an example app to show how this would work:
require 'pry'
require 'pry-byebug'
Pry.hooks.add_hook(:before_session, 'step') do |output, binding, pry|
Pry.hooks.delete_hook(:before_session, 'step')
pry.run_command('step 1')
end
binding.pry
puts 'Pry will run `whereami` and point at this line with => first'
puts 'But when the hook runs it will step to and point at this line with =>'
puts 'And it will stop before it reaches this line'
binding.pry
puts 'And after this second binding, there will be no hook and thus no step'
puts 'And it will stop before it reaches this line'
And here's its output demonstrating that it works as described:
$ ruby foo.rb
From: /Users/foo/foo.rb:10 :
5: Pry.hooks.delete_hook(:before_session, 'step')
6: pry.run_command('step 1')
7: end
8:
9: binding.pry
=> 10: puts 'Pry will run `whereami` and point at this line with => first'
11: puts 'But when the hook runs it will step to and point at this line with =>'
12: puts 'And it will stop before it reaches this line'
13:
14: binding.pry
15: puts 'And after this second binding, there will be no hook and thus no step'
Pry will run `whereami` and point at this line with => first
From: /Users/foo/foo.rb:11 :
6: pry.run_command('step 1')
7: end
8:
9: binding.pry
10: puts 'Pry will run `whereami` and point at this line with => first'
=> 11: puts 'But when the hook runs it will step to and point at this line with =>'
12: puts 'And it will stop before it reaches this line'
13:
14: binding.pry
15: puts 'And after this second binding, there will be no hook and thus no step'
16: puts 'And it will stop before it reaches this line'
foo|(main):1 ⇒ exit
But when the hook runs it will step to and point at this line with =>
And it will stop before it reaches this line
From: /Users/foo/foo.rb:15 :
10: puts 'Pry will run `whereami` and point at this line with => first'
11: puts 'But when the hook runs it will step to and point at this line with =>'
12: puts 'And it will stop before it reaches this line'
13:
14: binding.pry
=> 15: puts 'And after this second binding, there will be no hook and thus no step'
16: puts 'And it will stop before it reaches this line'
foo|(main):1 ⇒
Integrating this into your app should be pretty straightforward:
rspec.before(:example, pry: true) do |_|
# rubocop:disable Lint/Debugger
# You should find a good way to set this value as it seems likely to change
steps = 25
Pry.hooks.add_hook(:before_session, 'step') do |output, binding, pry|
Pry.hooks.delete_hook(:before_session, 'step')
pry.run_command("step #{steps}")
end
binding.pry
# rubocop:enable Lint/Debugger
end