{:deps {com.fulcrologic/fulcro-tui {:mvn/version "RELEASE"}}}
Fulcro normally renders through React to the browser DOM. This library provides an alternative rendering target: it lays out a tree of terminal-native nodes (boxes, text, inputs, buttons) and paints them into a character-cell buffer that is displayed in a real terminal via JLine. Components are written with the familiar tui/defsc macro and driven by the same Fulcro data-management primitives (mutations, normalized state, transactions).
Works on the JVM and under babashka. The historical bb blockers (Fulcro’s Mutation deftype not being constructable by bb’s SCI, and transitively-pulled spec.alpha/clojurescript jars shadowing bb’s built-ins) are resolved in the Fulcro build this depends on; JLine’s inner-class resize-signal API is routed through sun.misc.Signal so it works on both runtimes. Run the demo under babashka with bb run tui — see bb.edn for details.
Released to Clojars — use the version shown in the badge above (deps.edn):
{:deps {com.fulcrologic/fulcro-tui {:mvn/version "RELEASE"}}}
Run the example two-field form in a real terminal, on the JVM:
clojure -M:tui -m tui-example.form
…or under babashka (faster startup, no JVM):
bb run tui
Controls:
Tab / Shift-Tab move focus through the fields, the multiline notes box, the Save button, and into the item list.
Arrow keys move the caret (in the notes box, Up/Down move by visual line).
Type to edit the focused field.
In the multiline notes box, Enter inserts a newline (it does not submit); the box wraps to its width and self-scrolls to keep the caret visible.
Enter / Space activates the focused Save button or list item.
PageUp / PageDown scroll the item list; tabbing into the list auto-scrolls to keep the focused item visible.
Pick a fruit opens a modal list picker (see below): Up / Down move the highlight, Enter chooses, Escape cancels.
Ctrl-Q quits.
A tui/modal node is an overlay window that floats over the rest of the UI. The driver composites it
on top of the base tree and traps focus and keyboard input to it while it is open, so the controls
behind it are inert. It is declarative — its presence is just app state, via an :open? flag:
(tui/modal {:id :confirm :open? confirm-open?
:width 30 :height 7 :title "Confirm"
:on-dismiss #(tui/transact! this [(close-confirm)])} ; Escape calls this
(tui/text {} "Delete everything?")
(tui/button {:id :yes :on-activate #(tui/transact! this [(do-delete)])} " Yes "))
The library owns no lifecycle: you toggle :open? (and record any result) with your own mutations,
exactly as the rest of a Fulcro app works. :width/:height accept a cell count or [:fraction f];
:align (default :center) positions the window; :border? defaults to true; :on-dismiss is
called on Escape.
tui/picker is a list picker built on modal — a scrollable :viewport of selectable rows where the
focused row is the highlight (Up/Down move it, the list scrolls to follow, Enter selects, Escape
cancels):
(tui/picker {:id :fruit
:open? picker-open?
:title "Pick a fruit"
:width 24 :height 8
:options [{:value :apple :label "Apple"}
{:value :pear :label "Pear"}]
:on-select (fn [v] (tui/transact! this [(choose-fruit {:v v})]))
:on-cancel (fn [] (tui/transact! this [(close-picker)]))})
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |