I like to make sure I'm logged into the right host by having a specific color for each host. I copy my .bashrc around to different hosts, and edit it with a different color for each one.

However, I would like to not have to manually edit the color on each host, but instead automatically populate the colors for my bash prompt on each host, with a distinctive one for each hostname.

I'm imagining a command in .bashrc that gets the hostname, turns it into a unique color, and sets it to be the bash prompt color.

Question: How can I hash the hostname into a color in bash?

It might even make a judgment about the set of reasonable colors based on the terminal background color.


Solution 1:

this might not get a "nice" color based on background, but it should work, assuming the default background color is always color 0:

tput setaf $(hostname | sum | awk -v ncolors=$(infocmp -1 | expand | sed -n -e "s/^ *colors#\([0-9][0-9]*\),.*/\1/p") 'ncolors>1 {print 1 + ($1 % (ncolors - 1))}')

To break this down:

  • tput - output a terminal control string
  • setaf - the terminal control string; in this case, set ANSI foreground
  • $(...) - BASH nestable command substitution for the color parameter
    • hostname - get the hostname
    • sum - calculate a simple checksum on the hostname
    • awk...
    • -v ncolors=$(...) - set the AWK variable ncolors to the value of the command substitution within $(...)
      • infocmp -1 - display the terminal information about the current terminal type with 1 parameter per line
      • expand - expand tabs to spaces to make the sed script a bit easier
      • sed -n -e "s/^ *colors#\([0-9][0-9]*\),.*/\1/p" - extract the value of the integer colors terminal capability
    • 'ncolors>1 {...}' - the awk script, which runs the {...} code only if ncolors is greater than 1
      • print 1 + ($1 % (ncolors - 1)) - take the absolute$1 (field 1 of the input, which is coming from sum, which means $1 is the checksum value), find its remainder after being divided by (ncolors - 1) (which has the effect of limiting it to the range 0 through (ncolors - 2)), then add 1 and print it.

Solution 2:

You might be interested in context-color, which I've put together based on J Earls answer: https://github.com/ramnes/context-color

It's a simple script that, when executed, outputs a color based on a command output's hash. With it installed somewhere in your $PATH, you could do something like this in your .bashrc:

export PS1="$(context-color -p)$PS1\[\e[0m\]"

(where --prompt/-p is the switch so that the color is escaped for prompts, and \[\e[0m\] the escape sequence to reset color)

By default, the command used to generate the hash is whoami; hostname. If you just want the color to change according to the hostname, you can change the $CONTEXT variable environment (export CONTEXT="hostname") or simply use the --context/-c option (context-color -c "hostname").

See below for an example:

demo