Reading_keys
Reading keys from the keyboard is a thing of itself.. because no programming language can read the keyboard. Instead they rely on the terminal or the window manager.
A terminal key can be read with Ruby by STDIN.getc
.
If you press Return, the result is \r
.
If you press an arrow-key, the result is \e
.. and it’s the start of an escape sequence. If you read another key, it will return [
.. and the next will return A
, B
, C
or D
for the four arrow keys.
Then you have the -echo
/ -raw
to handle.
Anyway.. to make this simpler, there are options. You can import io/console
; ncursesw
or tty-reader
. I will focus on tty-reader here.
tty-reader Link to heading
A good thing with tty-reader is that you decide what you want to read by the call. You can do read_char
; read_keypress
; read_line
or read_multiline
. And in the call, you can give an option.. like raw: true, echo: false
.
An even better thing is how tty-reader is using whisper
wisper
to create listeners that receives the data produced by the reader.
The third great thing is that you can trigger a listener manually.. without the key being pressed.
Example:
require 'tty-reader'
# here is the reader
reader = TTY::Reader.new
# here is the listener.. it listens for three keys
reader.on(:keyleft, :keyright, :keydown) {|ev|
(ev.key.name == :down) ?
reader.trigger(:keyescape, 'Keydown => Esc triggered !!') :
(print ev.key.name)
}
# here is another listener.. listening for just one key
reader.on(:keyescape) {|ev|
print ev.is_a?(String) ? ev : ev.key.name; puts; exit
}
# the main loop.. reading keypresses
# (blocking since nonblock: true is not given)
loop {
print ' => press a key ... '
reader.read_keypress; puts
}
Each cycle of the loop is waiting for a keypress. If any listener is defined to respond.. the key is handled there. So..
:keyescape
will exit.:keydown
will print ‘:down’ and trigger:keyescape
(where it exists):keyleft
andkeyright
will print ‘:left’ or ‘:right’