old-www/HOWTO/Xterm-Title-4.html

269 lines
8.7 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
<TITLE>How to change the title of an xterm: Examples for different shells</TITLE>
<LINK HREF="Xterm-Title-5.html" REL=next>
<LINK HREF="Xterm-Title-3.html" REL=previous>
<LINK HREF="Xterm-Title.html#toc4" REL=contents>
</HEAD>
<BODY>
<A HREF="Xterm-Title-5.html">Next</A>
<A HREF="Xterm-Title-3.html">Previous</A>
<A HREF="Xterm-Title.html#toc4">Contents</A>
<HR>
<H2><A NAME="s4">4. Examples for different shells</A></H2>
<P>Below we provide an set of examples for some of the more common shells.
We start with <CODE>zsh</CODE> as it provides several facilities that
make our job much easier. We will then progress through increasingly
difficult examples.
<P>
<P>In all the examples we test the environment variable <CODE>$TERM</CODE>
to make sure we only apply the escapes to xterms. We test for
<CODE>$TERM=xterm*</CODE>; the wildcard is because some variants (such as
rxvt) can set <CODE>$TERM=xterm-color</CODE>.
<P>
<P>We should make an extra comment about C shell derivatives, such as
<CODE>tcsh</CODE> and <CODE>csh</CODE>. In C shells, undefined variables are
fatal errors. Therefore, before testing the variable <CODE>$TERM</CODE>, it
is necessary to test for its existence so as not to break non-interactive
shells. To achieve this you must wrap the examples below in something
like:
<BLOCKQUOTE><CODE>
<PRE>
if ($?TERM) then
...
endif
</PRE>
</CODE></BLOCKQUOTE>
(In our opinion this is just one of many reasons not to use C shells. See
<I>
<A HREF="http://language.perl.com/versus/csh.whynot">Csh Programming Considered Harmful</A></I> for a useful
discussion).
<P>
<P>The examples below should be used by inserting them into the appropriate
shell initialisation file; i.e. one that is sourced by interactive shells
on startup. In most cases this is called something like
<CODE>.<I>shell</I>rc</CODE> (e.g. <CODE>.zshrc</CODE>, <CODE>.tcshrc</CODE>, etc).
<P>
<P>
<P>
<H2><A NAME="ss4.1">4.1 zsh</A>
</H2>
<P><CODE>zsh</CODE> provides some functions and expansions, which we will use:
<BLOCKQUOTE><CODE>
<PRE>
precmd () a function which is executed just before each prompt
chpwd () a function which is executed whenever the directory is changed
\e escape sequence for escape (ESC)
\a escape sequence for bell (BEL)
%n expands to $USERNAME
%m expands to hostname up to first '.'
%~ expands to directory, replacing $HOME with '~'
</PRE>
</CODE></BLOCKQUOTE>
There are many more expansions available: see the <CODE>zshmisc</CODE> man page.
<P>
<P>Thus, the following will set the xterm title to
"<CODE><I>username</I>@<I>hostname</I>: <I>directory</I></CODE>":
<BLOCKQUOTE><CODE>
<PRE>
case $TERM in
xterm*)
precmd () {print -Pn "\e]0;%n@%m: %~\a"}
;;
esac
</PRE>
</CODE></BLOCKQUOTE>
This could also be achieved by using <CODE>chpwd()</CODE> instead
of <CODE>precmd()</CODE>. The <CODE>print</CODE> builtin works like
<CODE>echo</CODE>, but gives us access to the <CODE>%</CODE> prompt escapes.
<P>
<P>
<H2><A NAME="ss4.2">4.2 tcsh</A>
</H2>
<P><CODE>tcsh</CODE> has some functions and expansions similar to those of
<CODE>zsh</CODE>:
<BLOCKQUOTE><CODE>
<PRE>
precmd () a function which is executed just before each prompt
cwdcmd () a function which is executed whenever the directory is changed
%n expands to username
%m expands to hostname
%~ expands to directory, replacing $HOME with '~'
%# expands to '>' for normal users, '#' for root users
%{...%} includes a string as a literal escape sequence
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>Unfortunately, there is no equivalent to <CODE>zsh</CODE>'s <CODE>print</CODE>
command allowing us to use prompt escapes in the title string,
so the best we can do is to use shell variables (in <CODE>~/.tcshrc</CODE>):
<BLOCKQUOTE><CODE>
<PRE>
switch ($TERM)
case "xterm*":
alias precmd 'echo -n "\033]0;${HOST}:$cwd\007"'
breaksw
endsw
</PRE>
</CODE></BLOCKQUOTE>
However, this gives the directory's full path instead of using <CODE>~</CODE>.
Instead you can insert the string in the prompt:
<BLOCKQUOTE><CODE>
<PRE>
switch ($TERM)
case "xterm*":
set prompt="%{\033]0;%n@%m:%~\007%}tcsh%# "
breaksw
default:
set prompt="tcsh%# "
breaksw
endsw
</PRE>
</CODE></BLOCKQUOTE>
which sets a prompt of "<CODE>tcsh% </CODE>", and an xterm title and icon
of "<CODE><I>username</I>@<I>hostname</I>: <I>directory</I></CODE>". Note that
the "<CODE>%{...%}</CODE>" must be placed around escape sequences (and cannot
be the last item in the prompt: see the <CODE>tcsh</CODE> man page for details).
<P>
<P>
<H2><A NAME="ss4.3">4.3 bash</A>
</H2>
<P><CODE>bash</CODE> supplies a variable <CODE>$PROMPT_COMMAND</CODE> which contains a
command to execute before the prompt. This example sets the title to
<CODE>username@hostname: directory</CODE>:
<BLOCKQUOTE><CODE>
<PRE>
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
</PRE>
</CODE></BLOCKQUOTE>
where <CODE>\033</CODE> is the character code for <CODE>ESC</CODE>,
and <CODE>\007</CODE> for <CODE>BEL</CODE>.
<P>
<P>Note that the quoting is important here: variables are expanded in
<CODE>"..."</CODE>, and not expanded in <CODE>'...'</CODE>. So
<CODE>$PROMPT_COMMAND</CODE> is set to an unexpanded value, but the
variables inside <CODE>"..."</CODE> are expanded when
<CODE>$PROMPT_COMMAND</CODE> is used.
<P>
<P>However, <CODE>$PWD</CODE> produces the full directory path. If we want to
use the <CODE>~</CODE> shorthand we need to embed the escape string in the
prompt, which allows us to take advantage of the following prompt expansions
provided by the shell:
<BLOCKQUOTE><CODE>
<PRE>
\u expands to $USERNAME
\h expands to hostname up to first '.'
\w expands to directory, replacing $HOME with '~'
\$ expands to '$' for normal users, '#' for root
\[...\] embeds a sequence of non-printing characters
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>Thus, the following produces a prompt of <CODE>bash$ </CODE>, and an xterm
title of <CODE>username@hostname: directory</CODE>:
<BLOCKQUOTE><CODE>
<PRE>
case $TERM in
xterm*)
PS1="\[\033]0;\u@\h: \w\007\]bash\\$ "
;;
*)
PS1="bash\\$ "
;;
esac
</PRE>
</CODE></BLOCKQUOTE>
Note the use of <CODE>\[...\]</CODE>, which tells <CODE>bash</CODE> to ignore
the non-printing control characters when calculating the width
of the prompt. Otherwise line editing commands get confused while
placing the cursor.
<P>
<P>
<H2><A NAME="ss4.4">4.4 ksh</A>
</H2>
<P><CODE>ksh</CODE> provides little in the way of functions and expansions, so
we have to insert the escape string in the prompt to have it updated
dynamically. This example produces a title of
<CODE>username@hostname: directory</CODE> and a prompt of <CODE>ksh$ </CODE>.
<BLOCKQUOTE><CODE>
<PRE>
case $TERM in
xterm*)
HOST=`hostname`
PS1='^[]0;${USER}@${HOST}: ${PWD}^Gksh$ '
;;
*)
PS1='ksh$ '
;;
esac
</PRE>
</CODE></BLOCKQUOTE>
However, <CODE>$PWD</CODE> produces the full directory path. We can remove the
prefix of <CODE>$HOME/</CODE> from the directory using the <CODE>${...##...}</CODE>
construct. We can also use <CODE>${...%%...}</CODE> to truncate the hostname:
<BLOCKQUOTE><CODE>
<PRE>
HOST=`hostname`
HOST=${HOST%%.*}
PS1='^[]0;${USER}@${HOST}: ${PWD##${HOME}/}^Gksh$ '
</PRE>
</CODE></BLOCKQUOTE>
Note that the <CODE>^[</CODE> and <CODE>^G</CODE> in the prompt string are single
characters for <CODE>ESC</CODE> and <CODE>BEL</CODE> (can be entered in emacs
using <CODE>C-q ESC</CODE> and <CODE>C-q C-g</CODE>).
<P>
<P>
<H2><A NAME="ss4.5">4.5 csh</A>
</H2>
<P>This is very difficult indeed in <CODE>csh</CODE>, and we end up doing something
like the following:
<BLOCKQUOTE><CODE>
<PRE>
switch ($TERM)
case "xterm*":
set host=`hostname`
alias cd 'cd \!*; echo -n "^[]0;${user}@${host}: ${cwd}^Gcsh% "'
breaksw
default:
set prompt='csh% '
breaksw
endsw
</PRE>
</CODE></BLOCKQUOTE>
where we have had to alias the <CODE>cd</CODE> command to do the work of
sending the escape sequence. Note that the <CODE>^[</CODE> and <CODE>^G</CODE> in
the string are single characters for <CODE>ESC</CODE> and <CODE>BEL</CODE>
(can be entered in emacs using <CODE>C-q ESC</CODE> and <CODE>C-q C-g</CODE>).
<P>
<P>Notes: on some systems <CODE>hostname -s</CODE> may be used to get
a short, rather than fully-qualified, hostname. Some users with
symlinked directories may find <CODE>`pwd`</CODE> (backquotes to run the
<CODE>pwd</CODE> command) gives a more accurate path than <CODE>$cwd</CODE>.
<P>
<P>
<P>
<HR>
<A HREF="Xterm-Title-5.html">Next</A>
<A HREF="Xterm-Title-3.html">Previous</A>
<A HREF="Xterm-Title.html#toc4">Contents</A>
</BODY>
</HTML>