Chrome: commands, modals, dialogs & footer
lib/chrome/tui_cmd.sh, lib/chrome/tui_modal.sh, lib/chrome/tui_dialog.sh, lib/chrome/tui_footer.sh - the command palette, the overlay/modal layer dialogs and toasts are built on, the dialogs themselves, and the <footer/> key-hint bar. ← API index for the full module list and a task-oriented tour with examples.
Functions return 0 unless their entry says otherwise.
Commands and palette
The command bar (default ctrl+p or :) lists registered commands and runs one. DABT’s own commands are registered the same way, from share/defaults/commands.xml.
| Function | Summary |
|---|---|
tui.cmd.add |
Registers a command in the command palette. |
tui.cmd.remove |
Unregisters a command. A key bound with --key stays bound; remove it with tui.unbind. |
tui.cmd.run |
Runs a command by id. Returns 1 and prints a message on stderr for an unknown id. |
tui.cmd.list |
Prints every command as ID<TAB>GROUP<TAB>TITLE<TAB>ACTION, in registration order. |
tui.cmd.load |
Registers the commands in an XML file, one <cmd id="…" title="…" action="…" [group="…"] [desc="…"] [when="…"] [key="…"]/> per line. |
tui.cmd.provider |
Registers a function that runs every time the palette opens and adds commands that depend on current state. |
tui.palette.open |
Opens the command palette, optionally with the search prefilled. Bound to ctrl+p and : by default. |
tui.palette.close |
Closes the palette if it is open. |
tui.cmd.add
tui.cmd.add ID TITLE ACTION [--group G] [--desc TEXT] [--when FN] [--key KEY]
Registers a command in the command palette.
Parameters
ID: unique command id. Adding an existingIDreplaces it.TITLE: what the palette shows and searches.ACTION: function plus arguments, chained with;if needed. Same rules as atui.bindcommand.
Options
--group G: heading the command is listed under.--desc TEXT: second line in the palette.--when FN: the command is listed only whileFNreturns0.--key KEY: also bindsKEYto the command; the palette shows it as the hint.
Returns: 1 when ID, TITLE or ACTION is missing.
Notes
- Commands added while a plugin loads are removed when that plugin is disabled, and show the plugin’s name as their hint.
Example
tui.cmd.add export "Export report" on_export --group App --desc "Write report.csv" --key ctrl+e
tui.cmd.remove
tui.cmd.remove ID
Unregisters a command. A key bound with --key stays bound; remove it with tui.unbind.
tui.cmd.run
tui.cmd.run ID
Runs a command by id. Returns 1 and prints a message on stderr for an unknown id.
tui.cmd.list
tui.cmd.list
Prints every command as ID<TAB>GROUP<TAB>TITLE<TAB>ACTION, in registration order.
tui.cmd.load
tui.cmd.load FILE
Registers the commands in an XML file, one <cmd id="…" title="…" action="…" [group="…"] [desc="…"] [when="…"] [key="…"]/> per line.
Returns: 1 when FILE can’t be read.
Notes
- Lines missing
id,titleoractionare skipped.share/defaults/commands.xmlis an example.
tui.cmd.provider
tui.cmd.provider FN
Registers a function that runs every time the palette opens and adds commands that depend on current state.
Notes
- Commands added inside
FNare removed and rebuilt on every open, so they never go stale. - Registering the same
FNtwice is a no-op.
Example
theme_commands() {
local f
for f in "$APP"/themes/*.css; do
tui.cmd.add "theme:${f##*/}" "Theme: ${f##*/}" "tui.theme.set $f" --group Themes
done
}
tui.cmd.provider theme_commands
tui.palette.open
tui.palette.open [QUERY]
Opens the command palette, optionally with the search prefilled. Bound to ctrl+p and : by default.
Notes
- Does nothing before the app runs.
- Keys inside: type to filter (every word must match), Up/Down or
ctrl+p/ctrl+n, PgUp/PgDn, Enter runs, Esc closes,ctrl+uclears. Click a row to run it. - Shows
TUI_PALETTE_ROWSrows (default 10).
tui.palette.close
tui.palette.close
Closes the palette if it is open.
Modal and overlay
An overlay is a draw function called after every repaint, so it stays on top. A modal is an overlay that also captures all input.
| Function | Summary |
|---|---|
tui.overlay.add |
Registers a function that draws on top of the panes after every repaint. |
tui.overlay.remove |
Unregisters an overlay. |
tui.overlay.box |
Draws a framed box at an absolute position. Meant for overlay and modal draw functions. |
tui.modal.open |
Opens a modal: an overlay that receives all input until it is closed. |
tui.modal.close |
Closes the open modal and repaints the screen under it. |
tui.modal.active |
Returns 0 while a modal is open (or, with NAME, while that modal is open). |
tui.modal.redraw |
Redraws all overlays now. Call it after changing the state a modal draws. |
tui.overlay.add
tui.overlay.add DRAWFN
Registers a function that draws on top of the panes after every repaint.
Parameters
DRAWFN: draws with absolute cursor moves (e.g.tui.overlay.box) and keeps no state of its own.
Notes
- Overlays survive page changes; remove page-specific ones yourself.
- Adding the same function twice is a no-op.
tui.overlay.remove
tui.overlay.remove DRAWFN
Unregisters an overlay.
Notes
- What it drew stays on screen until the next full repaint. Call
tui.relayoutto wipe it.
tui.overlay.box
tui.overlay.box ROW COL WIDTH SGR TITLE [LINE...]
Draws a framed box at an absolute position. Meant for overlay and modal draw functions.
Parameters
ROW,COL: top-left corner, 1-based.WIDTH: outer width including the frame.SGR: colors as SGR parameters, e.g.1;97;44.LINE: one per content row, cut or padded to the inner width.
Notes
- Saves and restores the cursor. Draws immediately; nothing is kept.
tui.modal.open
tui.modal.open NAME KEYFN DRAWFN [MOUSEFN]
Opens a modal: an overlay that receives all input until it is closed.
Parameters
NAME: modal name, fortui.modal.active.KEYFN: called asKEYFN KEYfor every key (a,enter,ctrl+p, …), andKEYFN pastewithTUI_EVENT_PASTEset.DRAWFN: draws the modal.MOUSEFN: called asMOUSEFN EVENT X Y(mouse:left,wheel:up, … at a 1-based cell). Without it, mouse events are ignored.
Notes
- Opening a modal closes the one already open. Dialogs and the palette are modals too.
- While open, bindings, focus and scrolling are suspended. Only the terminal-mode chord still works.
- Closed on page change.
- Call
tui.modal.redrawafter your state changes.
Example
my_draw() { tui.overlay.box 5 10 40 "1;97;44" "Confirm" "Delete file?" "[y] yes [n] no"; }
my_keys() { case "$1" in y) do_delete; tui.modal.close ;; n|esc) tui.modal.close ;; esac; }
tui.modal.open confirm my_keys my_draw
tui.modal.close
tui.modal.close
Closes the open modal and repaints the screen under it.
tui.modal.active
tui.modal.active [NAME]
Returns 0 while a modal is open (or, with NAME, while that modal is open).
tui.modal.redraw
tui.modal.redraw
Redraws all overlays now. Call it after changing the state a modal draws.
Dialogs and notifications
Dialogs never block: they return at once and call your function after the user answers, when the dialog is gone and the screen repainted, so the callback may open the next dialog or change page. A callback is a function name plus optional fixed arguments ("do_delete file1"); answers such as the prompt text are appended. One dialog at a time: opening a second replaces the first. TUI_DIALOG_RESULT holds yes, no, ok, submit, cancel or choose while the callback runs.
Common flags: --title T, --width N, --ok LABEL, --yes LABEL, --no LABEL, --danger, --default yes|no. Theme classes (all optional): .dialog .dialog_title .dialog_btn .dialog_btn_sel .dialog_danger .dialog_dim .dialog_error and .toast .toast_success .toast_warn .toast_error.
| Function | Summary |
|---|---|
tui.confirm |
Shows a Yes/No dialog and returns immediately; the callback runs after the user answers. |
tui.message |
Shows a message with an OK button. ON_CLOSE runs after OK, Enter or Esc. |
tui.prompt |
Shows a one-line text input dialog. ON_SUBMIT is called with the text appended as its last argument. |
tui.choose |
Shows a list picker. ON_CHOOSE is called with the 0-based index and the item text appended. |
tui.view |
Shows scrollable read-only text, for help screens and logs. |
tui.dialog.close |
Closes the open dialog without calling any of its callbacks. |
tui.dialog.active |
Returns 0 while a dialog is open. |
tui.notify |
Shows a toast notification that disappears on its own. |
tui.notify.clear |
Dismisses one toast by id, or all toasts, and repaints what they covered. |
tui.notify.count |
Prints the number of toasts showing. |
tui.notify.position |
Sets where toasts appear, or prints the current position without an argument. |
tui.notify.seconds |
Sets the default toast lifetime in seconds (decimals allowed, 0 = until cleared), or prints it without an argument. Default: 5. |
tui.confirm
tui.confirm MESSAGE [ON_YES [ON_NO]] [flags]
Shows a Yes/No dialog and returns immediately; the callback runs after the user answers.
Parameters
ON_YES,ON_NO: commands: a function name plus fixed arguments, split on spaces. Either may be empty.
Options
--danger: red primary button, titleWarning, and No selected by default.--default yes|no,--title T,--width N,--yes LABEL,--no LABEL.
Notes
- Keys:
yyes,nor Esc no, arrows/Tab move, Enter picks. Mouse clicks work. - The callback runs after the dialog is closed and the screen repainted, so it may open another dialog or change page.
TUI_DIALOG_RESULTisyesorno. - Commands can’t chain with
;or quote arguments, and must be shell functions. Pass values with spaces through a variable. - Does nothing before the app runs.
Example
tui.confirm "Delete report.csv?" "rm_file report.csv" --danger --yes Delete --no Keep
tui.message
tui.message MESSAGE [ON_CLOSE] [flags]
Shows a message with an OK button. ON_CLOSE runs after OK, Enter or Esc.
Notes
- Flags:
--title,--width,--ok LABEL.
tui.prompt
tui.prompt MESSAGE ON_SUBMIT [flags]
Shows a one-line text input dialog. ON_SUBMIT is called with the text appended as its last argument.
Options
--value TEXT: initial text.--placeholder TEXT: grey hint while empty.--validate FN: called asFN TEXTon submit. A non-zero return keeps the dialog open; setTUI_DIALOG_ERRORto show why.--cancel CMD: runs on Esc or Cancel.- Common:
--title,--width,--ok.
Notes
- Supports the text-editing keys of an input (cursor, Home/End,
ctrl+u/ctrl+k/ctrl+w, paste).
Example
name_ok() { [[ -n "$1" && "$1" != */* ]] || { TUI_DIALOG_ERROR="no slashes, not empty"; return 1; }; }
tui.prompt "New name:" do_rename --value "$old" --validate name_ok
do_rename() { mv -- "$old" "$1" && tui.notify "Renamed to $1" success; }
tui.choose
tui.choose TITLE ON_CHOOSE ITEM... [flags]
Shows a list picker. ON_CHOOSE is called with the 0-based index and the item text appended.
Options
--message TEXT: text above the list.--selected N: initially selected index.--cancel CMD: runs on Esc.
Returns: 1 when there are no items.
Notes
- Keys: arrows,
j/k, PgUp/PgDn, Enter, digits1–9pick directly. Click and wheel work.
Example
tui.choose "Export as" do_export csv json yaml
do_export() { tui.notify "Exporting as $2 (#$1)"; }
tui.view
tui.view TITLE TEXT [--width N] [--close CMD]
Shows scrollable read-only text, for help screens and logs.
Notes
- Keys: Up/Down,
j/k, PgUp/PgDn, Space, Home/End, wheel. Esc,qor Enter close. --close CMD(or--cancel CMD) runs after it closes.
tui.dialog.close
tui.dialog.close
Closes the open dialog without calling any of its callbacks.
tui.dialog.active
tui.dialog.active
Returns 0 while a dialog is open.
tui.notify
tui.notify MESSAGE [LEVEL] [SECONDS]
Shows a toast notification that disappears on its own.
Parameters
LEVEL:info(default),success,warn(orwarning),error. Anything else counts asinfo.SECONDS: lifetime. Default:tui.notify.seconds(5).0= until cleared.
Sets: TUI_NOTIFY_ID to the new toast’s id.
Notes
- Up to 5 toasts stack; the oldest is dropped. Toasts survive page changes.
- Position:
tui.notify.position. - Styled with
.toast,.toast_success,.toast_warn,.toast_errorwhen the theme defines them.
Example
tui.notify "Report saved" success
tui.notify "Upload failed" error 0; err_toast=$TUI_NOTIFY_ID
tui.notify.clear
tui.notify.clear [ID]
Dismisses one toast by id, or all toasts, and repaints what they covered.
tui.notify.count
tui.notify.count
Prints the number of toasts showing.
tui.notify.position
tui.notify.position [POS]
Sets where toasts appear, or prints the current position without an argument.
Parameters
POS:bottom-right(default),bottom-left,bottom-center,top-right,top-left,top-center.
Returns: 1 and a message on stderr for any other value.
Notes
- Lasts for this run. Persist it with
tui.config.set notify.position POS(the Settings page does).
tui.notify.seconds
tui.notify.seconds [N]
Sets the default toast lifetime in seconds (decimals allowed, 0 = until cleared), or prints it without an argument. Default: 5.
Notes
- Invalid values are ignored silently. Persist it with the
notify.secondsconfig key.
Footer
| Function | Summary |
|---|---|
tui.footer.set |
Declares the footer bar, as <footer/> does. Records the items only; the page layout then leaves the last row free. |
tui.footer.show |
Sets and shows the footer at runtime, then relayouts so the outermost pane gives up the last row. Empty ITEMS shows the default items. |
tui.footer.add |
Appends one item to the footer (to the default items when none were set) and shows it. |
tui.footer.hide |
Removes the footer and gives the last row back to the panes. |
tui.footer.set
tui.footer.set [ITEMS]
Declares the footer bar, as <footer/> does. Records the items only; the page layout then leaves the last row free.
Parameters
ITEMS:KEY|LABEL[|WHEN_FN]items separated by;. Empty: the default (quit, command bar, and Back when there is a page to go back to).KEYis shown as written (ctrl+s), or@COMMANDshows whichever key is bound to that command right now, so the footer follows rebinding. An@COMMANDwith no key is skipped.WHEN_FN: the item is shown only while it returns0.
Notes
- The footer belongs to its page and is removed on page change. At runtime use
tui.footer.show, which also relayouts. - Styled with
.footer,.footer_key,.footer_label.
Example
tui.footer.set "@tui.action.quit|Quit;@tui.palette.open|Commands;ctrl+s|Save|is_dirty"
tui.footer.show
tui.footer.show [ITEMS]
Sets and shows the footer at runtime, then relayouts so the outermost pane gives up the last row. Empty ITEMS shows the default items.
tui.footer.add
tui.footer.add KEY LABEL [WHEN_FN]
Appends one item to the footer (to the default items when none were set) and shows it.
tui.footer.hide
tui.footer.hide
Removes the footer and gives the last row back to the panes.
