Liking cljdoc? Tell your friends :D

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

Magit-style TRANSIENT as a REUSABLE, EMBEDDABLE component.

A transient is a VALUE — a spec — and this namespace knows how to lay it out, paint it into a rectangle, and (optionally) run its key loop. It owns NO screen, NO dialog chrome and NO Lanterna types, so ANY surface that can hand over a TextGraphics and answer keystrokes can embed one: the magit status buffer, the provider dialog, a modal of its own (dialogs/transient-dialog!), or a panel that does not exist yet.

THREE values, three concerns:

spec WHAT the transient is — a pure, reusable description: {:title "Commit" :groups [{:title "Arguments" :items [item …]} …] :read-option (fn [item current] str|nil)} where an item is {:key "h" :type :switch|:option|:action :id :no-verify :label "Disable hooks" :arg "--no-verify" :secret? false}. FLAGS (:switch / :option) render with magit's leading - and TOGGLE — press once to arm, again to disarm — while COMMANDS (:action) fire once and close. Keys are CASE-SENSITIVE, exactly like magit (-f is not -F). :read-option (impure, optional) fetches an OPTION's value; nil (Esc) leaves it unchanged.

region WHERE it sits — the host's rectangle: {:left :inner-w :hint-row :text-w :min-row :clear-above?}. :left/:inner-w are the host frame's border column and inner width, :hint-row the row the host's hint bar owns (the popup REPLACES it), :text-w the text budget inside the padding. :min-row is the first row the popup may touch — a tall transient stops there instead of climbing over whatever the host keeps visible — and :clear-above? also wipes from :min-row down, for a host that repaints PAGES of different heights in one frame.

host HOW to talk to the terminal — the ONLY impure dependency: {:g TextGraphics to paint into :hint-bar! (fn [g left row inner-w pairs]) :refresh! (fn []) flush the frame :read-key! (fn []):esc| Character | nil} nil from :read-key! means "nothing actionable" — the loop simply repaints. dialogs/transient-host builds the standard modal one.

The popup is bottom-anchored INSIDE the host's frame and reads ─── / bold title / ─── / groups / ─── / hint bar: the same chrome the host gives any other titled section, never a second window pasted on top.

Magit-style TRANSIENT as a REUSABLE, EMBEDDABLE component.

A transient is a VALUE — a `spec` — and this namespace knows how to lay it
out, paint it into a rectangle, and (optionally) run its key loop. It owns NO
screen, NO dialog chrome and NO Lanterna types, so ANY surface that can hand
over a `TextGraphics` and answer keystrokes can embed one: the magit status
buffer, the provider dialog, a modal of its own (`dialogs/transient-dialog!`),
or a panel that does not exist yet.

THREE values, three concerns:

  `spec`   WHAT the transient is — a pure, reusable description:
           `{:title "Commit"
             :groups [{:title "Arguments" :items [item …]} …]
             :read-option (fn [item current] str|nil)}`
           where an `item` is
           `{:key "h" :type :switch|:option|:action :id :no-verify
             :label "Disable hooks" :arg "--no-verify" :secret? false}`.
           FLAGS (`:switch` / `:option`) render with magit's leading `-` and
           TOGGLE — press once to arm, again to disarm — while COMMANDS
           (`:action`) fire once and close. Keys are CASE-SENSITIVE, exactly
           like magit (`-f` is not `-F`). `:read-option` (impure, optional)
           fetches an OPTION's value; nil (Esc) leaves it unchanged.

  `region`  WHERE it sits — the host's rectangle:
           `{:left :inner-w :hint-row :text-w :min-row :clear-above?}`.
           `:left`/`:inner-w` are the host frame's border column and inner
           width, `:hint-row` the row the host's hint bar owns (the popup
           REPLACES it), `:text-w` the text budget inside the padding.
           `:min-row` is the first row the popup may touch — a tall transient
           stops there instead of climbing over whatever the host keeps
           visible — and `:clear-above?` also wipes from `:min-row` down, for
           a host that repaints PAGES of different heights in one frame.

  `host`   HOW to talk to the terminal — the ONLY impure dependency:
           `{:g          TextGraphics to paint into
             :hint-bar!  (fn [g left row inner-w pairs])
             :refresh!   (fn [])         flush the frame
             :read-key!  (fn [])         `:esc` | Character | nil}`
           nil from `:read-key!` means "nothing actionable" — the loop simply
           repaints. `dialogs/transient-host` builds the standard modal one.

The popup is bottom-anchored INSIDE the host's frame and reads
`───` / bold title / `───` / groups / `───` / hint bar: the same chrome the
host gives any other titled section, never a second window pasted on top.
raw docstring

columnsclj

(columns spec)

PURE: {:key-w :label-w} column widths for the transient grid. Every group's items share one key column and one description column, so flags and commands line up as a grid exactly like magit's popup.

PURE: `{:key-w :label-w}` column widths for the transient grid. Every group's
items share one key column and one description column, so flags and commands
line up as a grid exactly like magit's popup.
sourceraw docstring

geometryclj

(geometry {:keys [hint-row min-row clear-above?]} spec)

PURE: which row of region every part of the popup lands on, for spec.

:sep-row the band's opening separator :title-row the bold title, alone on its row :title-rule-row the title's OWN rule, closing the title band :body-top first group header :visible display rows that actually fit (overflow is dropped) :foot-rule-row the rule directly above the hint bar :foot-row the hint bar (the host's own hint row) :wipe-top first row the popup wipes before painting

Everything is clamped to :min-row, so a tall transient — or a short terminal — stops at the host's content top instead of climbing over it.

PURE: which row of `region` every part of the popup lands on, for `spec`.

  `:sep-row`         the band's opening separator
  `:title-row`       the bold title, alone on its row
  `:title-rule-row`  the title's OWN rule, closing the title band
  `:body-top`        first group header
  `:visible`         display rows that actually fit (overflow is dropped)
  `:foot-rule-row`   the rule directly above the hint bar
  `:foot-row`        the hint bar (the host's own hint row)
  `:wipe-top`        first row the popup wipes before painting

Everything is clamped to `:min-row`, so a tall transient — or a short
terminal — stops at the host's content top instead of climbing over it.
sourceraw docstring

heightclj

(height spec)

PURE: rows the popup needs INSIDE the host's frame — its opening separator, the title, the title's rule, and every display row. The closing rule and the hint bar are the host's OWN bottom chrome, so they are not counted; a host sizes its box with this before it paints one.

PURE: rows the popup needs INSIDE the host's frame — its opening separator,
the title, the title's rule, and every display row. The closing rule and the
hint bar are the host's OWN bottom chrome, so they are not counted; a host
sizes its box with this before it paints one.
sourceraw docstring

hint-pairsclj

The footer every transient shows: what a flag key does, what a command key does, and the way out.

The footer every transient shows: what a flag key does, what a command key
does, and the way out.
sourceraw docstring

item-argclj

(item-arg {:keys [type arg secret?]} value)

PURE: the trailing git-argument cell magit shows for a FLAG: (--no-verify) for a switch, (%topic=fix) for an option carrying value. nil for actions (a command contributes no argument) and for flags that name none.

A :secret? true option NEVER renders what it holds: an armed API key shows as (••••••), so a credential can be carried by a transient without being echoed onto the screen or into a screenshot.

PURE: the trailing git-argument cell magit shows for a FLAG: `(--no-verify)` for
a switch, `(%topic=fix)` for an option carrying `value`. nil for actions (a
command contributes no argument) and for flags that name none.

A `:secret? true` option NEVER renders what it holds: an armed API key shows
as `(••••••)`, so a credential can be carried by a transient without being
echoed onto the screen or into a screenshot.
sourceraw docstring

item-by-keyclj

(item-by-key spec ch)

PURE: the spec item bound to single character ch (a Character or string), scanning every group in order. nil when nothing is bound.

PURE: the spec item bound to single character `ch` (a Character or string),
scanning every group in order. nil when nothing is bound.
sourceraw docstring

key-glyphclj

(key-glyph {:keys [type key]})

PURE: the key column glyph magit paints for one item. FLAGS (:switch / :option) carry magit's leading --h, -t — so a toggle can never be mistaken for a fire-once verb; COMMANDS (:action) show the bare key.

PURE: the key column glyph magit paints for one item. FLAGS (`:switch` /
`:option`) carry magit's leading `-` — `-h`, `-t` — so a toggle can never be
mistaken for a fire-once verb; COMMANDS (`:action`) show the bare key.
sourceraw docstring

paint!clj

(paint! {:keys [g hint-bar!]}
        {:keys [left inner-w text-w] :as region}
        spec
        state)

Paint ONE frame of spec at state into region on host. Pure geometry, one pass, no key handling — a host that owns its own event loop embeds a transient with this plus toggle; run! is the batteries-included loop.

Paint ONE frame of `spec` at `state` into `region` on `host`. Pure geometry,
one pass, no key handling — a host that owns its own event loop embeds a
transient with this plus `toggle`; `run!` is the batteries-included loop.
sourceraw docstring

rowsclj

(rows spec)

PURE: the popup's display rows, top to bottom — {:kind :header :text}, {:kind :item :item} and {:kind :blank} spacers between groups.

The title carries its OWN rule underneath (see geometry), so the first group header needs no blank margin of its own; groups after it still get one from the trailing blank of the group before.

PURE: the popup's display rows, top to bottom — `{:kind :header :text}`,
`{:kind :item :item}` and `{:kind :blank}` spacers between groups.

The title carries its OWN rule underneath (see `geometry`), so the first
group header needs no blank margin of its own; groups after it still get one
from the trailing blank of the group before.
sourceraw docstring

run!clj

(run! {:keys [read-key! refresh!] :as host} region spec)

Paint spec into region on host and run its key loop until an ACTION fires or the user cancels. Returns {:action id :switches #{…} :options {…}}, or nil on Esc. Flags toggle in place and keep the popup open; an OPTION calls the spec's :read-option for a value.

Paint `spec` into `region` on `host` and run its key loop until an ACTION
fires or the user cancels. Returns `{:action id :switches #{…} :options {…}}`,
or nil on Esc. Flags toggle in place and keep the popup open; an OPTION calls
the spec's `:read-option` for a value.
sourceraw docstring

toggleclj

(toggle spec state ch)

PURE reducer for ONE keystroke against a transient state ({:switches #{ids} :options {id val}}). Returns a map whose :kind tells the impure caller what to do next: {:kind :continue :state s'} a SWITCH flipped (or an unbound key — no-op) {:kind :option :item it} an OPTION was hit; caller reads a value then re-enters with it stored under [:options id] {:kind :action :item it} an ACTION fires; caller runs it and closes. Switches are the only kind this fn mutates; options/actions leave state untouched (the impure loop finishes their job).

PURE reducer for ONE keystroke against a transient `state`
(`{:switches #{ids} :options {id val}}`). Returns a map whose `:kind` tells
the impure caller what to do next:
  {:kind :continue :state s'}  a SWITCH flipped (or an unbound key — no-op)
  {:kind :option   :item it}   an OPTION was hit; caller reads a value then
                               re-enters with it stored under [:options id]
  {:kind :action   :item it}   an ACTION fires; caller runs it and closes.
Switches are the only kind this fn mutates; options/actions leave `state`
untouched (the impure loop finishes their job).
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