Contents
- Overview
- ASCII Escape Character
- ANSI Escape Codes for Terminal Graphics
- Color Schemes
- Windows Colors
- My Preferred Color Scheme
Overview
Terminals traditionally take an input of bytes and display them as white text on a black background. If the input contains specific “control characters,” then the terminal may alter certain display properties of the text, such as the color or font. Old terminals could only display a maximum of 8 colors. However, modern computer screens are capable of displaying 24-bit RGB color, so modern terminals have to implement a mapping of the 8 original colors to RGB values. This mapping can usually be changed according to user-defined color schemes.
ASCII Escape Character
The ANSI ASCII standard represents the escape ESC
character by the decimal number 27 (33 in octal, 1B in hexadecimal). This is one of the control characters (0-31 and 127), not one of the printable characters (32-126).
ASCII code 27 is indeed the character corresponding to the Escape key on a keyboard. However, most shells recognize the Escape key as a control character (usually for a keyboard shortcut) and therefore do not translate the Escape key into any text representation. Thus, each programming language has its own method of representing the escape character within a string:
Bash | C | Python 3 | |
---|---|---|---|
literal | \e , \E |
\e (non-standard) |
Python 3.3+ only: \N{ESCAPE} , \N{escape} , \N{ESC} , \N{esc} |
octal | \033 |
\33 , \033 |
\33 , \033 |
hexadecimal | \x1b |
\x1b |
\x1b |
Unicode | \u1b , \U1b |
– | \u001b , \U0000001b |
Additional notes
- For all 3 languages, any place where
1b
appears, the capitalized hexadecimal1B
also works. - Bash supports Unicode characters of the form
\uXXXX
(\u
+ 4 hexadecimal digits) and\UXXXXXXXX
(\U
+ 8 hexadecimal digits), but unlike Python, it allows for leading zeros to be omitted. - Most major C compilers, including gcc and clang, support the non-standard
\e
syntax for the escape character. - While C generally supports unicode characters of the form
\uXXXX
and\UXXXXXXXX
, it oddly does not support Unicode control characters. From the C18 specification on universal character names:A universal character name shall not specify a character whose short identifier is less than 00A0 other than 0024 ($), 0040 (@), or 0060 (‘)
ANSI Escape Codes for Terminal Graphics
The ANSI escape code standard, formally adopted as ISO/IEC 6429, defines a series of control sequences. Each control sequence begins with a Control Sequence Inducer (CSI), defined as an escape character followed immediately by a bracket: ESC[
. In particular, a CSI followed by a certain number of “parameter bytes” (ASCII 0–9:;<=>?
) then the letter m
forms a control sequence known as a Select Graphic Rendition (SGR). If no parameter bytes are explicitly given, then it is assumed to be 0
. SGR parameters can be chained together with a semicolon ;
as the delimiter.
Some common SGR parameters are shown below:
Parameter | Effect |
---|---|
0 |
reset all SGR effects to their default |
1 |
bold or increased intensity |
2 |
faint or decreased intensity |
4 |
singly underlined |
5 |
slow blink |
30-37 |
foreground color (8 colors) |
38;5;x |
foreground color (256 colors, non-standard) |
38;2;r;g;b |
foreground color (RGB, non-standard) |
40-47 |
background color (8 colors) |
48;5;x |
background color (256 colors, non-standard) |
48;2;r;g;b |
background color (RGB, non-standard) |
90-97 |
bright foreground color (non-standard) |
100-107 |
bright background color (non-standard) |
The 8 actual colors within the ranges (30-37, 40-47, 90-97, 100-107) are defined by the ANSI standard as follows:
Last Digit | Color |
---|---|
0 | black |
1 | red |
2 | green |
3 | yellow |
4 | blue |
5 | magenta |
6 | cyan |
7 | white |
We put these pieces together to create a SGR command. Thus, ESC[1m
specifies bold (or bright) text, and ESC[31m
specifies red foreground text. We can chain together parameters; for example, ESC[32;47m
specifies green foreground text on a white background.
The following diagram shows a complete example for rendering the word “text” in red with a single underline.
Notes
- For terminals that support bright foreground colors,
ESC[1;3Xm
is usually equivalent toESC[9Xm
(whereX
is a digit in 0-7). However, the reverse does not seem to hold, at least anecdotally:ESC[2;9Xm
usually does not render the same asESC[3Xm
. - Not all terminals support every effect.
- Documentation is available for Microsoft Windows Console and Linux.
- Microsoft and the Linux manual pages both refer to SGR as “Set Graphics Rendition,” instead of “Select Graphic Rendition.”
Examples
- Bash:
printf "\u1b[31mtest\033[ming\n"
- C:
printf("%s\n", "\x1b[31mtest\033[0ming");
- Python:
print('\N{ESC}[31mtest\u001b[0ming')
- Output:
testing
Additional Sources
- Colors In Terminal: describes control sequences at a high level and covers 256-color support
- ANSI Escape sequences: easy-to-read chart of control sequences
Color Schemes
The role of terminal color schemes is to map the 8 colors to RGB values. Most terminals support an additional 8 colors corresponding to the bold or bright variants of the original colors. The GitHub repo mbadolato/iTerm2-Color-Schemes provides a sampling of common color schemes.
Windows Colors
While the 8 standard color names are widely used within ANSI and ISO standards documents as well as the Linux community, Microsoft uses slightly different names and ordering of colors.
Windows Console (Command Prompt)
The command color
sets the default console foreground and background colors, and it can also be used to list out the supported colors with color /?
. The colors are named as follows:
0 = Black 8 = Gray
1 = Blue 9 = Light Blue
2 = Green A = Light Green
3 = Aqua B = Light Aqua
4 = Red C = Light Red
5 = Purple D = Light Purple
6 = Yellow E = Light Yellow
7 = White F = Bright White
Notably, Microsoft renames “cyan” to “aqua” and “magenta” to “purple,” and it names the bold/bright variant of black as “gray.” This ordering is also the ordering of colors that appear in the Windows Console settings.
Windows Terminal (beta)
Windows Terminal now uses the ANSI color names except that it still uses “purple” instead of “magenta.” However, there is an open issue (as of March 28, 2020) where Microsoft seems to be considering “magenta.”
My Preferred Color Scheme
Personally, here is the color scheme that I’ve found to work well for me. It is largely based on Ubuntu’s default terminal color scheme (changes are marked by an asterisk *).
Color | RGB | Hexadecimal |
---|---|---|
■ black* | 0, 0, 0 |
000000 |
■ red | 204, 0, 0 |
cc0000 |
■ green | 78, 154, 6 |
4e9a06 |
■ yellow | 196, 160, 0 |
c4a000 |
■ blue* | 114, 159, 207 |
729fcf |
■ magenta | 117, 80, 123 |
75507b |
■ cyan | 6, 152, 154 |
06989a |
■ white | 211, 215, 207 |
d3d7cf |
■ bright black | 85, 87, 83 |
555753 |
■ bright red | 239, 41, 41 |
ef2929 |
■ bright green | 138, 226, 52 |
8ae234 |
■ bright yellow | 252, 233, 79 |
fce94f |
■ bright blue* | 50, 175, 255 |
32afff |
■ bright magenta | 173, 127, 168 |
ad7fa8 |
■ bright cyan | 52, 226, 226 |
34e2e2 |
■ bright white* | 255, 255, 255 |
ffffff |