fix: CSI escape detection for arrow keys, fix paren balance
- Add CSI escape sequence detection: when ESC (27) is received, poll for up to 20ms for the next bytes to detect arrow/home/end keys - Use listen+read-char polling (not nested with-timeout) to reliably collect multi-byte sequences while keeping standalone ESC responsive - Fix paren balance in main code block (2 extra opens from nested esc-seq forms needed matching closes)
This commit is contained in:
@@ -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*
|
||||
|
||||
Reference in New Issue
Block a user