[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

IRB module with non-blocking asynchronous gets

Shane Liesegang

8/25/2007 8:09:00 AM

Is there a way to use the IRB module so that it evaluates code on-demand
only instead of running in a constant loop?

I don't need to use readline and have IRB wait for input -- I can
trigger its need to evaluate from elsewhere in the program. I was
hoping, though, that I could have the gets function from my
IRB::StdioInputMethod subclass return a properly formatted string, let
IRB do its thing, and then give me back control until it was needed
again.

It seems, though, that the eval_input function just keeps executing gets
and never returns control. I understand that's the intended behavior of
eval_input, but I'm a little surprised there's not a more asynchronous
way of requesting evaluation.

Am I just approaching the problem from the wrong angle? I keep feeling
like Ruby has to provide a way to do what I'm after, but I haven't been
able to track it down thus far.

Any help would be appreciated.
--
Posted via http://www.ruby-....

7 Answers

James Gray

8/26/2007 3:18:00 AM

0

On Aug 25, 2007, at 3:09 AM, Shane Liesegang wrote:

> Is there a way to use the IRB module so that it evaluates code on-
> demand
> only instead of running in a constant loop?

I'm working on my glue code speech for Lone Star Rubyconf today so my
first thought was:

#!/usr/bin/env ruby -wKU

class IRbOnDemand
def initialize
@irb = IO.popen("irb -f --simple-prompt --noreadline", "r+")
end

def run(ruby)
@irb.puts ruby
@irb.flush

@irb.each do |line|
return eval($1) if line =~ /\A=>\s*(.+)/
end
end
end

irb = IRbOnDemand.new
result = irb.run %Q{a = %w[words] * 3}
puts "Result: #{result.inspect}"

puts "Doing other things..."
sleep 3

result = irb.run %Q{a}
puts "Result: #{result.inspect}"

__END__

Is that what you are after? If it is, do we really need IRb at all?
How's this:

#!/usr/bin/env ruby -wKU

class IRbOnDemand
def initialize
@binding = binding
end

def run(ruby)
eval ruby, @binding
end
end

irb = IRbOnDemand.new
result = irb.run %Q{a = %w[words] * 3}
puts "Result: #{result.inspect}"

puts "Doing other things..."
sleep 3

result = irb.run %Q{a}
puts "Result: #{result.inspect}"

__END__

James Edward Gray II


Shane Liesegang

8/27/2007 2:46:00 PM

0

Hi James. Thanks for the recommendations.

James Gray wrote:
>
> Is that what you are after? If it is, do we really need IRb at all?
> How's this:

I could just use eval to run the strings; that's true. I was hoping to
leverage IRB's prompt mechanism and the ability to define functions on
the fly. As below:

-----
irb(main):001:0> def test
irb(main):002:1> puts "testing..."
irb(main):003:1> end
=> nil
irb(main):004:0> test
testing...
=> nil
irb(main):005:0>
-----

I'm finding that it's pretty tricky, though. I managed to make it
non-blocking for a single line by overriding eval_input and having it
break after evaluating a line instead of waiting for input. That seems
to work fine, but when doing any kind of multi-line input, it still goes
into a loop that it doesn't want to return from.

It seems like IRB, to its core, is based on constantly waiting for
input, and trying to make it work in an on-demand fashion is like
running uphill. I'm still rooting through its source, trying to find the
spots where I can poke at it to make it work that way, but it's slow
going with a large mass of interrelated code that's not terribly easy
for humans to parse. :-)
--
Posted via http://www.ruby-....

Giles Bowkett

8/28/2007 1:52:00 AM

0

go with #eval, it makes it dead simple:

>> arbitrary_code = <<-MUPPETS
def muppets
"muppets"
end
MUPPETS
=> "def muppets\n "muppets"\nend\n"
>> muppets
NameError: undefined local variable or method `muppets' for main:Object
from (irb):6
>> eval(arbitrary_code)
=> nil
>> muppets
=> "muppets"

is that what you need, basically?

--
Giles Bowkett

Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles.t...

Shane Liesegang

8/28/2007 5:42:00 PM

0

Giles Bowkett wrote:
>
> is that what you need, basically?

Close, but it doesn't let me enter arbitrary lines of input and know
whether they need to be joined to execution or can be executed
individually, the way IRB does.

I've got the majority of my desired behavior now, by applying some
patches to RubyLex: http://pastie.cabo...

When the user presses enter, I call get_statement on the lexer, which
either returns the line and line number if it's ready for execution or
nil if it's not.

The only thing this doesn't currently handle is string continuations --
once again, IRB happily enters an infinite loop when it detects an
incomplete string in a line. I would like to hit this border case as
well, but it's looking like it's going to require some pretty deep digs
into the lexing code. It doesn't terribly excite me, and I don't
personally use string continuation very much, so I'm tempted to just
call it a halfway-victory.

Unless there are some particularly knowledgeable IRB hackers waiting in
the wings to offer advice...
--
Posted via http://www.ruby-....

Giles Bowkett

8/28/2007 10:56:00 PM

0

> Unless there are some particularly knowledgeable IRB hackers waiting in
> the wings to offer advice...

I wish! I know a bunch of IRB tricks and tidbits but this is getting
pretty deep into IRB internals.

--
Giles Bowkett

Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles.t...

Shane Liesegang

8/29/2007 6:09:00 PM

0

For anyone still reading this thread (or who stumbles across it in the
future), I have been able to solve the string continuation problem -- it
may be a bit inefficient, but I run my own processing on the line before
trying to pass it to the lexer. If I determine that it's the start of a
string continuation, I set the flags appropriately.

No code in pastie this time, but the algorithm for finding unfinished
strings is pretty straightforward, provided you cover all the cases
provided in Ruby (single quotes, double quotes, %q, %w, %x, %Q, %W, %X,
and heredocs).

I leave it as an exercise to the reader. :-)
--
Posted via http://www.ruby-....

The Peeler

2/18/2011 12:11:00 PM

0

On Fri, 18 Feb 2011 06:27:39 +0100, Dumb Heini, the Dutch resident Nazi
troll of sci and scj, wrote:

>>>
>>> The USS Enterprise Carrier Strike Group transited the Suez Canal February
>>> 15, 2011 on a pre-planned mission to the Fifth Fleet area to help with
>>> operations in Afghanistan and Iraq, according to the US military source.
>>>
>>
>> Nazi swine like you deserve islamofascism.
>>
>>
>
> thank you for your kind words, now continue to lick jew balls

Sounds like you've finally accepted that everyone (mis)treats you as a piece
of shit troll, Dumb Dutch Nazi Heini. You will have to "accept" a lot more
still, you abysmally stupid Dutch Nazi moron! Trust me! <BG>


--
Dumb Heini about himself: "i was diagnozed with the syndromeof asperger, no
idea what it means but i am feelingperfectly oke"
MID: <7u8b41FjtnU1@mid.individual.net>