» A Guide to 256 Color Codes

A Guide to 256 Color Codes

Tuesday, April 22, 2014

To kick-start the new site, I’ve resurrected one of the more popular previous entries, albeit touched up, and at a new location. I apologize for all the broken links.

This article was originally published on November 10, 2009.

Terminal capabilities have some of the sparsest documentation I have ever had the misfortune of having to dig through. Popular terminal applications such as vim, emacs, mutt, etc. seem to make use of every last bit of a terminal’s flexibility, but exactly how they do that always appears to be a mystery.

Among these capabilities are those to display a 256 color pallette.

Most terminals can handle at least 16 colors (8, and a bold version of each), and the ANSI codes necessary to invoke them are already a mess. Getting a terminal to display 256 colors requires character gymnastics that are altogether incomprehensible.

After hours of poring over non-existent documentation stretching back to a time when color actually meant ink, I think I’ve identified a pattern. In this entry, I’ll be giving you a run-down on what a 256 color escape seqence looks like, and how you can use them1.

Terminal Basics

The primary function of a terminal is to display text. Terminals of yore were serial terminals – text came in as a stream, and the terminal had one pass to do whatever it needed to do. While this limitation probably derived from a lack of resources to store more than a small buffer, most of the terminals we use today are still built in this way, so that’s what we’re stuck with.

Terminals use a pattern of delimiters to mark-up regions of text with attributes, the same way an HTML document uses start and end tags to mark-up text in a document. However terminals usually can’t express attributes as rich as HTML, nor can they afford to include a sufficiently powerful parser to do so. The delimiters for terminal attributes are therefore extremely simple, and are known as escape-codes.

Every escape code is a sequence of characters which tell the terminal to do something special. The most common escape code is one you might be familiar with: \n. This tells the terminal to print a newline character instead of the literal characters \ followed by n.

For more complex text attributes such as foreground color, bold-ness, etc, the terminal keeps a small flag to remember which state it’s in. When it sees the turn-on-bold escape code, it sets that flag, and continues to display bold text until it’s given an escape code that tells it otherwise.

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 (Clear all text attributes, including color, effects, etc.)
  • Bold
  • Italic
  • Underline
  • Blink
  • 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 256 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

A few observations about the above:

  • The parentheses aren’t really necessary.
  • Any leading zeroes can be skipped.
  • That is a literal m in the code.
  • The ^[[ is an escape key (U+001B) followed by a literal [.

The attribute codes are one of the following:

Effect Code
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, on 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

$> echo "$FG[214]Hello, World"

# Make the same text bold.
$> echo "$FX[bold]$FG[214]Hello, World"

# 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"

  1. Although I might specifically mention my terminal (rxvt-unicode) or my shell (zsh), the information here is largely portable across all such terminals and shells.