Liking cljdoc? Tell your friends :D

com.blockether.vis.ext.channel-tui.dialogs


adaptive-content-heightclj

(adaptive-content-height rows requested)

Clamp a dialog's REQUESTED content height so the box sizes to its own content instead of the shared footprint.

  • nil requested -> the shared full-height footprint (default-content-height). Spacious logo / welcome screens and long browsers opt in this way.
  • a number -> clamped between min-adaptive-content-h and the terminal-bounded dialog-max-height, so short dialogs are compact and long ones still scroll.
Clamp a dialog's REQUESTED content height so the box sizes to its own
content instead of the shared footprint.

- `nil` requested -> the shared full-height footprint (`default-content-height`).
  Spacious logo / welcome screens and long browsers opt in this way.
- a number -> clamped between `min-adaptive-content-h` and the terminal-bounded
  `dialog-max-height`, so short dialogs are compact and long ones still scroll.
sourceraw docstring

band-questionsclj

(band-questions screen g {:keys [left inner-w hint-row text-w] :as region})

Everything a band can ASK, bound to its own region once:

:read! one line of text on the hint row — [label] / [label opts] :choose! WHICH one, single-key — [title choices], returns the :id :confirm! y/n — [question] :transient! ANOTHER transient over the SAME band region — [spec] :read-option the :read-option a spec with OPTION items hands tr/run!

A transient that opens a transient, and a question asked on the hint row instead of in a window, is how magit asks a second thing without a second frame — every band in the TUI does both through this map.

Everything a band can ASK, bound to its own `region` once:

  `:read!`        one line of text on the hint row — `[label]` / `[label opts]`
  `:choose!`      WHICH one, single-key — `[title choices]`, returns the `:id`
  `:confirm!`     y/n — `[question]`
  `:transient!`   ANOTHER transient over the SAME band region — `[spec]`
  `:read-option`  the `:read-option` a spec with OPTION items hands `tr/run!`

A transient that opens a transient, and a question asked on the hint row
instead of in a window, is how magit asks a second thing without a second
frame — every band in the TUI does both through this map.
sourceraw docstring

choice-markclj

(choice-mark exclusive? checked?)

The status glyph a choice row wears in front of its label. An EXCLUSIVE choice takes the shared ●/○ pair the settings rows and the footer already speak — pick one and the other drops; an INCLUSIVE one takes the [✓]/[ ] box — pick as many as apply. One place, so "choose one" and "choose any" can never end up looking alike.

The status glyph a choice row wears in front of its label. An EXCLUSIVE choice
takes the shared ●/○ pair the settings rows and the footer already speak — pick
one and the other drops; an INCLUSIVE one takes the `[✓]`/`[ ]` box — pick as
many as apply. One place, so "choose one" and "choose any" can never end up
looking alike.
sourceraw docstring

clear-screen!clj

(clear-screen! screen)

Fill the entire screen with terminal background. Call before sub-dialogs to cleanly replace the current dialog (wizard step pattern).

Fill the entire screen with terminal background. Call before sub-dialogs
to cleanly replace the current dialog (wizard step pattern).
sourceraw docstring

command-palette!clj

(command-palette! screen)
(command-palette! screen extra-commands)
(command-palette! screen extra-commands ctx)

Show the searchable command palette. Returns the FULL chosen command map (so the caller's run-command! can read :id and any slash keys), or nil on Esc. extra-commands are the engine slash roots appended after the built-ins. Opened with C-x C-p (Emacs C-x prefix + Ctrl+P).

ctx ({:has-turns? bool}) gates context-only verbs via palette-commands-for — without turns the Fork Session entries are not listed at all.

Show the searchable command palette. Returns the FULL chosen command map
(so the caller's `run-command!` can read `:id` and any slash keys), or nil
on Esc. `extra-commands` are the engine slash roots appended after the
built-ins. Opened with C-x C-p (Emacs C-x prefix + Ctrl+P).

`ctx` (`{:has-turns? bool}`) gates context-only verbs via
[[palette-commands-for]] — without turns the Fork Session entries are not
listed at all.
sourceraw docstring

confirm-dialog!clj

(confirm-dialog! screen title message)

Show Y/N confirmation with side-by-side buttons. Returns true/false, nil on Esc.

Show Y/N confirmation with side-by-side buttons. Returns true/false, nil on Esc.
sourceraw docstring

copy-dialog!clj

(copy-dialog! screen messages)

Show copy dialog for chat messages. Space toggles, A toggles all, Enter copies selected, Esc cancels.

Show copy dialog for chat messages.
Space toggles, A toggles all, Enter copies selected, Esc cancels.
sourceraw docstring

default-content-heightclj

(default-content-height rows)

Shared content height every dialog uses, derived from rows. Clamped to a common modal footprint so dialogs keep equal height.

Shared content height every dialog uses, derived from `rows`.
Clamped to a common modal footprint so dialogs keep equal height.
sourceraw docstring

default-content-widthclj

(default-content-width cols)

Shared content width every dialog uses, derived from cols. Clamped between the theme's dialog min/max widths and bounded by the terminal so the box never paints off-screen.

Shared content width every dialog uses, derived from `cols`. Clamped
between the theme's dialog min/max widths and bounded by the terminal so
the box never paints off-screen.
sourceraw docstring

dialog-boundsclj

(dialog-bounds cols rows content-w content-h)

Pure geometry twin of draw-dialog-chrome! (explicit width+height arity): the box rectangle a content-w×content-h dialog occupies, computed WITHOUT painting. Lets a component measure its full layout — and reconcile a scroll window — before any drawing happens. Returns the SAME shape the chrome does ({:left :top :right :bottom :inner-w :inner-h}), from the same golden math.

Pure geometry twin of `draw-dialog-chrome!` (explicit width+height arity):
the box rectangle a `content-w`×`content-h` dialog occupies, computed WITHOUT
painting. Lets a component measure its full layout — and reconcile a scroll
window — before any drawing happens. Returns the SAME shape the chrome does
({:left :top :right :bottom :inner-w :inner-h}), from the same golden math.
sourceraw docstring

dialog-layoutclj

(dialog-layout bounds)
(dialog-layout {:keys [top bottom]} content-count)

Compute content area layout. When content-count is provided and smaller than the available height, content is vertically centered within the frame. Layout: border -> title bar -> top separator -> CONTENT -> bottom separator -> hint -> border.

Compute content area layout. When `content-count` is provided and smaller than
the available height, content is vertically centered within the frame.
Layout: border -> title bar -> top separator -> CONTENT -> bottom separator -> hint -> border.
sourceraw docstring

draft-transient!clj

(draft-transient! screen content-top draft-rows)
(draft-transient! screen content-top draft-rows pressed)

The DRAFT band: create, switch and abandon a draft workspace without ever leaving the session. Returns the choice the screen executes — :trunk, :draft, :new (with the typed :label and :clean?) or :abandon (with :workspace-id and :reason) — or nil when the human backed out at any step.

Creating, switching and abandoning are three separate keys: c/d fork a draft and name it inline, s opens the switch band, k abandons one. No step opens a window.

pressed is one of those commands named by a SLASH instead of by a key (drafts/slash-band): /draft new IS d, already pressed. A command this band does not offer right now (/draft resume with no drafts) opens the band itself rather than firing something the human was never shown.

The DRAFT band: create, switch and abandon a draft workspace without ever
leaving the session. Returns the choice the screen executes — `:trunk`,
`:draft`, `:new` (with the typed `:label` and `:clean?`) or `:abandon` (with
`:workspace-id` and `:reason`) — or nil when the human backed out at any
step.

Creating, switching and abandoning are three separate keys: `c`/`d` fork a
draft and name it inline, `s` opens the switch band, `k` abandons one. No
step opens a window.

`pressed` is one of those commands named by a SLASH instead of by a key
(`drafts/slash-band`): `/draft new` IS `d`, already pressed. A command this
band does not offer right now (`/draft resume` with no drafts) opens the band
itself rather than firing something the human was never shown.
sourceraw docstring

drain-modal-paste!clj

(drain-modal-paste! screen)

After a bracketed-paste START keystroke is seen, drain screen until PASTE_END and return the pasted text (PUA markers stripped). Lets any modal text input accept clipboard paste without re-implementing the paste state machine. Returns "" on a clipboard that yields no chars.

After a bracketed-paste START keystroke is seen, drain `screen` until
PASTE_END and return the pasted text (PUA markers stripped). Lets any
modal text input accept clipboard paste without re-implementing the
paste state machine. Returns "" on a clipboard that yields no chars.
sourceraw docstring

draw-checkbox-item!clj

(draw-checkbox-item! g left row inner-w selected? checked? label)

MULTI-choice LIST row — cursor glyph, a [✓]/[ ] box, then the label. The cursor glyph and the checkbox glyph carry independent meaning: the first says "this row is the cursor", the second says "this option is currently on". Anchored at (inc left) so the marker sits right at the dialog's inner edge (see draw-list-item!).

MULTI-choice LIST row — cursor glyph, a `[✓]`/`[ ]` box, then the label. The
cursor glyph and the checkbox glyph carry independent meaning: the first says
"this row is the cursor", the second says "this option is currently on".
Anchored at `(inc left)` so the marker sits right at the dialog's inner edge
(see `draw-list-item!`).
sourceraw docstring

draw-dialog-chrome!clj

(draw-dialog-chrome! g cols rows title content-h)
(draw-dialog-chrome! g cols rows title content-w content-h)

Draw dialog background, shadow, border, and title.

Three arities:

  • (g cols rows title content-h) - shared default width; the box HEIGHT is sized to content-h via adaptive-content-height. Pass nil as content-h for the shared full-height footprint.
  • (g cols rows title content-w content-h) - fully explicit. Use only when a dialog genuinely needs a non-default width.

Returns {:left :top :right :bottom :inner-w :inner-h}.

Draw dialog background, shadow, border, and title.

Three arities:
- `(g cols rows title content-h)` - shared default width; the box HEIGHT is
  sized to `content-h` via `adaptive-content-height`. Pass `nil` as
  `content-h` for the shared full-height footprint.
- `(g cols rows title content-w content-h)` - fully explicit. Use
  only when a dialog genuinely needs a non-default width.

Returns {:left :top :right :bottom :inner-w :inner-h}.
sourceraw docstring

draw-dialog-close-button!clj

(draw-dialog-close-button! g box-right title-row)

Paint a clickable X close button at a dialog's top-right title row and record its click bounds (thread-local) so read-modal-input! can turn a click into Escape. Every dialog inherits it via draw-dialog-chrome!. Lights up to the red pill (close-button-hover-fg + bold) when the thread-local close-hover flag is set - the same affordance the header and help/tasks overlay close buttons use - so modal X buttons are no longer static.

Paint a clickable X close button at a dialog's top-right title row and
record its click bounds (thread-local) so `read-modal-input!` can turn a
click into Escape. Every dialog inherits it via `draw-dialog-chrome!`.
Lights up to the red pill (`close-button-hover-fg` + bold) when the
thread-local close-hover flag is set - the same affordance the header and
help/tasks overlay close buttons use - so modal X buttons are no longer
static.
sourceraw docstring

draw-field-row!clj

(draw-field-row! g left row inner-w focused? content)

TYPED row — the painter for a form row text is entered into: a line, a password, an OTP's boxes. An input is drawn as an INPUT: input-field-bg, padded a space each side, the very control components/find-bar! paints its query box with — so an empty field is still visibly a field and every place the TUI takes typing is the same object. It starts at the dialog's own inner edge, directly under its label.

Focus is the other half, and it is said three ways at once: the focused field wears the accent ring down its left edge, keeps the full field surface, and takes the ink (box-fg, bold). A field the keyboard is NOT in loses the ring, recedes to theme/field-resting-bg and dims to dialog-hint. That contrast IS the cursor in a form — there is no gutter, because a marker in front of every row says the same thing about all of them.

A TOGGLE is not typed into and does not wear this paper: see draw-toggle-row!.

content is the field's already-rendered text (ada@example.com, [1] [2] [ ]). Returns the column its first cell landed on, so a caller that owns the terminal cursor can place it.

TYPED row — the painter for a form row text is entered into: a line, a
password, an OTP's boxes. An input is drawn as an INPUT: `input-field-bg`,
padded a space each side, the very control `components/find-bar!` paints its
query box with — so an empty field is still visibly a field and every place
the TUI takes typing is the same object. It starts at the dialog's own inner
edge, directly under its label.

Focus is the other half, and it is said three ways at once: the focused field
wears the accent ring `▎` down its left edge, keeps the full field surface, and
takes the ink (`box-fg`, bold). A field the keyboard is NOT in loses the ring,
recedes to `theme/field-resting-bg` and dims to `dialog-hint`. That contrast IS
the cursor in a form — there is no `•` gutter, because a marker in front of
every row says the same thing about all of them.

A TOGGLE is not typed into and does not wear this paper: see
[[draw-toggle-row!]].

`content` is the field's already-rendered text (`ada@example.com`,
`[1] [2] [ ]`). Returns the column its first cell landed on, so a caller that
owns the terminal cursor can place it.
sourceraw docstring

draw-flat-dialog-chrome!clj

(draw-flat-dialog-chrome! g cols rows title)

Flat variant of draw-dialog-chrome!: no drop shadow, no accent title stripe, no separators - one thin-bordered rect on the dialog background with the title inline on the top border. Same default footprint and the same bounds map as the boxed chrome, so dialog-layout works unchanged.

Flat variant of `draw-dialog-chrome!`: no drop shadow, no accent title
stripe, no separators - one thin-bordered rect on the dialog background
with the title inline on the top border. Same default footprint and the
same bounds map as the boxed chrome, so `dialog-layout` works unchanged.
sourceraw docstring

draw-hint-bar!clj

(draw-hint-bar! g left row inner-w hint)

Draw hint bar. hint can be:

  • a string: rendered as-is, left-aligned
  • a vec of strings: centered, dim italic, joined with ' · '
  • a vec of [key action] pairs: key bold, action dim italic, the whole run centered with thin ' · ' separators between pairs

Hints are CENTERED (not full-width justified) so short hint sets read as one tidy line instead of being stretched ragged across the dialog. Examples: "simple hint" ["move" "select" "cancel"] [["Up/Dn" "move"] ["Enter" "select"] ["Esc" "cancel"]]

Draw hint bar. `hint` can be:
- a string: rendered as-is, left-aligned
- a vec of strings: centered, dim italic, joined with ' · '
- a vec of [key action] pairs: key bold, action dim italic, the whole
  run centered with thin ' · ' separators between pairs

Hints are CENTERED (not full-width justified) so short hint sets read as
one tidy line instead of being stretched ragged across the dialog.
Examples:
  "simple hint"
  ["move" "select" "cancel"]
  [["Up/Dn" "move"] ["Enter" "select"] ["Esc" "cancel"]]
sourceraw docstring

draw-input-item!clj

(draw-input-item! g left row inner-w focused? text cursor placeholder)

A form's TYPED row: draw-field-row! plus what typing needs — the horizontal scroll that keeps the cursor inside the field and the dim placeholder an empty field shows. Returns the TerminalPosition the caller parks the terminal cursor at.

A form's TYPED row: `draw-field-row!` plus what typing needs — the horizontal
scroll that keeps the cursor inside the field and the dim `placeholder` an
empty field shows. Returns the `TerminalPosition` the caller parks the
terminal cursor at.
sourceraw docstring

draw-selectable-row!clj

(draw-selectable-row! g left row inner-w selected? text)

The ONE focusable-row painter for LIST dialogs: p/selection-prefix's cursor glyph, the text, bold while the cursor is on it.

draw-checkbox-item! is this row with a status glyph in front of the label, and any new focusable LIST row joins them here instead of inventing a second way to look selected. A form is the other family: its rows are drawn as INPUTS on their own surface (draw-field-row!) and wear no cursor glyph at all, because a in front of every row says the same thing about all of them.

The ONE focusable-row painter for LIST dialogs: `p/selection-prefix`'s cursor
glyph, the text, bold while the cursor is on it.

`draw-checkbox-item!` is this row with a status glyph in front of the label,
and any new focusable LIST row joins them here instead of inventing a second
way to look selected. A form is the other family: its rows are drawn as
INPUTS on their own surface (`draw-field-row!`) and wear no cursor glyph at
all, because a `•` in front of every row says the same thing about all of
them.
sourceraw docstring

draw-text-input-field!clj

(draw-text-input-field! g left row inner-w text cursor)
(draw-text-input-field! g left row inner-w text cursor placeholder)

Borderless › text input row with an optional dim placeholder. Returns the TerminalPosition the caller should park the terminal cursor at.

Borderless `› text` input row with an optional dim `placeholder`. Returns the
`TerminalPosition` the caller should park the terminal cursor at.
sourceraw docstring

draw-toggle-row!clj

(draw-toggle-row! g left row inner-w focused? content)

TOGGLED row — an option of a :select, a checkbox, a slider's track. Exactly the geometry of draw-field-row!, so a form's rows line up whatever they are, but painted on the dialog's OWN paper: nothing is typed here, so there is no input surface to fill. Paper that says "type here" under a row that cannot take a character is a lie about what the keyboard will do.

Focus is then the accent ring and the bold ink alone, and the status glyph (choice-mark) says what the toggle currently IS.

TOGGLED row — an option of a `:select`, a checkbox, a slider's track. Exactly
the geometry of [[draw-field-row!]], so a form's rows line up whatever they
are, but painted on the dialog's OWN paper: nothing is typed here, so there is
no input surface to fill. Paper that says "type here" under a row that cannot
take a character is a lie about what the keyboard will do.

Focus is then the accent ring `▎` and the bold ink alone, and the status glyph
([[choice-mark]]) says what the toggle currently IS.
sourceraw docstring

ellipsizeclj

(ellipsize s max-w)

Right-truncate s to max-w columns with a trailing . Thin delegate over the canonical p/ellipsize (lanterna-backed).

Right-truncate `s` to `max-w` columns with a trailing `…`.
Thin delegate over the canonical `p/ellipsize` (lanterna-backed).
sourceraw docstring

embed-transient!clj

(embed-transient! screen g region spec)

Run ONE transient (tr/run!) INSIDE a frame someone else owns — same box, same hint row, no second window.

region is already in tr/run! geometry (:left, :inner-w, :hint-row, :text-w, plus the optional :min-row floor and the :restore! snapshot a host that pages bands of different heights hands in). Returns tr/run!'s {:action :switches :options}, or nil on Esc.

This is THE seam between a Lanterna surface and the host-agnostic transient component. Nothing else calls tr/run! with a transient-host.

Run ONE transient (`tr/run!`) INSIDE a frame someone else owns — same box,
same hint row, no second window.

`region` is already in `tr/run!` geometry (`:left`, `:inner-w`, `:hint-row`,
`:text-w`, plus the optional `:min-row` floor and the `:restore!` snapshot a
host that pages bands of different heights hands in). Returns `tr/run!`'s
`{:action :switches :options}`, or nil on Esc.

This is THE seam between a Lanterna surface and the host-agnostic transient
component. Nothing else calls `tr/run!` with a `transient-host`.
sourceraw docstring

field-content-wclj

(field-content-w inner-w)

Columns a form field's TEXT gets on an inner-w-wide dialog row: the focus ring and the field's own padding come off the top. Public because paint and cursor placement have to measure the very same field.

Columns a form field's TEXT gets on an `inner-w`-wide dialog row: the focus
ring and the field's own padding come off the top. Public because paint and
cursor placement have to measure the very same field.
sourceraw docstring

filter-select-itemsclj

(filter-select-items items query)

Apply the shared picker filter: case-insensitive substring matching, preserving source order. Items may provide :search-text to include metadata beyond the visible label; otherwise :label is the haystack. A blank query shows all.

Apply the shared picker filter: case-insensitive substring matching, preserving
source order. Items may provide `:search-text` to include metadata beyond the
visible label; otherwise `:label` is the haystack. A blank query shows all.
sourceraw docstring

fit-hint-pairsclj

(fit-hint-pairs hint text-w)

Longest prefix of [key action] hint pairs whose rendered width (with ' · ' separators) fits in text-w columns. put-str! clips to the SCREEN, not the dialog box, so a footer wider than the content area must drop whole trailing chords instead of painting across the border.

Longest prefix of `[key action]` hint pairs whose rendered width (with
'  ·  ' separators) fits in `text-w` columns. `put-str!` clips to the
SCREEN, not the dialog box, so a footer wider than the content area must
drop whole trailing chords instead of painting across the border.
sourceraw docstring

(footer-content-width cols hint)
(footer-content-width cols hint min-content)

Content width for an action-footer dialog: sized so the box is EXACTLY the footer's natural width plus two columns of padding on each side, never narrower than min-content (the widest content line) nor wider than the terminal. The +2 supplies the extra pad beyond the single-column gutter draw-dialog-chrome! already reserves inside the border, so a footer of width W yields 2 blank columns between the frame and the hints on each side.

Content width for an action-footer dialog: sized so the box is EXACTLY the
footer's natural width plus two columns of padding on each side, never
narrower than `min-content` (the widest content line) nor wider than the
terminal. The `+2` supplies the extra pad beyond the single-column gutter
`draw-dialog-chrome!` already reserves inside the border, so a footer of
width W yields 2 blank columns between the frame and the hints on each side.
sourceraw docstring

fork-turn-itemsclj

(fork-turn-items turns)

Rows for the fork-at-turn palette (searchable-select!), one per turn of the current session (from db-list-session-turns), top-to-bottom. Each row's :label is the turn's user message (whitespace-collapsed, truncated) and :hint its ordinal tN; :turn-id carries the session_turn_soul id the fork copies THROUGH — selecting a row forks the session keeping every turn up to and INCLUDING it. Type to filter by message text.

Rows for the fork-at-turn palette (`searchable-select!`), one per turn of the
current session (from `db-list-session-turns`), top-to-bottom. Each row's
`:label` is the turn's user message (whitespace-collapsed, truncated) and
`:hint` its ordinal `tN`; `:turn-id` carries the `session_turn_soul` id the
fork copies THROUGH — selecting a row forks the session keeping every turn up
to and INCLUDING it. Type to filter by message text.
sourceraw docstring

frame-restorerclj

(frame-restorer screen)

Snapshot the screen's back buffer NOW and return (fn [] …) / (fn [from to]) that puts those rows back exactly as they look at this moment.

A magit band paints over the host's rows, and when a SHORTER band replaces a taller one the rows between them belong to the HOST again. Blanking them punched a hole in the settings list behind the popup — the whole point of a band is that the buffer it is about stays readable. The host is not repainted while a band flow runs, so restoring the snapshot is the only honest answer.

Returns nil when there is no screen: unit tests redefine every dialog away.

Snapshot the screen's back buffer NOW and return `(fn [] …)` / `(fn [from to])`
that puts those rows back exactly as they look at this moment.

A magit band paints over the host's rows, and when a SHORTER band replaces a
taller one the rows between them belong to the HOST again. Blanking them
punched a hole in the settings list behind the popup — the whole point of a
band is that the buffer it is about stays readable. The host is not repainted
while a band flow runs, so restoring the snapshot is the only honest answer.

Returns nil when there is no screen: unit tests redefine every dialog away.
sourceraw docstring

hint-bar-widthclj

(hint-bar-width hint)

Natural rendered width (chars) of a draw-hint-bar! hint — a plain string, a vec of strings, or a vec of [key action] pairs — using the SAME segment and separator math the hint bar paints with. Lets a dialog size its box to the footer instead of a fixed terminal ratio.

Natural rendered width (chars) of a `draw-hint-bar!` hint — a plain string,
a vec of strings, or a vec of `[key action]` pairs — using the SAME segment
and separator math the hint bar paints with. Lets a dialog size its box to
the footer instead of a fixed terminal ratio.
sourceraw docstring

list-dialog!clj

(list-dialog! screen title items opts)

Reusable scrollable, selectable list dialog — the SINGLE implementation behind select-dialog! (plain) and searchable-select! (type-to-filter). Now a THIN driver: select-modal-component supplies the pure geometry / scroll / key logic and run-modal! owns the loop. Returns the chosen item map (the full map, so callers recover :id/slash keys), or nil on Esc.

items is a vec of maps with at least :label. opts: :filter? type-to-filter on :label, case-insensitive (default false) :placeholder query placeholder shown while the filter is empty :enter-label hint-bar verb for Enter (default "select") :height :content sizes the box to the item count (+ the query field), capped; nil uses the shared (tall) footprint.

Reusable scrollable, selectable list dialog — the SINGLE implementation
behind `select-dialog!` (plain) and `searchable-select!` (type-to-filter).
Now a THIN driver: `select-modal-component` supplies the pure geometry /
scroll / key logic and `run-modal!` owns the loop. Returns the chosen item
map (the full map, so callers recover `:id`/slash keys), or nil on Esc.

`items` is a vec of maps with at least `:label`. opts:
  :filter?      type-to-filter on `:label`, case-insensitive (default false)
  :placeholder  query placeholder shown while the filter is empty
  :enter-label  hint-bar verb for Enter (default "select")
  :height       `:content` sizes the box to the item count (+ the query
                field), capped; nil uses the shared (tall) footprint.
sourceraw docstring

load-mcp-inventory!clj

(load-mcp-inventory!)

Refresh the cached MCP inventory from the gateway. Never throws: a gateway that is down, or a rejected verb, becomes an inline row instead of yet another modal.

Refresh the cached MCP inventory from the gateway. Never throws: a gateway
that is down, or a rejected verb, becomes an inline row instead of yet
another modal.
sourceraw docstring

load-provider-inventory!clj

(load-provider-inventory!)

Refresh the cached provider fleet from config + gateway. Never throws: a gateway that is down becomes an inline row instead of yet another modal. The auth probes fan out, because one serial round trip per provider would stall the dialog for as long as the slowest provider takes.

Router selection is part of the fleet, not a separate lookup: each entry carries whether it is the default or the fallback AND the model that choice picked, so Settings can SHOW what d/f just did.

Refresh the cached provider fleet from config + gateway. Never throws: a
gateway that is down becomes an inline row instead of yet another modal. The
auth probes fan out, because one serial round trip per provider would stall
the dialog for as long as the slowest provider takes.

Router selection is part of the fleet, not a separate lookup: each entry
carries whether it is the default or the fallback AND the model that choice
picked, so Settings can SHOW what `d`/`f` just did.
sourceraw docstring

log-view-dialog!clj

(log-view-dialog! screen
                  title
                  lines
                  &
                  {:keys [refresh-fn tail? grammar] :or {grammar "bash"}})

FULLSCREEN, syntax-highlighted log viewer — the whole terminal, edge to edge.

Unlike text-view-dialog! (a centered modal box) this owns the entire screen: a title strip on the top row, the log body filling every row beneath it, and a hint strip on the bottom row. Each line is colorized by parsing the WHOLE buffer with tree-sitter (highlight/highlight, default the bash grammar) and painting the resulting ANSI runs through render/paint-ansi-line! — the same path that carries syntax color on the transcript's code fences. Fails open to plain text when the native grammar pack isn't loadable.

Keys: ↑/↓ line, PgUp/PgDn page, Home/End jump, mouse-wheel scroll, r refresh (when :refresh-fn), Enter/Esc close. Options:

  • :refresh-fn thunk returning fresh lines — enables r refresh so a live buffer (e.g. background-shell logs) can be re-pulled in place.
  • :tail? start pinned to the newest line and re-follow the bottom on refresh (log-tail behaviour); scrolling up releases the pin.
  • :grammar tree-sitter grammar for coloring (default "bash"); nil = plain. Returns nil after close.
FULLSCREEN, syntax-highlighted log viewer — the whole terminal, edge to edge.

Unlike `text-view-dialog!` (a centered modal box) this owns the entire screen:
a title strip on the top row, the log body filling every row beneath it, and a
hint strip on the bottom row. Each line is colorized by parsing the WHOLE
buffer with tree-sitter (`highlight/highlight`, default the `bash` grammar) and
painting the resulting ANSI runs through `render/paint-ansi-line!` — the same
path that carries syntax color on the transcript's code fences. Fails open to
plain text when the native grammar pack isn't loadable.

Keys: ↑/↓ line, PgUp/PgDn page, Home/End jump, mouse-wheel scroll, `r` refresh
(when `:refresh-fn`), Enter/Esc close. Options:
- :refresh-fn  thunk returning fresh lines — enables `r` refresh so a live
               buffer (e.g. background-shell logs) can be re-pulled in place.
- :tail?       start pinned to the newest line and re-follow the bottom on
               refresh (log-tail behaviour); scrolling up releases the pin.
- :grammar     tree-sitter grammar for coloring (default "bash"); nil = plain.
Returns nil after close.
sourceraw docstring

magit-dialog!clj

(magit-dialog! screen root-or-repos)

Magit-style status buffer over the git CLI — the C-x g / footer-git modal.

root-or-repos is either ONE root (string/File — the classic single-repo buffer) or a vector of repo entries {:root :label :draft?} from magit/workspace-roots — the session's primary workspace root. gets a Repository <label> — <path> header and its own full section stack; for a DRAFT session the entries already point at the CLONES the session edits, so the buffer shows the draft's git state, not the trunk's.

Sections: head/upstream facts, untracked, unmerged, unstaged, staged, stashes and recent commits. TAB folds a file's diff peek open under its row; RET visits it FULLSCREEN (a file's syntax-highlighted body, a commit's or stash's full patch). Verbs mirror magit and route to the repo UNDER THE CURSOR: s/u stage/unstage the file or the whole section, S/U all, k discard with a confirm, c commit/amend (message prompt), P push (plain / -u / --force-with-lease), F pull, f fetch, b branch (checkout / create / delete), z stash (push / pop / apply / drop), g refresh, C-w copy the sha/path/ref under point, q/Esc close. Every verb shells to the real git binary via internal.git, and the buffer re-reads every repo after each action, so what you see is always git status truth. Returns nil.

Magit-style status buffer over the git CLI — the C-x g / footer-git modal.

`root-or-repos` is either ONE root (string/File — the classic single-repo
buffer) or a vector of repo entries `{:root :label :draft?}` from
`magit/workspace-roots` — the session's primary workspace root.
gets a `Repository <label> — <path>` header and its own full section stack;
for a DRAFT session the entries already point at the CLONES the session
edits, so the buffer shows the draft's git state, not the trunk's.

Sections: head/upstream facts, untracked, unmerged, unstaged, staged,
stashes and recent commits. TAB folds a file's diff peek open under
its row; RET visits it FULLSCREEN (a file's syntax-highlighted body, a
commit's or stash's full patch). Verbs mirror magit and route to the repo
UNDER THE CURSOR:
`s`/`u` stage/unstage the file or the whole section, `S`/`U` all, `k`
discard with a confirm, `c` commit/amend (message prompt), `P` push
(plain / -u / --force-with-lease), `F` pull, `f` fetch, `b` branch
(checkout / create / delete), `z` stash (push / pop / apply / drop), `g`
refresh, `C-w` copy the sha/path/ref under point, `q`/Esc close. Every verb
shells to the real `git` binary via
`internal.git`, and the buffer re-reads every repo after each action, so
what you see is always `git status` truth. Returns nil.
sourceraw docstring

magit-mini-read!clj

(magit-mini-read! screen
                  g
                  left
                  inner-w
                  hint-row
                  text-w
                  label
                  {:keys [initial mask]})

Inline editable minibuffer painted over the magit hint-bar row: <label> <text> with a live cursor. Enter submits the trimmed string (may be empty), Esc returns nil. Opts: :initial (seed text), :mask (echo char).

Inline editable minibuffer painted over the magit hint-bar row:
`<label> <text>` with a live cursor. Enter submits the trimmed string (may
be empty), Esc returns nil. Opts: :initial (seed text), :mask (echo char).
sourceraw docstring

markdown-viewer-dialog!clj

(markdown-viewer-dialog! screen title md)

Scrollable read-only MARKDOWN viewer: md is lifted to canonical IR (vis/markdown->ast) and painted with styled headings, bold, and code accents, tables — through the SAME IR walker the chat uses (layout/ast->lines). The rich twin of text-viewer-dialog!. Returns nil on Esc. Supports keyboard scrolling.

Scrollable read-only MARKDOWN viewer: `md` is lifted to canonical IR
(`vis/markdown->ast`) and painted with styled headings, bold, and code
accents, tables — through the SAME IR walker the chat uses
(`layout/ast->lines`). The rich twin of `text-viewer-dialog!`.
Returns nil on Esc. Supports keyboard scrolling.
sourceraw docstring

(modal-close-click? key)

True when key is a mouse click on the dialog close (✕) button.

True when `key` is a mouse click on the dialog close (✕) button.
sourceraw docstring

(modal-enter-key? key)
source

(modal-escape-key? key)
source

(modal-input-pending? screen)

True when another keystroke is ALREADY queued for this modal loop. The peeked event is stashed in the same thread-local slot read-modal-input! drains, so nothing is lost.

This is the TUI's DEBOUNCE primitive: an expensive per-keystroke effect (the gateway transcript search) can skip itself while the user is still typing and run once on the keystroke that lands in a pause — no threads, no timers, and no repaint problem from an async result arriving while the loop blocks in readInput.

True when another keystroke is ALREADY queued for this modal loop. The peeked
event is stashed in the same thread-local slot `read-modal-input!` drains, so
nothing is lost.

This is the TUI's DEBOUNCE primitive: an expensive per-keystroke effect (the
gateway transcript search) can skip itself while the user is still typing and
run once on the keystroke that lands in a pause — no threads, no timers, and
no repaint problem from an async result arriving while the loop blocks in
`readInput`.
sourceraw docstring

(modal-wheel-delta key)

Return list-selection delta for a wheel mouse event, else nil. Negative moves up; positive moves down.

Return list-selection delta for a wheel mouse event, else nil.
Negative moves up; positive moves down.
sourceraw docstring

(modal-wheel-step key)

Return wheel delta multiplied by any coalesced event count.

Return wheel delta multiplied by any coalesced event count.
sourceraw docstring

model-picker!clj

(model-picker! screen current)

Searchable per-session model picker — TUI parity with the web footer chooser. Lists every configured model as a row (<provider> / <model>, the active one marked ● current) plus a top ★ router default row that CLEARS the per-session override. current is the session's stored model preference ({:provider <str|kw> :model <str>}) or nil; it marks the active row exactly like the web picker. Returns the chosen item map — {:reset? true} for the router-default row, else {:provider <str> :model <str>} — or nil on Esc.

Searchable per-session model picker — TUI parity with the web footer
chooser. Lists every configured model as a row (`<provider> / <model>`,
the active one marked `● current`) plus a top `★ router default` row
that CLEARS the per-session override. `current` is the session's stored
model preference (`{:provider <str|kw> :model <str>}`) or nil; it marks
the active row exactly like the web picker. Returns the chosen item map
— `{:reset? true}` for the router-default row, else `{:provider <str>
:model <str>}` — or nil on Esc.
sourceraw docstring

multi-select-dialog!clj

(multi-select-dialog! screen title items)

Checkbox multi-select over items (vec of strings). Space toggles the cursor row, a toggles all, Enter confirms, Esc cancels. Returns the vec of selected strings (possibly empty) on confirm, nil on Esc. Mirrors the web modal's alias chips — same proposed options, multi-pick semantics.

Checkbox multi-select over `items` (vec of strings). Space toggles the
cursor row, `a` toggles all, Enter confirms, Esc cancels. Returns the vec
of selected strings (possibly empty) on confirm, nil on Esc. Mirrors the
web modal's alias chips — same proposed options, multi-pick semantics.
sourceraw docstring

(navigator-dialog! screen opts)

Global C-g session picker. Full-width project/session hierarchy; transcript lookup is debounced and asynchronous so typing never waits on the gateway.

Global C-g session picker. Full-width project/session hierarchy; transcript
lookup is debounced and asynchronous so typing never waits on the gateway.
sourceraw docstring

normalize-modal-keyclj

(normalize-modal-key key)

Normalize raw terminal CR/LF/ESC character keystrokes to Lanterna Enter/Escape key types, and C-g to Escape. Some terminals surface modal Enter/Escape as KeyType/Character; modal code should not need to special-case that.

C-g (Emacs keyboard-quit) is rewritten here too, so EVERY dialog closes on it through the KeyType/Escape branch it already has - one rewrite instead of an abort clause per key loop.

Normalize raw terminal CR/LF/ESC character keystrokes to Lanterna
Enter/Escape key types, and C-g to Escape. Some terminals surface modal
Enter/Escape as `KeyType/Character`; modal code should not need to
special-case that.

C-g (Emacs `keyboard-quit`) is rewritten here too, so EVERY dialog closes on
it through the `KeyType/Escape` branch it already has - one rewrite instead of
an abort clause per key loop.
sourceraw docstring

open-nested!clj

(open-nested! screen f)

Run f with the screen cleared before AND after it, for a dialog opened from inside another dialog.

Modals float over the CHAT on purpose, but a modal opened over another modal paints a SMALLER box on top of the parent's, so the parent's border, ✕ and hint bar keep framing it and the user sees two stacked popups. Erasing on the way in gives the nested flow a clean surface; erasing on the way out lets the caller repaint its own frame from scratch.

Run `f` with the screen cleared before AND after it, for a dialog opened
from inside another dialog.

Modals float over the CHAT on purpose, but a modal opened over another modal
paints a SMALLER box on top of the parent's, so the parent's border, ✕ and
hint bar keep framing it and the user sees two stacked popups. Erasing on the
way in gives the nested flow a clean surface; erasing on the way out lets the
caller repaint its own frame from scratch.
sourceraw docstring

palette-commandsclj

Command palette entries. Each is {:id keyword :label str}. The :id is the action the screen's run-command! executes. Quit is intentionally NOT here — use Ctrl+C to quit.

The palette is THE discoverable entry point for every app verb: opened with C-x p (reliable on every terminal, unlike Alt/Option chords on macOS) and filtered by typing.

Command palette entries. Each is {:id keyword :label str}. The `:id` is the
action the screen's `run-command!` executes. Quit is intentionally NOT here
— use Ctrl+C to quit.

The palette is THE discoverable entry point for every app verb: opened with
C-x p (reliable on every terminal, unlike Alt/Option chords on macOS) and
filtered by typing.
sourceraw docstring

palette-commands-forclj

(palette-commands-for {:keys [has-turns?]})

palette-commands filtered to the entries that can ACT in ctx. Mirrors the which-key strip's :show-when gating: an entry tagged :has-turns (both Fork Session verbs) is DROPPED in a session with no turns — forking a turnless session is prohibited, so it must not even be discoverable.

ctx is {:has-turns? bool}; a missing/nil ctx is the conservative turnless case. Untagged entries always survive.

`palette-commands` filtered to the entries that can ACT in `ctx`. Mirrors the
which-key strip's `:show-when` gating: an entry tagged `:has-turns` (both
Fork Session verbs) is DROPPED in a session with no turns — forking a
turnless session is prohibited, so it must not even be discoverable.

`ctx` is `{:has-turns? bool}`; a missing/nil ctx is the conservative
turnless case. Untagged entries always survive.
sourceraw docstring

read-modal-input!clj

(read-modal-input! screen)

Read one modal input event. Consecutive pending wheel events are drained and returned as one :scroll-delta, so a wheel flood costs one redraw. The first non-wheel event encountered while draining is held for the next modal read on this thread. MOVE/DRAG events also refresh the close (X) hover flag so the button can light up under the cursor.

Read one modal input event. Consecutive pending wheel events are drained
and returned as one `:scroll-delta`, so a wheel flood costs one redraw.
The first non-wheel event encountered while draining is held for the next
modal read on this thread. MOVE/DRAG events also refresh the close (X)
hover flag so the button can light up under the cursor.
sourceraw docstring

read-modal-key!clj

(read-modal-key! screen)

Like Screen/readInput, but drains wheel floods into one synthetic wheel event. Existing modal loops can use it without bespoke scroll-delta code.

Like `Screen/readInput`, but drains wheel floods into one synthetic wheel
event. Existing modal loops can use it without bespoke scroll-delta code.
sourceraw docstring

region-option-readerclj

(region-option-reader screen g {:keys [left inner-w hint-row text-w]})

A :read-option for a transient EMBEDDED in someone else's frame.

transient-dialog! builds this for its own modal; a band painted into a host region (Settings, the provider manager) needs the same minibuffer, on the host's hint row, so an OPTION is typed without opening a second window.

A `:read-option` for a transient EMBEDDED in someone else's frame.

`transient-dialog!` builds this for its own modal; a band painted into a host
region (Settings, the provider manager) needs the same minibuffer, on the
host's hint row, so an OPTION is typed without opening a second window.
sourceraw docstring

run-modal!clj

(run-modal! screen {:keys [init measure reconcile paint on-key]})

Shared modal driver — the ONE event loop every ported dialog reuses instead of hand-rolling its own loop/recur. component is a map of PURE fns (they never touch the screen) plus one impure paint fn:

:init immutable start state (a map), or a 0-arg fn returning it :measure (fn [state cols rows] -> geom) — geometry, screen-free, TESTABLE :reconcile (fn [state geom] -> state) — optional clamp (e.g. scroll window) :paint (fn [g state geom] -> cursor|nil) — the only impure piece; draws to g :on-key (fn [state key geom] -> state | {::done result}) — screen-free, TESTABLE

run-modal! owns everything the old dialogs copy-pasted: terminal sizing, the TextGraphics, wheel/close/Esc normalization (via read-modal-key!), the cursor + DELTA refresh, and the recur loop. A key handler returns the next state to continue, or {::done v} to close the modal with value v (nil on Esc/close). Because :measure/:reconcile/:on-key are pure functions of data, a dialog's geometry and key logic can be unit-tested with no live terminal at all — the React-like win.

Shared modal driver — the ONE event loop every ported dialog reuses instead
of hand-rolling its own `loop/recur`. `component` is a map of PURE fns (they
never touch the screen) plus one impure paint fn:

  :init      immutable start state (a map), or a 0-arg fn returning it
  :measure   (fn [state cols rows] -> geom)     — geometry, screen-free, TESTABLE
  :reconcile (fn [state geom] -> state)         — optional clamp (e.g. scroll window)
  :paint     (fn [g state geom] -> cursor|nil)  — the only impure piece; draws to `g`
  :on-key    (fn [state key geom] -> state | {::done result})  — screen-free, TESTABLE

run-modal! owns everything the old dialogs copy-pasted: terminal sizing, the
`TextGraphics`, wheel/close/Esc normalization (via `read-modal-key!`), the
cursor + DELTA refresh, and the recur loop. A key handler returns the next
state to continue, or `{::done v}` to close the modal with value `v` (nil on
Esc/close). Because `:measure`/`:reconcile`/`:on-key` are pure functions of
data, a dialog's geometry and key logic can be unit-tested with no live
terminal at all — the React-like win.
sourceraw docstring

searchable-select!clj

(searchable-select! screen title items)
(searchable-select! screen title items {:keys [placeholder enter-label]})

Type-to-filter selection list — the searchable spine of the command palette. Thin wrapper over list-dialog! (filter on, content-sized, palette placeholder). Returns the FULL chosen item map (so callers recover :id / slash keys), or nil on Esc.

The optional opts map overrides the filter field's :placeholder and the :enter-label — so callers other than the command palette (e.g. the project switcher) show a fitting prompt instead of "Type a command…".

Type-to-filter selection list — the searchable spine of the command palette.
Thin wrapper over `list-dialog!` (filter on, content-sized, palette
placeholder). Returns the FULL chosen item map (so callers recover
`:id` / slash keys), or nil on Esc.

The optional `opts` map overrides the filter field's `:placeholder` and the
`:enter-label` — so callers other than the command palette (e.g. the project
switcher) show a fitting prompt instead of "Type a command…".
sourceraw docstring

select-dialog!clj

(select-dialog! screen title items)

Show a selection list dialog. Returns the selected item map or nil on Esc. items is a vec of {:label str, …} maps. Thin wrapper over list-dialog!.

Show a selection list dialog. Returns the selected item map or nil on Esc.
`items` is a vec of `{:label str, …}` maps. Thin wrapper over `list-dialog!`.
sourceraw docstring

select-modal-componentclj

(select-modal-component title
                        items
                        {:keys [filter? placeholder enter-label height]})

Build the run-modal! component behind list-dialog! — a scrollable, selectable, optionally type-to-filter list. This is the pure-fn heart of the dialog: its :measure (geometry), :reconcile (scroll window) and :on-key (navigation / filtering / select) are plain functions of immutable state, so they can be exercised in tests WITHOUT a terminal. Only :paint touches the screen. items/opts match list-dialog!.

Build the `run-modal!` component behind `list-dialog!` — a scrollable,
selectable, optionally type-to-filter list. This is the pure-fn heart of the
dialog: its `:measure` (geometry), `:reconcile` (scroll window) and `:on-key`
(navigation / filtering / select) are plain functions of immutable state, so
they can be exercised in tests WITHOUT a terminal. Only `:paint` touches the
screen. `items`/opts match `list-dialog!`.
sourceraw docstring

session-band!clj

(session-band! screen content-top spec f)
(session-band! screen content-top spec f pressed)

Run ONE transient as a magit BAND inside the LIVE SESSION frame — the same in-frame band the human-input form and the magit status buffer use, painted over the bottom of the transcript instead of in a window of its own.

content-top is the first row the band may touch (the screen's [:layout :messages-top]), so the header and the session it is about stay readable above it. The frame is snapshotted before the band paints and put back on the way out — the transcript underneath is never repainted from scratch and never blanked.

f is called with {:screen :g :region :result} ONLY when the transient produced an action, on the band's own rows: that is where an inline minibuffer (magit-mini-read!, magit-mini-choose!, magit-mini-confirm!) asks its follow-up question, on the hint row, instead of opening a modal. Returns f's value, or nil on Esc.

pressed is that action ALREADY chosen — a slash that names one command of this band (/draft new) is exactly that key, pre-pressed, so the band paints itself and goes straight to the question instead of waiting for a keystroke the human already typed.

Run ONE transient as a magit BAND inside the LIVE SESSION frame — the same
in-frame band the human-input form and the magit status buffer use, painted
over the bottom of the transcript instead of in a window of its own.

`content-top` is the first row the band may touch (the screen's
`[:layout :messages-top]`), so the header and the session it is about stay
readable above it. The frame is snapshotted before the band paints and put
back on the way out — the transcript underneath is never repainted from
scratch and never blanked.

`f` is called with `{:screen :g :region :result}` ONLY when the transient
produced an action, on the band's own rows: that is where an inline
minibuffer (`magit-mini-read!`, `magit-mini-choose!`, `magit-mini-confirm!`)
asks its follow-up question, on the hint row, instead of opening a modal.
Returns `f`'s value, or nil on Esc.

`pressed` is that action ALREADY chosen — a slash that names one command of
this band (`/draft new`) is exactly that key, pre-pressed, so the band paints
itself and goes straight to the question instead of waiting for a keystroke
the human already typed.
sourceraw docstring

session-dialog-headerclj

(session-dialog-header body-w)
source

session-dialog-itemsclj

(session-dialog-items sessions active-id)
(session-dialog-items sessions active-id body-w)

Build table rows for existing sessions only. New/fork stay dialog options via the N/F shortcuts and command palette; they are not fake table data rows. Rows are sorted by Modified at desc, then Created at desc.

Build table rows for existing sessions only. New/fork stay dialog
options via the N/F shortcuts and command palette; they are not fake table
data rows. Rows are sorted by Modified at desc, then Created at desc.
sourceraw docstring

session-dialog-labelclj

(session-dialog-label session active-id body-w)

Format one fixed-width session table row. Columns are intentionally stable so the picker reads as a table inside the shared dialog chrome.

Format one fixed-width session table row. Columns are intentionally
stable so the picker reads as a table inside the shared dialog chrome.
sourceraw docstring

session-picker-dialog!clj

(session-picker-dialog! screen sessions active-id)

Show recent TUI sessions in a fixed-size table. Returns {:action :new}, {:action :fork}, {:action :switch :id <session-id>}, or nil on Esc.

Show recent TUI sessions in a fixed-size table. Returns
`{:action :new}`, `{:action :fork}`, `{:action :switch :id <session-id>}`,
or nil on Esc.
sourceraw docstring

settings-dialog!clj

(settings-dialog! screen settings)
(settings-dialog! screen settings callbacks)

Show the settings dialog.

ONE flat, grouped, scrollable list (mirrors the web settings modal), laid out VS Code-style: a left Table-of-Contents sidebar rail lists the sections with per-section counts and highlights the one owning the selection, while the right pane shows the settings themselves. Toggle rows render a leading status glyph; choice rows cycle their value with Enter; action rows invoke a callback. The rail is a passive locator — arrow keys still move through the right pane and the rail tracks where you are.

settings is the persisted TUI settings map (see state/default-settings). callbacks also carries :focus-section (a section label to park the cursor on, e.g. MCP Servers or Providers), :mcp-add / :provider-add (the add row of each section), :mcp-action (the verb a server's transient fired) and :provider-transient (one provider's transient, handed the graphics and the region it paints into). Esc clears an active search first, then closes and returns the current settings map.

Show the settings dialog.

ONE flat, grouped, scrollable list (mirrors the web settings modal), laid
out VS Code-style: a left Table-of-Contents sidebar rail lists the sections
with per-section counts and highlights the one owning the selection, while
the right pane shows the settings themselves. Toggle rows render a leading
status glyph; choice rows cycle their value with Enter; action rows invoke
a callback. The rail is a passive locator — arrow keys still move through
the right pane and the rail tracks where you are.

`settings` is the persisted TUI settings map (see
`state/default-settings`). `callbacks` also carries `:focus-section` (a
section label to park the cursor on, e.g. `MCP Servers` or `Providers`),
`:mcp-add` / `:provider-add` (the add row of each section), `:mcp-action`
(the verb a server's transient fired) and `:provider-transient` (one
provider's transient, handed the graphics and the region it paints into).
Esc clears an active search first, then closes and returns the
current settings map.
sourceraw docstring

start-in-transient!clj

(start-in-transient! screen content-top)

Ask WHERE a new session starts, as a band in the current session's frame: t the project itself, c a draft forked from the committed HEAD, d a draft carrying the uncommitted working tree. A draft is named inline on the hint row.

Returns {:start-in :trunk}, {:start-in :draft :clean? bool :draft {:label :clean?}}, or nil.

Ask WHERE a new session starts, as a band in the current session's frame:
`t` the project itself, `c` a draft forked from the committed HEAD, `d` a
draft carrying the uncommitted working tree. A draft is named inline on the
hint row.

Returns `{:start-in :trunk}`, `{:start-in :draft :clean? bool :draft {:label :clean?}}`,
or nil.
sourceraw docstring

table-modal-componentclj

(table-modal-component title grid)

Pure run-modal! component behind table-view-dialog! — the spreadsheet view of a vis-table artifact. grid is table/parse-csv output (first row is the header). Paging, sorting, geometry and the key map are plain functions of immutable state, so the whole viewer is testable with no terminal; only :paint touches the screen.

The sheet is PAGED, not scrolled: the window always starts on a page boundary (table/page-start), so a row never straddles two screens and the title says which page of how many you are on.

Keys: ↑/↓ pick a row, PgUp/PgDn turn a whole page, ←/→ pick a column, Enter sorts by that column (toggling ascending/descending), Tab yields the row, Esc closes.

Pure `run-modal!` component behind `table-view-dialog!` — the spreadsheet view
of a `vis-table` artifact. `grid` is `table/parse-csv` output (first row is the
header). Paging, sorting, geometry and the key map are plain functions of
immutable state, so the whole viewer is testable with no terminal; only
`:paint` touches the screen.

The sheet is PAGED, not scrolled: the window always starts on a page boundary
(`table/page-start`), so a row never straddles two screens and the title says
which page of how many you are on.

Keys: ↑/↓ pick a row, PgUp/PgDn turn a whole page, ←/→ pick a column, Enter
sorts by that column (toggling ascending/descending), Tab yields the row, Esc
closes.
sourceraw docstring

table-view-dialog!clj

(table-view-dialog! screen tbl)

Open a vis-table artifact — the CSV/TSV fence vis_attach writes — as a live spreadsheet: PgUp/PgDn to turn a page, ↑/↓ and ←/→ to move the row / column cursor, Enter to sort by the current column. tbl is the click region's :table payload ({:name :csv :cols :rows :title}). Returns nil, or the selected row on Tab.

Open a `vis-table` artifact — the CSV/TSV fence `vis_attach` writes — as a live
spreadsheet: PgUp/PgDn to turn a page, ↑/↓ and ←/→ to move the row /
column cursor, Enter to sort by the current column. `tbl` is the click region's
`:table` payload (`{:name :csv :cols :rows :title}`). Returns nil, or the
selected row on Tab.
sourceraw docstring

text-input-dialog!clj

(text-input-dialog! screen
                    title
                    label
                    &
                    {:keys [mask initial body flat?] :or {initial ""}})

Show a text input dialog. Returns string or nil on Esc. Options: :mask char (e.g. * for passwords), :initial string, :body string-or-lines rendered above the input label, :flat? true selects the minimal inline-border chrome.

Show a text input dialog. Returns string or nil on Esc.
Options: :mask char (e.g. \* for passwords), :initial string,
:body string-or-lines rendered above the input label,
:flat? true selects the minimal inline-border chrome.
sourceraw docstring

text-view-dialog!clj

(text-view-dialog! screen title lines & {:keys [refresh-fn tail?]})

Show read-only lines in a scrollable modal. Returns nil after close.

Keys: ↑/↓ line, PgUp/PgDn page, Home/End jump, mouse-wheel scroll, Enter/Esc close. Options:

  • :refresh-fn thunk returning fresh lines — enables [r] refresh so a live buffer (e.g. background logs) can be re-pulled in place.
  • :tail? start pinned to the newest line and re-follow the bottom on refresh (log-tail behaviour); scrolling up releases the pin.
Show read-only lines in a scrollable modal. Returns nil after close.

Keys: ↑/↓ line, PgUp/PgDn page, Home/End jump, mouse-wheel scroll,
Enter/Esc close. Options:
- :refresh-fn  thunk returning fresh lines — enables [r] refresh so a live
               buffer (e.g. background logs) can be re-pulled in place.
- :tail?       start pinned to the newest line and re-follow the bottom on
               refresh (log-tail behaviour); scrolling up releases the pin.
sourceraw docstring

text-viewer-dialog!clj

(text-viewer-dialog! screen title text)

Show a scrollable read-only text viewer dialog. title is the dialog header. text is a string (may contain newlines) that is rendered VERBATIM - same content the LLM receives, only soft- wrapped to fit the dialog width. No markdown, no truncation, no reformatting. Returns nil on Esc. Supports keyboard scrolling.

Show a scrollable read-only text viewer dialog.
`title` is the dialog header. `text` is a string (may contain newlines)
that is rendered VERBATIM - same content the LLM receives, only soft-
wrapped to fit the dialog width. No markdown, no truncation, no
reformatting.
Returns nil on Esc. Supports keyboard scrolling.
sourceraw docstring

transient-dialog!clj

(transient-dialog! screen title body spec)

Host ONE magit transient in its OWN modal — the popup for flows that have no status buffer to sit in (provider authentication). body (a string or lines) is the caller's guidance, painted once at the top of the content area; the transient owns every row under it and its hint bar lands on the dialog's own hint row. The box is sized to what it actually holds, so a two-line prompt opens a small dialog instead of a half-screen one.

OPTION items are read INLINE on that hint row (magit-mini-read!), honouring the item's :prompt (default <label>:) and :mask (\* for a credential); mark such an item :secret? true and its value renders as dots, never as text. spec may carry a :title for the popup itself when the frame's title would read redundantly.

Returns tr/run!'s {:action :switches :options}, or nil on Esc.

Host ONE magit transient in its OWN modal — the popup for flows that have no
status buffer to sit in (provider authentication). `body` (a string or lines)
is the caller's guidance, painted once at the top of the content area; the
transient owns every row under it and its hint bar lands on the dialog's own
hint row. The box is sized to what it actually holds, so a two-line prompt
opens a small dialog instead of a half-screen one.

OPTION items are read INLINE on that hint row (`magit-mini-read!`), honouring
the item's `:prompt` (default `<label>:`) and `:mask` (`\*` for a credential);
mark such an item `:secret? true` and its value renders as dots, never as
text. `spec` may carry a `:title` for the popup itself when the frame's title
would read redundantly.

Returns `tr/run!`'s `{:action :switches :options}`, or nil on Esc.
sourceraw docstring

transient-hostclj

(transient-host screen g)

The standard modal HOST for tr/run! — the one adapter between a Lanterna screen and the host-agnostic transient component. It paints through g, flushes with the modal cursor hidden, borrows this namespace's hint bar, and normalizes one modal keystroke into what the component understands: :esc, a Character, or nil for "nothing actionable, just repaint".

Any surface holding a screen and a TextGraphics embeds a transient with this — the magit status buffer, the provider dialog, transient-dialog!.

The standard modal HOST for `tr/run!` — the one adapter between a Lanterna
`screen` and the host-agnostic transient component. It paints through `g`,
flushes with the modal cursor hidden, borrows this namespace's hint bar, and
normalizes one modal keystroke into what the component understands: `:esc`,
a Character, or nil for "nothing actionable, just repaint".

Any surface holding a screen and a `TextGraphics` embeds a transient with
this — the magit status buffer, the provider dialog, `transient-dialog!`.
sourceraw docstring

update-modal-close-hover!clj

(update-modal-close-hover! key)

On a MOVE/DRAG event, set the thread-local close-hover flag when the cursor is within the recorded close-button bounds, clear it otherwise. Lets the modal close (X) button light up on hover like the header/overlay buttons.

On a MOVE/DRAG event, set the thread-local close-hover flag when the cursor
is within the recorded close-button bounds, clear it otherwise. Lets the
modal close (X) button light up on hover like the header/overlay buttons.
sourceraw docstring

visible-window-startclj

(visible-window-start idx current-start visible-count total-count)
source

with-frame-restored!clj

(with-frame-restored! screen f)

Run f — typically a nested dialog or a full-screen prompt — and put THIS frame back exactly as it was.

open-nested! erases the screen on the way OUT, which is right when the caller repaints itself afterwards and catastrophic in the middle of a magit band flow: the next band lands on blank paper and everything above it is gone. Snapshotting the back buffer and writing it back costs one delta refresh and keeps the host frame on screen across the detour.

Run `f` — typically a nested dialog or a full-screen prompt — and put THIS
frame back exactly as it was.

`open-nested!` erases the screen on the way OUT, which is right when the
caller repaints itself afterwards and catastrophic in the middle of a magit
band flow: the next band lands on blank paper and everything above it is
gone. Snapshotting the back buffer and writing it back costs one delta
refresh and keeps the host frame on screen across the detour.
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