8

When I execute echo -e '\033[49;36m\u2588\033[40;36m\u2588' in a linux terminal, I get two blocks of the same color:

linux colored blocks

Here, the first block has no background color (49) while the second block has a black background color. The character displayed should generally take up the entire space, so the background is not visible and they appear the same.

However, if I repeat this in Mac Terminal I get something very surprising:

enter image description here

For some reason, mac terminal is changing the foreground color for different background colors. Through some experimentation, I've found that the foreground color is constant for any fixed background color, and only different for the default background color. The color it renders is distinct from any of the other dim or bright modifications offered by ansi terminals.

Why is this happening, and more importantly, can I fix it?

2 Answers 2

2

Not a clue as to why. It seems the Terminal app has a strange behavior where it renders foreground colors differently when using the default terminal background.

As a workaround, try using \033[48;5;256 instead of \033[49 to specify the default background color. The 48 code is used to set the background color, but it only has a range of 0-255. Setting a value outside this range (256) still renders whatever the default background color is, but it also seems to trigger the proper foreground color as if a background color was specified.

4

Short answer: don't use "compound" color codes like \033[49;36m, use separated colour instructions like \033[0;42m\033[0;36m instead. The difference can be nicely seen by comparing the output of those two commands:

echo -e "\033[0;42;36m\xe2\x96\x88\033[0;49;36m\xe2\x96\x88"
echo -e "\033[0;42m\033[0;36m\xe2\x96\x88\033[0;49;36m\xe2\x96\x88"

(note that my version of bash could not process \u2588, so I had to resort to the hex variant \xe2\x96\x88).

Suggestion for future code:

Create a file (for example in ~/.bash_color_definitions) with the following content:

# Setup some colors to use later in interactive shell or scripts

# Color reset:
export COLOR_RESET='\033[0m' # reset color

# foreground colors

export FG_WHITE='\033[1;37m'
export FG_BLACK='\033[0;30m'
export FG_BLUE='\033[0;34m' 
export FG_LIGHT_BLUE='\033[1;34m'
export FG_GREEN='\033[0;32m'
export FG_LIGHT_GREEN='\033[1;32m'
export FG_CYAN='\033[0;36m'
export FG_LIGHT_CYAN='\033[1;36m'
export FG_RED='\033[0;31m'
export FG_LIGHT_RED='\033[1;31m'
export FG_PURPLE='\033[0;35m'
export FG_LIGHT_PURPLE='\033[1;35m'
export FG_BROWN='\033[0;33m'
export FG_YELLOW='\033[1;33m'
export FG_GRAY='\033[1;30m'
export FG_LIGHT_GRAY='\033[0;37m'


# background colors

export BG_WHITE='\033[1;47m'
export BG_BLACK='\033[0;40m'
export BG_BLUE='\033[0;44m' 
export BG_LIGHT_BLUE='\033[1;44m'
export BG_GREEN='\033[0;42m'
export BG_LIGHT_GREEN='\033[1;42m'
export BG_CYAN='\033[0;46m'
export BG_LIGHT_CYAN='\033[1;46m'
export BG_RED='\033[0;41m'
export BG_LIGHT_RED='\033[1;41m'
export BG_PURPLE='\033[0;45m'
export BG_LIGHT_PURPLE='\033[1;45m'
export BG_BROWN='\033[0;43m'
export BG_YELLOW='\033[1;43m'
export BG_GRAY='\033[1;40m'
export BG_LIGHT_GRAY='\033[0;47m'

And source it on every bash start by putting source ~/.bash_color_definitions into your .bashrc or .bash_profile. Then start producing more readable code like this:

 echo -e "$BG_BLACK$FG_CYAN\xe2\x96\x88$BG_GRAY$FG_CYAN\xe2\x96\x88$COLOR_RESET"

EDIT:

Turns out, the code in my answer actually reset the background (as Erik noted in the comments). After a bit of testing, it appears that the Mac Terminal "mixes" the foreground/background colours a bit different when you try to use color code 49, i.e. the "default background color".

iTerm.app for example does not behave in this way, so you could easily switch terminals, if you want to.

A valid solution, however, is to fully specify the background color (i.e. don't just use 49;36m, use 47;36m if your background is white). Or better use the xterm-256color color specifications; that is \033[38;5;___m for the foreground and \033[48;5;___m for the background colours (replacing the underscore with a number in 0-255). At least on my computer, this then produces consistent colours:

echo -e "\033[48;5;256m\033[38;5;6m\xe2\x96\x88\033[40;36m\033[38;5;6m\xe2\x96\x88\033[0m"

If you want to check which ANSI xterm-256color best matches your actual background color, you could use this script (modified version from the one found here):

#!/bin/bash

for fgbg in 38 48 ; do #Foreground/Background
    for color in {0..256} ; do #Colors
        #Display the color
        echo -e "\033[${fgbg};5;${color}m ${color}\t\033[0m"
    done
    echo #New line
done

exit 0
5
  • This doesn't work on my machine. Even when I separate the color codes out, I still get a color difference. The reason why your initial example works is because you're using the compound color code \033[0;36m, where the 0 is clearing the background style specified earlier, thus both blocks look the same, but they also have the same background color (default)
    – Erik
    Commented May 8, 2017 at 16:51
  • @Erik you're right, my answer wasn't correct. I've updated it and hope it now works for you.
    – Asmus
    Commented May 9, 2017 at 16:06
  • This does seem like a bug in Terminal.app, but neither solution you put forward is great. Switching to iTerm is fine, and probably what I'll end up doing, but it doesn't actually address the problem. The fix with larger colors is a nice local solution, but this is part of a script I use on many computers with different color themes, and to require configuration on every computer, and reconfiguration if the color theme changes is not ideal.
    – Erik
    Commented May 9, 2017 at 16:44
  • @Erik if you use this script on "many computers with different color themes" I wouldn't rely on the "default background color" (49) at all, if I were you. I have no idea what your script actually does, and why this minute color difference is so important to you (especially since you're not even using 256 colors, and it's highly unlikely all computer are calibrated), but If you can't specify a distinct background colour, you'd best be switching terminal apps.
    – Asmus
    Commented May 9, 2017 at 17:46
  • In my particular case, I'm using this for a custom powerline command prompt. I need the 49 color to blend in with the rest of the command prompt, and due to powerline, I need the foreground color of one glyph to match the background color of the previous one. However, this should work independent of the color scheme in the ansi terminal.
    – Erik
    Commented May 9, 2017 at 18:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .