This commit is contained in:
2026-01-21 10:30:07 -05:00
parent a990076b03
commit b14ba33c3a
20 changed files with 3718 additions and 43 deletions
+24 -8
View File
@@ -1,23 +1,37 @@
(ns tui.terminal
"Terminal management: raw mode, size, input/output."
(:require [tui.ansi :as ansi]
[clojure.java.io :as io]
[clojure.java.shell :refer [sh]])
[clojure.java.io :as io])
(:import [java.io BufferedReader InputStreamReader]))
;; === Terminal State ===
(def ^:private original-stty (atom nil))
(defn- stty [& args]
(let [result (apply sh "stty" (concat args [:in (io/file "/dev/tty")]))]
(when (zero? (:exit result))
(clojure.string/trim (:out result)))))
(let [cmd (concat ["sh" "-c" (str "stty " (clojure.string/join " " args) " </dev/tty")]
(when (empty? args) ["sh" "-c" "stty </dev/tty"]))
pb (ProcessBuilder. ^java.util.List (vec cmd))
_ (.inheritIO pb)
proc (.start pb)
exit (.waitFor proc)]
(when (zero? exit)
"")))
(defn- stty-get [& args]
(let [cmd ["sh" "-c" (str "stty " (clojure.string/join " " args) " </dev/tty")]
pb (ProcessBuilder. ^java.util.List (vec cmd))
_ (.redirectInput pb java.lang.ProcessBuilder$Redirect/INHERIT)
proc (.start pb)
output (slurp (.getInputStream proc))
exit (.waitFor proc)]
(when (zero? exit)
(clojure.string/trim output))))
(defn get-terminal-size
"Get terminal dimensions as [width height]."
[]
(try
(let [result (stty "size")]
(let [result (stty-get "size")]
(when result
(let [[rows cols] (map parse-long (clojure.string/split result #"\s+"))]
{:width cols :height rows})))
@@ -27,7 +41,7 @@
(defn raw-mode!
"Enter raw terminal mode (no echo, no line buffering)."
[]
(reset! original-stty (stty "-g"))
(reset! original-stty (stty-get "-g"))
(stty "raw" "-echo" "-icanon" "min" "1")
(print ansi/hide-cursor)
(flush))
@@ -66,7 +80,9 @@
[s]
(print ansi/cursor-home)
(print ansi/clear-to-end)
(print s)
;; In raw mode, \n only moves down without returning to column 0
;; Replace \n with \r\n to get proper line breaks
(print (clojure.string/replace s "\n" "\r\n"))
(flush))
;; === Input Handling ===