Liking cljdoc? Tell your friends :D

com.blockether.vis.ext.channel-tui.human-input

TUI rendering for :human-input/request — the terminal half of the engine's typed human-input pause primitive (com.blockether.vis.internal.human-input).

The engine parks an extension thread and publishes a request VIEW; this namespace turns that view into a form the operator can fill in, and hands the collected values back through submit-human-input! / cancel-human-input!.

Everything except paint! is PURE: init-form builds the form model from a request view, handle-event is a reducer over one normalized keystroke, and form-rows is the paint plan. The Lanterna surface only shows up in key->event (decoding) and paint! (drawing), so the whole interaction is testable without a terminal.

Navigation is a flat list of STOPS — one per text field, one per checkbox, and one per select/multiselect OPTION — so ↑/↓/Tab walks the form the way the settings dialog walks its rows.

TUI rendering for `:human-input/request` — the terminal half of the engine's
typed human-input pause primitive (`com.blockether.vis.internal.human-input`).

The engine parks an extension thread and publishes a request VIEW; this
namespace turns that view into a form the operator can fill in, and hands
the collected values back through `submit-human-input!` / `cancel-human-input!`.

Everything except [[paint!]] is PURE: [[init-form]] builds the form model
from a request view, [[handle-event]] is a reducer over one normalized
keystroke, and [[form-rows]] is the paint plan. The Lanterna surface only
shows up in [[key->event]] (decoding) and [[paint!]] (drawing), so the whole
interaction is testable without a terminal.

Navigation is a flat list of STOPS — one per text field, one per checkbox,
and one per select/multiselect OPTION — so ↑/↓/Tab walks the form the way
the settings dialog walks its rows.
raw docstring

action-barclj

(action-bar {:keys [stops focus]})

The request's own buttons as ONE row: the solid Submit pill, then the muted Cancel one.

PRIMARY vs SECONDARY is a SEMANTIC ranking, not a focus state — submit is the confirming action and keeps the ink fill wherever the cursor is, so walking the caps never promotes Cancel to look like the default. :is-focused says which cap the cursor sits on, and the painter answers it with the project-wide marker instead of a second colour.

No chord travels with a button: a cap is a focus stop reached with ↑/↓ like every other row of the form. The hint bar one row below stays silent about submit and cancel too (hint) — it used to reprint these very labels as Enter submit · Esc cancel, two rows of chrome for one meaning.

PINNED by the painter under the scrolling body instead of trailing it, so a form taller than the band can never push the two controls that END the pause off the screen — the same reason the companion pins them in its footer.

The request's own buttons as ONE row: the solid ` Submit ` pill, then the muted
` Cancel ` one.

PRIMARY vs SECONDARY is a SEMANTIC ranking, not a focus state — submit is the
confirming action and keeps the ink fill wherever the cursor is, so walking the
caps never promotes Cancel to look like the default. `:is-focused` says which
cap the cursor sits on, and the painter answers it with the project-wide `•`
marker instead of a second colour.

No chord travels with a button: a cap is a focus stop reached with ↑/↓ like
every other row of the form. The hint bar one row below stays silent about
submit and cancel too ([[hint]]) — it used to reprint these very labels as
`Enter submit · Esc cancel`, two rows of chrome for one meaning.

PINNED by the painter under the scrolling body instead of trailing it, so a
form taller than the band can never push the two controls that END the pause
off the screen — the same reason the companion pins them in its footer.
sourceraw docstring

action-stopsclj

(action-stops request)

The request's own confirm/cancel buttons, as focus stops of their own.

A transient that can only be accepted by a chord is a transient nobody accepts: these are the LAST stops, so ↓ walks off the final field straight onto the Submit cap and Enter presses it. Cancel only exists when the request allows it — an uncancellable ask must not offer a button that does nothing.

The request's own confirm/cancel buttons, as focus stops of their own.

A transient that can only be accepted by a chord is a transient nobody
accepts: these are the LAST stops, so ↓ walks off the final field straight
onto the `Submit` cap and Enter presses it. Cancel only exists when the request
allows it — an uncancellable ask must not offer a button that does nothing.
sourceraw docstring

default-valueclj

(default-value {:keys [type default] :as field})

The value a field starts with: its declared :default coerced to the shape the field type submits, else that type's empty value.

The value a field starts with: its declared `:default` coerced to the shape
the field type submits, else that type's empty value.
sourceraw docstring

focused-rowclj

(focused-row rows)

Index of the row carrying the focused stop, or 0.

Index of the row carrying the focused stop, or 0.
sourceraw docstring

focused-stopclj

(focused-stop {:keys [stops focus]})

The stop under the cursor, or nil for a form with no stops.

The stop under the cursor, or nil for a form with no stops.
sourceraw docstring

form-rowsclj

(form-rows form)
(form-rows {:keys [request focus stops] :as form} text-w)

PURE paint plan: the ordered rows the dialog body draws for form.

Fields only — the confirm/cancel buttons live in action-bar, pinned below this body, so they are never scrolled away.

text-w is the column budget prose gets — the request's description and every field's wrap to it. Omit it (or pass nil) for the unwrapped plan.

PURE paint plan: the ordered rows the dialog body draws for `form`.

Fields only — the confirm/cancel buttons live in [[action-bar]], pinned below
this body, so they are never scrolled away.

`text-w` is the column budget prose gets — the request's description and
every field's wrap to it. Omit it (or pass nil) for the unwrapped plan.
sourceraw docstring

handle-eventclj

(handle-event form {:keys [kind char] :as _event})

PURE reducer: apply ONE normalized event to form.

Returns {:form form' :action action} where action is nil (stay open), :submit (ask the engine to accept submit-values), or :cancel.

PURE reducer: apply ONE normalized event to `form`.

Returns `{:form form' :action action}` where `action` is nil (stay open),
`:submit` (ask the engine to accept `submit-values`), or `:cancel`.
sourceraw docstring

hintclj

(hint form)

Hint-bar pairs for form — TYPING chords only, spelled the canonical dialog way: chord, then a lowercase action.

NAVIGATION IS NOT A HINT. ↑/↓ move used to lead this list on every single pause: a permanent row of chrome teaching the one thing every terminal operator already knows, printed under a form whose focus ring already shows where the cursor is. So the bar is EMPTY unless the FOCUSED stop accepts a chord the band itself cannot show — Space on a toggle, digits in an OTP, ←/→ on a slider, Enter for a newline.

Submit and cancel are not here either: action-bar paints those two controls one row above with their own chords ON the caps, so a hint pair for either would print the same verb twice, a row apart. The one Enter that belongs here is the multiline NEWLINE — that is a typing chord, and it is also why the submit cap switches to ^S.

Hint-bar pairs for `form` — TYPING chords only, spelled the canonical dialog
way: chord, then a lowercase action.

NAVIGATION IS NOT A HINT. `↑/↓ move` used to lead this list on every single
pause: a permanent row of chrome teaching the one thing every terminal
operator already knows, printed under a form whose focus ring already shows
where the cursor is. So the bar is EMPTY unless the FOCUSED stop accepts a
chord the band itself cannot show — Space on a toggle, digits in an OTP, ←/→
on a slider, Enter for a newline.

Submit and cancel are not here either: [[action-bar]] paints those two
controls one row above with their own chords ON the caps, so a hint pair for
either would print the same verb twice, a row apart. The one Enter that
belongs here is the multiline NEWLINE — that is a typing chord, and it is also
why the submit cap switches to `^S`.
sourceraw docstring

init-formclj

(init-form request)

Build the form model for a request VIEW. Text cursors start at end-of-text and focus starts on the first stop.

Build the form model for a request VIEW. Text cursors start at end-of-text
and focus starts on the first stop.
sourceraw docstring

key->eventclj

(key->event key)

Normalize one Lanterna keystroke into the event map handle-event takes, or nil when the keystroke means nothing to a form (mouse, unknown chords).

Normalize one Lanterna keystroke into the event map [[handle-event]] takes,
or nil when the keystroke means nothing to a form (mouse, unknown chords).
sourceraw docstring

paint!clj

(paint! g cols rows form)
(paint! g cols rows form content-top)

Draw the human-input band for form INSIDE the session's own frame. Returns the TerminalPosition the caller should place the terminal cursor at (the focused text field), or nil when no text field has focus.

A magit-style TRANSIENT, not a modal. The band is bottom-anchored on the session's bottom chrome — it takes over the prompt's rows and grows UPWARD over the transcript, never past content-top — and reads ─── / bold title / ─── / the fields / the action bar / ─── / hint bar, the same chrome every other transient in the TUI wears. The rule directly above the hint bar is the host's closing rule, so the footer below the band is never swallowed.

The action bar is PINNED: only the fields scroll under it, so the Submit and Cancel caps stay on screen for a form of any length.

TWO passes over the plan, because a scrollbar costs a column: the first plan sizes the band, and an overflowing one re-wraps one column narrower.

Draw the human-input band for `form` INSIDE the session's own frame. Returns
the `TerminalPosition` the caller should place the terminal cursor at (the
focused text field), or nil when no text field has focus.

A magit-style TRANSIENT, not a modal. The band is bottom-anchored on the
session's bottom chrome — it takes over the prompt's rows and grows UPWARD
over the transcript, never past `content-top` — and reads `───` / bold title /
`───` / the fields / the action bar / `───` / hint bar, the same chrome every
other transient in the TUI wears. The rule directly above the hint bar is the
host's closing rule, so the footer below the band is never swallowed.

The action bar is PINNED: only the fields scroll under it, so the `Submit`
and `Cancel` caps stay on screen for a form of any length.

TWO passes over the plan, because a scrollbar costs a column: the first plan
sizes the band, and an overflowing one re-wraps one column narrower.
sourceraw docstring

request-idclj

(request-id form)

The engine request id this form answers.

The engine request id this form answers.
sourceraw docstring

request<-wireclj

(request<-wire wire)

Rehydrate a request VIEW from the canonical snake_case wire map a human_input.request SESSION event carries — the only shape a request takes when the parked run lives in the serve daemon instead of this process. The ENGINE owns that inverse (view<-wire); the terminal never keeps a second field vocabulary.

Rehydrate a request VIEW from the canonical snake_case wire map a
`human_input.request` SESSION event carries — the only shape a request takes
when the parked run lives in the serve daemon instead of this process. The
ENGINE owns that inverse (`view<-wire`); the terminal never keeps a second
field vocabulary.
sourceraw docstring

session-idclj

(session-id form)

The gateway session whose run this form parks, or nil. A form built from a session event must be answered over the gateway that owns it.

The gateway session whose run this form parks, or nil. A form built from a
session event must be answered over the gateway that owns it.
sourceraw docstring

set-errorsclj

(set-errors form errors)

The ONE way a form turns red: the engine's per-field verdict on a CONFIRMATION. Focus lands on the first offending field, and the next touch of that field clears its message (see [[put-text]], [[nudge-range]], [[toggle-stop]]) — so the form is pristine again until the next confirmation.

The ONE way a form turns red: the engine's per-field verdict on a CONFIRMATION.
Focus lands on the first offending field, and the next touch of that field
clears its message (see [[put-text]], [[nudge-range]], [[toggle-stop]]) — so
the form is pristine again until the next confirmation.
sourceraw docstring

stopsclj

(stops request)

Flat vector of focus stops for request — the linear order ↑/↓/Tab walks.

Flat vector of focus stops for `request` — the linear order ↑/↓/Tab walks.
sourceraw docstring

submit-valuesclj

(submit-values form)

The values map handed to submit-human-input! — keyed by field id.

The values map handed to `submit-human-input!` — keyed by field id.
sourceraw docstring

window-startclj

(window-start rows visible)

First plan row to draw so the focused field stays usable: the minimal scroll that keeps the focused row on screen, pulled up to that field's LABEL row when the window is too short to hold both — a bare unlabelled input row would not say which field is being edited.

First plan row to draw so the focused field stays usable: the minimal scroll
that keeps the focused row on screen, pulled up to that field's LABEL row when
the window is too short to hold both — a bare unlabelled input row would not
say which field is being edited.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close