That 256 Color Thing
Documentation at its lousiest.
The 256 color capabilities of color terminals must be one of the least documented features I have ever had the misfortune of digging through. Sure, there are many programs: vim, mutt, etc. which can take advantage of the extended palette, but how do I use it? ANSI color codes are hard enough to understand for an 8 coior system, for 256 colors, it’s a nightmare!
Anyway, after hours of poring over non-existent manuals stretching back to the time when color meant ink, and trying the same keywords in google again and again albeit in different orders, I think I’ve finally cracked the code. Here, I’ll be giving a run down of what a 256 color escape sequence looks like, and what you can do with them.
Although I may mention specifics about the terminal I use (rxvt-unicode) or the shell I use (zsh), nothing is really specific about them, everything can be duplicated on other terminals and shells, provided the capability is present.
Some Background
The basic output mechanism of a terminal is to display text. This text can have various properties, such as foreground color, background color, bold, italics, underline, etc. The original terminals, after which our current ones are designed, were serial devices. They couldn’t go back and forth in the input stream as they wished, they could only go one way: forward.
Because of this limitation, in order to display text of varying characteristics, it used a fairly simple mechanism called escape codes. These are characters, which are given in the input sequence, but are not displayed. Instead, they are a reminder to the terminal to do something special. The most common escape sequence, that almost every programmer should know about, is \n, which tells the terminal to display a new line.
Every change in state of text is indicated by an escape code. You send an escape code to tell the terminal to start printing text in bold, and another to stop. The same goes for colors, and other effects.
For the standard 8-color palette, these codes are fairly well documented. However, finding the codes for the 256 color palette, and furthermore the syntax in which they may be used, has driven me almost to distraction. It would seem that although they’ve managed to increase the number of colors, they haven’t added any more documentation in that direction.
Special Effects
There are a variety of effects that you can apply to text, but not all of them are supported on every terminal/emulator. The following are the most common:
- Reset: Reset all color settings to terminal default.
- Bold
- Italic
- Underline
- Blink: Doesn’t work when a background is set.
- Reverse: Swap foreground and background.
Colors are themselves special effects, but they need a different code, depending on whether they are to be applied on the foreground or the background.
Anatomy of a Color Code
The general structure of a color code is:
code :: ^[[(value)m
value :: (attributes);(foreground);(background)
attributes :: attribute;attributes
attribute :: 00|01|03|04|05|07|22|23|24|25|27
foreground :: 38;05;color
background :: 48;05;color
color :: 000-255
Note that that’s presented in a kind of grammar-y form. Also note that parentheses aren’t necessary, I’ve included them for readability; it doesn’t matter if you use them or not, as long as all numbers are separated by semicolons. You can also skip any leading zero anywhere, they aren’t necessary either.
Another caveat is the “m” in the “code”. Yes, it is a literal letter “m”. Also, the ^[[ is actually an “Escape” followed by an opening [. To get an Escape, press Control-V followed by the Escape Key. At least that’s the default way to get it. If you’ve changed the binding, then you should know what it is anyway. Otherwise, you should be able to use it’s numerical code, \033. Of course this means that you’ll have to enable backslash escapes.
The attribute codes mean the following, similar to the list in the previous section:
+--------------+----+
| Effect | # |
+--------------+----+
| Reset | 00 |
| Bold | 01 |
| Italic | 03 |
| Underline | 04 |
| Blink | 05 |
| Reverse | 07 |
| No Bold | 22 |
| No Italic | 23 |
| No Underline | 24 |
| No Blink | 25 |
| No Reverse | 27 |
+--------------+----+
The “No-” variations are codes to turn off the particular effect. They’re enormously useful if you have a lot of effects, you only want to turn off one and you don’t want to use reset followed by re-enabling everything else.
That’s pretty much all you need to start making use of them yourself. However, examples are always nice, so:
# Print text normally, in color 214, which happens to be a nice orange.
$> echo "^[[38;05;214mHello, World"
# Make the same text bold.
$> echo "^[[(01);(38;05;214)mHello, World"
# Print underlined and italicized text, with normal foreground, and blue
# background.
$> echo "^[[(03;04);(48;05;20)mHello, World"
# Bold, blinking purple text.
$> echo "^[[(01;05);(38;05;93)mHello, World"
# Simple purple text on yellow background.
$> echo "^[[(38;05;93);(48;05;226)mHello, World"
A Note on Prompt Usage
If you want to use these colors and effects in your prompt, you can do so, but you will need to wrap each color code in a %{%} construct. This tells the shell that everything in between should not actually be printed, and terminal space should not be reserved for those characters.
Spectrum, a ZSH Abstraction
I’ve abstracted these codes and put them together in a zsh function which I call spectrum. The code for spectrum can be found as part of my ~/etc, at my GitHub.
To use, first either source or autoload-and-run the spectrum script. It will set up three mappings, FX, FG and BG. FX is a mapping from effect names to their corresponding codes, and FG and BG are mappings from color number to codes. All numbers are 0-padded to 3 digits, so if you want light blue, use $FG[000]. The source is quite readable, take a look. Note that you can’t run the script, as this would execute it in a different shell, and the changes wouldn’t stick.
The above examples then, could be replicated as follows:
# Provided spectrum is in your $fpath,
$> autoload spectrum && spectrum
# Print text normally, in color 214, which happens to be a nice orange.
$> echo "$FG[214]Hello, World"
# Make the same text bold.
$> echo "$FX[bold]$FG[214]Hello, World"
# Print underlined and italicized text, with normal foreground, and blue
# background.
$> echo "$FX[italic]$FX[underline]$BG[020]Hello, World"
# Bold, blinking purple text.
$> echo "$FX[bold]$FX[blink]$FG[093]Hello, World"
# Simple purple text on yellow background.
$> echo "$FG[093]$BG[226]Hello, World"




Thank God I found this, I would’ve been searching for hours!
If anyone stumbles across this looking for the $LS_COLORS syntax, it’s slightly different. You’d use ‘di=(38;05;39)’ rather than ‘di=^[[38;05;39’.
You’re right, I didn’t mention the LS_COLOR syntax. It doesn’t need the actual escape characters, since ls inserts it by itself.
I’ll update in a bit.
Thanks.
Gee, I keep coming back for more. Zsh has a built-in abstraction for color codes, which I’ve found to be more portable (e.g. doesn’t break the default OS X terminal, or other 8-color monstrosities). Thus:
PROMPT='%{^[[38;05;253m%}%n@%m %{^[[38;05;156m%}%~ %{^[[38;05;253m%}%# %{^[[38;05;231m %}'Can be rewritten as:
Although 256 color is an option, I’d rather override the 8(16 including dull/bright) colors locally with fully specified RGB colors in #000000 format. I wish there was a terminal that supported some sort of full RGB color while preserving backwards compatibility.