D.A.B.Tv0.0.17 Tutorial API DABT Tools ↗ GitHub ↗

Widgets: forms & text editing

lib/tui.sh (basic widgets), lib/widgets/tui_widgets.sh, lib/widgets/tui_text.sh - the widget constructors and the text-editing engine shared by input, password and textarea. Guide: ../guide/widgets.md. ← API index for the full module list and a task-oriented tour with examples.

Constructors take ID PANE ROW .... ROW is 0-based inside the pane’s content area. A missing ID or PANE prints an error and skips the widget. Functions return 0 unless their entry says otherwise.

Every widget callback gets the widget id first, so one function can serve several widgets:

Widget Callback Called as
button, list, table, select action FN ID
checkbox action FN ID VALUE (value 0/1)
input, password, textarea submit FN ID TEXT
any tui.on_change FN ID

Widgets

Function Summary
tui.label Creates a static text widget.
tui.button Creates a focusable button.
tui.input Creates a single-line text input.
tui.checkbox Creates a checkbox.
tui.checkbox.toggle Flips a checkbox, redraws it and calls its action as ACTION ID VALUE, as a click would.
tui.get Prints a widget’s value, without a trailing newline.
tui.set Sets a widget’s value without redrawing it.
tui.update Sets a widget’s value and redraws the widget.
tui.set_label Changes the caption of a button or checkbox, or the text of a label, and redraws it.
tui.get.label Prints the caption of a widget: button text, checkbox label, input label or label text.
tui.on_action Sets or replaces the action function of a widget. Buttons, lists and tables call it as FN ID; checkboxes as FN ID VALUE.
tui.on_submit Sets or replaces the submit function of an input, password or textarea, called as FN ID TEXT.
tui.align Sets the horizontal alignment of one widget, overriding the pane default.
tui.valign Sets the vertical anchor of one widget, overriding the pane default.
tui.minsize Sets the minimum width of a widget in columns.
tui.maxsize Sets the maximum width of a widget in columns.
tui.pad Sets blank columns and rows around one widget. An empty value is left unchanged.
tui.label_align Aligns an input label inside its label column.
tui.label_width Gives an input label a fixed column width, so fields in a form line up.
tui.input.retain Sets whether an input keeps focus after Enter.
tui.input.blur_on_submit Old name for tui.input.retain ID false.
tui.input.sticky With true (default), clicking empty space no longer takes focus away from the input; Esc and Tab still do.
tui.focus Focuses a widget. Its pane becomes the keyboard pane.

tui.label

tui.label ID PANE ROW TEXT

Creates a static text widget.

Parameters

  • ID: unique widget id.
  • PANE: a leaf pane.
  • ROW: 0-based row inside the pane’s content area, counted from the pane’s vertical anchor (see tui.pane_valign).
  • TEXT: the text.

Returns: 1 and a message on stderr when ID or PANE is empty.

Notes

Example

tui.label lbl_name form 0 "Name"

tui.button

tui.button ID PANE ROW TEXT [ACTION]

Creates a focusable button.

Parameters

  • TEXT: caption, drawn as given (include brackets yourself: "[ Save ]").
  • ACTION: function called as ACTION ID on Enter or click.

Returns: 1 when ID or PANE is empty.

Notes

Example

tui.button btn_save form 3 "[ Save ]" on_save
on_save() { tui.notify "Saved $(tui.get inp_name)" success; }

See also: tui.on_action, tui.set_label

tui.input

tui.input ID PANE ROW [PLACEHOLDER] [LABEL] [SUBMIT]

Creates a single-line text input.

Parameters

  • PLACEHOLDER: grey text shown while empty.
  • LABEL: text drawn before the field.
  • SUBMIT: function called on Enter as SUBMIT ID TEXT: the widget id, then the current text.

Returns: 1 when ID or PANE is empty.

Notes

  • The id lets one function serve several inputs: case $1 in inp_name) ... ;; inp_mail) ... ;; esac.
  • Without SUBMIT, an action set with tui.on_action is called as ACTION ID instead.
  • The text is not cleared after submit. Clear it in SUBMIT with tui.update ID "".
  • The input keeps focus after Enter by default; see tui.input.retain.
  • Full editing keys (selection, word jumps, clipboard, undo): press f1 in the app, or see tui.action.text_keys.

Example

tui.input inp_cmd shell 0 "type a command" "> " run_cmd
run_cmd() { tui.output_append log "\$ $2"; tui.update "$1" ""; }     # $1 = this input's id, $2 = the text

See also: tui.password, tui.textarea

tui.checkbox

tui.checkbox ID PANE ROW LABEL [CHECKED] [ACTION]

Creates a checkbox.

Parameters

  • CHECKED: 1, true or yes to start checked. Anything else starts unchecked.
  • ACTION: function called as ACTION ID VALUE after each toggle: the checkbox id, then the new value 0 or 1.

Returns: 1 when ID or PANE is empty.

Notes

  • The id comes first, as for every widget callback, so one function can handle a whole group of checkboxes.
  • tui.get prints 0/1; tui.get.checked works in conditions.

Example

tui.checkbox chk_wrap  opts 0 "Wrap lines"   1 on_opt
tui.checkbox chk_times opts 1 "Show times"   0 on_opt
on_opt() {                           # ID VALUE
    case "$1" in
        chk_wrap)  tui.config.set my.wrap  "$2" ;;
        chk_times) tui.config.set my.times "$2" ;;
    esac
}

See also: tui.checkbox.toggle

tui.checkbox.toggle

tui.checkbox.toggle ID

Flips a checkbox, redraws it and calls its action as ACTION ID VALUE, as a click would.

Notes

  • Does nothing for a widget that is not a checkbox.
  • To set a value without calling the action, use tui.update ID 0|1.

tui.get

tui.get ID

Prints a widget’s value, without a trailing newline.

Output: by type: input, password and textarea: the text (textarea lines joined by newlines); checkbox: 0 or 1; label: its text; select: the chosen option; progress: the percent. Buttons, lists and tables print nothing; use tui.list.item / tui.table.row.

Example

name="$(tui.get inp_name)"

tui.set

tui.set ID VALUE

Sets a widget’s value without redrawing it.

Notes

  • Use it to prepare several widgets before one repaint, or before the first render. While the app runs, use tui.update so the change is visible.
  • Checkbox values must be 0 or 1.

tui.update

tui.update ID VALUE

Sets a widget’s value and redraws the widget.

Notes

  • Does not call the widget’s action or on_change function.
  • For a button or checkbox caption use tui.set_label; VALUE is not the caption.

Example

tui.update inp_name ""          # clear an input
tui.update chk_wrap 1           # check a checkbox without running its action

tui.set_label

tui.set_label ID TEXT

Changes the caption of a button or checkbox, or the text of a label, and redraws it.

Returns: 1 for an unknown id.

Example

tui.set_label btn_run "[ Running… ]"

tui.get.label

tui.get.label ID

Prints the caption of a widget: button text, checkbox label, input label or label text.

tui.on_action

tui.on_action ID FN

Sets or replaces the action function of a widget. Buttons, lists and tables call it as FN ID; checkboxes as FN ID VALUE.

tui.on_submit

tui.on_submit ID FN

Sets or replaces the submit function of an input, password or textarea, called as FN ID TEXT.

tui.align

tui.align ID left|center|right|fill

Sets the horizontal alignment of one widget, overriding the pane default.

Notes

  • fill stretches the widget to the pane width (used by tab headers).

tui.valign

tui.valign ID top|middle|bottom

Sets the vertical anchor of one widget, overriding the pane default.

Notes

  • With bottom, the widget ROW counts up from the last line.

tui.minsize

tui.minsize ID WIDTH

Sets the minimum width of a widget in columns.

tui.maxsize

tui.maxsize ID WIDTH

Sets the maximum width of a widget in columns.

tui.pad

tui.pad ID [HPAD] [VPAD]

Sets blank columns and rows around one widget. An empty value is left unchanged.

Notes

tui.label_align

tui.label_align ID left|right

Aligns an input label inside its label column.

Notes

tui.label_width

tui.label_width ID N

Gives an input label a fixed column width, so fields in a form line up.

tui.input.retain

tui.input.retain ID [true|false]

Sets whether an input keeps focus after Enter.

Parameters

  • true (default): the cursor stays in the field, like a shell prompt or chat box.
  • false: form style; Enter submits and leaves the field.

Notes

  • Inputs without their own setting use TUI_INPUT_RETAIN_ON_SUBMIT (1), or the input.retain config key.
  • Any value other than true means false.

tui.input.blur_on_submit

tui.input.blur_on_submit ID

Old name for tui.input.retain ID false.

tui.input.sticky

tui.input.sticky ID [true|false]

With true (default), clicking empty space no longer takes focus away from the input; Esc and Tab still do.

tui.focus

tui.focus ID

Focuses a widget. Its pane becomes the keyboard pane.

Notes

  • Redraws only the old and new widget and their pane borders.
  • Focusing a text widget places the cursor for editing.

See also: tui.get.focused, tui.action.unfocus

Richer widgets

Key tables and mouse behaviour: ../guide/widgets.md. Markup tags: <password> <textarea> <list> <table> <select> <progress> (attributes in share/tui.xsd). Theme classes (all optional): .list_sel .table_head .table_sel .progress .progress_fill .select .selection.

Function Summary
tui.password Creates a single-line input that shows • for each character.
tui.textarea Creates a multi-line text editor.
tui.list Creates a scrollable single-choice list.
tui.table Creates a scrollable table: a header row plus rows of \|-separated cells, one selectable row at a time.
tui.select Creates a one-row dropdown. Enter, Space, Down or a click opens a picker dialog.
tui.progress Creates a progress bar showing 0–100 %. Not focusable.
tui.list.set Replaces all items and selects the first one (none when empty).
tui.list.add Appends items. Selects the first item when nothing was selected.
tui.list.clear Removes all items and clears the selection.
tui.list.select Moves the selection to INDEX (0-based), clamped to the list. A negative index clears it.
tui.list.selected Prints the selected index, or -1 when nothing is selected.
tui.list.item Prints the item at INDEX, default the selected one. Prints nothing for an index out of range.
tui.list.count Prints the number of items.
tui.table.set Replaces the header and all rows, and selects the first row.
tui.table.add Appends rows (\|-separated cells). Selects the first row when nothing was selected.
tui.table.clear Removes all rows and clears the selection. The header is kept.
tui.table.count Prints the number of rows (the header not counted).
tui.table.select Moves the selection to row INDEX (0-based), clamped. Does not call on_change.
tui.table.selected Prints the selected row index, or -1.
tui.table.row Prints a row as a\|b\|c, default the selected one.
tui.select.set Replaces the options. The current value stays selected when it is among the new options.
tui.select.index Prints the index of the current value among the options, or -1.
tui.select.pick Chooses option INDEX (0-based) as if the user picked it: sets the value, redraws, then calls the on_change function and the action.
tui.progress.set Sets a progress bar to VALUE out of MAX and redraws it.
tui.on_change Sets a function called as FN ID whenever the widget changes through the user.

tui.password

tui.password ID PANE ROW [PLACEHOLDER] [LABEL] [SUBMIT]

Creates a single-line input that shows • for each character.

Notes

  • Same parameters and SUBMIT ID TEXT call as tui.input. Read the value with tui.get.
  • Copy and cut are disabled, so the text never reaches the clipboard.

tui.textarea

tui.textarea ID PANE ROW [PLACEHOLDER] [ROWS] [SUBMIT]

Creates a multi-line text editor.

Parameters

  • ROWS: height in rows. Omitted or 0: fill the rest of the pane.
  • SUBMIT: called as SUBMIT ID TEXT on alt+enter or ctrl+enter. Enter inserts a newline.

Notes

  • Supports mouse placement, drag-select, word jumps, cut/copy/paste and undo. Up/Down at the first/last line move focus out of the widget.
  • Tabs are converted to four spaces, and non-printable characters are dropped on insert.

Example

tui.textarea notes editor 0 "notes..." 0 save_notes
tui.on_change notes mark_dirty

tui.list

tui.list ID PANE ROW [ACTION] [ROWS]

Creates a scrollable single-choice list.

Parameters

  • ACTION: called as ACTION ID on Enter or double-click.
  • ROWS: height. Omitted or 0: fill the pane.

Notes

  • Keys: Up/Down, PgUp/PgDn, Home/End. At the first/last row Up/Down move focus out.
  • Selection moves call the tui.on_change function.

Example

tui.list files side 0 open_file
tui.list.set files *.txt
open_file() { tui.output view "$(<"$(tui.list.item "$1")")"; }

tui.table

tui.table ID PANE ROW [ACTION] [ROWS]

Creates a scrollable table: a header row plus rows of |-separated cells, one selectable row at a time.

Parameters

Example

tui.table procs main 0 show_proc
tui.table.set procs "PID|Name|CPU" "1|init|0.0" "42|bash|1.2"

tui.select

tui.select ID PANE ROW LABEL [ACTION]

Creates a one-row dropdown. Enter, Space, Down or a click opens a picker dialog.

Parameters

  • LABEL: text before the value, also the picker title.
  • ACTION: called as ACTION ID after a new value is picked.

Notes

Example

tui.select mode form 3 "Mode:" mode_changed
tui.select.set mode fast balanced careful

tui.progress

tui.progress ID PANE ROW [LABEL]

Creates a progress bar showing 0–100 %. Not focusable.

See also: tui.progress.set

tui.list.set

tui.list.set ID ITEM...

Replaces all items and selects the first one (none when empty).

Notes

  • Does not call the on_change function.

tui.list.add

tui.list.add ID ITEM...

Appends items. Selects the first item when nothing was selected.

tui.list.clear

tui.list.clear ID

Removes all items and clears the selection.

tui.list.select

tui.list.select ID INDEX

Moves the selection to INDEX (0-based), clamped to the list. A negative index clears it.

Notes

  • Does not call the on_change function.

tui.list.selected

tui.list.selected ID

Prints the selected index, or -1 when nothing is selected.

tui.list.item

tui.list.item ID [INDEX]

Prints the item at INDEX, default the selected one. Prints nothing for an index out of range.

tui.list.count

tui.list.count ID

Prints the number of items.

tui.table.set

tui.table.set ID HEADER ROW...

Replaces the header and all rows, and selects the first row.

Parameters

  • HEADER, ROW: cells separated by |, e.g. "Name|Size" and "a.txt|1k".

Notes

  • Each column is as wide as its widest cell; when the table is too wide, the widest columns shrink first (to at least 3). A cell cannot contain |.

tui.table.add

tui.table.add ID ROW...

Appends rows (|-separated cells). Selects the first row when nothing was selected.

tui.table.clear

tui.table.clear ID

Removes all rows and clears the selection. The header is kept.

tui.table.count

tui.table.count ID

Prints the number of rows (the header not counted).

tui.table.select

tui.table.select ID INDEX

Moves the selection to row INDEX (0-based), clamped. Does not call on_change.

tui.table.selected

tui.table.selected ID

Prints the selected row index, or -1.

tui.table.row

tui.table.row ID [INDEX]

Prints a row as a|b|c, default the selected one.

Notes

  • Split it with IFS="|" read -r name size <<<"$(tui.table.row procs)".

tui.select.set

tui.select.set ID ITEM...

Replaces the options. The current value stays selected when it is among the new options.

Notes

tui.select.index

tui.select.index ID

Prints the index of the current value among the options, or -1.

tui.select.pick

tui.select.pick ID INDEX

Chooses option INDEX (0-based) as if the user picked it: sets the value, redraws, then calls the on_change function and the action.

Returns: 1 for an index out of range.

tui.progress.set

tui.progress.set ID VALUE [MAX]

Sets a progress bar to VALUE out of MAX and redraws it.

Parameters

  • VALUE: integer.
  • MAX: integer. Default: 100.

Notes

  • Stored as a whole percent, clamped to 0–100.

Example

tui.progress.set job "$done" "$total"

tui.on_change

tui.on_change ID FN

Sets a function called as FN ID whenever the widget changes through the user.

Notes

  • Fires after every edit (input, password, textarea), selection move (list, table) or picked value (select).
  • Not called for programmatic changes such as tui.update or tui.list.set.

Example

tui.on_change notes mark_dirty
mark_dirty() { tui.set_label btn_save "[ Save* ]"; }

Text editing

For input, password and textarea widgets. Offsets are 0-based character positions in the whole text. TUI_CLIPBOARD holds the text of the last copy or cut inside a text widget; every copy is also sent to the terminal clipboard (tui.clipboard.copy).

Function Summary
tui.text.selection Prints the selected text of a text widget (nothing when nothing is selected).
tui.text.select Selects characters START to END (0-based offsets into the whole text) and redraws. Offsets beyond the end are clamped.
tui.text.select_all Selects the whole text and redraws.
tui.text.cursor Prints the cursor position as ROW COL (1-based).
tui.text.set_cursor Moves the cursor to character OFFSET (0-based, clamped) and clears the selection.
tui.text.insert Inserts TEXT at the cursor, replacing the selection, as typing would. The change can be undone and calls the on_change function.
tui.text.delete_selection Deletes the selected text. Returns 1 when nothing is selected.
tui.text.undo Undoes the last edit (ctrl+z/alt+z). Returns 1 when there is nothing to undo.
tui.text.redo Redoes the last undone edit (ctrl+y/alt+y). Returns 1 when there is nothing to redo.
tui.text.line_count Prints the number of lines in a text widget (1 for an input).
tui.action.text_keys Opens a scrollable list of every text-editing key. Bound to f1 by default.

tui.text.selection

tui.text.selection ID

Prints the selected text of a text widget (nothing when nothing is selected).

tui.text.select

tui.text.select ID START END

Selects characters START to END (0-based offsets into the whole text) and redraws. Offsets beyond the end are clamped.

tui.text.select_all

tui.text.select_all ID

Selects the whole text and redraws.

tui.text.cursor

tui.text.cursor ID

Prints the cursor position as ROW COL (1-based).

tui.text.set_cursor

tui.text.set_cursor ID OFFSET

Moves the cursor to character OFFSET (0-based, clamped) and clears the selection.

tui.text.insert

tui.text.insert ID TEXT

Inserts TEXT at the cursor, replacing the selection, as typing would. The change can be undone and calls the on_change function.

Notes

  • In single-line widgets newlines become spaces and control characters are removed. Tabs become four spaces.

Example

tui.text.insert notes "$(date +%F) "

tui.text.delete_selection

tui.text.delete_selection ID

Deletes the selected text. Returns 1 when nothing is selected.

tui.text.undo

tui.text.undo ID

Undoes the last edit (ctrl+z/alt+z). Returns 1 when there is nothing to undo.

tui.text.redo

tui.text.redo ID

Redoes the last undone edit (ctrl+y/alt+y). Returns 1 when there is nothing to redo.

tui.text.line_count

tui.text.line_count ID

Prints the number of lines in a text widget (1 for an input).

tui.action.text_keys

tui.action.text_keys

Opens a scrollable list of every text-editing key. Bound to f1 by default.