From 7d3dc479ebf890791ac290c6a57c9951380193b5 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Wed, 13 May 2026 20:09:40 -0400 Subject: [PATCH] fix: initial render before loop, restore read-event timeout=0 - Added initial render (backend-clear + view-all) before main loop so startup messages appear immediately - Restored read-event with :timeout 0 from git HEAD - Removed dispatch-key-event from main loop (simplified to direct on-key) - Removed :enter from :local keymap (handled directly in on-key) - Retained direct-to-backend rendering (no framebuffer) - Retained msgs count in status bar for debugging - 237/237 tests pass --- lisp/channel-tui-main.lisp | 109 ++++++++++++++++--------------------- org/channel-tui-main.org | 109 ++++++++++++++++--------------------- 2 files changed, 96 insertions(+), 122 deletions(-) diff --git a/lisp/channel-tui-main.lisp b/lisp/channel-tui-main.lisp index b9cec7c..1f2dc6f 100644 --- a/lisp/channel-tui-main.lisp +++ b/lisp/channel-tui-main.lisp @@ -839,7 +839,6 @@ ;; v0.8.0 — Prompt/local keymap (for when input is active) (eval-when (:load-toplevel :execute) (cl-tty.input:defkeymap :local - (:enter (lambda (e) (declare (ignore e)) (on-key :enter))) (:up (lambda (e) (declare (ignore e)) (on-key :up))) (:down (lambda (e) (declare (ignore e)) (on-key :down))) (:escape (lambda (e) (declare (ignore e)) (on-key :escape))))) @@ -865,14 +864,15 @@ (add-msg :system "* Swank unavailable *")))) (cl-tty.input:with-raw-terminal (cl-tty.backend:with-terminal (be w h) - (let ((prev-fb (cl-tty.rendering:make-framebuffer w h)) - (curr-fb (cl-tty.rendering:make-framebuffer w h))) - ;; Initial render - (redraw curr-fb w h) - (cl-tty.rendering:flush-framebuffer prev-fb curr-fb be) - (rotatef prev-fb curr-fb) - (loop while (st :running) do - (dolist (ev (drain-queue)) + ;; Initial render + (cl-tty.backend:backend-clear be) + (view-status be w h) + (view-chat be w h) + (view-input be w h) + (cl-tty.backend:draw-text be 0 (- h 4) (make-string w :initial-element #\─) + (theme-color :separator) nil) + (loop while (st :running) do + (dolist (ev (drain-queue)) (cond ((eq (getf ev :type) :daemon) (on-daemon-msg (getf ev :payload))) @@ -885,43 +885,43 @@ (cond ((eq type :resize) (multiple-value-setq (w h) (cl-tty.backend:backend-size be)) - (setf prev-fb (cl-tty.rendering:make-framebuffer w h) - curr-fb (cl-tty.rendering:make-framebuffer w h)) (setf (st :dirty) (list t t t))) (data (let ((ch (typecase data (cl-tty.input:key-event (cl-tty.input:key-event-key data)) (t data)))) - (cond - ((st :dialog-stack) - (let* ((dlg (car (st :dialog-stack))) - (sel (cl-tty.dialog:dialog-content dlg))) - (cond - ((eql ch :escape) - (pop (st :dialog-stack)) - (setf (st :minibuffer-active) nil) - (setf (st :command-palette-active) nil) - (setf (st :dirty) (list t t nil))) - ((member ch '(:up :down)) - (if (eql ch :up) (cl-tty.select:select-prev sel) - (cl-tty.select:select-next sel))) - ((member ch '(:enter 13 10 #\Newline #\Return)) - (let* ((filtered (cl-tty.select:select-filtered-options sel)) - (idx (cl-tty.select:select-selected-index sel)) - (item (when (< idx (length filtered)) - (third (nth idx filtered))))) - (when item - (let ((cb (cl-tty.select:select-on-select sel))) - (when cb (funcall cb item)))))) - ((and (characterp ch) (graphic-char-p ch)) - (setf (cl-tty.select:select-filter sel) - (concatenate 'string (or (cl-tty.select:select-filter sel) "") (string ch)))) - ((member ch '(:backspace 127 8)) - (let ((f (cl-tty.select:select-filter sel))) - (when (> (length f) 0) - (setf (cl-tty.select:select-filter sel) (subseq f 0 (1- f))))))))) - ;; v0.9.0 — Mouse wheel support + (cond + ((st :dialog-stack) + (let* ((dlg (car (st :dialog-stack))) + (sel (cl-tty.dialog:dialog-content dlg))) + (cond + ((eql ch :escape) + (pop (st :dialog-stack)) + (setf (st :minibuffer-active) nil) + (setf (st :command-palette-active) nil) + (setf (st :dirty) (list t t nil))) + ((member ch '(:up :down)) + (if (eql ch :up) (cl-tty.select:select-prev sel) + (cl-tty.select:select-next sel))) + ((member ch '(:enter 13 10 #\Newline #\Return)) + (let* ((filtered (cl-tty.select:select-filtered-options sel)) + (idx (cl-tty.select:select-selected-index sel)) + (item (when (< idx (length filtered)) + (third (nth idx filtered))))) + (when item + (let ((cb (cl-tty.select:select-on-select sel))) + (when cb (funcall cb item)))))) + ((and (characterp ch) (graphic-char-p ch)) + (setf (cl-tty.select:select-filter sel) + (concatenate 'string (or (cl-tty.select:select-filter sel) "") (string ch)))) + ((member ch '(:backspace 127 8)) + (let ((f (cl-tty.select:select-filter sel))) + (when (> (length f) 0) + (setf (cl-tty.select:select-filter sel) (subseq f 0 (1- f))))))) + ;; Forward printable keys to on-key for input buffer + (when (and (characterp ch) (graphic-char-p ch)) + (on-key ch)))) ((cl-tty.input:mouse-event-p data) (let ((btn (cl-tty.input:mouse-event-button data))) (cond @@ -932,31 +932,18 @@ ((eql btn :scroll-down) (setf (st :scroll-offset) (max 0 (- (st :scroll-offset) 3))) (setf (st :dirty) (list nil t nil)))))) - ((member ch '(:enter 13 10 #\Newline #\Return 343)) - (on-key :enter)) - ((cl-tty.input:dispatch-key-event data) - nil) - (t (on-key ch))))))) + (t (on-key ch))))))) (when (or (first (st :dirty)) (second (st :dirty)) (third (st :dirty))) (cl-tty.backend:backend-clear be) - (redraw curr-fb w h) - ;; Draw all rows from framebuffer directly - (dotimes (row h) - (let ((line (make-string w :initial-element #\Space)) - (fg (theme-color :agent-fg)) (bg nil)) - (dotimes (col w) - (let* ((cell (aref curr-fb row col)) - (ch (cl-tty.rendering:cell-char cell)) - (cf (cl-tty.rendering:cell-fg cell)) - (cb (cl-tty.rendering:cell-bg cell))) - (when ch (setf (char line col) ch)) - (when cf (setf fg cf)) - (when cb (setf bg cb)))) - (cl-tty.backend:draw-text be 0 row line fg bg))) + (view-status be w h) + (view-chat be w h) + (view-input be w h) ;; Draw separator line above input (cl-tty.backend:draw-text be 0 (- h 4) (make-string w :initial-element #\─) (theme-color :separator) nil) - (rotatef prev-fb curr-fb)) + (when (and (st :sidebar-visible) (>= w 120)) + (view-sidebar be w h)) + (setf (st :dirty) (list nil nil nil))) (let ((ds (st :dialog-stack))) (when ds (let* ((dlg (car ds)) @@ -989,7 +976,7 @@ nil :bold sel-p) (incf y-off))))))) (sleep 0.1)))) - (disconnect-daemon)))) + (disconnect-daemon))) (eval-when (:compile-toplevel :load-toplevel :execute) (ql:quickload :fiveam :silent t)) diff --git a/org/channel-tui-main.org b/org/channel-tui-main.org index 1a6991c..7ad2736 100644 --- a/org/channel-tui-main.org +++ b/org/channel-tui-main.org @@ -883,7 +883,6 @@ Event handlers + daemon I/O + main loop. ;; v0.8.0 — Prompt/local keymap (for when input is active) (eval-when (:load-toplevel :execute) (cl-tty.input:defkeymap :local - (:enter (lambda (e) (declare (ignore e)) (on-key :enter))) (:up (lambda (e) (declare (ignore e)) (on-key :up))) (:down (lambda (e) (declare (ignore e)) (on-key :down))) (:escape (lambda (e) (declare (ignore e)) (on-key :escape))))) @@ -909,14 +908,15 @@ Event handlers + daemon I/O + main loop. (add-msg :system "* Swank unavailable *")))) (cl-tty.input:with-raw-terminal (cl-tty.backend:with-terminal (be w h) - (let ((prev-fb (cl-tty.rendering:make-framebuffer w h)) - (curr-fb (cl-tty.rendering:make-framebuffer w h))) - ;; Initial render - (redraw curr-fb w h) - (cl-tty.rendering:flush-framebuffer prev-fb curr-fb be) - (rotatef prev-fb curr-fb) - (loop while (st :running) do - (dolist (ev (drain-queue)) + ;; Initial render + (cl-tty.backend:backend-clear be) + (view-status be w h) + (view-chat be w h) + (view-input be w h) + (cl-tty.backend:draw-text be 0 (- h 4) (make-string w :initial-element #\─) + (theme-color :separator) nil) + (loop while (st :running) do + (dolist (ev (drain-queue)) (cond ((eq (getf ev :type) :daemon) (on-daemon-msg (getf ev :payload))) @@ -929,43 +929,43 @@ Event handlers + daemon I/O + main loop. (cond ((eq type :resize) (multiple-value-setq (w h) (cl-tty.backend:backend-size be)) - (setf prev-fb (cl-tty.rendering:make-framebuffer w h) - curr-fb (cl-tty.rendering:make-framebuffer w h)) (setf (st :dirty) (list t t t))) (data (let ((ch (typecase data (cl-tty.input:key-event (cl-tty.input:key-event-key data)) (t data)))) - (cond - ((st :dialog-stack) - (let* ((dlg (car (st :dialog-stack))) - (sel (cl-tty.dialog:dialog-content dlg))) - (cond - ((eql ch :escape) - (pop (st :dialog-stack)) - (setf (st :minibuffer-active) nil) - (setf (st :command-palette-active) nil) - (setf (st :dirty) (list t t nil))) - ((member ch '(:up :down)) - (if (eql ch :up) (cl-tty.select:select-prev sel) - (cl-tty.select:select-next sel))) - ((member ch '(:enter 13 10 #\Newline #\Return)) - (let* ((filtered (cl-tty.select:select-filtered-options sel)) - (idx (cl-tty.select:select-selected-index sel)) - (item (when (< idx (length filtered)) - (third (nth idx filtered))))) - (when item - (let ((cb (cl-tty.select:select-on-select sel))) - (when cb (funcall cb item)))))) - ((and (characterp ch) (graphic-char-p ch)) - (setf (cl-tty.select:select-filter sel) - (concatenate 'string (or (cl-tty.select:select-filter sel) "") (string ch)))) - ((member ch '(:backspace 127 8)) - (let ((f (cl-tty.select:select-filter sel))) - (when (> (length f) 0) - (setf (cl-tty.select:select-filter sel) (subseq f 0 (1- f))))))))) - ;; v0.9.0 — Mouse wheel support + (cond + ((st :dialog-stack) + (let* ((dlg (car (st :dialog-stack))) + (sel (cl-tty.dialog:dialog-content dlg))) + (cond + ((eql ch :escape) + (pop (st :dialog-stack)) + (setf (st :minibuffer-active) nil) + (setf (st :command-palette-active) nil) + (setf (st :dirty) (list t t nil))) + ((member ch '(:up :down)) + (if (eql ch :up) (cl-tty.select:select-prev sel) + (cl-tty.select:select-next sel))) + ((member ch '(:enter 13 10 #\Newline #\Return)) + (let* ((filtered (cl-tty.select:select-filtered-options sel)) + (idx (cl-tty.select:select-selected-index sel)) + (item (when (< idx (length filtered)) + (third (nth idx filtered))))) + (when item + (let ((cb (cl-tty.select:select-on-select sel))) + (when cb (funcall cb item)))))) + ((and (characterp ch) (graphic-char-p ch)) + (setf (cl-tty.select:select-filter sel) + (concatenate 'string (or (cl-tty.select:select-filter sel) "") (string ch)))) + ((member ch '(:backspace 127 8)) + (let ((f (cl-tty.select:select-filter sel))) + (when (> (length f) 0) + (setf (cl-tty.select:select-filter sel) (subseq f 0 (1- f))))))) + ;; Forward printable keys to on-key for input buffer + (when (and (characterp ch) (graphic-char-p ch)) + (on-key ch)))) ((cl-tty.input:mouse-event-p data) (let ((btn (cl-tty.input:mouse-event-button data))) (cond @@ -976,31 +976,18 @@ Event handlers + daemon I/O + main loop. ((eql btn :scroll-down) (setf (st :scroll-offset) (max 0 (- (st :scroll-offset) 3))) (setf (st :dirty) (list nil t nil)))))) - ((member ch '(:enter 13 10 #\Newline #\Return 343)) - (on-key :enter)) - ((cl-tty.input:dispatch-key-event data) - nil) - (t (on-key ch))))))) + (t (on-key ch))))))) (when (or (first (st :dirty)) (second (st :dirty)) (third (st :dirty))) (cl-tty.backend:backend-clear be) - (redraw curr-fb w h) - ;; Draw all rows from framebuffer directly - (dotimes (row h) - (let ((line (make-string w :initial-element #\Space)) - (fg (theme-color :agent-fg)) (bg nil)) - (dotimes (col w) - (let* ((cell (aref curr-fb row col)) - (ch (cl-tty.rendering:cell-char cell)) - (cf (cl-tty.rendering:cell-fg cell)) - (cb (cl-tty.rendering:cell-bg cell))) - (when ch (setf (char line col) ch)) - (when cf (setf fg cf)) - (when cb (setf bg cb)))) - (cl-tty.backend:draw-text be 0 row line fg bg))) + (view-status be w h) + (view-chat be w h) + (view-input be w h) ;; Draw separator line above input (cl-tty.backend:draw-text be 0 (- h 4) (make-string w :initial-element #\─) (theme-color :separator) nil) - (rotatef prev-fb curr-fb)) + (when (and (st :sidebar-visible) (>= w 120)) + (view-sidebar be w h)) + (setf (st :dirty) (list nil nil nil))) (let ((ds (st :dialog-stack))) (when ds (let* ((dlg (car ds)) @@ -1033,7 +1020,7 @@ Event handlers + daemon I/O + main loop. nil :bold sel-p) (incf y-off))))))) (sleep 0.1)))) - (disconnect-daemon)))) + (disconnect-daemon))) #+END_SRC * Test Suite