On 7/17/10, Jean-Julien Fleck <jeanjulien.fleck / gmail.com> wrote:
> Hello,
>
> I'm stuck with a problem concerning IO.popen
> It's not necessarily related to irb but that's a good point where to start.
>
> I'd like to drive irb from ruby using IO.popen. The problem is: each
> time I type something inside irb, I can get one, two or more lines of
> output I'd like to store with no way to know beforehand how many there
> will be.
>
> The thing is: I don't know how to detect when irb has ended its output
> and is waiting for me to give some input.
>
> I tried the following:
>
>   def irb(string)
>     output = ''
>     puts "Trying to talk to irb"
>     IO.popen('irb --simple-prompt','r+') do |io|
>       string.chomp.split.each do |s|
>         io.puts s
>         while line = io.gets
>           line = io.gets
>           puts line
>           output += line
>         end
>       end
>     end
>     return output
>   end
>
>   s = "2+2\n'2'+'2'\n'2'+2"
>
>   irb(s)
>
> I was hoping that io.gets would be nil when irb is waiting for input,
> but it's not. So this little program gets stuck after the first
> statement:
>
> brisingr ~/tmp>ruby essai_irb.rb
> Trying to talk to irb
> => 4
>
> Rather, I would like him to return
>
>>> 2+2
> => 4
>>> '2'+'2'
> => "22"
>>> '2'+2
> TypeError: can't convert Fixnum into String
>         from (irb):4:in `+'
>         from (irb):4
>
> Does someone have a workaround ?

You could try to detect whether irb is waiting based an what prompt it
prints. Alternately, you could use non-blocking io with a timeout to
determine when it is no longer printing anything to output. Neither
method is going to be a sure-fire way to determine when irb is
waiting, but you should be able to come up with something that works
well enough most of the time. You could even combine the 2 for greater
reliability.