fix: backend-size returns both cols and rows via multi-value-bind (or discards secondary values)
The OR pattern inside backend-size used (or (multiple-value-bind ...) ...), but multiple-value-bind only returns the primary value of its body. When the env-var shortcut was removed, both calls to backend-size (the cols nth-value 0 and rows nth-value 1) returned the same primary value, making rows always nil. Restructure with nested multiple-value-bind/values chains so both return values propagate correctly through all fallback stages. Also remove MY_TERM_COLS/ROWS env-var pre-check — it returned stale startup dimensions after terminal resize.
This commit is contained in:
@@ -820,68 +820,61 @@ No-op — simple backend has no terminal state to restore.
|
||||
Queries actual terminal dimensions through a fallback chain, with
|
||||
a hard-coded 80x24 at the end:
|
||||
|
||||
1. **Env var pre-check** — ~MY_TERM_COLS~ / ~MY_TERM_ROWS~, set by the
|
||||
calling script before ~exec sbcl~. Checked with ~return-from~ so that
|
||||
/both/ values are preserved (Common Lisp's ~or~ discards secondary
|
||||
values).
|
||||
2. **ioctl on fd 0 (stdin)** — the parent's real terminal fd.
|
||||
3. **ioctl on stdout** — fast and correct after SIGWINCH at runtime.
|
||||
4. **ioctl on ~/dev/tty~** — fallback when stdin/stdout are pipes.
|
||||
5. **~(values 80 24)~** — last resort.
|
||||
1. **ioctl on fd 0 (stdin)** — the parent's real terminal fd.
|
||||
2. **ioctl on stdout** — fast and correct after SIGWINCH at runtime.
|
||||
3. **ioctl on ~/dev/tty~** — fallback when stdin/stdout are pipes.
|
||||
4. **~(values 80 24)~** — last resort.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/backend/simple.lisp
|
||||
(defmethod backend-size ((b simple-backend))
|
||||
;; MY_TERM_COLS/MY_TERM_ROWS — set by the calling script.
|
||||
;; Check with return-from to preserve both values.
|
||||
(let ((cstr (sb-ext:posix-getenv "MY_TERM_COLS"))
|
||||
(rstr (sb-ext:posix-getenv "MY_TERM_ROWS")))
|
||||
(when (and cstr rstr)
|
||||
(let ((cols (parse-integer cstr :junk-allowed t))
|
||||
(rows (parse-integer rstr :junk-allowed t)))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(return-from backend-size (values cols rows))))))
|
||||
(or ;; ioctl on fd 0 (stdin) — the parent's own terminal.
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl 0 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((c (sb-alien:deref winsize 1))
|
||||
(r (sb-alien:deref winsize 0)))
|
||||
(when (and c r (> c 0) (> r 0))
|
||||
(values c r)))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)))
|
||||
;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime.
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)))
|
||||
;; Try ioctl on fd 0 (stdin), then stdout, then /dev/tty, then 80x24.
|
||||
;; Use multiple-value-bind/values to preserve both cols and rows
|
||||
;; (or discards secondary values).
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(values 80 24)))
|
||||
(let ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl 0 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((c (sb-alien:deref winsize 1))
|
||||
(r (sb-alien:deref winsize 0)))
|
||||
(when (and c r (> c 0) (> r 0))
|
||||
(values c r)))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
;; ioctl on stdout fd
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
;; Direct ioctl on /dev/tty
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
(values 80 24))))))))
|
||||
#+END_SRC
|
||||
|
||||
*** Backend Write (Simple)
|
||||
|
||||
@@ -642,59 +642,48 @@ is responsible for redrawing the full screen after resume.
|
||||
(values))
|
||||
#+END_SRC
|
||||
|
||||
** Backend-size via ioctl and env vars
|
||||
** Backend-size via ioctl
|
||||
|
||||
*** backend-size
|
||||
|
||||
Uses a fallback chain to determine terminal dimensions:
|
||||
|
||||
1. **Env var pre-check** — ~MY_TERM_COLS~ / ~MY_TERM_ROWS~, set by
|
||||
the calling script before ~exec sbcl~. Uses ~return-from~ to preserve
|
||||
both values (~or~ discards secondary values).
|
||||
2. **ioctl on stdout** — fast, correct after SIGWINCH at runtime.
|
||||
3. **ioctl on ~/dev/tty~** — fallback when stdout is not a terminal.
|
||||
4. **~(values 80 24)~** — last resort.
|
||||
Uses ioctl (TIOCGWINSZ = 21523) to query actual terminal dimensions
|
||||
from the kernel, with a ~/dev/tty~ fallback and 80x24 last resort.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/backend/modern.lisp
|
||||
(defmethod backend-size ((b modern-backend))
|
||||
;; MY_TERM_COLS/MY_TERM_ROWS — set by the calling script.
|
||||
;; Check FIRST with return-from so both values (cols and rows)
|
||||
;; are preserved (or discards secondaries).
|
||||
(let ((cstr (sb-ext:posix-getenv "MY_TERM_COLS"))
|
||||
(rstr (sb-ext:posix-getenv "MY_TERM_ROWS")))
|
||||
(when (and cstr rstr)
|
||||
(let ((cols (parse-integer cstr :junk-allowed t))
|
||||
(rows (parse-integer rstr :junk-allowed t)))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(return-from backend-size (values cols rows))))))
|
||||
(or
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1) ;; cols
|
||||
(sb-alien:deref winsize 0)))) ;; rows
|
||||
(sb-alien:free-alien winsize))))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)))
|
||||
;; Direct ioctl on /dev/tty.
|
||||
;; Try ioctl on stdout, fall back to /dev/tty, then 80x24.
|
||||
;; Each arm uses multiple-value-bind/values to preserve both cols and rows
|
||||
;; (or discards secondary values, so we avoid it for multi-value returns).
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((cols (sb-alien:deref winsize 1))
|
||||
(rows (sb-alien:deref winsize 0)))
|
||||
(values cols rows)))))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(values 80 24)))
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1) ;; cols
|
||||
(sb-alien:deref winsize 0)))) ;; rows
|
||||
(sb-alien:free-alien winsize))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
;; Direct ioctl on /dev/tty.
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((cols (sb-alien:deref winsize 1))
|
||||
(rows (sb-alien:deref winsize 0)))
|
||||
(values cols rows)))))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
(values 80 24))))))
|
||||
#+END_SRC
|
||||
|
||||
** Capability query and write
|
||||
|
||||
@@ -162,44 +162,39 @@ as a fallback when a keyword is not in *named-colors*.")
|
||||
(values))
|
||||
|
||||
(defmethod backend-size ((b modern-backend))
|
||||
;; MY_TERM_COLS/MY_TERM_ROWS — set by the calling script.
|
||||
;; Check FIRST with return-from so both values (cols and rows)
|
||||
;; are preserved (or discards secondaries).
|
||||
(let ((cstr (sb-ext:posix-getenv "MY_TERM_COLS"))
|
||||
(rstr (sb-ext:posix-getenv "MY_TERM_ROWS")))
|
||||
(when (and cstr rstr)
|
||||
(let ((cols (parse-integer cstr :junk-allowed t))
|
||||
(rows (parse-integer rstr :junk-allowed t)))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(return-from backend-size (values cols rows))))))
|
||||
(or
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1) ;; cols
|
||||
(sb-alien:deref winsize 0)))) ;; rows
|
||||
(sb-alien:free-alien winsize))))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)))
|
||||
;; Direct ioctl on /dev/tty.
|
||||
;; Try ioctl on stdout, fall back to /dev/tty, then 80x24.
|
||||
;; Each arm uses multiple-value-bind/values to preserve both cols and rows
|
||||
;; (or discards secondary values, so we avoid it for multi-value returns).
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((cols (sb-alien:deref winsize 1))
|
||||
(rows (sb-alien:deref winsize 0)))
|
||||
(values cols rows)))))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(values 80 24)))
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1) ;; cols
|
||||
(sb-alien:deref winsize 0)))) ;; rows
|
||||
(sb-alien:free-alien winsize))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
;; Direct ioctl on /dev/tty.
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((cols (sb-alien:deref winsize 1))
|
||||
(rows (sb-alien:deref winsize 0)))
|
||||
(values cols rows)))))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
(values 80 24))))))
|
||||
|
||||
(defmethod backend-write ((b modern-backend) string)
|
||||
(let ((stream (backend-output-stream b)))
|
||||
|
||||
@@ -22,57 +22,54 @@
|
||||
(values))
|
||||
|
||||
(defmethod backend-size ((b simple-backend))
|
||||
;; MY_TERM_COLS/MY_TERM_ROWS — set by the calling script.
|
||||
;; Check with return-from to preserve both values.
|
||||
(let ((cstr (sb-ext:posix-getenv "MY_TERM_COLS"))
|
||||
(rstr (sb-ext:posix-getenv "MY_TERM_ROWS")))
|
||||
(when (and cstr rstr)
|
||||
(let ((cols (parse-integer cstr :junk-allowed t))
|
||||
(rows (parse-integer rstr :junk-allowed t)))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(return-from backend-size (values cols rows))))))
|
||||
(or ;; ioctl on fd 0 (stdin) — the parent's own terminal.
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl 0 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((c (sb-alien:deref winsize 1))
|
||||
(r (sb-alien:deref winsize 0)))
|
||||
(when (and c r (> c 0) (> r 0))
|
||||
(values c r)))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)))
|
||||
;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime.
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(when (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)))
|
||||
;; Try ioctl on fd 0 (stdin), then stdout, then /dev/tty, then 80x24.
|
||||
;; Use multiple-value-bind/values to preserve both cols and rows
|
||||
;; (or discards secondary values).
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(values 80 24)))
|
||||
(let ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl 0 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(let ((c (sb-alien:deref winsize 1))
|
||||
(r (sb-alien:deref winsize 0)))
|
||||
(when (and c r (> c 0) (> r 0))
|
||||
(values c r)))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
;; ioctl on stdout fd
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(unwind-protect
|
||||
(let ((ok (sb-unix:unix-ioctl
|
||||
(sb-sys:fd-stream-fd (backend-output-stream b))
|
||||
21523 (sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
;; Direct ioctl on /dev/tty
|
||||
(multiple-value-bind (cols rows)
|
||||
(ignore-errors
|
||||
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
|
||||
(when (and tty-fd (numberp tty-fd) (> tty-fd 0))
|
||||
(unwind-protect
|
||||
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
|
||||
(let ((ok (sb-unix:unix-ioctl tty-fd 21523
|
||||
(sb-alien:alien-sap winsize))))
|
||||
(when ok
|
||||
(values (sb-alien:deref winsize 1)
|
||||
(sb-alien:deref winsize 0))))
|
||||
(sb-alien:free-alien winsize))
|
||||
(sb-unix:unix-close tty-fd)))))
|
||||
(if (and cols rows (> cols 0) (> rows 0))
|
||||
(values cols rows)
|
||||
(values 80 24))))))))
|
||||
|
||||
(defmethod backend-write ((b simple-backend) string)
|
||||
(let ((stream (backend-output-stream b)))
|
||||
|
||||
Reference in New Issue
Block a user