# IRB module with non-blocking asynchronous gets

**URL:** <https://rubytalk.org/t/irb-module-with-non-blocking-asynchronous-gets/40180>\
**Category:** ruby-talk\
**Created:** [25 August 2007 08:09 UTC](https://rubytalk.org/t/irb-module-with-non-blocking-asynchronous-gets/40180 "2007-08-25T08:09:17Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shane\_Liesegang](https://avatars.discourse-cdn.com/v4/letter/s/d9b06d/32.png) [@Shane\_Liesegang](https://rubytalk.org/u/Shane_Liesegang)\
**Post date:** [25 August 2007 08:09 UTC](https://rubytalk.org/t/irb-module-with-non-blocking-asynchronous-gets/40180/1 "2007-08-25T08:09:17Z")

</div>

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-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [26 August 2007 03:17 UTC](https://rubytalk.org/t/irb-module-with-non-blocking-asynchronous-gets/40180/2 "2007-08-26T03:17:36Z")

</div>

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  
&nbsp;&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@irb = IO.popen("irb -f --simple-prompt --noreadline", "r+")  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def run(ruby)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@irb.puts ruby  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@irb.flush

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@irb.each do |line|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return eval($1) if line =~ /\A=\>\s\*(.+)/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;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  
&nbsp;&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@binding = binding  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def run(ruby)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eval ruby, @binding  
&nbsp;&nbsp;&nbsp;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

> **···**
>
> 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?

---

<div class="post-metadata">

**Author:** ![Shane\_Liesegang](https://avatars.discourse-cdn.com/v4/letter/s/d9b06d/32.png) [@Shane\_Liesegang](https://rubytalk.org/u/Shane_Liesegang)\
**Post date:** [27 August 2007 14:46 UTC](https://rubytalk.org/t/irb-module-with-non-blocking-asynchronous-gets/40180/3 "2007-08-27T14:46:05Z")

</div>

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-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Shane\_Liesegang](https://avatars.discourse-cdn.com/v4/letter/s/d9b06d/32.png) [@Shane\_Liesegang](https://rubytalk.org/u/Shane_Liesegang)\
**Post date:** [29 August 2007 18:08 UTC](https://rubytalk.org/t/irb-module-with-non-blocking-asynchronous-gets/40180/4 "2007-08-29T18:08:45Z")

</div>

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-forum.com/](http://www.ruby-forum.com/).
