# colourshell.sh # In an interactive Bash shell, cycles through a sequence of colours, # one per command, so that you can more easily see where one finishes # and the next starts. # (C) 2006 Philip Endecott # See http://chezphil.org/colourshell/ for more information. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # As far as I'm aware this won't work in any shells other than bash # because it uses bash-specific features. # To try it out, source this file into an interactive shell: # source /path/to/colourshell.sh # For permanent use this file should be sourced from your bash startup # script(s). # # Bash may execute various different startup scripts; see the # INVOCATION section of the bash man page for details. To have this # script called for both login shells (e.g. virtual consoles) and # non-login shells (e.g. xterms) you need to call it from both # .bash_profile and .bashrc. .bashrc may also be called for # non-interactive shells; to avoid running this in that case you can # enclose the source command in an if block that tests for # interactivity by checking for PS1: # # if [ "$PS1" ] # then # source /path/to/colourshell.sh # fi # Source this from somewhere near the end of those files. In # particular, source it from after any code that sets the prompt # variables (PS1 etc.) since this code adds its stuff to the existing # PS1 setting. # If your startup scripts don't set PS1 to PS4, things could get # interesting if you start one shell inside another: this code will be # called twice! It should still work, but ideally this script would # scrub any existing colour-setting codes from the prompts before # adding its own. # This code generates colour-changing escape sequences using the tput # program. This is a simple utility that uses the termcap database to # look up escape sequences for the current terminal. It seems to be # included in the major Linux distributions. For details, see "man # tput" and "man 5 terminfo". In particular see the "Color Handling" # section of "man 5 terminfo". # Most terminals with colour support have 8 colours. An exception is # rxvt-unicode (and other rxvts?) which claims to have 88. This script # doesn't know what to do with any other cases, so gives up immediately # without error. ncolours=`tput colors` case $ncolours in 8) ;; 88) ;; *) return 0 ;; esac # The following are the standard colour codes; see "man 5 terminfo". setaf_black=`tput setaf 0` setaf_blue=`tput setaf 1` setaf_green=`tput setaf 2` setaf_cyan=`tput setaf 3` setaf_red=`tput setaf 4` setaf_magenta=`tput setaf 5` setaf_yellow=`tput setaf 6` setaf_white=`tput setaf 7` # For 88-colour rxvt-unicode these 8 colours are near-enough right. # Try something like this to see the available colours: # # i=0 # while true # do # tput setaf $i # echo "$i: Hello World" # i=$(($i+1)) # done # Define the colours to use. # Set prompt_colour to the escape sequence for the colour to use for # the prompt, and cmd_colours (an array) to the escape sequences for # the colours to use for the commands, in turn. declare -a cmd_colours # A complicating factor is that we don't know whether this terminal # has a white / light-coloured background or a black / dark-coloured # background. This should influence our choice of colours. # Here is a heuristic: virtual consoles have TERM=linux and are # white-on-black, while X terminals and similar have TERM=xterm and # are black-on-white. case $TERM in linux) background=dark ;; *xterm*) background=light ;; *) background=light ;; esac # Choose colours, based on the guessed background colour: case $background in dark) prompt_colour=$setaf_white cmd_colours=($setaf_cyan $setaf_magenta $setaf_yellow) ;; light) prompt_colour=$setaf_black cmd_colours=($setaf_blue $setaf_green $setaf_red) ;; esac # This variable tracks which command colour is currently in use: declare -i cmd_colour_index=-1 # This function increments cmd_colour_index modulo the number of # command colours: function next_colour() { cmd_colour_index=$(( ($cmd_colour_index+1) % (${#cmd_colours[*]}) )) } # PROMPT_COMMAND is a bash builtin variable that names a command to # run before each prompt. (This will override any existing use of # this variable; how can multiple commands be chained together?) PROMPT_COMMAND=next_colour # This function returns the escape sequence for the current command # colour, from the array defined above: function cmd_colour() { echo ${cmd_colours[$cmd_colour_index]} } # Define the prompt variables. For each one we encapsulate the # current setting between a prefix and a suffix; the prefix sets the # colour for the prompt and the suffix sets the colour for the # command. # \[ ... \] are used around non-printing characters and are needed so # that Bash correctly calculates the screen position. Functions can # be called using `...`, as long as the promptvars option is enabled: shopt -s promptvars prompt_prefix="\\[${prompt_colour}\\]" prompt_suffix='\[`cmd_colour`\]' PS1="${prompt_prefix}${PS1}${prompt_suffix}" PS2="${prompt_prefix}${PS2}${prompt_suffix}" PS3="${prompt_prefix}${PS3}${prompt_suffix}" PS4="${prompt_prefix}${PS4}${prompt_suffix}"