Carries partially-received terminal input across reads.
Terminal input arrives in arbitrary chunks, and a control sequence can be split
across two of them. feed/2 decodes whatever is complete and holds the
undecided tail until the rest arrives.
A trailing lone ESC is held too, since it is both a complete keypress and the
start of every escape sequence. flush/1 resolves it as the escape key.
Whenever bytes are held, an :input_flush message is scheduled to the calling
process after flush_after_ms/0; drivers resolve the tail by calling flush/1
on receipt.
iex> buffer = Drafter.Terminal.InputBuffer.new()
iex> {events, buffer} = Drafter.Terminal.InputBuffer.feed(buffer, "ab\e[")
iex> events
[{:key, :a}, {:key, :b}]
iex> {events, _buffer} = Drafter.Terminal.InputBuffer.feed(buffer, "A")
iex> events
[{:key, :up}]
Summary
Functions
Append a chunk and decode whatever is now complete.
Resolve any held bytes without waiting for more input.
Milliseconds of silence after which a held sequence is resolved.
An empty buffer, holding no bytes and with no flush scheduled.
Discard held bytes and any pending flush, decoding nothing.
Types
Functions
@spec feed(t(), binary()) :: {[Drafter.Terminal.ANSI.event()], t()}
Append a chunk and decode whatever is now complete.
Returns the decoded events and the updated buffer. When bytes remain undecided
an :input_flush message is scheduled to the calling process, replacing any
previously scheduled one.
iex> {events, buffer} = Drafter.Terminal.InputBuffer.feed(Drafter.Terminal.InputBuffer.new(), "hi\e")
iex> events
[{:key, :h}, {:key, :i}]
iex> buffer.pending
"\e"
@spec flush(t()) :: {[Drafter.Terminal.ANSI.event()], t()}
Resolve any held bytes without waiting for more input.
Call on :input_flush, or when the input stream closes. Any scheduled flush is
cancelled.
iex> {_events, buffer} = Drafter.Terminal.InputBuffer.feed(Drafter.Terminal.InputBuffer.new(), "\e")
iex> Drafter.Terminal.InputBuffer.flush(buffer)
{[{:key, :escape}], %Drafter.Terminal.InputBuffer{pending: "", timer: nil}}An empty buffer yields no events.
iex> Drafter.Terminal.InputBuffer.flush(Drafter.Terminal.InputBuffer.new())
{[], %Drafter.Terminal.InputBuffer{pending: "", timer: nil}}
@spec flush_after_ms() :: pos_integer()
Milliseconds of silence after which a held sequence is resolved.
iex> Drafter.Terminal.InputBuffer.flush_after_ms()
40
@spec new() :: t()
An empty buffer, holding no bytes and with no flush scheduled.
iex> Drafter.Terminal.InputBuffer.new()
%Drafter.Terminal.InputBuffer{pending: "", timer: nil}
Discard held bytes and any pending flush, decoding nothing.
iex> {_events, buffer} = Drafter.Terminal.InputBuffer.feed(Drafter.Terminal.InputBuffer.new(), "\e[")
iex> Drafter.Terminal.InputBuffer.reset(buffer)
%Drafter.Terminal.InputBuffer{pending: "", timer: nil}