# API Reference Complete API documentation for Clojure TUI. ## Table of Contents - [tui.core](#tuicore) - Main runtime - [tui.render](#tuirender) - Hiccup rendering - [tui.input](#tuiinput) - Key input parsing - [tui.terminal](#tuiterminal) - Terminal control - [tui.ansi](#tuiansi) - ANSI escape codes --- ## tui.core Main runtime using core.async. Provides timers, async commands, background operations, and responsive layout support. ### run ```clojure (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 size] hiccup)` where size is `{:width w :height h}` | | `: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:** ```clojure (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]} _size] [:text (str "Count: " count)]) :fps 30 :alt-screen true}) ``` ### quit ```clojure quit ``` Constant value returned as a command to exit the application. **Example:** ```clojure (defn update-fn [model msg] (if (tui/key= msg "q") [model tui/quit] [model nil])) ``` ### tick ```clojure (tick ms) ``` Create a command that sends `:tick` message after a delay. **Parameters:** - `ms` - Delay in milliseconds **Returns:** A tick command **Example:** ```clojure ;; 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 ```clojure (batch & cmds) ``` Create a command that executes multiple commands in parallel. **Parameters:** - `cmds` - Variable number of commands **Returns:** A batch command **Example:** ```clojure ;; 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 ```clojure (sequentially & cmds) ``` Create a command that executes commands one after another. **Parameters:** - `cmds` - Variable number of commands **Returns:** A sequential command **Example:** ```clojure ;; 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 ```clojure (send-msg msg) ``` Create a command that immediately sends a message. **Parameters:** - `msg` - Message to send **Returns:** A send-msg command **Example:** ```clojure (defn update-fn [model msg] (if (tui/key= msg "r") [{:status :resetting} (tui/send-msg :do-reset)] [model nil])) ``` ### key= ```clojure (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:** ```clojure (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 ```clojure (key-str msg) ``` Convert a key message to a human-readable string. **Parameters:** - `msg` - Key message **Returns:** String representation **Example:** ```clojure (tui/key-str [:key {:char \a}]) ;; => "a" (tui/key-str [:key :up]) ;; => "up" (tui/key-str [:key {:ctrl true :char \c}]) ;; => "ctrl+c" ``` ### render ```clojure (render hiccup) ``` Re-exported from `tui.render`. Render hiccup to ANSI string. --- ## tui.render Converts hiccup data structures to ANSI-formatted strings. ### render ```clojure (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:** ```clojure (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 ```clojure (text & args) ``` Helper function to create `:text` elements. **Example:** ```clojure (text "Hello") ;; => [:text "Hello"] (text {:fg :red} "Error") ;; => [:text {:fg :red} "Error"] ``` ### row ```clojure (row & args) ``` Helper function to create `:row` elements. **Example:** ```clojure (row "A" "B" "C") ;; => [:row "A" "B" "C"] (row {:gap 2} "A" "B") ;; => [:row {:gap 2} "A" "B"] ``` ### col ```clojure (col & args) ``` Helper function to create `:col` elements. **Example:** ```clojure (col "Line 1" "Line 2") ;; => [:col "Line 1" "Line 2"] (col {:gap 1} "A" "B") ;; => [:col {:gap 1} "A" "B"] ``` ### box ```clojure (box & args) ``` Helper function to create `:box` elements. **Example:** ```clojure (box "Content") ;; => [:box "Content"] (box {:title "Info"} "Content") ;; => [:box {:title "Info"} "Content"] ``` --- ## tui.input Parses raw terminal input into structured key messages. ### read-key ```clojure (read-key) ``` Read a single key event from the terminal. **Returns:** Key message vector `[:key ...]` **Key message formats:** ```clojure ;; 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? ```clojure (key-match? msg pattern) ``` Internal function used by `key=` to match patterns. ### key->str ```clojure (key->str msg) ``` Convert key message to string representation. **Example:** ```clojure (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 ```clojure (get-terminal-size) ``` Get the terminal dimensions. **Returns:** Map with `:width` and `:height` keys **Example:** ```clojure (require '[tui.terminal :as term]) (term/get-terminal-size) ;; => {:width 120 :height 40} ``` ### raw-mode! ```clojure (raw-mode!) ``` Enter raw terminal mode. Disables echo and line buffering. ### restore! ```clojure (restore!) ``` Restore terminal to original state. ### alt-screen! ```clojure (alt-screen!) ``` Enter the alternate screen buffer. ### exit-alt-screen! ```clojure (exit-alt-screen!) ``` Exit the alternate screen buffer. ### clear! ```clojure (clear!) ``` Clear the screen and move cursor to home position. ### render! ```clojure (render! s) ``` Render a string to the terminal. **Parameters:** - `s` - String to render (typically from `tui.render/render`) ### Input Functions ```clojure (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 ```clojure (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:** ```clojure (require '[tui.ansi :as ansi]) (ansi/style "Error" :fg :red :bold true) (ansi/style "Warning" :fg :yellow :bg :black :underline true) ``` ### Color Functions ```clojure (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:** ```clojure (ansi/fg :red "Error") (ansi/bg :yellow "Highlighted") (ansi/fg-256 208 "Orange") (ansi/fg-rgb 255 128 0 "True color orange") ``` ### String Utilities ```clojure (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:** ```clojure (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 ```clojure (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 ```clojure 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 ```clojure 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 ```clojure 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: ```clojure ;; 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` | Main runtime with Elm architecture and async commands | | `tui.render` | Hiccup to ANSI rendering | | `tui.input` | Key input parsing | | `tui.terminal` | Low-level terminal control | | `tui.ansi` | ANSI codes and text utilities |