REPL(僕は CLISP を使ってる)に表示される文字は基本モノトーンだよね?
何かメッセージを表示するときに文字の色を選べたら便利だなと思って探していたら案の定作ってる人がいた。
ただ個人的に必要な部分とそうでない部分があって、あと、何よりどうやって文字色を変えてるのかやり方が知りたかったので、CL-RAINBOW のソースコードを拝見させてもらって、自分用の関数を実装した。
つまるところ、肝の部分を凝縮するとこういうことだ。
;; "aaa" という文字列を太文字(foreground: bold)で印字 (format t "~C[~Am~A~C[0m" (code-char #o33) "1" "aaa" (code-char #o33))
文字色、文字の表示形式(文字の太さ、アンダーラインの有無)を変更したりと言っても何か特別なことをしてるわけじゃなくて、単にシェル(この場合はイコールREPL)がそう認識できるようなメタ文字で文字列の該当部分を囲ってやればいい。
関数はこんな感じ。
;; 補助マクロで Paul Graham のaif を定義してる。 ;; このマクロは if の評価結果を、 ;; 変数 it が補足するアナフォリックマクロ。 ;; すごく便利だからよく使う。 (defmacro aif (test then &optional else) `(let ((it ,test)) (if it ,then ,else))) ;; で、これが本体。 (defun style (style-sym str) ;; (style 'red "aaaaa") (let* ((lib '((black . "38;5;0") (red . "38;5;1") (green . "38;5;2") (yellow . "38;5;3") (blue . "38;5;4") (pink . "38;5;5") ;; magenta (cyan . "38;5;6") (b . 1) ;; bright bold (u . 4) ;; underline (inverse . 7))) ;; 反転 (code (aif (cdr (assoc style-sym lib)) it 0)) (esc (code-char #o33))) (format nil "~C[~Am~A~C[0m" esc code str esc)))
こんな感じで呼び出す。
(format t "~A ~A" (style 'red "WARNING:") (style 'u "foo doesn't work...")) -> WARNING: foo doesn't work...
面白いのは、これをそのままプレーンテキストに書き出して、cat コマンドなどで読み込むと、シェルが文字の表示形式を認識してくれる。