Color Hostname

I often have a lot of SSH shells open at a time, and it is not easy to distinguish between the different hosts on the first glance. I usually have a mu@hostname like prompt, but I often started to type in the wrong terminal.

To tell the different computers apart I assigned them a color each so that in the prompt each hostname would be in a different color. And on the computer I am physically sitting at, no hostname is displayed because it is obvious. Except it is a computer which name does not begin with Martin-, then the hostname is displayed even when I am sitting right at it.

The color is assigned using the hash sum of the hostname, therefore every host has the same color at all times, and different hosts (hopefully) have different colors. Given the limited choice of colors, some hosts do have the same color, but better than green on all hosts.

This is the code I have in my .bashrc:

#!/bin/bash
# Copyright © 2012-2013 Martin Ueding <dev@martin-ueding.de>

# This script has been placed in the public domain via the CC0 license:
# https://creativecommons.org/publicdomain/zero/1.0/

# This sets the bash promt. I grant you that this might be a little overkill
# here.
#
# If we are *not* connected via SSH and this is one of Martin's computers,
# there is no point in displaying the hostname as it is obvious.
#
# In any other case, display the hostname. In order to be able to differentiate
# them in various terminal windows, give the hosts different colors based on
# their hostname. The use of a hash function asserts that the color will the
# same every time, but hopefully different on every computer. Since there are
# not that many colors, collisions will happen.

set_prompt() {
	# Gather color codes using ``tput``. This is better than hard-coding the
	# ANSI escapes directly into this script, making this more sane and
	# portable. If there is no ``tput`` or if setting something with it fails,
	# the color codes are set empty, so there will be no color output.
	if [[ -x /usr/bin/tput ]] && tput setaf 1 >&/dev/null
	then
		local bold="\[$(tput bold)\]"

		local blue="\[$(tput setaf 4)\]"
		local green="\[$(tput setaf 2)\]"
		local cyan="\[$(tput setaf 6)\]"
		local purple="\[$(tput setaf 5)\]"
		local orange="\[$(tput setaf 3)\]"
		local red="\[$(tput setaf 1)\]"

		local reset="\[$(tput sgr0)\]"
	else
		local bold=

		local blue=
		local green=
		local orange=
		local red=

		local reset=
	fi

	# Check whether one is connected via SSH.
	if [[ -z "$SSH_CLIENT" && $HOSTNAME =~ ^Martin- ]]
	then
		local ps1_host=
	else
		# Legal colors for use.
		local colors=( 1 2 3 4 5 6 7 )

		# Generate a hash from the hostname.
		local host_hash="$(echo "$HOSTNAME" | md5sum | awk '{print $1}')"

		# Convert into a positive integer.
		local host_number=$(( 0x$host_hash % ${#colors[@]} ))
		if [[ $host_number -lt 0 ]]
		then
			local host_number=$(( -$host_number ))
		fi

		local host_color="\[$(tput setaf ${colors[host_number]})\]"

		local ps1_host="${host_color}${bold}@\\h${reset}"
	fi

	# If the user is root, give it a red user name.
	if [[ "$USER" == root ]]
	then
		local ps1_user="${red}${bold}\\u${reset}"
	else
		local ps1_user="${green}${bold}\\u${reset}"
	fi

	# Put it all together.
	PS1="${ps1_user}${ps1_host}:${blue}${bold}\\w${reset}${orange}\$(scmprompt)${reset}${cyan}\$(command_duration)${reset}${red}\$(returncode)${reset} "

	# Set the command to be executed before the prompt is displayed. That way,
	# the return code is stored. If there is a function ``command-finished``
	# call that as well.
	if type command-finished &> /dev/null
	then
		PROMPT_COMMAND='last_return_code=$?; command-finished'
	else
		PROMPT_COMMAND='last_return_code=$?';
	fi
}

# This prints the return code, but only, if it a failure (i. e. greater than
# 0).
returncode() {
	if (( last_return_code != 0 ))
	then
		echo " ${last_return_code}"
	fi
}

command_duration() {
	if [[ -n $last_command_duration ]]
	then
		echo " $last_command_duration"
	fi
}

set_prompt

# Clean up.
unset -f set_prompt