diff --git a/src/backend/modern.lisp b/src/backend/modern.lisp index fa9fe2c..db4c992 100644 --- a/src/backend/modern.lisp +++ b/src/backend/modern.lisp @@ -162,25 +162,21 @@ as a fallback when a keyword is not in *named-colors*.") (values)) (defmethod backend-size ((b modern-backend)) - (or ;; stty size via subprocess — most reliable across all systems. - ;; Returns "ROWS COLS". stty size queries the terminal via ioctl, - ;; not stdin, so no :input redirection is needed. + (or ;; tput lines / tput cols via subprocess — most reliable across + ;; all systems. Each outputs a single number. Works in any + ;; subprocess context, no parsing complexity. (multiple-value-bind (cols rows) - (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 parts - (let ((a (parse-integer (first parts) :junk-allowed t)) - (b (when (cdr parts) (parse-integer (second parts) :junk-allowed t)))) - (if (and a b (> a 0) (> b 0)) - ;; stty returns "ROWS COLS" - (values b a) - ;; stty returned only one value — treat as cols - (when (and a (> a 0)) - (values a nil))))))) + (values + (ignore-errors + (parse-integer + (string-trim '(#\newline #\space) + (uiop:run-program '("tput" "cols") :output :string + :ignore-error-status t)))) + (ignore-errors + (parse-integer + (string-trim '(#\newline #\space) + (uiop:run-program '("tput" "lines") :output :string + :ignore-error-status t))))) (when (and cols rows (> cols 0) (> rows 0)) (values cols rows))) ;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime. diff --git a/src/backend/simple.lisp b/src/backend/simple.lisp index 7ce8a55..3a76769 100644 --- a/src/backend/simple.lisp +++ b/src/backend/simple.lisp @@ -22,21 +22,19 @@ (values)) (defmethod backend-size ((b simple-backend)) - (or ;; stty size via subprocess — most reliable across all systems. + (or ;; tput cols / tput lines via subprocess (multiple-value-bind (cols rows) - (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 parts - (let ((a (parse-integer (first parts) :junk-allowed t)) - (b (when (cdr parts) (parse-integer (second parts) :junk-allowed t)))) - (if (and a b (> a 0) (> b 0)) - (values b a) ; stty returns "ROWS COLS" - (when (and a (> a 0)) - (values a nil))))))) + (values + (ignore-errors + (parse-integer + (string-trim '(#\newline #\space) + (uiop:run-program '("tput" "cols") :output :string + :ignore-error-status t)))) + (ignore-errors + (parse-integer + (string-trim '(#\newline #\space) + (uiop:run-program '("tput" "lines") :output :string + :ignore-error-status t))))) (when (and cols rows (> cols 0) (> rows 0)) (values cols rows))) ;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime.