I am using Open3's popen3 method to start a process that functions in a console-like / REPL fashion to repeatedly accept input and return output.
I am able to open the process, send input, and receive the output just fine, with code like this:
Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr|
stdin.puts "a string of input"
stdin.close_write
stdout.each_line { |line| puts line } #successfully prints all the output
end
I want to do that many times in a row, without re-opening the process, as it takes a long time to start up.
I know I have to close stdin in order for stdout to return.. but what I don't know is, how do I 'reopen' stdin so I can write more input?
Ideally I want to do something like this:
Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr|
stdin.puts "a string of input"
stdin.close_write
stdout.each_line { |line| puts line }
stdin.reopen_somehow()
stdin.puts "another string of input"
stdin.close_write
stdout.each_line { |line| puts line }
# etc..
end
solution
Thanks to pmoo's answer, I was able to devise a solution using PTY
and expect
, expecting the prompt string that the process returns whenever it is ready for more input, like so:
PTY.spawn("console_REPL_process") do |output, input|
output.expect("prompt >") do |result|
input.puts "string of input"
end
output.expect("prompt >") do |result|
puts result
input.puts "another string of input"
end
output.expect("prompt >") do |result|
puts result
input.puts "a third string of input"
end
# and so forth
end