1

Is there a way to have IO.select return a single input character without receiving an EOF? I would like to be able to read user input from the keyboard the same way I read from any other stream, like an open TCP socket connection. It would allow me to make an event loop like this:

loop {
  rd, _, _ = IO.select([long_lived_tcp_connection, stdin])

  case rd[0]
  when long_lived_tcp_connection
    handle_server_sent_event(rd[0].read)
  when stdin
    handle_keypress(rd[0].read)
  end
}

I've been looking into io/console but it doesn't quite give me this capability (although IO#getch comes pretty close).

rickyrickyrice
  • 577
  • 3
  • 14

2 Answers2

2

You can set stdin to raw mode (taken from this answer):

begin
  state = `stty -g`
  `stty raw -echo -icanon isig`
  loop do
    rd, _, _ = IO.select([$stdin])
    handle_keypress(rd[0].getc)
  end
ensure
  `stty #{state}`
end

IO#getc returns a single character from stdin. Another option is IO#read_nonblock to read all available data.

Community
  • 1
  • 1
Stefan
  • 109,145
  • 14
  • 143
  • 218
0

To read one character at a time I would use:

STDIN.each_char {|char| p char}
Aurélien Bottazini
  • 3,249
  • 17
  • 26