fix: ioctl on stdin fd (0) first, then stdout fd, then env vars

The user's terminal reports 186x60 via stty (which uses stdin fd)
and via COLUMNS/LINES, but ioctl on stdout's fd returns 80x24.
Priority: fd 0 → backend output fd → env vars → 80x24 fallback.
This commit is contained in:
2026-05-14 13:07:05 -04:00
parent 7813e27907
commit 4a86ae3274
2 changed files with 45 additions and 42 deletions

View File

@@ -164,19 +164,22 @@ as a fallback when a keyword is not in *named-colors*.")
(values)) (values))
(defmethod backend-size ((b modern-backend)) (defmethod backend-size ((b modern-backend))
(or (ignore-errors (flet ((ioctl-size (fd)
(let* ((+tiocgwinsz+ 21523) ; 0x5413 on Linux (let* ((+tiocgwinsz+ 21523) ; 0x5413 on Linux
(winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) (winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(unwind-protect (unwind-protect
(progn (progn
(sb-unix:unix-ioctl (sb-sys:fd-stream-fd (backend-output-stream b)) (sb-unix:unix-ioctl fd +tiocgwinsz+
+tiocgwinsz+
(sb-alien:alien-sap winsize)) (sb-alien:alien-sap winsize))
(values (sb-alien:deref winsize 1) ;; cols (values (sb-alien:deref winsize 1) ;; cols
(sb-alien:deref winsize 0))) ;; rows (sb-alien:deref winsize 0))) ;; rows
(sb-alien:free-alien winsize)))) (sb-alien:free-alien winsize)))))
;; $COLUMNS/$LINES fallback — some systems don't update the (or ;; Try ioctl on fd 0 first (stdin — stty uses this)
;; TTY size via ioctl on stdout's fd. (ignore-errors (ioctl-size 0))
;; Then try the output stream's fd
(ignore-errors
(ioctl-size (sb-sys:fd-stream-fd (backend-output-stream b))))
;; $COLUMNS/$LINES fallback — set by every POSIX shell
(ignore-errors (ignore-errors
(let* ((cstr (sb-ext:posix-getenv "COLUMNS")) (let* ((cstr (sb-ext:posix-getenv "COLUMNS"))
(rstr (sb-ext:posix-getenv "LINES")) (rstr (sb-ext:posix-getenv "LINES"))
@@ -184,7 +187,7 @@ as a fallback when a keyword is not in *named-colors*.")
(rows (when rstr (parse-integer rstr :junk-allowed t)))) (rows (when rstr (parse-integer rstr :junk-allowed t))))
(when (and cols rows (> cols 0) (> rows 0)) (when (and cols rows (> cols 0) (> rows 0))
(values cols rows)))) (values cols rows))))
(values 80 24))) (values 80 24))))
(defmethod backend-write ((b modern-backend) string) (defmethod backend-write ((b modern-backend) string)
(let ((stream (backend-output-stream b))) (let ((stream (backend-output-stream b)))

View File

@@ -27,19 +27,19 @@
(values)) (values))
(defmethod backend-size ((b simple-backend)) (defmethod backend-size ((b simple-backend))
(or (ignore-errors (flet ((ioctl-size (fd)
(let* ((+tiocgwinsz+ 21523) (let* ((+tiocgwinsz+ 21523)
(winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) (winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(unwind-protect (unwind-protect
(progn (progn
(sb-unix:unix-ioctl (sb-sys:fd-stream-fd (sb-unix:unix-ioctl fd +tiocgwinsz+
(backend-output-stream b))
+tiocgwinsz+
(sb-alien:alien-sap winsize)) (sb-alien:alien-sap winsize))
(values (sb-alien:deref winsize 1) (values (sb-alien:deref winsize 1)
(sb-alien:deref winsize 0))) (sb-alien:deref winsize 0)))
(sb-alien:free-alien winsize)))) (sb-alien:free-alien winsize)))))
;; $COLUMNS/$LINES fallback (or (ignore-errors (ioctl-size 0))
(ignore-errors
(ioctl-size (sb-sys:fd-stream-fd (backend-output-stream b))))
(ignore-errors (ignore-errors
(let* ((cstr (sb-ext:posix-getenv "COLUMNS")) (let* ((cstr (sb-ext:posix-getenv "COLUMNS"))
(rstr (sb-ext:posix-getenv "LINES")) (rstr (sb-ext:posix-getenv "LINES"))
@@ -47,7 +47,7 @@
(rows (when rstr (parse-integer rstr :junk-allowed t)))) (rows (when rstr (parse-integer rstr :junk-allowed t))))
(when (and cols rows (> cols 0) (> rows 0)) (when (and cols rows (> cols 0) (> rows 0))
(values cols rows)))) (values cols rows))))
(values 80 24))) (values 80 24))))
(defmethod backend-write ((b simple-backend) string) (defmethod backend-write ((b simple-backend) string)
(let ((stream (backend-output-stream b))) (let ((stream (backend-output-stream b)))