Data

TerminalOutput

A terminal-like window with a title, commands after a prompt and their output, errors in red, for docs and tutorials.

#data#code#document#no-js

Demo

Preview
~/app — zsh
# start the app and watch for changesquillo run app.qwe --watchquillo: 3 routes listening on http://127.0.0.1:8080curl -s localhost:8080/healthokcurl -s localhost:8080/missing404 not found
lsREADME.md  app.qwe  publiccat notes.txtcat: notes.txt: No such file or directoryecho donedone

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/terminal_output.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/terminal_output.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/terminal_output.qwe
view TerminalOutputDemo() =    <div.demo-stack>        <TerminalOutput id="terminal-output-demo-run" title="~/app — zsh" lines={[            { note: "start the app and watch for changes" },            { cmd: "quillo run app.qwe --watch" },            { out: "quillo: 3 routes listening on http://127.0.0.1:8080" },            { cmd: "curl -s localhost:8080/health" },            { ok: "ok" },            { cmd: "curl -s localhost:8080/missing" },            { err: "404 not found" },        ]}/>        <TerminalOutput id="terminal-output-demo-text" theme="system" prompt="%" errors={["No such file"]} max_height="160px"                        label="Listing files" text={"% ls\nREADME.md  app.qwe  public\n% cat notes.txt\ncat: notes.txt: No such file or directory\n% echo done\ndone"}/>    </div>

Source

ui/terminal_output.qwe
// TerminalOutput: what a terminal session looked like: a window with a title,// commands after a prompt, and what they printed, errors in red: for docs,// tutorials and READMEs. It is text, not a live terminal.////   <TerminalOutput title="~/app" lines={[//       { cmd: "quillo run app.qwe --watch" },//       { out: "quillo: 3 routes listening on http://127.0.0.1:8080" },//       { cmd: "curl localhost:8080/health" },//       { ok: "ok" },//   ]}/>//   <TerminalOutput text={"$ ls\nREADME.md  app.qwe\n$ cat nope\ncat: nope: No such file or directory"} errors={["No such file"]}/>//// lines: maps, each one of { cmd } (a command after the prompt), { out } (what// it printed), { err } (an error, red), { ok } (a success, green) or { note } (a// comment, muted, after #). Or text: the session as text, where a line starting// with "$ " (or the prompt and a space) is a command and the rest is output;// errors: words that make an output line an error. prompt: "$" by default// ("PS>", ">>>"). title: in the window's bar (none: no bar). theme: "dark"// (default, whatever the page's theme), "light" or "system". max_height: a CSS// height past which it scrolls. label: what screen readers call it (the title, or// "Terminal"). id: the element's id. The prompt is not selected with the// commands, so copying them gives only the commands.import ui/theme.qwe use ui_clslet terminal_output_css = css`.ui-terminal { min-width: 0; overflow: hidden; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); background: var(--ui-bg);  color: var(--ui-fg); font: 13px/1.6 var(--ui-mono); box-shadow: var(--ui-shadow); }.ui-terminal-bar { position: relative; display: flex; align-items: center; height: 34px; padding: 0 14px; border-bottom: 1px solid var(--ui-border);  background: var(--ui-surface); }.ui-terminal-dots { display: flex; gap: 6px; }.ui-terminal-dots i { width: 11px; height: 11px; border-radius: 50%; background: var(--ui-danger); }.ui-terminal-dots i:nth-child(2) { background: var(--ui-warning); }.ui-terminal-dots i:nth-child(3) { background: var(--ui-success); }.ui-terminal-title { position: absolute; left: 70px; right: 70px; overflow: hidden; color: var(--ui-muted); font: 500 12px/1 var(--ui-font);  text-align: center; text-overflow: ellipsis; white-space: nowrap; }.ui-terminal-body { margin: 0; padding: 12px 16px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; color: inherit; }.ui-terminal-body:focus-visible { outline: none; box-shadow: inset var(--ui-focus); }.ui-terminal-line { display: block; min-height: 1.6em; }.ui-terminal-prompt { color: var(--ui-accent); font-weight: 700; user-select: none; -webkit-user-select: none; }.ui-terminal-cmd { color: var(--ui-fg); font-weight: 600; }.ui-terminal-out { color: color-mix(in srgb, var(--ui-fg) 78%, var(--ui-bg)); }.ui-terminal-err { color: var(--ui-danger); }.ui-terminal-ok { color: var(--ui-success); }.ui-terminal-note { color: var(--ui-muted); font-style: italic; }`// The session's text as lines: commands after the prompt, errors where the words say so.fn terminal_output_lines(text: str, prompt: str, errors: list) -> list =    split(replace(text, "\r\n", "\n"), "\n") | map((l) => {        let p = `${prompt} `        starts_with(l, p) ? { cmd: slice(l, len(p), len(l)) }            : any(errors, (w) => contains(l, w)) ? { err: l } : { out: l }    })view TerminalOutput(lines: list? = null, text: str? = null, prompt: str = "$", errors: list = [], title: str? = null,                    theme: str = "dark", max_height: str? = null, label: str? = null, id: str? = null, class: str? = null) {    style global terminal_output_css    let all = lines ?? (text != null ? terminal_output_lines(text, prompt, errors) : [])    <figure class={ui_cls(["ui-terminal", theme != "system" && `ui-${theme}`, class])} id={id} style="margin: 0">        {title != null && <figcaption.ui-terminal-bar>            <span.ui-terminal-dots aria-hidden="true"><i></i><i></i><i></i></span>            <span.ui-terminal-title>{title}</span>        </figcaption>}        <pre.ui-terminal-body tabindex="0" aria-label={label ?? title ?? "Terminal"} style={max_height != null ? `max-height: ${max_height}` : null}><code>            {for l in all => l.cmd != null                ? <span.ui-terminal-line><span.ui-terminal-prompt aria-hidden="true">{prompt} </span><span.ui-terminal-cmd>{l.cmd}</span></span>                : l.err != null ? <span.ui-terminal-line.ui-terminal-err>{l.err}</span>                : l.ok != null ? <span.ui-terminal-line.ui-terminal-ok>{l.ok}</span>                : l.note != null ? <span.ui-terminal-line.ui-terminal-note># {l.note}</span>                : <span.ui-terminal-line.ui-terminal-out>{l.out ?? ""}</span>}        </code></pre>    </figure>}
Thread
76Useful? Like it, or add to its thread below.

Thread 0 posts

On TerminalOutput: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.