arizona_terminal_io (arizona v0.4.0)
View SourceLow-level terminal byte helpers -- the arizona complement to OTP's io_ansi,
which only emits output sequences. This module starts on the input side and
has room to grow (CRLF, mouse, ...).
keys/1 translates a raw terminal read into a list of idiomatic keys, so a driver
(see arizona_terminal_driver) can pattern-match on them rather than on raw
bytes:
- a printable character is its code --
a->$a,+->$+, space ->$\\s; - named and escape keys are atoms --
up,down,left,right,enter,tab,backspace,escape,home,'end',page_up,page_down,insert,delete; - modified keys are tuples --
{ctrl, $c}(Ctrl-C),{alt, $a}(Alt-a).
A read can carry several keypresses (fast typing or a paste), so it returns a list.
Covers ASCII + the keys above. Not yet handled (skipped or split per byte): UTF-8
multibyte input and the function-key set (f1..f12); unrecognised escape
sequences are dropped.
Summary
Functions
Decode a raw terminal read into idiomatic keys.
Split a read into its leading decodable bytes and a trailing incomplete escape
sequence. A read may end mid-sequence -- a transport delivers bytes in chunks (the
local TTY reads fixed-size chunks; a network transport fragments on TCP boundaries),
so an escape sequence like \\e[A (an arrow key) can be cut after \\e[. Decoded in
isolation that tail is lost and the next read's A mis-decodes into a spurious $A.
Types
Functions
Decode a raw terminal read into idiomatic keys.
Split a read into its leading decodable bytes and a trailing incomplete escape
sequence. A read may end mid-sequence -- a transport delivers bytes in chunks (the
local TTY reads fixed-size chunks; a network transport fragments on TCP boundaries),
so an escape sequence like \\e[A (an arrow key) can be cut after \\e[. Decoded in
isolation that tail is lost and the next read's A mis-decodes into a spurious $A.
Returns {Complete, Incomplete}: Complete decodes cleanly via keys/1, and a
driver carries Incomplete in its state to prepend to the next read. The incomplete
tail is the trailing bytes of an unfinished CSI (\\e[ + parameter/intermediate
bytes, awaiting a final byte), an unfinished SS3 introducer (\\eO), or a lone
trailing \\e (which could begin any of those). A trailing lone \\e therefore
holds until the next read -- the classic terminal ESC-vs-sequence ambiguity, resolved
here by buffering rather than a timer.
The held tail is capped (real key sequences are tiny): a "CSI" still unfinished
past ~64 bytes is a hostile or garbage stream, not a split key, and holding it
would grow the pending buffer -- rescanned per read -- without bound. Past the
cap the tail is returned in Complete instead, where keys/1 consumes and
drops the unterminated sequence.