Is it possible to use background-aware color choices?

Viewed 117

The rich project allows to specify console markup, including text color. However it seems that any color choices need to be hardcoded, e.g. using red for important messages:

from rich import print

print('[red bold]This is a very important notification[/]')

This looks good on a terminal with light background color (e.g. Solarized light):

red on light background

However when the user has a dark background color, it makes it difficult to read (e.g. Solarized dark):

red on dark background

As the developer of a command line application using rich, however, I cannot assume any background color for the users' terminals and hence hardcoding specific colors doesn't seem like a good idea (I don't want to modify the background color either, since the user probably chose it for a good reason). So I was wondering whether rich offers background-aware color choices (e.g. via themes, so I could just specify something like category='important')?

2 Answers

The first 16 colors in the terminal (which includes red) are defined by the terminal software, and are generally chosen to work well together. For instance here is red on black within iTerm on MacOS.

Example of red on black in the terminal

Red on black will be perfectly readable on virtually all terminals. A notable exception would be the classic Windows terminal (which I'm guessing you are using) which has some very poorly thought out color palettes.

Regarding hard coded colors, you can create themed aliases via themes so you can use "[important] message" rather than "[bold red] message"

Detecting terminal color schemes

Depending on your terminal the color-settings are stored in config-files. Usually those have a plain/text format, e.g. rc-files on Linux systems.

For example in XFCE you can discover the current 16 base-colors, including background color and bold style by reading the terminalrc file:

cat ~/.config/xfce4/terminal/terminalrc | egrep 'ColorPalette|ColorBackground|ColorBold'
ColorBackground=#131926
ColorPalette=#000000;#aa0000;#44aa44;#aa5500;#0039aa;#aa22aa;#1a92aa;#aaaaaa;#777777;#ff8787;#4ce64c;#ded82c;#295fcc;#cc58cc;#4ccce6;#ffffff
ColorBold=#ffffff
ColorBoldUseDefault=FALSE

See themes - Change color scheme for xfce4 terminal manually - Ask Ubuntu.

Increasing contrast by applying foreground and background colors together

What about choosing a black or white background color along with your red text:

from rich import print

# bold font may also be rendered depending on terminal's predefined style and color
print('[bold]This is just bold, which can be rendered as different color depending on terminal\'s color-scheme[/]')
# only foreground may suffer readability, e.g. when transparent background
print('[red bold]This is a very important notification[/]')
# use foreground on background to achieve high contrast
print('[red bold on black] on black[/]')
print('[red bold on white] on white[/]')

Even within a transparent terminal window the background color can improve contrast and readability: better contrast with 'foreground on background'

Benefit:

This will make your TUI independent from terminal's color-schemes and ensures some kind of brand-identity to your application. Then the color-choice is consistently across all systems and terminals and the user can recognize your application by its unique colors.

See Set different background color using Rich.

Using configurable themes

Like answered by Will McGugan (the creator of Rich) you can leverage themes to let the user control colors. This follows the customization approach used in modern terminals and allows the user to align both color-themes (e.g. to have the same theme in terminal and app).

See the 16 base-colors and also bold-style color of the Solarized theme.

Related