My question is in general shell scripting with ansi colors but for reference I am using an Apple Mac OS X 10.9 Mavericks. I use "iTerm" terminal app as my default terminal but also checked with the built in "terminal" app as well. I use ZSH (5.0.7) as my default shell but also checked in BASH (3.2.51).
I have been trying to find out if there is a list of the RGB values for the 256 color indexed extended fore/background Ansi escape codes that are available using esc[38;5;xm and esc[48;5;xm where x is a number from 0 to 255. I have found some scripts that print out the colors as blocks (using the index) but I want to know the rgb values of each of the colors in the indexes.
Here is an example of the ansi codes in use:
printf '\e[38;5;222;48;5;238m Hi \e[m\n'
(\e can be replaced by \033 or \x1b)
So basically I am wondering if there is a list or agreed upon settings for these indexed colors? For example 232-255 seem to always be a gray gradient. Every site that I have found that references the extended colors pretty much just says how to use it and doesn't list any specific colors.
I found some references to X11 and an rgb.txt file which at first seemed like it was what I was looking for but they don't seem to match up to the index numbers. There are 752 colors in the file I found (most are duplicates so say 376 which is still more the 256). Also there are 50 shades of gray (100 if you count duplicates) but the Ansi indexed colors have 23 so it doesn't seem to be the same. If these in some way do contain the colors in the ansi extended color index does anyone have a list of which names are in which index?
PS. I know esc[38;2;r;g:bm can supposedly set a color using rgb values but I can't get it to work on my Mac and I am more interested in the default values for the indexed colors.
Some sites: (can only post 2 due to low rep? But I checked a lot of sites)
This one has the rgb for the standard colors but not the extended ones.
The color range of a 256 color terminal consists of 4 parts, often 5, in which case you actually get 258 colors:
Color numbers 0 to 7 are the default terminal colors, the actual RGB value of which is not standardized and can often be configured.
Color numbers 8 to 15 are the "bright" colors. Most of the time these are a lighter shade of the color with index - 8. They are also not standardized and can often be configured. Depending on terminal and shell, they are often used instead of or in conjunction with bold font faces.
Color numbers 16 to 231 are RGB colors. These 216 colors are defined by 6 values on each of the three RGB axes. That is, instead of values 0 - 255, each color only ranges from 0 - 5.
The color number is then calculated like this:
number = 16 + 36 * r + 6 * g + b
with r
, g
and b
in the range 0 - 5.
The color numbers 232 to 255 are grayscale with 24 shades of gray from dark to light.
The default colors for foreground and background. In many terminals they can be configured independently from the 256 indexed colors, giving an additional two configurable colors . You get them when not setting any other color or disabling other colors (i.e. print '\e[m'
).
Some sources:
urxvt
manpage:
In addition to the default foreground and background colours, urxvt can display up to 88/256 colours: 8 ANSI colours plus high-intensity (potentially bold/blink) versions of the same, and 72 (or 240 in 256 colour mode) colours arranged in an 4x4x4 (or 6x6x6) colour RGB cube plus a 8 (24) colour greyscale ramp.
xterm
manpage:
These specify the colors for the 256-color extension. The default resource values are for colors 16 through 231 to make a 6x6x6 color cube, and colors 232 through 255 to make a grayscale ramp.
Wikipedia article on ANSI escape codes (which in turn itself is lacking a citation on the topic)
Theoretically, in order to get an equally distributed range of colors, the RGB values for the colors in the range 16 - 231 could be calculated like this:
# example in Python: // is integer divison, % is modulo
rgb_R = ((number - 16) // 36) * 51
rgb_G = (((number - 16) % 36) // 6) * 51
rgb_B = ((number - 16) % 6) * 51
But it seems that the actual method is different:
Any terminal emulators I tested seems to follow XTerm and map the values [0, 1, 2, 3, 4, 5]
for red, green and blue to the values [0, 95, 135, 175, 215, 255]
on the RGB color axes. (I tested with XTerm (297) URxvt (v9.19), ROXTerm (2.8.1), gnome-terminal (3.6.2) and xfce4-terminal (0.6.3))
The RGB values for a given index can be calculated with this algorithm:
# example in Python: 'a = b if c else d' is 'a = (c) ? b : d` in C, Perl, etc.
index_R = ((number - 16) // 36)
rgb_R = 55 + index_R * 40 if index_R > 0 else 0
index_G = (((number - 16) % 36) // 6)
rgb_G = 55 + index_G * 40 if index_G > 0 else 0
index_B = ((number - 16) % 6)
rgb_B = 55 + index_B * 40 if index_B > 0 else 0
The grayscale seems to follow this simple formula:
rgb_R = rgb_G = rgb_B = (number - 232) * 10 + 8
256colres.pl
in the root of the XTerm sources (version 313) uses a similar algorithm to generate 256colres.h
, which contains the color definitions for 256 color mode:
$line1="COLOR_RES(\"%d\",";
$line2="\tscreen.Acolors[%d],";
$line3="\tDFT_COLOR(\"rgb:%2.2x/%2.2x/%2.2x\")),\n";
# colors 16-231 are a 6x6x6 color cube
for ($red = 0; $red < 6; $red++) {
for ($green = 0; $green < 6; $green++) {
for ($blue = 0; $blue < 6; $blue++) {
$code = 16 + ($red * 36) + ($green * 6) + $blue;
printf($line1, $code);
printf($line2, $code);
printf($line3,
($red ? ($red * 40 + 55) : 0),
($green ? ($green * 40 + 55) : 0),
($blue ? ($blue * 40 + 55) : 0));
}
}
}
# colors 232-255 are a grayscale ramp, intentionally leaving out
# black and white
$code=232;
for ($gray = 0; $gray < 24; $gray++) {
$level = ($gray * 10) + 8;
$code = 232 + $gray;
printf($line1, $code);
printf($line2, $code);
printf($line3,
$level, $level, $level);
}
Here is a zsh function that prints all colors on a 256 color terminal (if TERM
is set to a 256 color value):
function termcolors ()
{
print TERM
print -P "Foreground: >█<"
print -P "Background: >%S█%s<\n"
print " 0 1 2 3 4 5 6 7"
for b (0 1)
do
printf "%d %2d " $b $(( 8 * b ))
for r (0 1 2 3 4 5 6 7)
do
c=$(( 8 * b + r ))
print -nP "%K{$c} %k"
done
printf " %2d\n" $(( 8 * b + 7 ))
done
print
print RGB
for r (0 1 2 3 4 5)
do
print "$r $(( 16 + 36 * r )) - $(( 16 + 36 * r + 35 ))\n 0 1 2 3 4 5"
for g (0 1 2 3 4 5)
do
printf "%d %3d " $g $(( 16 + 36 * r + 6 * g ))
for b (0 1 2 3 4 5)
do
c=$(( 16 + 36 * r + 6 * g + b ))
print -nP "%K{$c} %k"
done
printf " %3d\n" $(( 16 + 36 * r + 6 * g + 5))
done
print
done
print
print GRAY
for g in $(seq 0 23)
do
c=$(( 232 + g ))
printf "%2d %3d " $g $c
print -P "%K{$c} %k"
done
}
In some terminals (at least xterm
, gnome-terminal
, termite
and urxvt
) all those colors can be changed during runtime by sending one of the following XTerm Control Sequences:
OSC 4; c ; spec BEL
OSC 4; c ; spec ST
where:
OSC
is the escape character (\e
or \033
) followed by ]
c
is the color number (0 - 255) spec
is a color specification (e.g. red
, #ff0000
, rgb:ff/00/00
, rgbi:1/0/0
- what actually works might depend on the terminal)BEL
is the bell character (\a
or \007
)ST
is the string terminator \e\\
or \033\\
These control sequences can be sent by simply printing them with echo
:
echo -en "\e]4;COLOR;SPEC\a"
echo -en "\e]4;COLOR;SPEC\a"
For example, in order to set color number 5 (usually some shade of magenta) to red, either of these should work:
echo -en "\e]4;5;red\a"
echo -en "\e]4;5;#ff0000\e\\"
echo -en "\033]4;5;rgb:ff/00/00\007"
Those colors can be reset to their (configured) default with one of the control sequences
OSC 104 ; c BEL
OSC 104 ; c ST
So the following loop will reset all colors from 0 to 255 to their configured or default value:
for c in {0..255}; do
echo -en "\e]104;$c\a"
done
For the default foreground and background colors the control sequences are OSC 10 ; spec BEL
and OSC 11 ; spec BEL
, respectively. For example:
echo -en "\e]10;red\a"
echo -en "\e]11;green\a"
Those can be reset with OSC 110 BEL
and OSC 111 BEL
respectively:
echo -en "\e]110\a"
echo -en "\e]111\a"