Templating, paths and expressions¶
Four small languages appear in the schema:
- Templates are strings with
${…}tokens, substituted before use (url,command,title,confirm, …). - Dot-paths name a value inside data (
root, a column'svalue, a field'spath). - Expressions compute a value per item (
where,keep,compute,by,on,success,activity.busy_when,window.growing.while). - Color values are used in
color_rulesandcolors.
Field tables in the other pages give each field's type as template,
path, expr or color.
Tokens¶
| Token | Resolves to | Where |
|---|---|---|
${env.NAME} |
The environment variable NAME; empty when unset |
Everywhere a template is accepted |
${params.NAME} |
A bound source parameter | A source's url, method, body, headers, path, command, env, initial_messages |
${selection} |
The focused row of a binding's from: component: a list's item, a table's first cell, a tree node's label, an eventlog item's key (${selection.PATH} reads that item's fields) |
Binding bind: and confirm:; a pushed screen's title, component content and source fields |
${selection.N} |
A table row's Nth cell, 1-based | As above |
${selection.Title} |
The cell in the column titled Title (case-insensitive, exact) |
As above |
${cursor} … |
The live focused row of an on_cursor driver (see below) |
on_cursor.bind |
${input.NAME} |
The committed value of the input or toggle named NAME on this screen (a toggle is true / false) |
on_input.bind, on_cursor.bind; a binding's bind:, confirm and notice; an action's run, url, method, headers, body (resolved when the action runs) |
${inputs.NAME} |
An action input, after bind: and the form |
An action's run, url, method, headers, body, message, error_message; a binding's confirm |
${code}, ${output} |
Exit or HTTP status; stdout or response body | message, error_message |
${body.PATH} |
A field of the action's JSON response, by dot-path | message, error_message |
${window.*} |
The window being requested (offset, limit, filter, sort; on Anchored sources cursor, dir and limit) | A windowed exec source's command; an Anchored http source's body, older and newer; see sources.md |
When tokens resolve¶
${env.*}is substituted once over the whole config: bytui-builderafterapp.promptsruns (so a boot prompt can supply a variable), and bywranglright after load. A resolved value is data: if it contains${env.OTHER}, that text is left alone.wrangl --describedeliberately shows the unsubstituted template, so secrets aren't printed.${params.*}is substituted when a caller binds the source. A token naming an undeclared parameter is left literal, so the typo is visible in the request.${selection…}is substituted when a binding fires or a screen is pushed, freezing the row at that moment. A column title that doesn't match is left literal.${cursor…}is substituted on every cursor move. Unresolved lookups become empty, so a missing column can't produce a request storm against a broken URL.${inputs.*}is substituted when the action runs. A known input with no value becomes empty. Unknown${…}text in an execrun:is left as written, so shell syntax like${PAGER:-less}survives.
Fields that name data rather than display text are never templated:
dot-paths (root, value, path, item, label) and expressions
(where, keep, compute, by, on, success, busy_when, while).
A good habit: let sources reference only ${params.*} and ${env.*},
and map selections onto parameters in bind:. The source then works the
same from a screen, from on_cursor, and from
wrangl --param.
Cursor¶
${cursor…} tokens read the driver named by on_cursor.source:
| Token | Table | List | Tree |
|---|---|---|---|
${cursor} |
first cell | the item | the node's label |
${cursor.N} |
Nth cell | ${cursor.1} is the item |
Nth path element (root is .1) |
${cursor.Title} |
cell by column title (case-insensitive, exact) | ${cursor.item} |
— |
${cursor.label} |
— | same as ${cursor} |
same as ${cursor} |
${cursor.depth} |
number of cells | number of cells | number of path elements |
${cursor.path} |
cells joined with / |
the item | path from the root, joined with / (e.g. a real file path) |
Dot-paths¶
A dot-path walks into parsed data: metadata.name, items.0.status or
items[0].status. An empty path is the value itself. A missing key, an
out-of-range index or a type mismatch gives an empty result rather than
an error.
Fields typed path (a column's value, a tree's label, children
and group_by, mark_key, row_key) also accept a list, tried in
order until one gives a non-empty value. This is how a kubectl-style
STATUS column falls back through container states:
value:
- status.containerStatuses.0.state.waiting.reason
- status.containerStatuses.0.state.terminated.reason
- status.phase
Expressions¶
Operator fields, an action's success:, activity.busy_when and
window.growing.while use
expr-lang expressions.
- In operators, each item's top-level fields are in scope
unprefixed:
status.phase == 'Running'. The whole item is alsoitem, which is how a plain text line is read:item contains 'ERROR'. An operator's own parameters areparams.NAME(strings; convert withint(params.min)). - In
success:, the variables arecode,outputandbody. - In
activity.busy_when, the row's item is in scope, the same way as in operators. Inwindow.growing.while, it's the value of the growingsource:. - A missing field is
nil, not an error. - A predicate (
where) is true fortrue, non-zero numbers and non-empty strings, and false forfalse,nil, zero and"". - Functions: expr-lang's built-ins (
len,hasPrefix,hasSuffix,indexOf,contains,matches,in,int,float,string,trim,split,join, date functions, …) pluslower,upper,nowandparseTime(accepts RFC 3339, with or without fractional seconds, and2006-01-02). - Index syntax is
items[0], not the dotteditems.0form that dot-paths accept.
Built-in names (count, sum, len, keys, values, filter,
map, all, any, one, none, sort, sortBy, contains,
startsWith, endsWith) shadow item fields of the same name. Rename
such a field with project: before referencing it.
where: "status.phase == 'Running' && !(metadata.namespace in ['kube-system'])"
compute:
containers: "len(spec.containers)"
name_upper: "upper(metadata.name)"
success: "code == 0 or output contains 'already exists'"
Color values¶
| Form | Example | Notes |
|---|---|---|
| Named | red, bright_green |
black, red, green, yellow, blue, magenta, cyan, white, gray / grey, and bright_ versions of each |
| Palette index | "160" |
0–255 |
| Hex | "#ff8800" |
Not usable for column_separator / header_rule or color rules, which need a palette color |
| Theme token | theme:accent |
Follows the active palette, including when themes cycle: accent, current, muted, subtle, key, border-active, border-inactive, bar-bg, bar-fg, info-bg, info-fg, error-bg, error-fg |
Durations¶
Go duration strings: 250ms, 5s, 1m30s, 2h. Used by refresh,
timeout, ttl, sort_debounce, window.follow_every and
type: duration inputs.