Common Lisp cl-charms报‘终端不支持颜色’错误,如何启用彩色输出?
问题:cl-charms编译时提示“Your terminal does not support color”
使用cl-charms库编写终端颜色程序时,编译阶段收到错误提示Your terminal does not support color,但终端实际支持颜色。复现代码如下:
(require 'uiop) (load "~/.sbclrc") (ql:quickload :cl-charms) (defun start-color () (when (eql (charms/ll:has-colors) charms/ll:FALSE) (error "Your terminal does not support color.")) (let ((ret-code (charms/ll:start-color))) (if (= ret-code 0) T (error "start-color error ~s." ret-code)))) (eval-when (:load-toplevel :compile-toplevel :execute) (defconstant +black+ charms/ll:COLOR_BLACK) (defconstant +red+ charms/ll:COLOR_RED) (defconstant +green+ charms/ll:COLOR_GREEN) (defconstant +yellow+ charms/ll:COLOR_YELLOW) (defconstant +blue+ charms/ll:COLOR_BLUE) (defconstant +magenta+ charms/ll:COLOR_MAGENTA) (defconstant +cyan+ charms/ll:COLOR_CYAN) (defconstant +white+ charms/ll:COLOR_WHITE)) (defmacro define-color-pair ((name pair) foreground background) `(progn (start-color) (defparameter ,name (progn (charms/ll:init-pair ,pair ,foreground ,background) (charms/ll:color-pair ,pair))))) (define-color-pair (+white/blue+ 1) +white+ +blue+) (define-color-pair (+black/red+ 2) +black+ +red+) (defun draw-window-background (window color-pair) (charms/ll:wbkgd (charms::window-pointer window) color-pair)) (defmacro with-colors ((window color-pair) &body body) (let ((winptr (gensym))) (alexandria:once-only (color-pair) `(let ((,winptr (charms::window-pointer ,window))) (charms/ll:wattron ,winptr ,color-pair) ,@body (charms/ll:wattroff ,winptr ,color-pair))))) (defun pretty-hello-world () (charms:with-curses () (charms:disable-echoing) (charms:enable-raw-input) (start-color) (loop named hello-world with window = (charms:make-window 50 15 10 10) do (progn (charms:clear-window window) (draw-window-background window +white/blue+) (with-colors (window +white/blue+) (charms:write-string-at-point window "Hello world!" 0 0)) (with-colors (window +black/red+) (charms:write-string-at-point window "Hello world!" 0 1)) (charms:refresh-window window) ;; Process input (when (eql (charms:get-char window :ignore-error t) #\q) (return-from hello-world)) (sleep 0.1))))) (defun main () (pretty-hello-world)) (sb-ext:save-lisp-and-die "colors2.exe" :toplevel #'main :executable t)
问题原因
核心问题在于颜色对的初始化时机错误:
define-color-pair宏在编译/加载阶段就会执行start-color函数,而此时charms:with-curses()还未运行,curses库尚未初始化终端上下文。charms/ll:has-colors需要在curses完成终端初始化后,才能正确检测终端的颜色支持能力;未初始化时会直接返回FALSE,触发错误。
解决思路
将颜色对的初始化逻辑移到charms:with-curses()上下文内部,确保在curses完成终端初始化后再执行颜色相关操作,具体有两种实现方式:
方式1:修改宏逻辑,延迟初始化
- 修改
define-color-pair宏,只定义参数和初始化函数,不立即执行初始化:
(defmacro define-color-pair ((name pair) foreground background) `(progn (defparameter ,name nil) (defun ,(intern (format nil "INIT-~a" name)) () (charms/ll:init-pair ,pair ,foreground ,background) (setf ,name (charms:ll:color-pair ,pair)))))
- 在
pretty-hello-world的with-curses块内调用初始化函数:
(defun pretty-hello-world () (charms:with-curses () (charms:disable-echoing) (charms:enable-raw-input) (start-color) ;; 初始化颜色对 (init-+white/blue+) (init-+black/red+) ;; 后续原有逻辑不变...
方式2:直接在上下文内初始化颜色对
去掉define-color-pair宏的自动执行逻辑,直接在with-curses块内完成颜色对初始化:
(defun pretty-hello-world () (charms:with-curses () (charms:disable-echoing) (charms:enable-raw-input) (start-color) ;; 直接初始化颜色对 (charms/ll:init-pair 1 +white+ +blue+) (defparameter +white/blue+ (charms/ll:color-pair 1)) (charms/ll:init-pair 2 +black+ +red+) (defparameter +black/red+ (charms/ll:color-pair 2)) ;; 后续原有逻辑不变...
额外注意事项
- 若编译时仍触发错误,可将颜色对初始化代码放在
eval-when (:execute)块中,确保仅在程序运行时执行,而非编译阶段。 - 确认终端的
TERM环境变量设置正确(如xterm-256color),curses依赖该变量识别终端能力。
内容的提问来源于stack exchange,提问作者ben.qre
相关产品推荐
相关产品推荐

