# `Drafter.Terminal.InputBuffer`
[🔗](https://github.com/jaman/drafter/blob/main/lib/drafter/terminal/input_buffer.ex#L1)

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}]

# `t`

```elixir
@type t() :: %Drafter.Terminal.InputBuffer{
  key_release: boolean(),
  pending: binary(),
  timer: reference() | nil
}
```

# `feed`

```elixir
@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"

# `flush`

```elixir
@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}}

# `flush_after_ms`

```elixir
@spec flush_after_ms() :: pos_integer()
```

Milliseconds of silence after which a held sequence is resolved.

    iex> Drafter.Terminal.InputBuffer.flush_after_ms()
    40

# `new`

```elixir
@spec new(keyword()) :: t()
```

An empty buffer, holding no bytes and with no flush scheduled.

    iex> Drafter.Terminal.InputBuffer.new()
    %Drafter.Terminal.InputBuffer{pending: "", timer: nil, key_release: false}

## Options

  * `:key_release` - `boolean()`, passed to every parse as
    `Drafter.Terminal.ANSI.parse_sequence/2` describes. Default `false`.

# `reset`

```elixir
@spec reset(t()) :: t()
```

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}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
