Below is a Python script which
- Randomizes a color based on the server host name. The same hostname always results to the same color.
- The color is randomized in HSL color space, so that only the hue component varies and saturation and lightness are locked. This prevents the creation of ugly color combinations like black text on black tab background.
Note: The effect can be also applied on terminal windows – for those who don’t use tabs.
The effective result is that
- You learn to identify terminal tabs by the color
- You can much more faster to switch between tabs, because you can visually pick up the terminal without needing to be able to read the text on it or remember its location in the list
Note: If your puny terminal does not support setting the color of window decorations, you can always set the terminal background color. This is useful e.g. if you want to red background for danger zone ™ when you are logged in as root on the production server 23:00 Friday night.
Note: Naturally you also need to have the script installed on the servers you are ssh’ing into
1. precmd() hook
You can run the script once and the tab color is set. However, if you SSH from the computer to another and then exit back, the color of the latest server would remain in this case.
This can be avoided by
- Calculating the OSC control code sequence needed to set the terminal tab color when the shell starts
- Have a precmd() hook (zsh terminology, not sure what other shells use) to reset the tab color every time the shell prompt is displayd
The script code lives on Github. Currently it supports iTerm 2 only and we plan to expand support to Konsole. Patches for other terminals are welcome.
(This probably could be done in pure shell code too, but Python is just so much more fun…)
#!/usr/bin/env python """ Set terminal tab / decoration color by the server name. Get a random colour which matches the server name and use it for the tab colour: the benefit is that each server gets a distinct color which you do not need to configure beforehand. """ import socket import random import colorsys import sys # http://stackoverflow.com/questions/1523427/python-what-is-the-common-header-format __copyright__ = "Copyright 2012 Mikko Ohtamaa - http://opensourcehacker.com" __author__ = "Mikko Ohtamaa <email@example.com>" __licence__ = "WTFPL" __credits__ = ["Antti Haapala"] USAGE = """ Colorize terminal tab based on the current host name. Usage: rainbow-parade.py [0-1.0] [0-1.0] # Lightness and saturation values An iTerm 2 example (recolorize dark grey background and black text): rainbow-parade.py 0.7 0.4 """ def get_random_by_string(s): """ Get always the same 0...1 random number based on an arbitrary string """ # Initialize random gen by server name hash random.seed(s) return random.random() def decorate_terminal(color): """ Set terminal tab / decoration color. Please note that iTerm 2 / Konsole have different control codes over this. Note sure what other terminals support this behavior. :param color: tuple of (r, g, b) """ r, g, b = color # iTerm 2 # http://www.iterm2.com/#/section/documentation/escape_codes" sys.stdout.write("\033]6;1;bg;red;brightness;%d\a" % int(r * 255)) sys.stdout.write("\033]6;1;bg;green;brightness;%d\a" % int(g * 255)) sys.stdout.write("\033]6;1;bg;blue;brightness;%d\a" % int(b * 255)) sys.stdout.flush() # Konsole # TODO # http://meta.ath0.com/2006/05/24/unix-shell-games-with-kde/ def rainbow_unicorn(lightness, saturation): """ Colorize terminal tab by your server name. Create a color in HSL space where lightness and saturation is locked, tune only hue by the server. http://games.adultswim.com/robot-unicorn-attack-twitchy-online-game.html """ name = socket.gethostname() hue = get_random_by_string(name) color = colorsys.hls_to_rgb(hue, lightness, saturation) decorate_terminal(color) def main(): """ From Toholampi with love http://www.toholampi.fi/tiedostot/119_yleisesite_englanti_naytto.pdf """ if(len(sys.argv) < 3): sys.exit(USAGE) lightness = float(sys.argv) saturation = float(sys.argv) rainbow_unicorn(lightness, saturation) if __name__ == "__main__": main()