# `Drafter.CellSession`
[🔗](https://github.com/jaman/drafter/blob/main/lib/drafter/cell_session.ex#L1)

Drives a Drafter app to an in-memory cell grid instead of a terminal.

A `CellSession` runs the ordinary app loop against a terminal driver that
discards its output, and exposes the composited screen as rows of cells —
`Drafter.Draw.Strip` structs, one per screen row — together with row-level
diffs. A host renders those rows however it likes and feeds input back in with
`feed_input/2`.

    session = Drafter.CellSession.start(MyApp, size: {80, 24})
    rows = Drafter.CellSession.take_cells(session)            # full grid
    Drafter.CellSession.feed_input(session, {:key, :enter})   # drive input
    {changed, session} = Drafter.CellSession.take_cells_diff(session)  # only changed rows
    Drafter.CellSession.resize(session, 100, 30)
    Drafter.CellSession.close(session)

Each session owns its own unnamed services, so many sessions run concurrently in one
BEAM node without colliding.

# `cell_row`

```elixir
@type cell_row() :: {non_neg_integer(), Drafter.Draw.Strip.t()}
```

# `t`

```elixir
@type t() :: %Drafter.CellSession{
  app_pid: term(),
  compositor: term(),
  driver: term(),
  event_manager: term(),
  services: term(),
  snapshot: term()
}
```

# `close`

```elixir
@spec close(t()) :: :ok
```

Shut down the session and all of its services.

# `feed_input`

```elixir
@spec feed_input(t(), term()) :: :ok
```

Inject an input event (e.g. `{:key, :enter}`, `{:mouse, %{...}}`) into the session.

# `resize`

```elixir
@spec resize(t(), pos_integer(), pos_integer()) :: :ok
```

Resize the virtual surface; the app re-renders to the new dimensions.

# `start`

```elixir
@spec start(
  module(),
  keyword()
) :: t()
```

Start a cell-backed session for `app_module`.

Options:

  * `:size` — `{columns, rows}` of the virtual surface, default `{80, 24}`
  * `:shared` — a shared-state server pid to join an existing
    multi-user session; omit for a session with private state

Every other option is passed to the app's `mount/1` as a mount prop.

Returns the session struct, which the other functions in this module take. The
caller must call `close/1` to release the processes the session owns.

# `take_cells`

```elixir
@spec take_cells(t()) :: [Drafter.Draw.Strip.t()]
```

Return the full current cell grid: one `Strip` per row.

# `take_cells_diff`

```elixir
@spec take_cells_diff(t()) :: {[cell_row()], t()}
```

Return the rows that changed since the previous diff (or first call) as
`{row_index, strip}` tuples, and an updated session tracking the new snapshot.

# `take_lines`

```elixir
@spec take_lines(t()) :: [String.t()]
```

Return the current screen as plain text, one string per row.

Styling is dropped and trailing blanks are trimmed, so a row is its content and
an empty row is `""`. The list is always as long as the surface is tall.

    ["hello world", "second line", "", "", "", ""]

This is the same view `Drafter.Test.screen_lines/1` gives of a headless app, for
asserting on what is displayed rather than rendering it.

# `take_text`

```elixir
@spec take_text(t()) :: String.t()
```

Return the current screen as one string, rows joined by newlines.

As `take_lines/1`, which documents the per-row form.

---

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