diff --git a/org/channel-tui-main.org b/org/channel-tui-main.org index b1d016a..3371c85 100644 --- a/org/channel-tui-main.org +++ b/org/channel-tui-main.org @@ -960,30 +960,49 @@ supplied (e.g. \"/\"), pre-fill the select filter with it." (setf (cl-tty.select:select-filter sel) (subseq f 0 (1- f)))))))) (on-key ch)))))))) - ;; Check for terminal resize (SIGWINCH sets this flag) - ;; Keyboard reader: block on cat pipe with 0.1s timeout. - (handler-case - (sb-ext:with-timeout 0.1 - (let ((raw-ch (read-char-no-hang *standard-input* nil nil))) - (when raw-ch - (let ((code (char-code raw-ch))) - (queue-event - (list :type :key - :payload (list :code code - :ch (cond - ((= code 13) :enter) - ((= code 10) :enter) - ((= code 27) :escape) - ((= code 9) :tab) - ((or (= code 127) (= code 8)) :backspace) - ((and (>= code 1) (<= code 26)) - (intern - (string-upcase - (format nil "CTRL-~a" - (code-char (+ #x60 code)))) - :keyword)) - (t code))))))))) - (sb-ext:timeout ())) + ;; Keyboard reader with CSI escape detection + (handler-case + (sb-ext:with-timeout 0.1 + (let* ((raw-ch (read-char-no-hang *standard-input* nil nil))) + (when raw-ch + (let* ((code (char-code raw-ch)) + (esc-seq (and (= code 27) + ;; Poll for up to 20ms to collect CSI bytes + (let ((b nil) (t2 nil)) + (dotimes (_ 20) + (when (listen *standard-input*) + (setq b (read-char *standard-input* nil nil)) + (return)) + (sleep 0.001)) + (and b (char= b #\[) + (dotimes (_ 10) + (when (listen *standard-input*) + (setq t2 (read-char *standard-input* nil nil)) + (return)) + (sleep 0.001)) + (case (and t2 (char-code t2)) + (65 :up) (66 :down) + (67 :right) (68 :left) + (72 :home) (70 :end) + (otherwise :escape)))))) + (queue-event + (list :type :key + :payload (list :code code + :ch (or esc-seq + (cond + ((= code 13) :enter) + ((= code 10) :enter) + ((= code 27) :escape) + ((= code 9) :tab) + ((or (= code 127) (= code 8)) :backspace) + ((and (>= code 1) (<= code 26)) + (intern + (string-upcase + (format nil "CTRL-~a" + (code-char (+ #x60 code)))) + :keyword)) + (t code))))))))))) + (sb-ext:timeout ())) ;; Check for terminal resize (SIGWINCH sets this flag) (when (boundp 'cl-tty.input::*terminal-resized-p*) (when cl-tty.input::*terminal-resized-p*