9

I know how to use 256 colors for text in terminal:

printf "\033[38;5;196mhello\n"

But for background color, I seem to be limited to the basic 8 colors only, ie:

printf "\033[41mhello\n"

How can I use 256 colors for background colors as well ?

I mean, the terminal already know the colors, so it should be possible. But what is the syntax?

In case it is relevant, I am using terminator as my terminal emulator, and zsh as my shell.

10

In zsh, you don't need to hardcode escape sequences as it has several builtin ways to set the background and foreground colours.

You can use echoti setaf to set the terminal ansi foreground colour and echoti setab to set the background one (setaf and setab being the names of the corresponding terminfo capabilities)

Assuming your terminal supports 256 colours (as VTE-based ones such as your gnome-terminator do) and $TERM is correctly set to a value that identifies a terminfo entry with the right escape sequences for that, it should work.

$ echoti setab 196 | sed -n l
\033[48;5;196m$

Or you can use prompt expansion with print -P or the % parameter expansion flag and:

$ print -rP '%K{196}' | sed -n l
\033[48;5;196m$

(here sed -n l is used to reveal the corresponding escape sequence that is being sent, $ is just to show where the line ends, it's not part of the output, \033 is GNU sed's l command's representation of the ESC character (with octal 033 byte value in ASCII))

Some terminals (including VTE-based ones such as your gnome-terminator) also support RGB specifications. On those, you could do

$ print -rP '%K{#ffffff}' | sed -n l
\033[48;2;255;255;255m$

(here with fffffff for bright white as that's ff the maximum value for all of the red, green and blue components). In that case, zsh hardcodes the xterm-style sequence (see there for the background) as there is no corresponding terminfo capability. Though not standard, that's currently the most widely supported across modern FLOSS terminal emulators.

%K sets the background colour, %F for foreground. %k/%f restore the default colour.

For terminals that don't support that but do support the 88 or 256 colour palette, zsh also has a zsh/nearcolor module to get you the colour nearest to that RGB specification:

$ zmodload zsh/nearcolor
$ echoti colors
256
$ print -rP '%K{#ffffff}' | sed -n l
\033[48;5;231m$

(here colour 231 on my 256 colour terminal is the closest one to bright white, it is actually bright white).

If you have access to the X11 rgb.txt file, you could also define associative arrays for each of the X11 colour names with something like:

typeset -A X11_bg X11_fg
while read -r r g b c; do
  [[ $r = [0-9]* ]] || continue
  printf -v hex %02x $r $g $b
  X11_fg[$c]=${(%):-%F{#$hex}}
  X11_bg[$c]=${(%):-%K{#$hex}}
done < /etc/X11/rgb.txt
X11_bg[default]=${(%):-%k} X11_fg[default]=${(%):-%f}

(Debian-like systems have /etc/X11/rgb.txt as part of the x11-common package).

To do things like:

print -r "$X11_bg[dark olive green]text$X11_bg[default]"

For more details, see:

  • man 5 terminfo
  • info zsh echoti
  • info zsh print
  • info zsh "Prompt Expansion"
  • info zsh "The zsh/nearcolor Module"

(beware that on some systems, you need to install a zsh-doc package or equivalent for the info pages to become available).

| improve this answer | |
6

printf "\033[48;5;226mhello\e[m\n"

printf "\033[48;2;255;255;0mhello\e[m\n"

The more standard variant of the second (RGB) form (which includes an unused "color space identifier" after the 2) is not supported in older versions of the VTE library (as e.g. libvte-2.91 used by Terminator 1.91 on Debian 10).

| improve this answer | |
  • Can you expand on this answer, please? – Kevdog777 Sep 9 at 7:41
  • Would you mind editing your post to explain why this solves the OPs problem? – AdminBee Sep 9 at 7:42
  • It's sometimes better to switch back the colours with SGR 39 and SGR 49 than to reset everything with SGR 0. And strictly speaking that version of SGR 48:2 has two mistakes, as there's properly a fifth sub-parameter. A few terminal emulators now understand the correct T.416 form. – JdeBP Sep 9 at 9:01
  • @JdeBP that's the only one that seems to work in the version of gnome-terminal I've tested on. – user414777 Sep 9 at 9:11
  • 1
    Yes, the date in the corner. Where did you get the idea that 2014 was current? (-: M. Koblinger fixed the colourspace in 2017 and even wrote about it on this WWW site. So if you have 2016 GNOME Terminator, try without the sub-parameter. – JdeBP Sep 9 at 10:18
3

The direct colour and indexed colour ITU T.416 control sequences for foreground are SGR 38:2 and SGR 38:5. The control sequences for background are similarly SGR 48:2 and SGR 48:5.

Read § 13.1.8 of ITU T.416.

% TERM=rxvt-256color setterm -7 --background "137" | hexdump -C
00000000  1b 5b 34 38 3b 35 3b 31  33 37 6d                 |.[48;5;137m|
0000000b
%

If you ever progress beyond indexed colour, by the way, you'll need to know that there are, in fact, terminal emulators nowadays that correctly implement SGR 38:2 and SGR 48:2. Two historical mistakes, now being rectified by some people, were not using sub-parameters and forgetting the colour space identifier sub-parameter. iTerm2 fixed this back in 2013; libvte (as used in GNOME Terminator) added support for the : sub-parameters delimiter in 2014, and for the (ignored) color space identifier in 2017.

% TERM=iterm setterm -7 --background "137" | hexdump -C
00000000  1b 5b 34 38 3a 32 3a 3a  31 37 35 3a 31 33 35 3a  |.[48:2::175:135:|
00000010  39 35 6d                                          |95m|
00000014
%

Further reading

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.