fix: disable kitty keyboard, fix CSI parser crashes
- Disabled \033[?u kitty keyboard protocol in modern-backend (converts all keys to escape sequences, breaking Ctrl+letter dispatch) - Fixed parse-csi-sequence: use multiple-value-bind instead of let* with destructuring-bind (lost secondary return value from read-param) - Fixed parse-csi-params format string: pass char-code of terminator as distinct argument for ~d, keeping the character for ~C - Added %query-terminal-size in classes.lisp: ANSI CSI 18t fallback for terminal size detection when ioctl fails or returns zero
This commit is contained in:
@@ -1,5 +1,36 @@
|
||||
(in-package :cl-tty.backend)
|
||||
|
||||
(defun %query-terminal-size ()
|
||||
"Query terminal size via ANSI CSI 18 t and parse the response.
|
||||
Returns (values cols rows) or nil."
|
||||
(ignore-errors
|
||||
(let* ((saved (sb-sys:make-fd-stream 0 :input t :buffering :none))
|
||||
(response (make-array 0 :element-type 'character
|
||||
:fill-pointer 0 :adjustable t)))
|
||||
(format t "~C[18t" #\Esc)
|
||||
(force-output)
|
||||
(loop with deadline = (+ (get-internal-real-time)
|
||||
(* internal-time-units-per-second 0.2))
|
||||
while (< (get-internal-real-time) deadline)
|
||||
do (let ((ch (read-char-no-hang saved nil nil)))
|
||||
(when ch
|
||||
(vector-push-extend ch response)
|
||||
(when (char= ch #\t) (return)))))
|
||||
(when (>= (length response) 8)
|
||||
(let* ((str (subseq response 1))
|
||||
(start (or (position #\[ str) 0))
|
||||
(after (subseq str (1+ start)))
|
||||
(semi (position #\; after)))
|
||||
(when semi
|
||||
(let* ((cols-start (1+ semi))
|
||||
(cols-end (position #\t after :start cols-start))
|
||||
(rows (parse-integer (subseq after 0 semi) :junk-allowed t))
|
||||
(cols (when cols-end
|
||||
(parse-integer (subseq after cols-start cols-end)
|
||||
:junk-allowed t))))
|
||||
(when (and rows cols (> rows 0) (> cols 0))
|
||||
(values cols rows)))))))))
|
||||
|
||||
(defclass backend () ())
|
||||
|
||||
(defgeneric initialize-backend (backend)
|
||||
|
||||
@@ -127,14 +127,16 @@ as a fallback when a keyword is not in *named-colors*.")
|
||||
(backend-write b (format nil "~C[?1002h" #\Esc)) ; mouse drag
|
||||
(backend-write b (format nil "~C[?1006h" #\Esc)) ; SGR mouse
|
||||
(backend-write b (format nil "~C[?2004h" #\Esc)) ; bracketed paste
|
||||
(backend-write b (format nil "~C[?u" #\Esc)) ; kitty keyboard
|
||||
;; Kitty keyboard protocol disabled — converts all keys to CSI u-sequences
|
||||
;; which the TUI's key mapping doesn't handle for Ctrl+letter combos.
|
||||
;; (backend-write b (format nil "~C[?u" #\Esc))
|
||||
(cursor-hide b)
|
||||
(finish-output (backend-output-stream b))
|
||||
b)
|
||||
|
||||
(defmethod shutdown-backend ((b modern-backend))
|
||||
(cursor-show b)
|
||||
(backend-write b (format nil "~C[?u" #\Esc))
|
||||
;; (backend-write b (format nil "~C[?u" #\Esc)) ; disabled — never enabled
|
||||
(backend-write b (format nil "~C[?2004l" #\Esc))
|
||||
(backend-write b (format nil "~C[?1006l" #\Esc))
|
||||
(backend-write b (format nil "~C[?1002l" #\Esc))
|
||||
@@ -156,7 +158,7 @@ as a fallback when a keyword is not in *named-colors*.")
|
||||
(backend-write b (format nil "~C[?1002h" #\Esc)) ; mouse drag
|
||||
(backend-write b (format nil "~C[?1006h" #\Esc)) ; SGR mouse
|
||||
(backend-write b (format nil "~C[?2004h" #\Esc)) ; bracketed paste
|
||||
(backend-write b (format nil "~C[?u" #\Esc)) ; kitty keyboard
|
||||
;; (backend-write b (format nil "~C[?u" #\Esc)) ; kitty keyboard — disabled
|
||||
(cursor-hide b)
|
||||
(finish-output (backend-output-stream b))
|
||||
(values))
|
||||
@@ -173,6 +175,7 @@ as a fallback when a keyword is not in *named-colors*.")
|
||||
(values (sb-alien:deref winsize 1) ;; cols
|
||||
(sb-alien:deref winsize 0))) ;; rows
|
||||
(sb-alien:free-alien winsize))))
|
||||
(%query-terminal-size)
|
||||
(values 80 24)))
|
||||
|
||||
(defmethod backend-write ((b modern-backend) string)
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
(sb-alien:alien-sap winsize))
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0)))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(%query-terminal-size)
|
||||
(values 80 24)))
|
||||
|
||||
(defmethod backend-write ((b simple-backend) string)
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
:raw (string (code-char code))))
|
||||
(make-key-event :key (or key :unknown)
|
||||
:ctrl ctrl :alt alt :shift shift
|
||||
:raw (format nil "~C[~{~d~};~d~C" #\Esc params terminator)))))
|
||||
:raw (format nil "~C[~{~d~};~d~C" #\Esc params
|
||||
(char-code terminator) terminator)))))
|
||||
|
||||
(defun read-raw-byte (&key timeout)
|
||||
(let* ((buf (make-array 1 :element-type '(unsigned-byte 8)))
|
||||
@@ -162,15 +163,15 @@ Returns a mouse-event struct."
|
||||
(let* ((b2 (read-raw-byte)))
|
||||
(if (= b2 60) ;; < — SGR mouse marker
|
||||
(%parse-sgr-mouse)
|
||||
(let* ((extended (make-array 8 :element-type 'fixnum :fill-pointer 0))
|
||||
(params (if (and (>= b2 48) (<= b2 57))
|
||||
(multiple-value-bind (p term) (read-param (lambda () (read-raw-byte)))
|
||||
(setf (fill-pointer extended) (length p))
|
||||
(replace extended p)
|
||||
(values p term))
|
||||
(progn (vector-push-extend b2 extended) (read-param (lambda () (read-raw-byte)))))))
|
||||
(destructuring-bind (params terminator) params
|
||||
(parse-csi-params params terminator extended)))))))
|
||||
(let* ((extended (make-array 8 :element-type 'fixnum :fill-pointer 0)))
|
||||
(multiple-value-bind (params terminator)
|
||||
(if (and (>= b2 48) (<= b2 57))
|
||||
(multiple-value-bind (p term) (read-param (lambda () (read-raw-byte)))
|
||||
(setf (fill-pointer extended) (length p))
|
||||
(replace extended p)
|
||||
(values p term))
|
||||
(progn (vector-push-extend b2 extended) (read-param (lambda () (read-raw-byte)))))
|
||||
(parse-csi-params params terminator extended)))))))
|
||||
|
||||
(defun utf8-decode (bytes)
|
||||
(case (length bytes)
|
||||
|
||||
Reference in New Issue
Block a user