Files
clojure-tui/docs/api-reference.md
Adam Jeniski dab0a27e4d add comprehensive documentation for external users
Includes getting started guide, hiccup views reference,
full API documentation, and annotated example walkthroughs
with ASCII output examples.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 11:37:16 -05:00

14 KiB

API Reference

Complete API documentation for Clojure TUI.

Table of Contents


tui.core

Full-featured async runtime using core.async. Use this when you need timers, async commands, or background operations.

run

(run options)

Run a TUI application synchronously (blocks until quit).

Parameters:

Key Type Required Description
:init any Yes Initial model value
:update function Yes (fn [model msg] [new-model cmd])
:view function Yes (fn [model] hiccup)
:init-cmd command No Initial command to execute
:fps integer No Frames per second (default: 60)
:alt-screen boolean No Use alternate screen (default: true)

Returns: Final model value after quit

Example:

(require '[tui.core :as tui])

(tui/run {:init {:count 0}
          :update (fn [model msg]
                    (if (tui/key= msg "q")
                      [model tui/quit]
                      [model nil]))
          :view (fn [{:keys [count]}]
                  [:text (str "Count: " count)])
          :fps 30
          :alt-screen true})

quit

quit

Constant value returned as a command to exit the application.

Example:

(defn update-fn [model msg]
  (if (tui/key= msg "q")
    [model tui/quit]
    [model nil]))

tick

(tick ms)

Create a command that sends :tick message after a delay.

Parameters:

  • ms - Delay in milliseconds

Returns: A tick command

Example:

;; Start a 1-second timer
(defn update-fn [model msg]
  (case msg
    :tick [(update model :seconds inc) (tui/tick 1000)]
    [model nil]))

;; Initial tick
(tui/run {:init {:seconds 0}
          :update update-fn
          :view view
          :init-cmd (tui/tick 1000)})

batch

(batch & cmds)

Create a command that executes multiple commands in parallel.

Parameters:

  • cmds - Variable number of commands

Returns: A batch command

Example:

;; Execute two async operations in parallel
(defn update-fn [model msg]
  (if (= msg :start)
    [model (tui/batch
             (fn [] (fetch-user))
             (fn [] (fetch-settings)))]
    [model nil]))

sequentially

(sequentially & cmds)

Create a command that executes commands one after another.

Parameters:

  • cmds - Variable number of commands

Returns: A sequential command

Example:

;; First save, then notify
(defn update-fn [model msg]
  (if (= msg :save)
    [model (tui/sequentially
             (fn [] (save-data model))
             (fn [] {:type :saved}))]
    [model nil]))

send-msg

(send-msg msg)

Create a command that immediately sends a message.

Parameters:

  • msg - Message to send

Returns: A send-msg command

Example:

(defn update-fn [model msg]
  (if (tui/key= msg "r")
    [{:status :resetting} (tui/send-msg :do-reset)]
    [model nil]))

key=

(key= msg pattern)

Check if a key message matches a pattern.

Parameters:

  • msg - The message to check
  • pattern - Pattern to match (see below)

Returns: true if matches, false otherwise

Pattern types:

Pattern Matches
"q" Character 'q'
:enter Enter key
:up Arrow up
[:ctrl \c] Ctrl+C
[:alt \x] Alt+X

Example:

(defn update-fn [model msg]
  (cond
    (tui/key= msg "q") [model tui/quit]
    (tui/key= msg :up) [(update model :y dec) nil]
    (tui/key= msg [:ctrl \c]) [model tui/quit]
    :else [model nil]))

key-str

(key-str msg)

Convert a key message to a human-readable string.

Parameters:

  • msg - Key message

Returns: String representation

Example:

(tui/key-str [:key {:char \a}])          ;; => "a"
(tui/key-str [:key :up])                 ;; => "up"
(tui/key-str [:key {:ctrl true :char \c}]) ;; => "ctrl+c"

render

(render hiccup)

Re-exported from tui.render. Render hiccup to ANSI string.


tui.simple

Synchronous runtime compatible with Babashka. Same API as tui.core but without async commands.

run

(run options)

Run a TUI application synchronously.

Parameters:

Key Type Required Description
:init any Yes Initial model value
:update function Yes (fn [model msg] [new-model cmd])
:view function Yes (fn [model] hiccup)
:alt-screen boolean No Use alternate screen (default: true)

Returns: Final model value after quit

Example:

(require '[tui.simple :as tui])

(tui/run {:init 0
          :update (fn [model msg]
                    (cond
                      (tui/key= msg "q") [model tui/quit]
                      (tui/key= msg "k") [(inc model) nil]
                      :else [model nil]))
          :view (fn [count]
                  [:text (str "Count: " count)])})

quit

Same as tui.core/quit.

key=

Same as tui.core/key=.

key-str

Same as tui.core/key-str.

render

Re-exported from tui.render.


tui.render

Converts hiccup data structures to ANSI-formatted strings.

render

(render hiccup)
(render hiccup ctx)

Render hiccup to ANSI string.

Parameters:

  • hiccup - Hiccup data structure
  • ctx - Optional context map (for internal use)

Returns: String with ANSI escape codes

Example:

(require '[tui.render :as r])

(r/render [:text {:fg :red :bold true} "Error!"])
;; => "\e[31m\e[1mError!\e[0m"

(r/render [:col
           [:text "Line 1"]
           [:text "Line 2"]])
;; => "Line 1\nLine 2"

(r/render [:box {:border :rounded} "Content"])
;; => "╭─────────╮\n│Content  │\n╰─────────╯"

text

(text & args)

Helper function to create :text elements.

Example:

(text "Hello")                     ;; => [:text "Hello"]
(text {:fg :red} "Error")          ;; => [:text {:fg :red} "Error"]

row

(row & args)

Helper function to create :row elements.

Example:

(row "A" "B" "C")                   ;; => [:row "A" "B" "C"]
(row {:gap 2} "A" "B")              ;; => [:row {:gap 2} "A" "B"]

col

(col & args)

Helper function to create :col elements.

Example:

(col "Line 1" "Line 2")             ;; => [:col "Line 1" "Line 2"]
(col {:gap 1} "A" "B")              ;; => [:col {:gap 1} "A" "B"]

box

(box & args)

Helper function to create :box elements.

Example:

(box "Content")                     ;; => [:box "Content"]
(box {:title "Info"} "Content")     ;; => [:box {:title "Info"} "Content"]

tui.input

Parses raw terminal input into structured key messages.

read-key

(read-key)

Read a single key event from the terminal.

Returns: Key message vector [:key ...]

Key message formats:

;; Regular character
[:key {:char \a}]

;; Special key
[:key :enter]
[:key :up]
[:key :f1]

;; Control combination
[:key {:ctrl true :char \c}]

;; Alt combination
[:key {:alt true :char \x}]

;; Unknown sequence
[:key :unknown "\e[xyz"]

Special Key Keywords

Keyword Key
:up Arrow Up
:down Arrow Down
:left Arrow Left
:right Arrow Right
:home Home
:end End
:page-up Page Up
:page-down Page Down
:insert Insert
:delete Delete
:escape Escape
:tab Tab
:shift-tab Shift+Tab
:enter Enter
:backspace Backspace
:f1 - :f12 Function keys

key-match?

(key-match? msg pattern)

Internal function used by key= to match patterns.

key->str

(key->str msg)

Convert key message to string representation.

Example:

(key->str [:key {:char \a}])              ;; => "a"
(key->str [:key :enter])                  ;; => "enter"
(key->str [:key {:ctrl true :char \c}])   ;; => "ctrl+c"
(key->str [:key {:alt true :char \x}])    ;; => "alt+x"

tui.terminal

Low-level terminal control functions.

get-terminal-size

(get-terminal-size)

Get the terminal dimensions.

Returns: Map with :width and :height keys

Example:

(require '[tui.terminal :as term])

(term/get-terminal-size)
;; => {:width 120 :height 40}

raw-mode!

(raw-mode!)

Enter raw terminal mode. Disables echo and line buffering.

restore!

(restore!)

Restore terminal to original state.

alt-screen!

(alt-screen!)

Enter the alternate screen buffer.

exit-alt-screen!

(exit-alt-screen!)

Exit the alternate screen buffer.

clear!

(clear!)

Clear the screen and move cursor to home position.

render!

(render! s)

Render a string to the terminal.

Parameters:

  • s - String to render (typically from tui.render/render)

Input Functions

(init-input!)       ;; Initialize input reader
(close-input!)      ;; Close input reader
(input-ready?)      ;; Check if input available (non-blocking)
(read-char)         ;; Read single character (blocking)
(read-available)    ;; Read all available characters
(read-char-timeout ms) ;; Read with timeout

tui.ansi

ANSI escape codes and text styling utilities.

style

(style text & {:keys [fg bg bold dim italic underline inverse strike]})

Apply multiple styles to text.

Parameters:

  • text - String to style
  • :fg - Foreground color
  • :bg - Background color
  • :bold - Boolean
  • :dim - Boolean
  • :italic - Boolean
  • :underline - Boolean
  • :inverse - Boolean
  • :strike - Boolean

Example:

(require '[tui.ansi :as ansi])

(ansi/style "Error" :fg :red :bold true)
(ansi/style "Warning" :fg :yellow :bg :black :underline true)

Color Functions

(fg color text)       ;; Set foreground color
(bg color text)       ;; Set background color
(fg-256 n text)       ;; 256-color foreground (0-255)
(bg-256 n text)       ;; 256-color background (0-255)
(fg-rgb r g b text)   ;; True color foreground (24-bit)
(bg-rgb r g b text)   ;; True color background (24-bit)

Example:

(ansi/fg :red "Error")
(ansi/bg :yellow "Highlighted")
(ansi/fg-256 208 "Orange")
(ansi/fg-rgb 255 128 0 "True color orange")

String Utilities

(visible-length s)     ;; Get visible length (excludes ANSI codes)
(pad-right s width)    ;; Pad with spaces on right
(pad-left s width)     ;; Pad with spaces on left
(pad-center s width)   ;; Center within width
(truncate s max-width) ;; Truncate with ellipsis

Example:

(ansi/visible-length "\e[31mRed\e[0m")  ;; => 3
(ansi/pad-right "Hi" 10)                ;; => "Hi        "
(ansi/pad-center "Hi" 10)               ;; => "    Hi    "
(ansi/truncate "Hello World" 8)         ;; => "Hello..."

Cursor Control

(cursor-to row col)    ;; Move cursor to position (1-indexed)
(cursor-up n)          ;; Move cursor up n lines
(cursor-down n)        ;; Move cursor down n lines
(cursor-forward n)     ;; Move cursor right n columns
(cursor-back n)        ;; Move cursor left n columns

Constants

clear-screen           ;; Clear entire screen
clear-line             ;; Clear current line
clear-to-end           ;; Clear from cursor to end of screen
cursor-home            ;; Move cursor to home (1,1)
hide-cursor            ;; Hide cursor
show-cursor            ;; Show cursor
enter-alt-screen       ;; Enter alternate screen buffer
exit-alt-screen        ;; Exit alternate screen buffer
cursor-save            ;; Save cursor position
cursor-restore         ;; Restore cursor position
reset                  ;; Reset all attributes

Box Drawing Characters

ansi/box-chars
;; => {:rounded {:tl "╭" :tr "╮" :bl "╰" :br "╯" :h "─" :v "│"}
;;     :single  {:tl "┌" :tr "┐" :bl "└" :br "┘" :h "─" :v "│"}
;;     :double  {:tl "╔" :tr "╗" :bl "╚" :br "╝" :h "═" :v "║"}
;;     :heavy   {:tl "┏" :tr "┓" :bl "┗" :br "┛" :h "━" :v "┃"}
;;     :ascii   {:tl "+" :tr "+" :bl "+" :br "+" :h "-" :v "|"}}

Color Maps

ansi/fg-colors         ;; Map of color keywords to ANSI codes
ansi/bg-colors         ;; Map of color keywords to ANSI codes
ansi/attrs             ;; Map of attribute keywords to ANSI codes

Custom Async Commands

In tui.core, you can create custom async commands by returning functions:

;; Custom command that fetches data
(defn fetch-data-cmd []
  (fn []
    ;; This runs asynchronously
    (let [result (http/get "https://api.example.com/data")]
      {:type :data-loaded :data (:body result)})))

(defn update-fn [model msg]
  (cond
    (tui/key= msg "f")
    [{:loading true} (fetch-data-cmd)]

    (= (:type msg) :data-loaded)
    [{:loading false :data (:data msg)} nil]

    :else
    [model nil]))

The function must:

  1. Take no arguments
  2. Return a message (any Clojure value)
  3. The returned message will be passed to your update function

Summary

Namespace Purpose
tui.core Full async runtime with all features
tui.simple Sync runtime for Babashka
tui.render Hiccup to ANSI rendering
tui.input Key input parsing
tui.terminal Low-level terminal control
tui.ansi ANSI codes and text utilities