fix: use global vars for cat subprocess to avoid let* scope crash
Replaced (let* ((cat-proc ...) (tty-in ...)) ...) with global special variables *cat-proc* and *tty-in* with defvar declarations. The let* caused 'unbound variable' errors on Ctrl+Q because the lexical scope didn't extend to terminate-process. Global vars have indefinite scope and work reliably regardless of paren nesting.
This commit is contained in:
@@ -886,6 +886,9 @@ Event handlers + daemon I/O + main loop.
|
|||||||
(:down (lambda (e) (declare (ignore e)) (on-key :down)))
|
(:down (lambda (e) (declare (ignore e)) (on-key :down)))
|
||||||
(:escape (lambda (e) (declare (ignore e)) (on-key :escape)))))
|
(:escape (lambda (e) (declare (ignore e)) (on-key :escape)))))
|
||||||
|
|
||||||
|
(defvar *cat-proc* nil "Cat subprocess for keyboard input")
|
||||||
|
(defvar *tty-in* nil "Stream from cat subprocess stdout")
|
||||||
|
|
||||||
(defun tui-main ()
|
(defun tui-main ()
|
||||||
(init-state)
|
(init-state)
|
||||||
(load-history)
|
(load-history)
|
||||||
@@ -912,12 +915,14 @@ Event handlers + daemon I/O + main loop.
|
|||||||
;; bytes through a pipe that SBCL reads reliably.
|
;; bytes through a pipe that SBCL reads reliably.
|
||||||
;; stty -icanon -echo is set by the bash script before exec sbcl.
|
;; stty -icanon -echo is set by the bash script before exec sbcl.
|
||||||
;; A cat subprocess reads keyboard input from the terminal.
|
;; A cat subprocess reads keyboard input from the terminal.
|
||||||
(let* ((cat-proc (uiop:launch-program '("cat")
|
;; Global vars for cat subprocess — avoid lexical let* scope issue
|
||||||
|
(progn
|
||||||
|
(setq *cat-proc* (uiop:launch-program '("cat")
|
||||||
:output :stream
|
:output :stream
|
||||||
:input :interactive
|
:input :interactive
|
||||||
:stderr nil))
|
:stderr nil)
|
||||||
(tty-in (uiop:process-info-output cat-proc)))
|
*tty-in* (uiop:process-info-output *cat-proc*)))
|
||||||
(add-msg :system (format nil "* cat pid=~a *" (uiop:process-info-pid cat-proc)))
|
(add-msg :system (format nil "* cat pid=~a *" (uiop:process-info-pid *cat-proc*)))
|
||||||
;; Guard against nil w/h from backend-size
|
;; Guard against nil w/h from backend-size
|
||||||
(setq w (or (and (numberp w) (> w 0) w) 80)
|
(setq w (or (and (numberp w) (> w 0) w) 80)
|
||||||
h (or (and (numberp h) (> h 0) h) 24))
|
h (or (and (numberp h) (> h 0) h) 24))
|
||||||
@@ -990,7 +995,7 @@ Event handlers + daemon I/O + main loop.
|
|||||||
;; Keyboard reader: block on cat pipe with 0.1s timeout.
|
;; Keyboard reader: block on cat pipe with 0.1s timeout.
|
||||||
(handler-case
|
(handler-case
|
||||||
(sb-ext:with-timeout 0.1
|
(sb-ext:with-timeout 0.1
|
||||||
(let ((raw-ch (read-char tty-in nil nil)))
|
(let ((raw-ch (read-char *tty-in* nil nil)))
|
||||||
(when raw-ch
|
(when raw-ch
|
||||||
(let ((code (char-code raw-ch)))
|
(let ((code (char-code raw-ch)))
|
||||||
(queue-event
|
(queue-event
|
||||||
@@ -1064,12 +1069,12 @@ Event handlers + daemon I/O + main loop.
|
|||||||
(cond (cat (theme-color :dim))
|
(cond (cat (theme-color :dim))
|
||||||
(sel-p (theme-color :accent))
|
(sel-p (theme-color :accent))
|
||||||
(t (theme-color :agent-fg)))
|
(t (theme-color :agent-fg)))
|
||||||
nil :bold sel-p)
|
nil :bold sel-p)
|
||||||
(incf y-off)))))))
|
(incf y-off)))))))
|
||||||
(sleep 0.1))
|
(sleep 0.1))
|
||||||
(uiop:terminate-process cat-proc))
|
(uiop:terminate-process *cat-proc*))
|
||||||
(add-msg :system (format nil "* cat ~a ended *" (uiop:process-info-pid cat-proc))))
|
(add-msg :system (format nil "* cat ~a ended *" (uiop:process-info-pid *cat-proc*))))
|
||||||
(progn (disconnect-daemon))))
|
(progn (disconnect-daemon)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
* Test Suite
|
* Test Suite
|
||||||
|
|||||||
Reference in New Issue
Block a user