# `Ascii.Pieces.Terminal`
[🔗](https://github.com/houllette/ascii_art/blob/main/lib/ascii/pieces/terminal.ex#L1)

A shell session: typed commands, output, scrolling, clear.

A shell session in a rounded frame. Each command is typed a key at a time,
its output prints line by line and scrolls, and a clear starts over. As
upstream draws it, it plays a session of its own; give it a `history`
and it shows yours: commands and their output, or a log's tail.

## Options

Give them to `Ascii.new/2` as `options:`, and new ones while it plays
with `Ascii.put_options/2` (or a Phoenix player's `options`). New
history carries on from what is on screen: with `typing`, what has been
typed stays, new entries are typed from then on, and new lines of output
under the last command print; without, the history is shown as it stands.

  * `history` - what the terminal shows instead of upstream's session: a
    list of `%{command: "...", output: ["...", ...]}`, each command after
    the prompt with the lines it printed under it. An entry without a
    command is output alone, so a log's tail is
    `history: [%{output: lines}]`. The newest lines are at the bottom,
    older ones scrolled away, and lines too long for the width are cut.
    After a command the prompt comes back, the cursor blinking after it;
    after output alone the cursor waits at the start of the next line, as
    it does while a command runs. Default `[]`: upstream's session.
  * `typing` - with `history`, play it out: each command typed a key at a
    time and its output printed a line at a time, once through, and then
    hold. Default `false`: the history shown at once.
  * `prompt` - before each command; a space follows it. Default
    `"~/notes $"`.
  * `title` - in the top of the frame; `""` for none. Default `"~/notes"`.
  * `cols`, `rows` - the frame's size, the border included, 12 to 200 by
    3 to 60; upstream's 62 by 18 by default.

## Colours

In one ink, or a gradient, with `:ink` and `:gradient` (see
`Ascii.Ink`); part by part with `:parts` (see `Ascii.Parts`),
`parts: true` taking the colours suggested here:

  * `frame` - the window's border, grey; `title`, its title.
  * `prompt` - the prompt, blue.
  * `command` - what is typed after it.
  * `output` - what the commands print; a todo list's items marked
    `checked` (`[x]`), green, or `unchecked` (`[ ]`), grey.
  * `cursor` - the cursor, yellow.

A line that reads as both a command and output (a prompt made to look
like output) is in no part.

## Keys and clicks

It takes none: it shows a session, and `Ascii.handle_event/2` ignores
every event. To make it a shell of your own, take the keys in your app
and give it the new `history`. A Phoenix player given `interactive` and
`notify` still tells your LiveView where it was clicked, and on which
part (`Ascii.part_at/4`), a command or a line of output, say.

## Screen readers

`Ascii.describe/1` tells the history: "terminal my_app: 1 command, the
last mix test", or for output alone "terminal ~/notes: 2 lines of output,
the last: two". Playing upstream's session, it gives the piece's name and
note.

## Example

```elixir
history = [%{command: "mix test", output: ["...........", "11 tests, 0 failures"]}]
options = %{title: "my_app", prompt: "$", history: history, cols: 40, rows: 8}
term = Ascii.new!("terminal", options: options, parts: true)
{frame, _term} = Ascii.frame(term, 0.0)
Enum.at(frame.lines, 3)
#=> "│ 11 tests, 0 failures                 │"

Ascii.describe(term)
#=> "terminal my_app: 1 command, the last mix test"
```

```heex
<Ascii.Phoenix.live_player id="log" piece="terminal" options={%{title: "deploy", history: [%{output: @log}]}} parts />
```

Ported from `src/pieces/terminal.ts` in bas3line/ascii (MIT).

---

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