terminal

A terminal renders a monospace character grid as inline SVG, drawn with a bundled Nerd Font. The grid is populated three ways: authored text primitives, an inline ANSI-bearing text field, or replay of an asciinema recording. cols / rows size the grid; chrome toggles the window frame; title labels it.

Preview

demoColoursredgreenblue#ff5fd2boxroundedborder
demoColoursredgreenblue#ff5fd2boxroundedborder

Example

terminal {
  cols = 46
  rows = 7
  title = "demo"
  term_text "Colours" {
    row = 1
    col = 2
    bold = true
    underline = true
  }
  term_text "red" {
    row = 2
    col = 2
    fg = "red"
  }
  term_text "green" {
    row = 2
    col = 8
    fg = "green"
  }
  term_text "blue" {
    row = 2
    col = 16
    fg = "blue"
  }
  term_text "#ff5fd2" {
    row = 2
    col = 23
    fg = "#ff5fd2"
  }
  term_box {
    row = 4
    col = 2
    width = 32
    height = 3
    border = :rounded
    fg = "cyan"
    title = "box"
  }
  term_text "rounded border" {
    row = 5
    col = 4
  }
}
PropertyTypeRequiredDescription
colsi64noGrid width in cells (default 80; a .cast header overrides it).
rowsi64noGrid height in cells (default 24; a .cast header overrides it).
font_sizef64noCell metric: font size.
line_heightf64noCell metric: line height.
palettesymbolnoSeed colours: :default (dark) or :light.
fgutf8noExplicit default foreground override.
bgutf8noExplicit default background override.
chromeboolnoDraw a window title bar (default true).
titleutf8noTitle shown in the chrome bar.
textutf8noInline content fed to the virtual terminal (ANSI included).
sourceutf8noPath to an asciinema .cast recording to replay.
autoplayboolnoReplay control: start playing automatically.
loopboolnoReplay control: loop playback.
speedf64noReplay control: playback speed multiplier.
ididentifiernoOptional explicit HTML id.
classlist<utf8>noStyle classes (the class themes the window <div>).

Child blocks

SlotAcceptsMultipleDescription
childrenTermPrimitiveyesPlaceable terminal primitives and widgets.

§ 1Primitives

term_text is the one base primitive — styled text at a 1-based (row, col) carrying fg / bg and bold / italic / underline. Higher-level helpers (term_box, term_glyph, term_fill) lower to runs of term_text. Colours are strings: an ANSI name ("red"), a 256-palette index ("208"), or a hex ("#ff5fd2"). All four side by side:

Preview

primitivesterm_textstyledterm_boxterm_glyphterm_fill
primitivesterm_textstyledterm_boxterm_glyphterm_fill

Example

terminal {
  cols = 40
  rows = 9
  title = "primitives"
  term_text "term_text — styled" {
    row = 1
    col = 2
    fg = "green"
    bold = true
  }
  term_box {
    row = 3
    col = 2
    width = 22
    height = 3
    border = :rounded
    fg = "cyan"
    title = "term_box"
  }
  term_glyph "" {
    row = 4
    col = 27
    fg = "yellow"
  }
  term_text "term_glyph" {
    row = 4
    col = 29
  }
  term_fill "" {
    row = 7
    col = 2
    width = 36
    height = 1
    fg = "magenta"
  }
  term_text "term_fill" {
    row = 8
    col = 2
  }
}

Styled text at a 1-based (row, col) carrying fg / bg and bold / italic / underline — the one base primitive every other terminal helper lowers to.

PropertyTypeRequiredDescription
contentutf8yesThe text (@inline(0), so term_text "hi" { … }).
rowi64yes1-based grid row.
coli64yes1-based grid column.
fgutf8noForeground colour — ANSI name, 256 index, or #hex.
bgutf8noBackground colour — ANSI name, 256 index, or #hex.
boldboolnoBold style.
dimboolnoDim style.
italicboolnoItalic style.
underlineboolnoUnderline style.
strikeboolnoStrikethrough style.
blinkboolnoBlink style.
inverseboolnoInverse (swap fg/bg) style.
concealboolnoConceal (hide) style.

A box drawn with line-drawing characters at (row, col) over a width / height, with a border style (:rounded, …) and an optional title.

PropertyTypeRequiredDescription
rowi64yes1-based grid row.
coli64yes1-based grid column.
widthi64yesBox width in cells.
heighti64yesBox height in cells.
bordersymbolnoBorder style: :single (default) / :double / :rounded / :heavy / :ascii.
titleutf8noOptional title drawn into the top border.
fgutf8noForeground colour.
bgutf8noBackground colour.
boldboolnoBold style.

A single placed glyph at (row, col) — handy for sigils, spinners, and box-drawing accents that aren't full text runs.

PropertyTypeRequiredDescription
glyphutf8yesThe text run (may contain \n), @inline(0).
rowi64yes1-based grid row.
coli64yes1-based grid column.
fgutf8noForeground colour.
bgutf8noBackground colour.
boldboolnoBold style.

Fills a rectangular region of the grid with a repeated character and colour, for backgrounds and shading.

PropertyTypeRequiredDescription
chutf8yesThe fill character (@inline(0)).
rowi64yes1-based grid row.
coli64yes1-based grid column.
widthi64yesRegion width in cells.
heighti64yesRegion height in cells.
fgutf8noForeground colour.
bgutf8noBackground colour.
boldboolnoBold style.

§ 2Inline ANSI and asciinema replay

Set text = "…" and the bundled avt virtual terminal evaluates it — ANSI sequences, cursor movement, and styling all apply (a bare \n is a newline). Set source = "rec.cast" for asciinema replay; frames replay at the recording's pace (override with speed) and stop at the end unless loop = true.

Preview

inlinefirstlinesecondline
inlinefirstlinesecondline

Example

terminal {
  cols = 30
  rows = 3
  title = "inline"
  text = "first line\nsecond line"
}

§ 3TUI widgets

Inside a terminal, stdlib TUI controls compose a small interface — each lowers to runs of term_text. Place each from its own (row, col); container widgets position their children relative to themselves.

Preview

controlsProgressUpload78%Sync40%ButtonsSaveDiscard
controlsProgressUpload78%Sync40%ButtonsSaveDiscard

Example

terminal {
  cols = 44
  rows = 8
  title = "controls"
  term_text "Progress" {
    row = 1
    col = 2
    bold = true
    underline = true
  }
  tui_progress "Upload" {
    row = 2
    col = 2
    value = 78
  }
  tui_progress "Sync" {
    row = 3
    col = 2
    value = 40
    accent = "cyan"
  }
  term_text "Buttons" {
    row = 5
    col = 2
    bold = true
    underline = true
  }
  tui_button "Save" {
    row = 6
    col = 2
    accent = "green"
  }
  tui_button "Discard" {
    row = 6
    col = 11
    accent = "red"
  }
}

§ 3.1tui_progress

A two-tone progress bar; value runs 0max (default 100), the @inline label sits to its left, and show_value appends a percentage.

Preview

Upload65%
Upload65%

Example

terminal {
  cols = 38
  rows = 1
  chrome = false
  tui_progress "Upload" {
    row = 1
    col = 1
    value = 65
  }
}
PropertyTypeRequiredDescription
labelutf8noOptional @inline caption to the left of the bar.
valuei64yesFilled amount (clamped to 0..max).
maxi64noScale maximum (default 100).
widthi64noBar width in cells (default 24).
show_valueboolnoAppend a NN% readout (default true).
accentutf8noFill colour.
mutedutf8noTrack colour.
rowi64yes1-based grid row.
coli64yes1-based grid column.

§ 3.2tui_button

A solid accent-fill button; the @inline label is centred, width pads it, accent colours the fill.

Preview

SaveQuit
SaveQuit

Example

terminal {
  cols = 24
  rows = 1
  chrome = false
  tui_button "Save" {
    row = 1
    col = 1
    accent = "green"
  }
  tui_button "Quit" {
    row = 1
    col = 9
    accent = "red"
  }
}
PropertyTypeRequiredDescription
labelutf8yesButton text (@inline).
widthi64noTotal width (default = label + padding).
accentutf8noFill colour (default blue).
fgutf8noLabel colour (default bright_white).
rowi64yes1-based grid row.
coli64yes1-based grid column.

§ 3.3tui_input

A single-line field with a left accent bar. With no value the @inline placeholder shows muted; focused = true draws a cursor.

Preview

SearchprojectsAdaLovelace
SearchprojectsAdaLovelace

Example

terminal {
  cols = 30
  rows = 2
  chrome = false
  tui_input "Search projects" {
    row = 1
    col = 1
    focused = true
  }
  tui_input "Name" {
    row = 2
    col = 1
    value = "Ada Lovelace"
  }
}
PropertyTypeRequiredDescription
placeholderutf8yesMuted prompt shown when empty (@inline).
valueutf8noCurrent text (overrides the placeholder).
focusedboolnoDraw a trailing cursor.
accentutf8noBar / cursor colour.
rowi64yes1-based grid row.
coli64yes1-based grid column.

§ 3.4tui_dropdown

A drop-down with a disclosure caret ( closed, open). With open = true and an items list, the options drop below the field and the selected one is highlighted.

Preview

ReleasebuildDebugbuildReleasebuildProfilebuild
ReleasebuildDebugbuildReleasebuildProfilebuild

Example

terminal {
  cols = 28
  rows = 4
  chrome = false
  tui_dropdown "Release build" {
    row = 1
    col = 1
    open = true
    items = ["Debug build", "Release build", "Profile build"]
  }
}
PropertyTypeRequiredDescription
textutf8yesSelected / shown label (@inline).
itemslist<utf8>noOption list shown below the field when open.
selectedi64noHighlighted item index (default: the item equal to text).
widthi64noField width (default: fits the label and longest item).
openboolnoDrop the list down (and flip the caret).
accentutf8noCaret + selected-row colour.
rowi64yes1-based grid row.
coli64yes1-based grid column.

§ 3.5tui_checkbox

An on/off checkbox; checked = true fills the marker in the accent colour.

Preview

TelemetryBeta
TelemetryBeta

Example

terminal {
  cols = 24
  rows = 2
  chrome = false
  tui_checkbox "Telemetry" {
    row = 1
    col = 1
    checked = true
  }
  tui_checkbox "Beta" {
    row = 2
    col = 1
  }
}
PropertyTypeRequiredDescription
labelutf8yesCheckbox caption (@inline).
checkedboolnoOn/off state.
accentutf8noChecked colour.
mutedutf8noUnchecked colour.
rowi64yes1-based grid row.
coli64yes1-based grid column.

§ 3.6tui_radio

A radio button — like a checkbox but round; selected = true marks the active choice in a group you lay out yourself.

Preview

DarkLight
DarkLight

Example

terminal {
  cols = 24
  rows = 2
  chrome = false
  tui_radio "Dark" {
    row = 1
    col = 1
    selected = true
  }
  tui_radio "Light" {
    row = 2
    col = 1
  }
}
PropertyTypeRequiredDescription
labelutf8yesRadio caption (@inline).
selectedboolnoWhether this option is chosen.
accentutf8noSelected colour.
mutedutf8noUnselected colour.
rowi64yes1-based grid row.
coli64yes1-based grid column.

§ 3.7tui_spinner

A single static spinner frame — pick the kind (:braille default, :circle, :line) and which frame to show, with an optional @inline label.

Preview

Building
Building

Example

terminal {
  cols = 24
  rows = 1
  chrome = false
  tui_spinner "Building…" {
    row = 1
    col = 1
    frame = 2
  }
}
PropertyTypeRequiredDescription
labelutf8noOptional @inline caption after the frame.
framei64noWhich frame index to show (default 0).
kindsymbolnoGlyph set: :dots/:braille (default) / :circle / :line.
accentutf8noFrame colour.
rowi64yes1-based grid row.
coli64yes1-based grid column.

§ 3.8tui_panel

A bordered container: it draws a box (optional title) and renders its child controls inset by one cell. Child positions are relative to the panel.

Preview

StatusLoad50%Go
StatusLoad50%Go

Example

terminal {
  cols = 30
  rows = 6
  chrome = false
  tui_panel {
    row = 1
    col = 1
    width = 30
    height = 6
    title = "Status"
    tui_progress "Load" {
      row = 1
      col = 1
      value = 50
      width = 16
    }
    tui_button "Go" {
      row = 3
      col = 1
      accent = "green"
    }
  }
}
PropertyTypeRequiredDescription
titleutf8noOptional heading drawn into the top border.
widthi64yesBox width in cells.
heighti64yesBox height in cells.
bordersymbolnoBorder style: :rounded (default) / :single / :double / :heavy / :ascii.
accentutf8noBorder colour.
rowi64yes1-based grid row.
coli64yes1-based grid column.

Child blocks

SlotAcceptsMultipleDescription
childrenTermPrimitiveyesTermPrimitive children, positioned relative to the panel.

§ 3.9tui_group

A borderless container — an optional title then its children. Use it to offset a cluster of controls without drawing a box.

Preview

OptionsTelemetryDark
OptionsTelemetryDark

Example

terminal {
  cols = 26
  rows = 3
  chrome = false
  tui_group {
    row = 1
    col = 1
    title = "Options"
    tui_checkbox "Telemetry" {
      row = 1
      col = 1
      checked = true
    }
    tui_radio "Dark" {
      row = 2
      col = 1
      selected = true
    }
  }
}
PropertyTypeRequiredDescription
titleutf8noOptional heading above the children.
rowi64yes1-based grid row.
coli64yes1-based grid column.

Child blocks

SlotAcceptsMultipleDescription
childrenTermPrimitiveyesTermPrimitive children, positioned relative to the group.

§ 4Custom TUI widgets

TUI widgets are user-extensible. Declare a @block("name") type … extends TuiWidget with a lower returning list<TermFundamental>, and it plugs into the renderer like the built-ins — a legal child of any terminal (or container). Lay it out from its own top-left (1, 1); the renderer offsets it by the widget's placement. Build the output from the shared term_run / term_repeat helpers, since styled text is the only thing the renderer paints.

Here's a kbd keycap — a coloured background run with the key label on top, the accent overridable per instance:

Preview

CtrlK
CtrlK

Example

terminal {
  cols = 30
  rows = 1
  chrome = false
  kbd "Ctrl" {
    row = 1
    col = 1
  }
  kbd "K" {
    row = 1
    col = 8
    accent = "blue"
  }
}
wcl
// Extends TuiWidget → a legal terminal child. The lower returns styled text
// runs (a background of spaces + the label on top).
@block("kbd")
type Kbd extends TuiWidget {
  @inline(0) key: utf8
  accent: utf8?
  row: i64  col: i64
  lower = fn(k: Kbd) -> list<TermFundamental> {
    let acc = if k.accent == none { "magenta" } else { k.accent };
    let w = len(k.key) + 2;
    [
      term_run(term_repeat(" ", w), 1, 1, none, acc, none),
      term_run(k.key, 1, 2, "bright_white", acc, true),
    ]
  }
}

terminal { cols = 30  rows = 1  chrome = false
  kbd "Ctrl" { row = 1  col = 1 }
  kbd "K"    { row = 1  col = 8  accent = "blue" }
}