ruby / irb

interactive Ruby
BSD 2-Clause "Simplified" License
393 stars 119 forks source link

Add disable_irb command to disable debug of binding.irb #898

Closed hogelog closed 8 months ago

hogelog commented 8 months ago

This PR is a proposal to add the command disable_irb, which is equivalent to the command disble-pry in pry.

Background

I often debug my programs with lots of binding.irb. Then, after I have finished debugging, the binding.irb I have planted sometimes makes it difficult to terminate the process normally.

Here is an extreme example.

$ ruby -e '100.times{ binding.irb }'
irb(main):001> exit
irb(main):001> exit
irb(main):001> exit
... # 100 times exit required!

I often use the following workaround.

$ ruby -e '1000.times{ binding.irb }'
irb(main):001> class ::Binding; def irb; end; end
=> :irb
irb(main):002> exit

Proposal

With disable_irb to be added in this PR, it is easy to skip binding.irb called in a large number of loops, as shown below.

$ ruby -e '1000.times{ binding.irb }'
irb(main):001> disable_irb
hogelog commented 8 months ago

Yay, thank you 🎉

paracycle commented 8 months ago

Pry used to have a really nice !!! command that would unconditionally exit the process and I'd been using exit! (which comes from Kernel) to do the same in irb. That works really well without needing this kind of extra command.

Actually, if any extra commands will be added, I would really like to see the equivalent of !!! to be added.

tompng commented 8 months ago

We already have exit! command equivalent to Pry's !!!. Added in https://github.com/ruby/irb/pull/851 The difference between Kernel.exit! is Kernel.exit! skips every callbacks like ensure statement, at_exit, IRB's history saving, and all other cleanups. exit! command executes Kernel.exit internally. Does not skip callbacks, saves IRB's history correctly.

paracycle commented 8 months ago

@tompng Awesome, thanks for linking to that PR, this is great to hear. Indeed Kernel.exit! was just a workaround for me.

Given that exit! exists as a command now, is disable_irb still something useful?

st0012 commented 8 months ago

disable_irb is a combination of the exit command and disabling all subsequent binding.irb invocations. So when used, the program still runs but just ignores later breakpoints.

brandondrew commented 8 months ago

I've always solved this problem by using binding.irb unless $continue in the first place... then I can just set $continue = true to skip all subsequent binding.irb calls.

I guess disable_irb is slightly more convenient... maybe...

chaadow commented 6 months ago
image

I get this :/ , I don't know if I should enable something, but i'm on the latest stable IRB version ( 1.13.1 )

st0012 commented 5 months ago

@chaadow sorry that I accidentally dropped it when working on the command refactorings, which was not detected because there were no tests for it. I've opened https://github.com/ruby/irb/pull/964 to address it.