Can a program be made to drop into irb?

G

Gavin Sinclair

I'd like to be able to write a program that, halfway through
execution, stops what it's doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it's possible? My instinct says it's probably
not. If that's the case, I'd like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

Cheers,
Gavin
 
D

David Alan Black

Hi --

Gavin Sinclair said:
I'd like to be able to write a program that, halfway through
execution, stops what it's doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it's possible? My instinct says it's probably
not. If that's the case, I'd like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

$ ruby -e 'require "irb"; print "irb? "; IRB.start if /y/.match(gets)'
irb? yes
irb(main):001:0>

New scope, of course, but still running same program. I don't know
that there's any way to get local variables involved, except maybe
grabbing the binding directly.


David
 
R

Robert Klemme

David Alan Black said:
Hi --



$ ruby -e 'require "irb"; print "irb? "; IRB.start if /y/.match(gets)'
irb? yes
irb(main):001:0>

New scope, of course, but still running same program. I don't know
that there's any way to get local variables involved, except maybe
grabbing the binding directly.

The program could provide a callback in some global var that presents all
interesting infos. Of course, locals were still not (directly)
accessible, but one could hack something together using set_trace_func.

Otherwise it might be better to use the debugger anyway...

Regards

robert
 
A

Ara.T.Howard

I'd like to be able to write a program that, halfway through
execution, stops what it's doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it's possible? My instinct says it's probably
not. If that's the case, I'd like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

Cheers,
Gavin



~ > cat a.rb
require 'irb'
a, b = 4, 2
begin
c = 42
syntax_error
rescue Exception => e
IRB.setup nil
IRB::Irb.new(IRB::WorkSpace.new(binding),nil).eval_input
end


~ > ruby a.rb
irb(main):001:0> p a,b,c
4
2
42
=> nil


i confess i have no idea how this works, but it seems to... you need to type
ctrl-D to get out (end STDIN), i'm not sure how to get back into the program...
perhaps someone else could figure it out...

a shorthand for this would be immensely useful - something like

ret = IRB.debug

....

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
G

Gavin Sinclair

On Wednesday, May 5, 2004, 12:03:56 AM, Ara.T.Howard wrote:

~ >> cat a.rb
require 'irb'
a, b = 4, 2
begin
c = 42
syntax_error rescue Exception =>> e
IRB.setup nil
IRB::Irb.new(IRB::WorkSpace.new(binding),nil).eval_input
end


~ >> ruby a.rb
irb(main):001:0>> p a,b,c
=>> nil

i confess i have no idea how this works, but it seems to... you need to type
ctrl-D to get out (end STDIN), i'm not sure how to get back into the program...
perhaps someone else could figure it out...
a shorthand for this would be immensely useful - something like
ret = IRB.debug


Well, that's a good start. Getting back to the program would be
handy.

Then calling IRB.debug is like using a debugger, except the
breakpoints are in the code, which I think is a good thing to be able
to do.

Gavin
 
P

Phil Tomson

Hi --



$ ruby -e 'require "irb"; print "irb? "; IRB.start if /y/.match(gets)'
irb? yes
irb(main):001:0>

New scope, of course, but still running same program. I don't know
that there's any way to get local variables involved, except maybe
grabbing the binding directly.

It would be cool if you could pass in the current binding to IRB.start.
Is that possible?

Phil
 
J

Joel VanderWerf

This is what I use to break from a program into an irb shell. I set my
app's interrupt handler to call it, and then reset the interrupt handler
when it is done (where noted). You can go back and forth between app and
shell with ^C and ^D. I usually add some methods to the object that gets
passed to start_session: #help, #commands, methods to pipe data to
gnuplot, etc.

Ara's idea to pass a binding to Workspace.new is great. Changes to
locals are even persistent after you leave the shell. I'm puzzled about
why that works--maybe irb detects that the object is a binding?

--

#!/usr/bin/env ruby

require 'irb'
require 'irb/completion'

module IRB
def IRB.parse_opts
# Don't touch ARGV, which belongs to the app which called this module.
end

def IRB.start_session(object)
unless $irb
IRB.setup nil
## maybe set some opts here, as in parse_opts in irb/init.rb?
end

workspace = WorkSpace.new(object)

if @CONF[:SCRIPT] ## normally, set by parse_opts
$irb = Irb.new(workspace, @CONF[:SCRIPT])
else
$irb = Irb.new(workspace)
end

@CONF[:IRB_RC].call($irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = $irb.context

trap 'INT' do
$irb.signal_handle
end

custom_configuration if defined?(IRB.custom_configuration)

catch :IRB_EXIT do
$irb.eval_input
end

## might want to reset your app's interrupt handler here
end
end

class Object
include IRB::ExtendCommandBundle # so that Marshal.dump works
end

if __FILE__ == $0
x = Object.new
puts "\nStarted irb shell for x"
IRB.start_session(x)
puts "\nStarted irb shell for current binding"
IRB.start_session(binding)
puts "\nExited irb shell"
p x
end
 
J

Joel VanderWerf

Joel said:
Ara's idea to pass a binding to Workspace.new is great. Changes to
locals are even persistent after you leave the shell. I'm puzzled about
why that works--maybe irb detects that the object is a binding?

Yes, that's what irb does. In irb/workspace.irb:

module IRB
class WorkSpace
# create new workspace. set self to main if specified, otherwise
# inherit main from TOPLEVEL_BINDING.
def initialize(*main)
if main[0].kind_of?(Binding)
@binding = main.shift

So you can get two useful effects with WorkSpace.new:

WorkSpace.new(obj)

Makes obj the self of a new workspace.

WorkSpace.new(b, obj)

Makes obj the self of a new workspace, and uses b as the binding.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top