1.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2+++ b/lisp/lib/cli/tests/ansi.lisp Tue Oct 01 22:29:08 2024 -0400
1.3@@ -0,0 +1,199 @@
1.4+;;; ansi.lisp --- ANSI Tests
1.5+
1.6+;;
1.7+
1.8+;;; Code:
1.9+(in-package :cli/tests)
1.10+(in-suite :cli)
1.11+
1.12+(defun ansi-t01 ()
1.13+ (erase)
1.14+ (cursor-position 0 0)
1.15+ (princ "0")
1.16+ (cursor-position 2 2)
1.17+ (princ "1")
1.18+ (cursor-position 5 15)
1.19+ (princ "test")
1.20+ (cursor-position 10 15)
1.21+ (force-output)
1.22+ (with-input-from-string (in (format nil "test~%~%"))
1.23+ (let ((a (read-line in)))
1.24+ (cursor-position 12 15)
1.25+ (princ a)
1.26+ (force-output))))
1.27+
1.28+(defun ansi-t02 ()
1.29+ (print "normal")
1.30+ (.sgr 1)
1.31+ (print "bold")
1.32+ (.sgr 4)
1.33+ (print "bold underline")
1.34+ (.sgr 7)
1.35+ (print "bold underline reverse")
1.36+ (.sgr 22)
1.37+ (print "underline reverse")
1.38+ (.sgr 24)
1.39+ (print "reverse")
1.40+ (.sgr 27)
1.41+ (print "normal")
1.42+ (.sgr 1 4 7)
1.43+ (print "bold underline reverse")
1.44+ (.sgr 0)
1.45+ (print "normal")
1.46+ (force-output))
1.47+
1.48+(defun ansi-t03 ()
1.49+ "Display the 256 color palette."
1.50+ (clear)
1.51+ (loop for i from 0 to 255 do
1.52+ (.sgr 48 5 i)
1.53+ (princ #\space))
1.54+ (terpri)
1.55+ (.sgr 0)
1.56+ (loop for i from 0 to 255 do
1.57+ (.sgr 38 5 i)
1.58+ (princ "X"))
1.59+ (.sgr 0)
1.60+ (force-output)
1.61+ ;; (sleep 3)
1.62+ (.ris)
1.63+ (force-output))
1.64+
1.65+(defun ansi-t04 ()
1.66+ "Hide and show the cursor."
1.67+ (princ "Cursor visible:")
1.68+ (force-output)
1.69+ ;; (sleep 2)
1.70+ (terpri)
1.71+ (princ "Cursor invisible:")
1.72+ (hide-cursor)
1.73+ (force-output)
1.74+ ;; (sleep 2)
1.75+ (terpri)
1.76+ (princ "Cursor visible:")
1.77+ (show-cursor)
1.78+ (force-output)
1.79+ ;; (sleep 2)
1.80+ )
1.81+
1.82+(defun ansi-t05 ()
1.83+ "Switch to and back from the alternate screen buffer."
1.84+ (princ "Normal screen buffer. ")
1.85+ (force-output)
1.86+ ;; (sleep 2)
1.87+ (save-cursor-position)
1.88+ (use-alternate-screen-buffer)
1.89+ (clear)
1.90+ (princ "Alternate screen buffer.")
1.91+ (force-output)
1.92+ ;; (sleep 2)
1.93+ (use-normal-screen-buffer)
1.94+ (restore-cursor-position)
1.95+ (princ "Back to Normal screen buffer.")
1.96+ (force-output)
1.97+ ;; (sleep 1)
1.98+ )
1.99+
1.100+(defun ansi-t06 ()
1.101+ "Set individual termios flags to enable raw and disable echo mode.
1.102+
1.103+Enabling raw mode allows read-char to return immediately after a key is pressed.
1.104+
1.105+In the default cooked mode, the entry has to be confirmed by pressing enter."
1.106+ (set-tty-mode t :ignbrk nil
1.107+ :brkint nil
1.108+ :parmrk nil
1.109+ :istrip nil
1.110+ :inlcr nil
1.111+ :igncr nil
1.112+ :icrnl nil
1.113+ :ixon nil
1.114+ :opost nil
1.115+ :echo nil
1.116+ :echonl nil
1.117+ :icanon nil
1.118+ :isig nil
1.119+ :iexten nil
1.120+ :csize nil
1.121+ :parenb nil
1.122+ :vmin 1
1.123+ :vtime 0)
1.124+ (erase)
1.125+ (cursor-position 1 1)
1.126+ (force-output)
1.127+ (let ((a (read-char)))
1.128+ (cursor-position 10 5)
1.129+ (princ a)
1.130+ (force-output))
1.131+
1.132+ (set-tty-mode t :echo t
1.133+ :brkint t
1.134+ :ignpar t
1.135+ :istrip t
1.136+ :icrnl t
1.137+ :ixon t
1.138+ :opost t
1.139+ :isig t
1.140+ :icanon t
1.141+ :veol 0))
1.142+
1.143+(defun ansi-t07 ()
1.144+ "Use combination modes that consist of several individual flags.
1.145+
1.146+Cooked and raw are opposite modes. Enabling cooked disbles raw and vice versa."
1.147+ (set-tty-mode t :cooked nil)
1.148+ (erase)
1.149+ (cursor-position 1 1)
1.150+ (force-output)
1.151+ (let ((a (read-char)))
1.152+ (cursor-position 3 1)
1.153+ (princ a)
1.154+ (force-output))
1.155+ (set-tty-mode t :raw nil))
1.156+
1.157+(defun ansi-t08 ()
1.158+ "Why doesnt calling the stty utility work?"
1.159+ (uiop:run-program "stty raw -echo" :ignore-error-status t)
1.160+ (erase)
1.161+ (cursor-position 1 1)
1.162+ (force-output)
1.163+ (let ((a (read-char)))
1.164+ (cursor-position 2 1)
1.165+ (princ a)
1.166+ (force-output))
1.167+ (uiop:run-program "stty -raw echo" :ignore-error-status t))
1.168+
1.169+(defun ansi-t09 ()
1.170+ "Query terminal size with ANSI escape sequences."
1.171+ ;; Put the terminal into raw mode so we can read the "user input"
1.172+ ;; of the reply char by char
1.173+ ;; Turn off the echo or the sequence will be displayed
1.174+ (set-tty-mode t :cooked nil :echo nil)
1.175+ (save-cursor-position)
1.176+ ;; Go to the bottom right corner of the terminal by attempting
1.177+ ;; to go to some high value of row and column
1.178+ (cursor-position 999 999)
1.179+ (let (chars)
1.180+ ;; The terminal returns an escape sequence to the standard input
1.181+ (device-status-report)
1.182+ (force-output)
1.183+ ;; The reply isnt immediately available, the terminal does need
1.184+ ;; some time to answer
1.185+ (sleep 0.1)
1.186+ ;; The reply has to be read as if the user typed an escape sequence
1.187+ (loop for i = (read-char-no-hang *standard-input* nil)
1.188+ until (null i)
1.189+ do (push i chars))
1.190+ ;; Put the terminal back into its initial cooked state
1.191+ (set-tty-mode t :raw nil :echo t)
1.192+ (restore-cursor-position)
1.193+ ;; Return the read sequence as a list of characters.
1.194+ (nreverse chars)))
1.195+
1.196+(deftest ansi ()
1.197+ (with-input-from-string (in (format nil "~%~%"))
1.198+ (ansi-t01)
1.199+ (ansi-t02)
1.200+ (ansi-t03)
1.201+ (ansi-t04)
1.202+ (ansi-t05)))