Class: TuiTui::KeyReader
- Inherits:
-
Object
- Object
- TuiTui::KeyReader
- Defined in:
- lib/tui_tui/key_reader.rb
Overview
Decodes raw-mode terminal input into literal keys, named keys, and mouse events.
Constant Summary collapse
- ESCAPES =
{ "\e[A" => :up, "\e[B" => :down, "\e[C" => :right, "\e[D" => :left, "\eOA" => :up, "\eOB" => :down, "\eOC" => :right, "\eOD" => :left, "\e[H" => :home, "\e[F" => :end, "\eOH" => :home, "\eOF" => :end, "\e[1~" => :home, "\e[4~" => :end, "\e[5~" => :pgup, "\e[6~" => :pgdn, "\e[3~" => :delete, "\e[Z" => :backtab }.freeze
- ESCAPE_TAIL_BYTES =
256- MOUSE =
SGR mouse reports can grow with coordinate length; decode the first report if several drag reports arrive in one non-blocking read.
/\A\[<(\d+);(\d+);(\d+)([Mm])/.freeze
- MOUSE_MOTION =
0x20- MOUSE_WHEEL =
0x40- MODIFIED =
A modified special key arrives as a CSI with a “1;<mod>” parameter, e.g. Ctrl+Right = “e[1;5C”, Shift+Up = “e[1;2A”, Ctrl+Delete = “e[3;5~”. MOD encodes the held modifiers as (1 + Shift(1) + Alt(2) + Ctrl(4)).
/\A\[(\d*);(\d+)([A-Za-z~])/.freeze
- MOD_LETTER =
{"A" => :up, "B" => :down, "C" => :right, "D" => :left, "H" => :home, "F" => :end}.freeze
- MOD_TILDE =
{1 => :home, 3 => :delete, 4 => :end, 5 => :pgup, 6 => :pgdn, 7 => :home, 8 => :end}.freeze
- MOD_BITS =
{shift: 1, alt: 2, ctrl: 4}.freeze
Instance Method Summary collapse
- #decode_escape(rest) ⇒ Object
-
#decode_escape_events(rest) ⇒ Object
Decode a whole ESC tail into events, batching consecutive mouse reports (and otherwise yielding a single key/escape).
-
#read(io) ⇒ Object
One keypress/event from ‘io` (String, Symbol, or MouseEvent), nil at EOF.
- #read_all(io) ⇒ Object
Instance Method Details
#decode_escape(rest) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/tui_tui/key_reader.rb', line 58 def decode_escape(rest) return :escape if rest.nil? || rest.empty? mouse = decode_mouse(rest) return mouse if mouse modified = decode_modified(rest) return modified if modified ESCAPES["\e" + rest] || :escape end |
#decode_escape_events(rest) ⇒ Object
Decode a whole ESC tail into events, batching consecutive mouse reports (and otherwise yielding a single key/escape).
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/tui_tui/key_reader.rb', line 72 def decode_escape_events(rest) return [:escape] if rest.nil? || rest.empty? mice = [] remainder = rest loop do remainder = remainder.sub(/\A\e/, "") match = MOUSE.match(remainder) or break mice << mouse_event_from(match) remainder = match.post_match end mice.empty? ? [decode_escape(rest)] : mice end |
#read(io) ⇒ Object
One keypress/event from ‘io` (String, Symbol, or MouseEvent), nil at EOF.
47 |
# File 'lib/tui_tui/key_reader.rb', line 47 def read(io) = read_all(io)&.first |
#read_all(io) ⇒ Object
49 50 51 52 53 54 55 56 |
# File 'lib/tui_tui/key_reader.rb', line 49 def read_all(io) first = io.getch return nil if first.nil? return decode_escape_events(read_escape_tail(io)) if first == KeyCode::ESCAPE return [assemble_utf8(io, first)] if first.bytesize == 1 && first.getbyte(0) >= 0x80 [first] end |