stdlib_libraries/irb_terminal_no_parens.rb
tests/_examples/stdlib_libraries/irb_terminal_no_parens.rb in the metorex repository.
# irb on a terminal reads each line through reline, which completes a name
# on Tab, and `exit` ends the session.
require "pty"
require "rbconfig"
require "tmpdir"
transcript = +""
status = nil
Dir.mktmpdir do |home|
environment = {"HOME" => home, "TERM" => "xterm-256color", "IRBRC" => nil, "XDG_CONFIG_HOME" => nil}
PTY.spawn(environment, RbConfig.ruby, "-e", "require 'irb'; IRB.start") do |reader, writer, pid|
read_until = lambda do |pattern|
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 60
until transcript.match?(pattern) || Process.clock_gettime(Process::CLOCK_MONOTONIC) > deadline
next unless IO.select([reader], nil, nil, 0.2)
begin
transcript << reader.read_nonblock(4096)
rescue IO::WaitReadable
rescue EOFError, Errno::EIO
break
end
end
end
read_until.(/irb\(main\):001/)
["rate = 7\r", "rat\t * 2\r", "[1, 2].fir\t\r"].each_with_index do |line, index|
writer.write(line)
read_until.(/irb\(main\):#{format("%03d", index + 2)}/)
end
writer.write("exit\r")
read_until.(/exit\r\r\n/)
Process.wait(pid)
status = $?.exitstatus
end
end
shown = transcript.b.gsub(/\e\[[0-9;?]*[A-Za-z]/n, "").delete("\r")
shown = shown[shown.index("irb(main):001")..]
puts shown.lines.map(&:chomp).reject(&:empty?).uniq
p status
Output:
irb(main):001> irb(main):001> rate = 7
=> 7
irb(main):002> irb(main):002> rate * 2
=> 14
irb(main):003> irb(main):003> [1, 2].first
=> 1
irb(main):004> irb(main):004> exit
0