I am using a dark theme. As you can see, the errors (ModuleNotFound from python) is almost unreadable. I have two questions.
- Is this colour controlled by python or the terminal?
- How can I change the colour? Is there any LS_COLOR setup?
I am using a dark theme. As you can see, the errors (ModuleNotFound from python) is almost unreadable. I have two questions.
Is this colour controlled by python or the terminal?
Both: Python chooses a general palette color from the "standard" 8/16-color palette, and the terminal's configuration controls the specific shade.
For example, Python outputs \033[35m to choose foreground color #5, which generally means "some kind of magenta", but different terminals have different defaults for "magenta" – and usually a ton of predefined schemes to choose from.
The "upper" 8 colors are usually bright versions of the "lower" ones (…except in the Solarized theme). There are specific codes to use them (e.g. 95 for bright magenta), but many terminals also implicitly treat bold text as bright as originally that was the only way for hardware CRT terminals to handle a 'strong' color in their fixed fonts. So when Python uses \033[1;35m for "bold magenta" this might be either color #5 or color #13.
Programs can also use a 256-color palette (6×6×6) which is more fixed, with little variation across terminals, but that is rarely used by default as it's tricky to determine whether a terminal supports it (and whether it supports the standard syntax or only the de facto "misunderstood the standard" syntax). Same for direct-color RGB, which most terminals support but few programs use.
The choice of color is not set separately for stdout vs stderr. By the time it reaches the terminal, there is no longer any distinction between stdout and stderr: both arrive intermixed through the same pipe (tty device), so the terminal cannot apply different coloring on its own.
#!/usr/bin/env bash
# showcolors -- Display the 16 basic terminal colors.
for y in 30 90; do
(( y == 30 )) || printf "\n"
for x in {0..7}; do
fx=$[y+x]
bx=$[10+y+x]
printf "%-9s" "Color $fx:"
printf " \e[2;%dm%s\e[m" $fx "Dimmed"
printf " \e[%dm%s\e[m" $fx "Normal"
printf " \e[1;%dm%s\e[m" $fx "Strong"
printf " "
printf " \e[%dm%s\e[m" $bx " Normal "
printf " \e[1;%dm%s\e[m" $bx " Strong "
printf " "
printf " \e[30;%dm%s\e[m" $bx " Normal "
printf " \e[1;30;%dm%s\e[m" $bx " Strong "
printf "\n"
done
done
How can I change the colour? Is there any LS_COLOR setup?
The color codes output by the program might be customizable or might not. For example, dmesg looks in terminal-colors.d(5).
Many programs – including Python – respect the NO_COLOR=1 variable to turn off all output colors. (Slightly overkill for normal use, but there's sadly no SENSIBLE_AMOUNT_OF_COLOR yet.)
Python supports disabling colors using the PYTHON_COLORS environment variable, but not customizing them – its Lib/traceback.py is hardcoded to use "bold magenta", which might be either color #5 or #13 depending on the terminal.
But since it only uses the base 8/16 color codes, the specific shade of those colors can be set in your terminal's configuration (and practically every terminal has it customizable, see e.g. the previous link). If its default 'magenta' is too dark, you can change that.
You could technically override Python's idea of what color code to use for "bold magenta" from within your $PYTHONSTARTUP script, but that might have confusing results since it is not guaranteed to be limited to only the traceback.
import _colorize
_colorize.ANSIColors.BOLD_MAGENTA = "\033[1;3;5;4;93;44m"
# _colorize.ANSIColors.BOLD_MAGENTA = _colorize.ANSIColors.INTENSE_RED
_colorize.ANSIColors.MAGENTA = "\033[1m"
import traceback
old_fn = traceback._format_final_exc_line
def new_fn(etype, value, *args, **kwargs):
text = old_fn(etype, value, *args, **kwargs)
head, tail = text.split("\n", 1)
# works in XTerm and PuTTY; doesn't work in GNOME Terminal
return f"\033#3{head}\n\033#4{head}\n{tail}"
traceback._format_final_exc_line = new_fn