class
TermBuf::Decoder
- TermBuf::Decoder
- Reference
- Object
Overview
Turns the bytes a terminal sends into events.
Three things arrive on the same stream and have to be told apart: replies
to queries the application made, text that was pasted rather than typed,
and key presses. The first is settled by ResponseRegistry, since nothing
about the bytes says whether a finger or a terminal produced them. The
second is settled by the bracketed paste markers. Everything left is a key.
State is carried between calls, because none of the three respects the boundaries of a read: an escape sequence, a UTF-8 character, and a paste can each be split across as many reads as the kernel feels like.
Defined in:
termbuf/input/decoder.crConstant Summary
-
ESCAPE_TIMEOUT =
25.milliseconds -
How long to wait for the rest of an escape sequence before deciding there is no rest.
The escape key sends one byte and so does the start of every arrow key, so the two are indistinguishable until either more bytes arrive or enough time passes that none will.
-
LETTER_KEYS =
{'A' => Key::Name::Up, 'B' => Key::Name::Down, 'C' => Key::Name::Right, 'D' => Key::Name::Left, 'H' => Key::Name::Home, 'F' => Key::Name::End, 'E' => Key::Name::Begin, 'P' => Key::Name::F1, 'Q' => Key::Name::F2, 'R' => Key::Name::F3, 'S' => Key::Name::F4} -
Arrows, and everything sharing their shape, in the
ESC [ 1 ; m xform. -
MAX_PASTE =
(4 * 1024) * 1024 -
Where a paste stops being a paste and starts being a denial of service. Reached only by a terminal that sent an opening marker and no closing one.
-
MINIMUM_DEADLINE =
1.millisecond -
Never ask for a read deadline shorter than this. A deadline that has already passed would otherwise become a zero or negative timeout.
-
PASTE_END =
"\e[201~".to_slice -
PASTE_NOTICE =
300.milliseconds -
How long a paste has to have been arriving before it is worth telling the application about. Measured from the opening marker whether or not anything followed it.
-
PASTE_PROGRESS =
100.milliseconds -
How often the byte count is worth resending. A paste large enough to notice arrives in hundreds of reads, and an application draining the channel slowly should not be made to drain hundreds of notices.
-
PASTE_STALL =
3.seconds -
How long a paste may go without a single byte before it is treated as abandoned.
Reset by every byte rather than measured from the opening marker, because the question is whether the paste is slow or stopped and the only evidence either way is whether anything is still arriving. A paste over a link with seconds of latency stays alive as long as it makes progress; one whose closing marker will never come ends here rather than swallowing every keystroke after it.
-
PASTE_START =
"\e[200~".to_slice -
SS3_KEYS =
{'A' => Key::Name::Up, 'B' => Key::Name::Down, 'C' => Key::Name::Right, 'D' => Key::Name::Left, 'H' => Key::Name::Home, 'F' => Key::Name::End, 'E' => Key::Name::Begin, 'M' => Key::Name::Enter, 'P' => Key::Name::F1, 'Q' => Key::Name::F2, 'R' => Key::Name::F3, 'S' => Key::Name::F4} -
TILDE_KEYS =
{1 => Key::Name::Home, 2 => Key::Name::Insert, 3 => Key::Name::Delete, 4 => Key::Name::End, 5 => Key::Name::PageUp, 6 => Key::Name::PageDown, 7 => Key::Name::Home, 8 => Key::Name::End, 11 => Key::Name::F1, 12 => Key::Name::F2, 13 => Key::Name::F3, 14 => Key::Name::F4, 15 => Key::Name::F5, 17 => Key::Name::F6, 18 => Key::Name::F7, 19 => Key::Name::F8, 20 => Key::Name::F9, 21 => Key::Name::F10, 23 => Key::Name::F11, 24 => Key::Name::F12, 25 => Key::Name::F13, 26 => Key::Name::F14, 28 => Key::Name::F15, 29 => Key::Name::F16, 31 => Key::Name::F17, 32 => Key::Name::F18, 33 => Key::Name::F19, 34 => Key::Name::F20} -
ESC [ n ~, where n names the key. The gaps are where DEC left room for keys nobody built.
Constructors
Instance Method Summary
-
#decode(bytes : Bytes) : Key
What one complete escape sequence means.
-
#escape_timeout : Time::Span
See
ESCAPE_TIMEOUT. -
#escape_timeout=(escape_timeout : Time::Span)
See
ESCAPE_TIMEOUT. -
#feed(bytes : Bytes, &emit : Event -> ) : Nil
Feeds bytes in, yielding whatever they completed.
-
#flush(&emit : Event -> ) : Nil
Gives up waiting and delivers what is held back for what it is: an escape that begins nothing is the escape key, and a truncated character is a broken one.
-
#paste_notice : Time::Span
See
PASTE_NOTICE. -
#paste_notice=(paste_notice : Time::Span)
See
PASTE_NOTICE. -
#paste_progress : Time::Span
See
PASTE_PROGRESS. -
#paste_progress=(paste_progress : Time::Span)
See
PASTE_PROGRESS. -
#paste_stall : Time::Span
See
PASTE_STALL. -
#paste_stall=(paste_stall : Time::Span)
See
PASTE_STALL. -
#pasting? : Bool
Whether a paste is open, so that text is being collected rather than delivered as keys.
-
#pending? : Bool
Whether anything is being held back for want of more bytes.
-
#read_deadline : Time::Span | Nil
How long the reader may wait before calling
#tick, ornilwhen it may block until something arrives. -
#tick(&emit : Event -> ) : Nil
Called when a read deadline expires.
Constructor Detail
Instance Method Detail
See ESCAPE_TIMEOUT. Worth raising over a slow link, where a sequence can
take longer than that to arrive in full.
See ESCAPE_TIMEOUT. Worth raising over a slow link, where a sequence can
take longer than that to arrive in full.
Feeds bytes in, yielding whatever they completed.
Gives up waiting and delivers what is held back for what it is: an escape that begins nothing is the escape key, and a truncated character is a broken one.
Whether a paste is open, so that text is being collected rather than delivered as keys.
Whether anything is being held back for want of more bytes.
What the escape timeout is for: a lone escape looks exactly like the start of an arrow key until enough time passes that no arrow key is coming.
How long the reader may wait before calling #tick, or nil when it may
block until something arrives.
Every piece of held state is a bet that more bytes are coming, and each one needs its losing case. With nothing held and no paste open there is nothing to time, so an idle application costs nothing.
Called when a read deadline expires. Works out which one it was.