diff --git a/src/backend/modern.lisp b/src/backend/modern.lisp index 348581b..17254a7 100644 --- a/src/backend/modern.lisp +++ b/src/backend/modern.lisp @@ -173,6 +173,19 @@ 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)))) + ;; stty size via subprocess — reliable on every Unix, bypasses + ;; SBCL's alien/ioctl quirks. Returns "ROWS COLS". + (ignore-errors + (let* ((out (uiop:run-program '("stty" "size") + :output :string + :ignore-error-status t)) + (parts (and out (uiop:split-string + (string-trim '(#\newline #\space) out))))) + (when (and parts (= (length parts) 2)) + (let ((rows (parse-integer (first parts) :junk-allowed t)) + (cols (parse-integer (second parts) :junk-allowed t))) + (when (and rows cols (> rows 0) (> cols 0)) + (values cols rows)))))) ;; Direct ioctl on /dev/tty — opens the real controlling terminal. (ignore-errors (let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0))) ; O_RDONLY diff --git a/src/backend/simple.lisp b/src/backend/simple.lisp index 0e6dcd0..9b1f479 100644 --- a/src/backend/simple.lisp +++ b/src/backend/simple.lisp @@ -33,7 +33,19 @@ (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)))) + ;; stty size via subprocess — reliable on every Unix. + (ignore-errors + (let* ((out (uiop:run-program '("stty" "size") + :output :string + :ignore-error-status t)) + (parts (and out (uiop:split-string + (string-trim '(#\newline #\space) out))))) + (when (and parts (= (length parts) 2)) + (let ((rows (parse-integer (first parts) :junk-allowed t)) + (cols (parse-integer (second parts) :junk-allowed t))) + (when (and rows cols (> rows 0) (> cols 0)) + (values cols rows)))))) (ignore-errors (let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0))) ; O_RDONLY (when (and tty-fd (numberp tty-fd) (> tty-fd 0))