Mark Karpov
Mark Karpov

Reputation: 7599

Use char-codes in strings

I'm working on a terminal program under Linux. I consider adding colorized output.

The task is not really hard, so I succeeded with the following:

[3]> (format t "~a[1;31mred text~a[0m" #\escape #\escape)
red text ; this text is really red and bold in terminal ;-)
NIL

But the code is ugly: I don't know how to put char #\escape (decimal value 27) into a string in 'inline' fashion. For example C++ code from this thread:

cout << "\033[1;31mbold red text\033[0m\n";

Here is #\Escape as \033 (octal). Is there something similar in Common Lisp?

My effort naïf doesn't work as intended:

[4]> (format t "#\escape1;31mred test#\escape[0m")
#escape1;31mred test#escape[0m
NIL

Upvotes: 3

Views: 540

Answers (1)

Joshua Taylor
Joshua Taylor

Reputation: 85823

You can type the characters manually…

You don't have to do anything special to have the control characters (or other "unusual" characters) in your strings. You just need to be able to type them into the editor. How easy it will be will depend on your editor. In Emacs, and in at least some terminal emulators, you can press Ctrl-Q followed by another character to insert that character literally. Thus, you can press Ctrl-Q followed by Escape to insert a literal #\escape character. How it appears will depend on the terminal emulator or editor. In my terminal, the literal Escape character is displayed as ^[. Thus, I end up with:

(format t "^[[1;31mhello^[[0!")
;          **           **     
;         result of C-Q Esc

This gives me some red text, as in your example:

enter image description here

…or use a library to make it easier!

If you don't want your source to contain characters that might not be easily readable, you might look into something like Edi Weitz's CL-INTERPOL:

CL-INTERPOL is a library for Common Lisp which modifies the reader so that you can have interpolation within strings similar to Perl or Unix Shell scripts. It also provides various ways to insert arbitrary characters into literal strings even if your editor/IDE doesn't support them. Here's an example:

* (let ((a 42))
    #?"foo: \xC4\N{Latin capital letter U with diaeresis}\nbar: ${a}")
"foo: ÄÜ
bar: 42"

Using CL-INTERPOL, this becomes easy:

* (interpol:enable-interpol-syntax)

* (format t #?"\e[1;31mhello\e[0m!")
hello!                                ; there's color here, honest!
NIL

Upvotes: 4

Related Questions