Bash Prompts HowTo Guide

---------------------- Begin Copyrighted Material -------------------
$Revision: 1.11 $
$Date: 2003/01/19 06:17:23 $

	This article is Copyright 1998-2003 by Douglas Barton. All
non-commercial uses of this article are granted explicitly; providing
that my name, this copyright notice, and all material between and
including the lines that say "Begin Copyrighted Material" and "End of
Copyrighted Material" are reproduced intact. All commercial uses of
this article are explicitly reserved, and must be arranged with the
author.

	I hope that does not sound extreme, but writing documentation
is one of the things I do for a living, and after putting as many hours
into something as I have this article, I feel that protecting my
interests is well within reason. :) Please feel free to send any
comments, suggestions, corrections or questions to DougB@dougbarton.net.

	I made reference to the "termcap" file that comes with the
FreeBSD distribution, the xterm source code, and the "ctlseqs.ms," both
from XFree86 3.3.2.3. Of course I also used the Bash man pages.

	The information in this article is specific to Bash version
2.x. Although the general information about xterm and ANSI escape
sequences is probably applicable to other shells, I have not tested it,
and have no intention of doing so. Those using Bash 1.14.x can
accomplish most of the things mentioned here by using the octal
equivalents of the various escape sequences (e.g., substituting \033
for \e, \007 for \a, etc.) and deleting the \[ and \] characters that
indicate the boundaries of the non-printable portions of the prompt to
Bash 2. This was tested briefly, but I give no guarantees that what you
want to do with Bash 1.14 will work.

	If you need help with the basics of creating a prompt string,
please see the PROMPTING section of the Bash man page.

	By including escape sequences in your prompt you can affect
various aspects of the terminal you are using; be that an xterm,
console device, or other terminal emulation. For example, xterm has
the following built in escape sequences (from misc.c in the xterm
source):

        0: /* new icon name and title*/
        1: /* new icon name only */
        2: /* new title only */

The icon name escape sequences work for X window managers like
AfterStep and Window Maker. The title bar sequences work in most
window managers. Both also work for some Windows based terminal
emulators. An example is PuTTY, which can be found at
http://www.chiark.greenend.org.uk/~sgtatham/putty/

Here is a simple example of a prompt using those attributes.

PS1='\[\e]1;My Desk\a\e]2;${PWD}\a\]\
[\u@ME \w]\n \#\$ '

To make things easier to read, I used a \ at the end of the first line
(which is interpreted by the shell as literally escaping the Return at
the end of that line) to continue the string onto the next line. You
can use all the examples in this article as they are here, or you can
join the lines. Make sure to delete the \ if you join them. Here is
how to interpret the elements of that line.

PS1=	set the shell variable PS1 equal to the string between the two
	' marks. Since this variable is only used by Bash, there is no
	need to export it.
\[	start a sequence of non-printing characters
\e	an ASCII escape character (033 octal)
]1;	xterm escape sequence for the name of the icon
My Desk	literal text string
\a	an ASCII bell character (007 octal)
	This ends the first xterm sequence.

\e]2;${PWD}\a
Put the present working directory in the xterm titlebar. I like to use
${PWD} here because \w puts ~ in the title when you use just 'cd' to
return to your home.

\]	ends the non-printing character sequence

[\u@ME \w]\n
[	literal [ character
\u	the username of the current user
@ME	literal characters
\w	the current working directory
]	literal ] character
\n	newline

\#\$
\#	the command number of this command
\$	if the effective UID is 0, a #, otherwise a $

Here are some examples of what the prompt looks like using the above
string.

While I am in my home directory:
[myusername@ME ~]
 22$

Another directory:
[myusername@ME /usr/ports/shells/bash2]
 23$

	Now assume you would like to add color to your prompt. The
following will make your prompt a lovely shade of blue, with the
caveat that not all ANSI sequences display exactly the same on
all terminals.

PS1='\[\e]1;My Desk\a\e]2;${PWD}\a\
\e[0;34m\]\
[\u@ME \w]\n \#\$ \
\[\e[m\]'

The astute reader will notice that there are two changes to the
previous string. Before the first \] which indicates the end of the
non-printing sequence, the ANSI escape code for the color blue was
added.

\e[	ANSI escape sequence indicator
0;	use the default attribute (i.e., no bold, underline, etc.)
34	use blue for the foreground color
m	end of ANSI escape indicator

At the end of the prompt we have included another set of non-printable
characters with the ANSI escape sequence for "cancel all attributes."
This will prevent the text you type in at the prompt from being
colored, or otherwise affected.

	Two very popular uses of color are to indicate that the user
has become root, and to use different colors for prompts on different
hosts. Because I log into machines on a lot of different hosts, I have
developed the following prompt system which allows me to simply change
the two variables below for each host.

PROMPT_HOSTNAME='ME'
PROMPT_COLOR='0;34m'

# If I am root, set the prompt to bright red
if [ ${UID} -eq 0 ]; then
PROMPT_COLOR='1;31m'
fi

PS1='\[\e]1;${PROMPT_HOSTNAME}\a\e]2;${PROMPT_HOSTNAME}:${PWD}\a\
\e[${PROMPT_COLOR}\]\
[\u@${PROMPT_HOSTNAME} \w]\n \#\$ \
\[\e[m\]'

	There are other ANSI attributes that can be added, such as
bold, inverse (or reverse) video, blink and underline. Not all
attributes are supported on all terminals however. For example, the
blink attribute is not available in xterm. Underline is generally not
available in cons25. A little experimentation with your terminal type
will show you what you need to do to achieve the effect you want.

	A chart with the most common escape sequences of interest; and
which ones are supported on xterm, cons25 and vt100 terminals is
appended to the end of this article. If your system uses terminfo
instead of termcap, your escape codes may be different.

	Let us say that you would like the hostname part of the prompt
to be in reverse video so that it stands out more than the rest.

PS1='\[\e[0;34m\]\
[\u@\e[7mME\e[27m \w]\n \#\$ \
\[\e[m\]'

The \e[7m sequence is the code for reverse video. On an xterm you can
use the sequence \e[27m to cancel the reverse attribute. On other
terminals you would either have to use \e[m to cancel all attributes
(which works fine if you are not using color) or use the same color
sequence you used previously to restore only the color attribute.

	If you have the same .bash_profile/.bashrc on a machine that
you log into from different terminal types, you may find the following
to be of use. This allows you to customize your prompt according to
what attributes are supported based on the various types of terminals
you use. This is based on my experience, you will probably need to
modify it to serve your needs.

PROMPT_HOSTNAME='ME'
PROMPT_COLOR='0;34m'

# If I am root, set the prompt to bright red
if [ ${UID} -eq 0 ]; then
PROMPT_COLOR='1;31m'
fi

case ${TERM} in
        xterm*)
PS1='\[\e]1;${PROMPT_HOSTNAME}\a\e]2;${PROMPT_HOSTNAME}:${PWD}\a\
\e[${PROMPT_COLOR}\][\u@${PROMPT_HOSTNAME} \w]\n \#\$ \[\e[m\]'
        ;;
        vt100)
PS1='[\u@${PROMPT_HOSTNAME} \w]\n \#\$ '
        ;;
        *)
PS1='\[\e[${PROMPT_COLOR}\][\u@${PROMPT_HOSTNAME} \w]\n \#\$ \[\e[m\]'
        ;;
esac


	Below is a chart of various interesting attributes for
prompting purposes. The first column is a description of the attribute.
The second column is the termcap code for that attribute. For more
information check 'man 5 termcap'. If the escape code listed does not
work for your terminal, check the termcap file for your machine. Those
using the terminfo system should check that file and the documentation
for it to find the information they need.

	The last three columns contain the codes for the various
terminals, if they are supported. Below this chart is a very long and
rather obnoxious prompt string that gives examples of these attributes,
and should allow you to test your terminal to see what it can support.
It also has the various color codes so you can use it as a reference
as well. The bold attribute when combined with a color has the effect
of "brightening" the color displayed. On some terminals this makes it
an entirely different color.

	When creating an escape sequence, you can combine the various
elements. For example, if you want a string that is bold, underlined,
with a red foreground and a green background you would use:

\e[1;4;31;42m

	To read this chart, keep in mind that an ANSI escape sequence
starts with \e[ and ends with a literal m. Thus from the chart, the
code to turn on the bold attribute is \e[1m. The \e[m sequence turns
off all ANSI attributes, and is the only way to cancel things like bold
and underline on most terminals. Obviously, "NO" means that terminal
does not support that attribute. The ^G for bell is the traditional
"hold down the Control key and press G" combination. It can of course
be represented in a Bash 2 prompt string with \a. On most terminals,
"inverse" and "standout" are identical. Most terminals display
unsupported attributes as bold.

Attribute     termcap	xterm	cons25	vt100
---------------------------------------------
bold on		md	1	1	1
bold off		22	[m

inverse on	mr	7	7	7
inverse off		27	[m

standout on	so	7	7	7
standout off	se	27	[m	[m

underline on	us	4	NO	4
underline off	ue	24		[m

blink on	mb	NO	5	5
blink off		25	[m	[m

blank/invis	mk	8

bell		bl	^G	^G	^G

all attr off	me	[m	[m	[m


	Here is a sample prompt with the list of color codes included.
Where more than one color is indicated it means that color is known to
display differently on different terminal types. Other colors may be
similarly affected.

PS1='[\u@TEST \w]\n \#\$ \n\
\[\
\e[1mBold Text\e[m\n\
\e[4mUnderline Text\e[m\n\
\e[5mBlink Text\e[m\n\
\e[7mInverse Text\e[m\]\n\
Should be normal text
Foreground colors:
\[\
\e[0;30m30: Black\n\
\e[0;31m31: Red\n\
\e[0;32m32: Green\n\
\e[0;33m33: Yellow\Orange\n\
\e[0;34m34: Blue\n\
\e[0;35m35: Magenta\n\
\e[0;36m36: Cyan\n\
\e[0;37m37: Light Gray\Black\n\
\e[0;39m39: Default\n\
Bright foreground colors:
\e[1;30m30: Dark Gray\n\
\e[1;31m31: Red\n\
\e[1;32m32: Green\n\
\e[1;33m33: Yellow\n\
\e[1;34m34: Blue\n\
\e[1;35m35: Magenta\n\
\e[1;36m36: Cyan\n\
\e[1;37m37: White\n\
\e[0;39m39: Default\n\
\e[m\]Background colors:
\[\e[1;37m\e[40m40: Black\e[0;49m\n\
\e[41m41: Red\e[0;49m\n\
\e[42m42: Green\e[0;49m\n\
\e[43m43: Yellow\Orange\e[0;49m\n\
\e[44m44: Blue\e[0;49m\n\
\e[45m45: Magenta\e[0;49m\n\
\e[46m46: Cyan\e[0;49m\n\
\e[47m47: Light Gray\Black\e[0;49m\n\
\e[49m49: Default\e[m\]\n'

	While I know that nothing in this article is going to cure
cancer, I hope that it does bring some small joy to your life, and
that you have as much fun using this information as I did bringing
it all together.

-------------------- End of Copyrighted Material -----------------------

An excellent web page with resources for other shells can be found at:
http://sunsite.unc.edu/LDP/HOWTO/mini/Xterm-Title.html

The Linux Bash prompt HOWTO maintained by Giles Orr can be found at:
http://www.dreaming.org/~giles/bashprompt/
There are a lot of interesting ideas in that extensive document, but he makes
use of a lot of external programs in his prompts (even when he doesn't have to),
which is something I think is a little excessive. But each to his own. :)