(in-package :cl-tty.backend) (defclass simple-backend (backend) ((output-stream :initform *standard-output* :initarg :output-stream :accessor backend-output-stream))) (defun make-simple-backend (&key output-stream) (make-instance 'simple-backend :output-stream (or output-stream *standard-output*))) (defmethod initialize-backend ((b simple-backend)) b) (defmethod shutdown-backend ((b simple-backend)) (values)) (defmethod backend-size ((b simple-backend)) ;; Try ioctl, fall back to 80x24 (values 80 24)) (defmethod backend-write ((b simple-backend) string) (let ((stream (backend-output-stream b))) (write-string string stream) (finish-output stream) (length string))) (defmethod draw-text ((b simple-backend) x y string fg bg &key bold italic underline reverse dim blink) (declare (ignore x y fg bg bold italic underline reverse dim blink)) (backend-write b string)) (defun %simple-border-char (edge-style pos) "Return ASCII border character for EDGE-STYLE at POS. POS is :top-left, :top-right, :bottom-left, :bottom-right, :horizontal, or :vertical." (case pos ((:top-left :top-right :bottom-left :bottom-right) #\+) (:horizontal #\-) (:vertical #\|))) (defmethod draw-border ((b simple-backend) x y width height &key style fg bg title title-align) (declare (ignore style fg bg title title-align)) (let ((h (%simple-border-char nil :horizontal)) (v (%simple-border-char nil :vertical))) ;; Position cursor with newlines and spaces (no escape sequences) (dotimes (row y) (backend-write b (string #\Newline))) ;; Top edge (backend-write b (make-string x :initial-element #\space)) (backend-write b (make-string width :initial-element h)) ;; Sides (loop for i from 1 below (1- height) do (backend-write b (string #\Newline)) (backend-write b (make-string x :initial-element #\space)) (backend-write b (string v)) (backend-write b (make-string (- width 2) :initial-element #\space)) (backend-write b (string v))) ;; Bottom edge (backend-write b (string #\Newline)) (backend-write b (make-string x :initial-element #\space)) (backend-write b (make-string width :initial-element h)))) (defmethod draw-rect ((b simple-backend) x y width height &key bg) (declare (ignore x y width height bg)) ;; On simple backend, background fill is a no-op (values)) (defmethod draw-link ((b simple-backend) x y string url &key fg bg) (declare (ignore url fg bg)) (draw-text b x y string nil nil)) (defmethod draw-ellipsis ((b simple-backend) x y width &key fg bg) (declare (ignore x y width fg bg)) (backend-write b "..."))