Liking cljdoc? Tell your friends :D

com.fulcrologic.fulcro.tui.application

The application/lifecycle front door for the TUI rendering target: build a Fulcro app, attach a terminal, run the input loop, and stop it. This is also where the side-effecting render driver lives (it renders a Fulcro app to a terminal and runs the keyboard input loop).

This is the edge that ties together the pure TUI pipeline in com.fulcrologic.fulcro.tui.engine (layout, paint, diff, focus, input) and the element generators in com.fulcrologic.fulcro.tui.elements with a concrete com.fulcrologic.fulcro.tui.terminal/Terminal. Use application to build a synchronous raw Fulcro app whose renders repaint the terminal, mount! (or run-blocking!) to attach a terminal and start the keyboard input loop, quit! to stop it, and step! to drive a single deterministic iteration (used by tests).

State/runtime keys (single source of truth):

  • Focus & carets & scroll are owned by com.fulcrologic.fulcro.tui.engine (see that ns).
  • The attached terminal and the bookkeeping for incremental painting live in the app RUNTIME-ATOM under this namespace's keys (see ::terminal, ::prev-buffer, ::placed, ::last-size).

This is JVM/babashka only (plain .clj).

Viewport scrolling: engine/place lays a viewport's single child out at its natural size into a virtual rect, and engine/render-buffer blits only the window [scroll-x scroll-y w h] of that virtual content into the viewport's ::rect. Scroll offsets are stored in the state-map under :com.fulcrologic.fulcro.tui.engine/scroll keyed by viewport id; render! injects them onto the placed tree (inject-scroll), follow-focus! advances them after focus changes to keep the focused node visible, and PageUp/PageDown page-scroll via viewport-scroll-key!. Up/Down arrows move focus item-to-item (in engine/process-key!) and follow-focus! autoscrolls to track the focused item.

The application/lifecycle front door for the TUI rendering target: build a Fulcro app, attach a
terminal, run the input loop, and stop it. This is also where the side-effecting render driver
lives (it renders a Fulcro app to a terminal and runs the keyboard input loop).

This is the edge that ties together the pure TUI pipeline in `com.fulcrologic.fulcro.tui.engine`
(layout, paint, diff, focus, input) and the element generators in
`com.fulcrologic.fulcro.tui.elements` with a concrete `com.fulcrologic.fulcro.tui.terminal/Terminal`. Use
`application` to build a synchronous raw Fulcro app whose renders repaint the terminal, `mount!`
(or `run-blocking!`) to attach a terminal and start the keyboard input loop, `quit!` to stop it,
and `step!` to drive a single deterministic iteration (used by tests).

State/runtime keys (single source of truth):
  * Focus & carets & scroll are owned by `com.fulcrologic.fulcro.tui.engine` (see that ns).
  * The attached terminal and the bookkeeping for incremental painting live in the app
    RUNTIME-ATOM under this namespace's keys (see `::terminal`, `::prev-buffer`, `::placed`,
    `::last-size`).

This is JVM/babashka only (plain `.clj`).

Viewport scrolling: `engine/place` lays a viewport's single child out at its natural size into a
virtual rect, and `engine/render-buffer` blits only the window `[scroll-x scroll-y w h]` of that
virtual content into the viewport's `::rect`. Scroll offsets are stored in the state-map under
`:com.fulcrologic.fulcro.tui.engine/scroll` keyed by viewport id; `render!` injects them onto the placed
tree (`inject-scroll`), `follow-focus!` advances them after focus changes to keep the focused node
visible, and PageUp/PageDown page-scroll via `viewport-scroll-key!`. Up/Down arrows move focus
item-to-item (in `engine/process-key!`) and `follow-focus!` autoscrolls to track the focused item.
raw docstring

com.fulcrologic.fulcro.tui.elements

The public TUI element API: the generators authors use to build a tree of terminal-native nodes from a Fulcro component's render — vbox, hbox, box, text, input, button, line, viewport, modal, picker — plus focused? (highlight the focused node). State changes use Fulcro's own com.fulcrologic.fulcro.components/transact!; this namespace adds no transact.

A node is a plain map keyed by the com.fulcrologic.fulcro.tui.engine vocabulary (::engine/tag, ::engine/attrs, ::engine/children); prefer these generators over building the maps by hand. The engine (com.fulcrologic.fulcro.tui.engine) lays the tree out and paints it; this namespace depends on the engine for that node vocabulary and node?/*current-focus*.

This is JVM/babashka only (plain .clj).

The public TUI element API: the generators authors use to build a tree of terminal-native *nodes*
from a Fulcro component's render — `vbox`, `hbox`, `box`, `text`, `input`, `button`, `line`,
`viewport`, `modal`, `picker` — plus `focused?` (highlight the focused node). State changes use
Fulcro's own `com.fulcrologic.fulcro.components/transact!`; this namespace adds no transact.

A node is a plain map keyed by the `com.fulcrologic.fulcro.tui.engine` vocabulary (`::engine/tag`,
`::engine/attrs`, `::engine/children`); prefer these generators over building the maps by hand.
The engine (`com.fulcrologic.fulcro.tui.engine`) lays the tree out and paints it; this namespace
depends on the engine for that node vocabulary and `node?`/`*current-focus*`.

This is JVM/babashka only (plain `.clj`).
raw docstring

com.fulcrologic.fulcro.tui.engine

The pure TUI engine: the layout, paint, diff, focus, input, and overlay-compositing pipeline that turns a tree of terminal-native nodes into a character cell buffer (and ANSI), plus the component-render walker. This namespace also owns the node-structure vocabulary (the ::tag/ ::attrs/::children keys and related specs) and the focus/scroll/caret state keys.

Build the node tree with the element generators in com.fulcrologic.fulcro.tui.elements; drive it to a terminal with com.fulcrologic.fulcro.tui.application; paint to a concrete terminal via com.fulcrologic.fulcro.tui.terminal.

A node is a plain map of the form:

{:com.fulcrologic.fulcro.tui.engine/tag      :vbox        ; one of `tags`
 :com.fulcrologic.fulcro.tui.engine/attrs    {...}        ; layout/style/event attributes
 :com.fulcrologic.fulcro.tui.engine/children [...]}       ; child nodes, strings, and numbers

This is JVM/babashka only (plain .clj).

The pure TUI engine: the layout, paint, diff, focus, input, and overlay-compositing pipeline that
turns a tree of terminal-native *nodes* into a character cell buffer (and ANSI), plus the
component-render walker. This namespace also owns the node-structure vocabulary (the `::tag`/
`::attrs`/`::children` keys and related specs) and the focus/scroll/caret state keys.

Build the node tree with the element generators in `com.fulcrologic.fulcro.tui.elements`; drive it
to a terminal with `com.fulcrologic.fulcro.tui.application`; paint to a concrete terminal via
`com.fulcrologic.fulcro.tui.terminal`.

A node is a plain map of the form:

```
{:com.fulcrologic.fulcro.tui.engine/tag      :vbox        ; one of `tags`
 :com.fulcrologic.fulcro.tui.engine/attrs    {...}        ; layout/style/event attributes
 :com.fulcrologic.fulcro.tui.engine/children [...]}       ; child nodes, strings, and numbers
```

This is JVM/babashka only (plain `.clj`).
raw docstring

com.fulcrologic.fulcro.tui.inspect

JVM (Clojure) Fulcro Inspect connector for TUI apps.

This is the small CLJ shim that fills the only gap preventing a plain JVM Fulcro app from connecting to the standalone Fulcro Inspect (Electron) app: a DevToolConnectionFactory that speaks Sente over a real websocket from the JVM.

The entire inspect event-generation pipeline (transactions, network, db-changed) and the devtools-remote transport (connection, target, resolvers) are already CLJC and ship transitively with Fulcro 3.10.x. The only CLJS-only piece is com.fulcrologic.devtools.electron.target (it uses goog-define and enc/get-win-loc). This namespace is a CLJ analog of that factory.

Usage (debug only):

(require '[com.fulcrologic.fulcro.tui.inspect :as tui-inspect]) (tui-inspect/install!) ; register the JVM websocket factory ONCE (tui-inspect/add-inspect! app) ; attach inspect to your TUI app

Requires the Fulcro Inspect Electron app to be running (it hosts the websocket server on localhost:8237). Also requires the inspect pipeline to be enabled in CLJ via the JVM property:

-Dcom.fulcrologic.fulcro.inspect=true

(Without that property fulcro.inspect.tool/add-fulcro-inspect! is a no-op, because its body is wrapped in the ilet macro that only emits in CLJ when that property is "true".)

JVM (Clojure) Fulcro Inspect connector for TUI apps.

This is the small CLJ shim that fills the only gap preventing a plain JVM Fulcro app from
connecting to the standalone Fulcro Inspect (Electron) app: a `DevToolConnectionFactory`
that speaks Sente over a real websocket from the JVM.

The entire inspect event-generation pipeline (transactions, network, db-changed) and the
devtools-remote transport (connection, target, resolvers) are already CLJC and ship transitively
with Fulcro 3.10.x. The only CLJS-only piece is `com.fulcrologic.devtools.electron.target`
(it uses `goog-define` and `enc/get-win-loc`). This namespace is a CLJ analog of that factory.

Usage (debug only):

  (require '[com.fulcrologic.fulcro.tui.inspect :as tui-inspect])
  (tui-inspect/install!)                 ; register the JVM websocket factory ONCE
  (tui-inspect/add-inspect! app)         ; attach inspect to your TUI app

Requires the Fulcro Inspect Electron app to be running (it hosts the websocket server on
localhost:8237). Also requires the inspect pipeline to be enabled in CLJ via the JVM property:

  -Dcom.fulcrologic.fulcro.inspect=true

(Without that property `fulcro.inspect.tool/add-fulcro-inspect!` is a no-op, because its body is
wrapped in the `ilet` macro that only emits in CLJ when that property is "true".)
raw docstring

com.fulcrologic.fulcro.tui.perf

A tiny, babashka-compatible profiler — the core of Tufte (p profile points, a profile scope, and a println report) reimplemented with only plain atoms / volatiles / dynamic vars so it runs under SCI. (Real Tufte does NOT load under babashka: its encore dependency uses a defrecord implementing clojure.lang.Counted, which SCI rejects.)

Design goals:

  • Truly zero overhead unless explicitly built in. p and profile are compile-time gated on the fulcro.tui.perf system property: unless it is set when the calling code is macro-expanded, both expand to just (do body...) — no runtime check, no volatile read, no trace of profiling in the compiled code. So these points are safe to leave in shipped render code, and the shipped library (compiled without the property) carries no profiling at all.
  • No new dependencies. Lives in src/main (the shipped render code calls p directly), but pulls in nothing.
  • Self-time accounting. Each p records both total (inclusive) and self (exclusive of nested ps) time, so it is safe to instrument recursive code (e.g. the paint walker) and read a meaningful per-id breakdown.

Usage — first build the instrumentation IN by setting the property (JVM: -Dfulcro.tui.perf=1; babashka: bb -Dfulcro.tui.perf=1 ...), then while running the TUI:

(perf/start!) ; enable + reset ;; ... exercise the code / interact with the app ... (perf/report) ; print the per-id table (self-time ranked) (perf/stop!) ; disable

Or scope it: (perf/profile {} (render! app)) enables for the dynamic extent, prints a report, and returns the body value. Without the property set, start!/stop!/report still work but have nothing to measure, since no p points were compiled in.

A tiny, babashka-compatible profiler — the core of Tufte (`p` profile points, a `profile`
scope, and a println report) reimplemented with only plain atoms / volatiles / dynamic vars so
it runs under SCI. (Real Tufte does NOT load under babashka: its `encore` dependency uses a
`defrecord` implementing `clojure.lang.Counted`, which SCI rejects.)

Design goals:

* **Truly zero overhead unless explicitly built in.** `p` and `profile` are *compile-time*
  gated on the `fulcro.tui.perf` system property: unless it is set when the calling code is
  macro-expanded, both expand to just `(do body...)` — no runtime check, no volatile read, no
  trace of profiling in the compiled code. So these points are safe to leave in shipped render
  code, and the shipped library (compiled without the property) carries no profiling at all.
* **No new dependencies.** Lives in `src/main` (the shipped render code calls `p` directly), but
  pulls in nothing.
* **Self-time accounting.** Each `p` records both *total* (inclusive) and *self* (exclusive of
  nested `p`s) time, so it is safe to instrument recursive code (e.g. the paint walker) and read
  a meaningful per-id breakdown.

Usage — first build the instrumentation IN by setting the property (JVM: `-Dfulcro.tui.perf=1`;
babashka: `bb -Dfulcro.tui.perf=1 ...`), then while running the TUI:

  (perf/start!)        ; enable + reset
  ;; ... exercise the code / interact with the app ...
  (perf/report)        ; print the per-id table (self-time ranked)
  (perf/stop!)         ; disable

Or scope it: `(perf/profile {} (render! app))` enables for the dynamic extent, prints a report,
and returns the body value. Without the property set, `start!`/`stop!`/`report` still work but
have nothing to measure, since no `p` points were compiled in.
raw docstring

com.fulcrologic.fulcro.tui.terminal

A self-contained terminal abstraction for a TUI rendering target.

This namespace OWNS the normalized key-event model that downstream TUI code consumes, a pure (JLine-free) key decoder, a Terminal protocol, a real JLine-backed implementation, and an atom-backed fake (string-terminal) used for tests.

This is JVM/babashka only (plain .clj).

A self-contained terminal abstraction for a TUI rendering target.

This namespace OWNS the normalized key-event model that downstream TUI code consumes, a pure
(JLine-free) key decoder, a `Terminal` protocol, a real JLine-backed implementation, and an
atom-backed fake (`string-terminal`) used for tests.

This is JVM/babashka only (plain `.clj`).
raw 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