69 lines
1.7 KiB
Clojure
69 lines
1.7 KiB
Clojure
(ns tui.simple
|
|
"Simplified TUI runtime - no core.async, works with Babashka.
|
|
Synchronous event loop, no timers/async commands."
|
|
(:require [tui.terminal :as term]
|
|
[tui.input :as input]
|
|
[tui.render :as render]
|
|
[tui.ansi :as ansi]))
|
|
|
|
;; === Commands ===
|
|
(def quit [:quit])
|
|
|
|
;; === Key Matching ===
|
|
(defn key=
|
|
"Check if message is a specific key."
|
|
[msg key-pattern]
|
|
(input/key-match? msg key-pattern))
|
|
|
|
(defn key-str
|
|
"Get string representation of key."
|
|
[msg]
|
|
(input/key->str msg))
|
|
|
|
;; === Simple Run Loop ===
|
|
(defn run
|
|
"Run a TUI application (synchronous, no async commands).
|
|
|
|
Options:
|
|
- :init - Initial model (required)
|
|
- :update - (fn [model msg] [new-model cmd]) (required)
|
|
- :view - (fn [model] hiccup) (required)
|
|
- :alt-screen - Use alternate screen buffer (default false)
|
|
|
|
Returns the final model."
|
|
[{:keys [init update view alt-screen]
|
|
:or {alt-screen false}}]
|
|
|
|
;; Setup terminal
|
|
(term/init-input!)
|
|
(term/raw-mode!)
|
|
(when alt-screen (term/alt-screen!))
|
|
(term/clear!)
|
|
|
|
(try
|
|
;; Initial render
|
|
(term/render! (render/render (view init)))
|
|
|
|
;; Main loop - simple synchronous
|
|
(loop [model init]
|
|
(if-let [key-msg (input/read-key)]
|
|
(let [[new-model cmd] (update model key-msg)]
|
|
;; Render
|
|
(term/render! (render/render (view new-model)))
|
|
|
|
;; Check for quit
|
|
(if (= cmd [:quit])
|
|
new-model
|
|
(recur new-model)))
|
|
(recur model)))
|
|
|
|
(finally
|
|
;; Cleanup
|
|
(when alt-screen (term/exit-alt-screen!))
|
|
(term/restore!)
|
|
(term/close-input!)
|
|
(println))))
|
|
|
|
;; Re-export render
|
|
(def render render/render)
|