Closed tom-adsfund closed 4 months ago
I will give it at shot more, soon. As far as I remember it can be difficult to get information about the dimensions of the terminal on runtime. But I will give it another try :-)
Wouldn't it be easiest to do a periodic refresh whatever happens? Maybe add a toggle to stop it if someone finds there's an issue?
Pressing ESC twice usually redraws everything, but it does not take into account, if the terminal has be resized. I will have to recalculate the size of each window. I think periodic refreshes will be a bit annoying since the user will experience a slight flicker when nothing is happening. But if I manage to create a good resize function, it should be possible to make a toggle on the periodic refresh.
stty size
gives the terminal size. Which you're actually using already in tty_output.cljc
.
SIGWINCH
process signal tells when the terminal has been resized. But Java only has a non-standard mechanism to get it:
; Nice GPT4o solution:
; (:import [sun.misc Signal SignalHandler])
(defn handle-sigwinch [ch]
(reify SignalHandler
(handle [_ signal]
(let [[rows cols] (get-terminal-size)]
(put! ch {:rows rows :cols cols})))))
(defn redraw-editor [rows cols]
(println (str "Terminal resized to " rows " rows and " cols " columns")))
(defn main-loop []
(let [sigwinch-chan (chan)]
(Signal/handle (Signal. "WINCH") (handle-sigwinch sigwinch-chan))
(go-loop []
(let [{:keys [rows cols]} (<! sigwinch-chan)]
(redraw-editor rows cols)
(recur)))))
But you can at least hook in stty size
to the ESC ESC
, and maybe put on a toggleable timer.
Also:
; (:require [clojure.java.shell :refer [sh]]
(defn get-terminal-size []
(let [size (sh "stty" "size")]
(mapv #(Integer/parseInt %) (re-seq #"\d+" (:out size)))))
#?(:clj
(try ; just ignore if class not found
(let [
signal-class (Class/forName "sun.misc.Signal")
winch-signal (new sun.misc.Signal "WINCH")]
(.handle sun.misc.Signal winch-signal (reify sun.misc.SignalHandler (handle [_ _] (redraw)))))
(catch Exception e)))
I've tried it and it works triggering when the terminal size changes.
This actually doesn't work at all with new versions of Java, which make these internal classes inaccessible.
To solve this in my copy of Liquid, I use the following (while requiring editor
):
(defn- future-check-size-change [rs cs]
(future (Thread/sleep 100)
(let [rs2 (rows) cs2 (cols)]
(if (or (not= rs rs2) (not= cs cs2))
(do (editor/paint-all-buffer-groups) (editor/paint-buffer)))
(future-check-size-change rs2 cs2))))
(def ^:private checking-size (atom nil))
(defn get-dimensions
[]
(let [rs (rows) cs (cols)]
(if (not @checking-size)
(do
(reset! checking-size true)
(future-check-size-change rs cs)))
{:rows rs :cols cs}))
In my window manager, i3, the shape of the terminal changes over time, and so if I return to Liquid, it's all jumbled up. Can we just have a running autorefresh, or something similar?