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 ishistory: [%{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- withhistory, 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. Defaultfalse: 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 markedchecked([x]), green, orunchecked([ ]), 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
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"<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).