The Modern Programmer's Guide To ANSI Color Codes
As a user of Arch (btw) and neovim, I spend quite a bit of time in the terminal. I'm also most comfortable developing CLIs, rather than TUIs or GUIs or even APIs.
Contrary to what some people may believe, the terminal doesn't have to be all black and white (or black and green, if you're a totally l33t h4x0r). Some terminal emulators support up to 16,581,375 unique colours, and some neat font features too! It's just a matter of knowing how to use them.
Basic Control Sequence Syntax
All we need in order to use the full graphical capabilities of our terminal emulator is a basic understanding of ANSI control sequences, which can be likened to functions you can call by presenting them on the terminal emulator.
The first part of calling such a function is letting the terminal emulator know that what comes next isn't just arbitrary text. We do this with the Control Sequence Indicator (CSI), which is an ASCII escape control character followed by [. We can't exactly type an escape character using a standard keyboard, so instead we use \033, \x1b, or simply \e.
Next up come the arguments (yep, before the function name!). Functions take 0 or more arguments, which are decimal-encoded unsigned 8-bit integers, suffixed with ;. We'll get to the different arguments you can pass in just a moment.
The final part of our function's invocation is the name. These are generally letters. We're only concerned with the SGR (Select Graphics Rendition) function, which is <sarcasm>oh-so-clearly named</sarcasm> m.
So, the simplest invocation of the SGR function we can come up with is \e[0m, which will reset all graphics features to their defaults.
Colouring Text & Backgrounds
You can achieve some very basic text colouring with arguments 30-37. Each of these values represents a named colour, as shown in the table below. It's down to the terminal emulator, and often configurable by the user, which specific colours these show up as.
| Value | Name |
|---|---|
| 30 | Black |
| 31 | Red |
| 32 | Green |
| 33 | Yellow |
| 34 | Blue |
| 35 | Purple |
| 36 | Cyan |
| 37 | White |
You can perform some arithmetic on these numbers to brighten the colours or use them as the background instead of the foreground. Note that the bright variants are non-standard, and were originally implemented by aixterm.
| Operation | Effect |
|---|---|
| +10 | Use colour as background |
| +60 | Use bright variant |
| +70 | Use bright variant as background |
Colours can be taken a step further. Arguments 38;5;n (for some byte n) opens up a range of 255 colours, while arguments 38;2;r;g;b brings out all 16,581,375 RGB colours. Arguments 48;5;n and 48;2;r;g;b can also be used to apply these colours as background.
Text Decorations
Various other values can be passed as a single argument to the SGR function to achieve a variety of decorative effects. Note that not all terminal emulators support all features, so your mileage may vary with these.
| Value | Effect | Reversed By |
|---|---|---|
| 1 | Bold | 0, sometimes 21 |
| 2 | Dim | 22 |
| 3 | Italic | 23 |
| 4 | Underline | 24 |
| 5 | Slow blink | 25 |
| 6 | Fast blink | 25 |
| 7 | Invert colours | 27 |
| 8 | Invisible | 28 |
| 9 | Strikethrough | 29 |
| 10 | Default font | |
| 11-19 | Alternative fonts 1-9 | 10 |
| 20 | Fraktur, sometimes reverse bold (1) | 50 |
| 21 | Double-underline, sometimes reverse bold (1) | 24 |
| 26 | Proportional spacing (unused in terminals) | 50 |
| 39 | Default foreground colour | |
| 49 | Default background colour | |
| 51 | Framed | 54 |
| 52 | Encircled | 54 |
| 53 | Overlined | 55 |
| 58 | Set underline colour | 59 |
| 60 | Ideogram underline / right line | 65 |
| 61 | Ideogram double underline / double right | 65 |
| 62 | Ideogram overline / left line | 65 |
| 63 | Ideogram double overline / double left | 65 |
| 64 | Ideogram stress marking | 65 |
| 73 | Superscript | 75 |
| 74 | Subscript | 75 |
Most terminal emulators don't support Fraktur, a heavy calligraphic hand of the Latin alphabet, or blinking. A limited number support double-underline, frames, encircles, ideograms, and super/subscript.
Recommended Resources
I certainly wouldn't recommend spending 221 of your own Swiss Francs on ISO/IEC 6429, or even 177 of them on ISO/IEC 2022. And I'll be honest, ECMA 48 is a little dry, and JIS X 0211 might be a little difficult for the average reader of this article.
I would recommend checking out fidion/ansi to check your terminal's compatibility with a variety of features. Also check out JBlond's gist, which was a great starting point for the research that went into this article. Finally, check the Wikipedia page for ANSI escape codes, where you can learn to manipulate the cursor for so much finer control than you'll get by printing \r at the end of your lines.