<!doctype linuxdoc system>

<article>

<!-- Title information -->

<title>Comment changer le titre d'un xterm</title>
<author>Ric Lister, <tt/ric&commat;giccs.georgetown.edu/ <newline>
traduction Jean-Albert Ferrez, <tt/Jean-Albert.Ferrez&commat;epfl.ch/ </author>
<date>Dernière modification&nbsp;: 22.11.1999, v2.0</date>

<abstract>
Ce document explique comment utiliser des séquences d'échappement pour
modifier dynamiquement le titre de la fenêtre et de l'icône d'un xterm. Des
exemples sont donnés pour plusieurs shells, et l'annexe donne les séquences
pour d'autres types de terminaux.
</abstract>

<toc>

<sect>Où trouver ce document
<p>
Ce document fait désormais partie des <url name="HOWTOs Linux"
url="http://sunsite.unc.edu/LDP/HOWTO/"> et peut être trouvé à&nbsp;: <url
url="http://sunsite.unc.edu/LDP/HOWTO/mini/Xterm-Title.html">.

<p>
La dernière version en date se trouve à&nbsp;: <url
url="http://www.giccs.georgetown.edu/~ric/howto/Xterm-Title/">.

<p>
Ce document remplace le howto initial écrit par Winfried Tr&uuml;mper.

<p>
Ndt&nbsp;: La version française de ce document se trouve à&nbsp;:
<url url="http://www.freenix.fr/linux/HOWTO/mini/Xterm-Title.html">

<sect>Titres statiques
<p>
Les titres des émulateurs de terminaux xterm, color-xterm ou rxvt peuvent
être donnés sur la ligne de commande avec les options -T et -n&nbsp;:

<tscreen><verb>
xterm -T "Le titre de mon XTerm" -n "Le titre de son icône"
</verb></tscreen>

<sect>Titres dynamiques
<p>
Bon nombre de personnes trouvent utile de faire apparaître dans le titre de
leur terminal une information qui change dynamiquement, telle que le nom du
serveur sur lequel on est connecté, le répertoire courant, etc.

<sect1>Les séquences d'échappement xterm

<p>
On peut changer le titre de la fenêtre et de l'icône dans un xterm lancé en 
utilisant les séquences d'échappement XTerm. Les séquences suivantes sont
utiles dans ce but&nbsp;:
<itemize>
  <item><tt>ESC]0;<bf>nom</bf>BEL</tt> -- Change le titre de la fenêtre et
  de l'icône
  <item><tt>ESC]1;<bf>nom</bf>BEL</tt> -- Change le titre de l'icône
  <item><tt>ESC]2;<bf>nom</bf>BEL</tt> -- Change le titre de la fenêtre
</itemize>

où ESC est le caractère escape (échappement, &bsol;033), et BEL est le
caractère bell (bip, &bsol;007).

<p>
Afficher l'une de ces séquences dans un xterm causera le changement du
titre de la fenêtre ou de l'icône.

<p>
<bf/Note/: Ces séquences fonctionnent également avec la plupart des dérivés de
xterm, tels que nxterm, color-xterm et rxvt. D'autres émulateurs de
terminaux utilisent d'autres séquences&nbsp;; quelques exemples sont donnés en
annexe. La liste complète des séquences d'échappement est donnée dans le
fichier <url name="ctlseq2.txt"
url="http://www.giccs.georgetown.edu/~ric/howto/Xterm-Title/ctlseq2.txt">
de la distribution de xterm, ou dans le fichier <url name="xterm.seq"
url="http://www.giccs.georgetown.edu/~ric/howto/Xterm-Title/xterm.seq"> de
la distribution de <url name="rxvt" url="http://www.rxvt.org/">.

<sect1>Afficher les séquences d'échappement

<p>
Pour les informations qui ne changent pas au cours de l'éxécution du shell,
telles que le serveur et le nom d'utilisateur, il suffit d'afficher les
séquences depuis le fichier rc du shell&nbsp;:
<tscreen><verb>
echo -ne "\033]0;${USER}@${HOST}\007"
</verb></tscreen>
devrait donner un titre du genre <tt>nom&commat;serveur</tt>, pour
autant que les variables <tt>$USER</tt> et <tt>$HOST</tt> soient
correctes. Les options requises pour echo peuvent dépendre du shell (cf
ci-dessous).

<p>
Pour les informations qui peuvent changer au cours de l'exécution du shell, 
telles que le répertoire courant, ces séquences doivent vraiment être
données lors de chaque changement de l'invite.
De cette façon, le titre est mis à jour lors de chaque commande
et peut ainsi refléter des informations telles que le répertoire en cours,
le nom d'utilisateur, le nom du serveur, etc. Certains shells offrent des
fonctions spéciales pour y parvenir, d'autres pas&nbsp;: il faut dans ce
cas insérer la chaîne directement dans le texte de l'invite.

<sect>Exemples pour quelques shells

<p>
Nous donnons ci-dessous des exemples pour les shells les plus
courants. Nous commençons avec <tt>zsh</tt> car il offre des possibilités
qui facilitent grandement notre tâche. Nous progresserons ensuite vers des
exemples de plus en plus difficiles.

<p>
Dans tous les exemples ci-dessous, on teste la variable d'environnement
TERM pour être certain de n'appliquer ces séquences que si l'on est dans un
xterm (ou dérivé). Le test est fait sur TERM=xterm*, de manière à inclure
au passage les variantes telles que TERM=xterm-color (défini par rxvt).

<p>
Encore une remarque au sujet des dérivés du C shell tels que <tt>tcsh</tt>
et <tt>csh</tt>. Dans ces shells, les variables non-définies causent des
erreurs fatales. Il est dès lors nécessaire avant de tester la valeur de la 
variable <tt>$TERM</tt>, de tester si elle existe pour ne pas
interrompre un shell non-interactif. Pour y parvenir, il faut inclure les
exemples ci-dessous dans quelque chose du genre&nbsp;:
<tscreen><verb>
  if ($?TERM) then
      ...
  endif
</verb></tscreen>
(À notre avis, il s'agit d'une raison parmi beaucoup d'autres de ne
pas utiliser les C shells. Voir <it><url name="Csh Programming Considered
Harmful" url="http://language.perl.com/versus/csh.whynot"></it> pour une
discussion utile).

<p>
Pour utiliser les exemples suivants, placez-les dans le fichier
d'initialisation du shell aproprié, c'est-à-dire un fichier lu lors du
lancement d'un shell interactif. Le plus souvent il s'agit de 
<tt>.<it>shell</it>rc</tt> (ex&nbsp;: <tt>.zshrc</tt>, <tt>.tcshrc</tt>, etc.)


<sect1>zsh

<p>
On utilise quelques fonctions et codes offerts par <tt>zsh</tt>&nbsp;:
<tscreen><verb>
precmd ()   fonction exécutée juste avant chaque invite
chpwd ()    fonction exécutée lors de chaque changement de répertoire
\e          code du caractère escape (ESC)
\a          code du caractère bip (BEL)
%n          code remplacé par $USERNAME
%m          code remplacé par le hostname jusqu'au premier '.'
%~          code remplacé par le répertoire, avec '~' à la place de $HOME
</verb></tscreen>
De nombreux autres codes sont disponibles, voir 'man zshmisc'.

<p>
Ainsi, le code suivant, mis dans &tilde;/.zshrc, affiche
"nom&commat;serveur:répertoire" dans le titre de la fenêtre (et de l'icône).
<tscreen><verb>
case $TERM in
   xterm*)
       precmd () {print -Pn "\e]0;%n@%m: %~\a"}
       ;;
esac
</verb></tscreen>
On arrive au même résultat en utilisant <tt>chpwd()</tt> au lieu de
<tt>precmd()</tt>. La commande interne <tt>print</tt> fonctionne comme
<tt>echo</tt>, mais donne accès aux séquences <tt>&percnt;</tt>.


<sect1>tcsh

<p>
<tt>tcsh</tt> offre des possibilités similaires à celles de
<tt>zsh</tt>&nbsp;:
<tscreen><verb>
precmd ()   fonction exécutée juste avant chaque invite
chpwd ()    fonction exécutée lors de chaque changement de répertoire
%n          code remplacé par $USERNAME
%m          code remplacé par le hostname jusqu'au premier '.'
%~          code remplacé par le répertoire, avec '~' à la place de $HOME
</verb></tscreen>

<p>
Malheureusement, il n'y a pas d'équivalent à la fonction print de
<tt>zsh</tt> qui permette d'utiliser les codes de l'invite dans la chaîne
du titre&nbsp;; le mieux que l'on puisse faire est d'utiliser les variables du
shell (dans <tt>&tilde;/.tcshrc</tt>)&nbsp;:
<tscreen><verb>
switch ($TERM)
   case "xterm*":
       alias precmd 'echo -n "\033]0;${HOST}:$cwd\007"'
       breaksw
endsw
</verb></tscreen>
mais on obtient alors le chemin complet du répertoire, sans '&tilde;'. Par
contre, on peut mettre la chaîne dans l'invite&nbsp;:
<tscreen><verb>
switch ($TERM)
   case "xterm*":
       set prompt="%{\033]0;%n@%m:%~\007%}tcsh%# "
       breaksw
   default:
       set prompt="tcsh%# "
       breaksw
endsw
</verb></tscreen>
ce qui donne "<tt>tcsh&percnt; </tt>" comme invite, et
"<tt><it>nom</it>&commat;<it>serveur</it>: <it>répertoire</it></tt>" dans
le titre (et l'icône) de xterm. Les "&percnt;&lcub;...&percnt;&rcub;"
doivent être placés autour des séquences d'échappement (et ne peuvent pas
être le dernier élément de l'invite, 'man tcsh' donne plus de détails).


<sect1>bash

<p>
<tt>bash</tt> offre la variable <tt>PROMPT_COMMAND</tt> qui contient une
commande à exécuter avant d'afficher l'invite. Ce code (inséré dans
<tt>&tilde;/.bashrc</tt>) affiche <tt>nom&commat;serveur: répertoire</tt>
dans le titre de la fenêtre (et de l'icône).
<tscreen><verb>
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
</verb></tscreen>
où <tt>&bsol;033</tt> est le caractère <tt>ESC</tt> et <tt>&bsol;007</tt>
<tt>BEL</tt>.

<p>
Il convient de noter que les guillemets jouent un rôle important&nbsp;: les
variables entre <tt>"..."</tt> sont évaluées, alors que celles entre
<tt>&quot;...&quot;</tt> ne le sont pas. Ainsi, <tt>PROMPT_COMMAND</tt>
reçoit bien le nom des variables, ces dernières étant évaluées lorsque
<tt>PROMPT_COMMAND</tt> est invoquée.

<p>
Cependant, <tt>&dollar;PWD</tt> donne le répertoire complet. Si l'on veut
utiliser le raccourci <tt>&tilde;</tt>, il faut placer toute la séquence
d'échappement dans l'invite pour avoir accès aux codes suivants&nbsp;:
<tscreen><verb>
\u          est remplacé par $USERNAME
\h          est remplacé par le hostname jusqu'au premier '.'
\w          est remplacé par le repertoire, avec '~' à la place de $HOME
\[...\]     signale une suite de caractère non-imprimables
</verb></tscreen>

<p>
Ainsi le code suivant produit l'invite <tt>bash&dollar; </tt>, et place
<tt>nom&commat;serveur: répertoire</tt> dans le titre (et l'icône) de
xterm.
<tscreen><verb>
case $TERM in
   xterm*)
       PS1="\[\033]0;\u@\h: \w\007\]bash\$ "
       ;;
   *)
       PS1="bash\$ "
       ;;
esac
</verb></tscreen>
L'utilisation de <tt>&bsol;&lsqb;...&bsol;&rsqb;</tt> signale à
<tt>bash</tt> la présence de caractères non-imprimables, information dont
il a besoin lorsqu'il calcule la longueur de l'invite. Sans cette
précaution, les commandes d'édition de ligne ne savent plus très bien où
placer le curseur.


<sect1>ksh

<p>
<tt>ksh</tt> n'offre pas grand chose en terme de fonctions et codes, il
faut donc mettre notre chaîne dans l'invite pour qu'elle soit mise à jour
dynamiquement. L'exemple suivant produit l'invite <tt>ksh&dollar; </tt>, et
place <tt>nom&commat;serveur: répertoire</tt> dans le titre (et l'icône) de
xterm.
<tscreen><verb>
case $TERM in
   xterm*)
       HOST=`hostname`
       PS1='^[]0;${USER}@${HOST}: ${PWD}^Gksh$ '
       ;;
   *)
       PS1='ksh$ '
       ;;
esac
</verb></tscreen>
Cependant, <tt>&dollar;PWD</tt> donne le répertoire complet. On peut ôter
le préfixe <tt>&dollar;HOME/</tt> en utilisant la construction
<tt>&dollar;&lcub;...&num;&num;...&rcub;</tt>. De même, on peut tronquer le
nom du serveur à l'aide de
<tt>&dollar;&lcub;...&percnt;&percnt;...&rcub;</tt>.
<tscreen><verb>
HOST=`hostname`
HOST=${HOST%%.*}
PS1='^[]0;${USER}@${HOST}: ${PWD##${HOME}/}^Gksh$ '
</verb></tscreen>
Les caractères <tt>&circ;&lsqb;</tt> et <tt>&circ;G</tt> désignent
<tt>ESC</tt> et <tt>BEL</tt> (ils peuvent être saisis dans emacs à l'aide
de <tt>C-q ESC</tt> et <tt>C-q C-g</tt>).


<sect1>csh

<p>
C'est assez difficile à réaliser avec <tt>csh</tt>. On finit par mettre ce
qui suit dans le &tilde;/.cshrc&nbsp;:
<tscreen><verb>
switch ($TERM)
   case "xterm*":
       set host=`hostname`
       alias cd 'cd \!*; echo -n "^[]0;${user}@${host}: ${cwd}^Gcsh% "'
       breaksw
   default:
       set prompt='csh% '
       breaksw
endsw
</verb></tscreen>
Il a fallu faire un alias de la commande <tt>cd</tt> pour mettre à jour
l'invite. Les caractères <tt>&circ;&lsqb;</tt> et <tt>&circ;G</tt>
désignent <tt>ESC</tt> et <tt>BEL</tt> (ils peuvent être saisis dans emacs
à l'aide de <tt>C-q ESC</tt> et <tt>C-q C-g</tt>).

<p>
Notes&nbsp;: sur certains systèmes <tt>hostname -s</tt> peut être utilisé
pour obtenir le nom de la machine au lieu du nom qualifié. Les utilisateurs
ayant des liens symboliques sur des répertoires trouveront <tt>`pwd`</tt>
plus précis que <tt>$cwd</tt>.


<sect>Afficher le nom de la commande en cours d'exécution

<p>
Souvent un utilisateur lance une longue commande en avant plan telle que
<tt>top</tt>, un éditeur, un lecteur de courrier électronique, etc, et
voudrait que le nom de cette commande figure dans le titre de la fenêtre.
C'est un problème délicat qui n'est facile à résoudre qu'avec <tt>zsh</tt>.

<sect1>zsh

<p>
<tt>zsh</tt> offre une fonction idéale pour cet objectif&nbsp;:
<tscreen><verb>
preexec()   fonction exécutée juste avant qu'une commande soit exécutée
$*,$1,...   arguments passés à preexec()
</verb></tscreen>
On peut donc insérer le nom de la commande de la manière suivante&nbsp;:
<tscreen><verb>
case $TERM in
    xterm*)
      preexec () {
        print -Pn "\e]0;$*\a"
      }
    ;;
esac
</verb></tscreen>
Note: la fonction <tt>preexec()</tt> est apparue vers la version 3.1.2 de 
<tt>zsh</tt>, vous devrez peut-être mettre à jour votre ancienne version.


<sect1>Autres shells

<p>
Ce n'est pas facile avec les autres shells qui n'ont pas l'équivalent de la 
fonction <tt>preexec()</tt>. Si quelqu'un a des exemples, merci de les
communiquer par email à l'auteur.


<sect>Annexe&nbsp;: séquences d'échappement pour d'autres émulateurs de
terminaux

<p>
De nombreux émulateurs de terminaux modernes sont des dérivés de
<tt>xterm</tt> ou <tt>rxvt</tt> et acceptent les séquences d'échappement
que nous avons utilisées jusqu'ici. Certains terminaux propriétaires
fournis avec les diverses variantes d'unix utilisent leur propres
séquences.


<sect1><tt>aixterm</tt> d'IBM

<p>
<tt>aixterm</tt> reconnaît les séquences d'échappement de <tt>xterm</tt>.


<sect1><tt>wsh</tt>, <tt>xwsh</tt> et <tt>winterm</tt> de SGI
<p>
Ces terminaux définissent <tt>$TERM=iris-ansi</tt> et utilisent&nbsp;:
<itemize>
<item><tt>ESCP1.y<it>texte</it>ESC\    Pour le titre de la fenêtre</tt>
<item><tt>ESCP3.y<it>texte</it>ESC\    Pour le titre de l'icône</tt>
</itemize>
La liste complète des séquences est donnée dans la page man
<tt>xwsh(1G)</tt>.

<p>
Les terminaux d'Irix supportent également les séquences de <tt>xterm</tt>
pour définir individuellement le titre de la fenêtre et de l'icône, mais
pas celle pour définir les deux en même temps.


<sect1><tt>cmdtool</tt> et <tt>shelltool</tt> de Sun
<p>
<tt>cmdtool</tt> et <tt>shelltool</tt> définissent <tt>$TERM=sun-cmd</tt> et
utilisent&nbsp;:
<itemize>
<item><tt>ESC]l<it>texte</it>ESC\    Pour le titre de la fenêtre</tt>
<item><tt>ESC]L<it>texte</it>ESC\    Pour le titre de l'icône</tt>
</itemize>
Ce sont des programmes vraiment horribles, il vaut mieux utiliser autre chose.

<sect1>CDE dtterm
<p>
<tt>dtterm</tt> définit <tt>$TERM=dtterm</tt>. Il semble qu'il reconnaisse à la fois les
séquences <tt>xterm</tt> standard ainsi que celles du <tt>cmdtool</tt> de
Sun (testé sur Solaris 2.5.1, Digital Unix 4.0, HP-UX 10.20).


<sect1>HPterm

<p>
<tt>hpterm</tt> définit <tt>$TERM=hpterm</tt> et utilise les séquences
suivantes&nbsp;:
<itemize>
<item><tt>ESC&amp;f0k<it>longueur</it>D<it>texte</it>  Donne le texte
<it>texte</it> de longueur <it>longueur</it> comme titre de fenêtre</tt>
<item><tt>ESC&amp;f-1k<it>longueur</it>D<it>texte</it>  Donne le texte
<it>texte</it> de longueur <it>longueur</it> comme nom de l'icône</tt>
</itemize>

<p>
Un programme C simple pour calculer la longueur et afficher la bonne
séquence ressemble à&nbsp;:
<tscreen><verb>
#include <string.h>
int main(int argc, char *argv[])
{
    printf("\033&amp;f0k%dD%s", strlen(argv[1]), argv[1]);
    printf("\033&amp;f-1k%dD%s", strlen(argv[1]), argv[1]);
    return(0);
}
</verb></tscreen>

<p>
On peut également écrire un shell-script équivalent, utilisant
<tt>${#string}</tt> (<tt>zsh</tt>, <tt>bash</tt>, <tt>ksh</tt>) ou
<tt>${%string}</tt> (<tt>tcsh)</tt> pour obtenir la longueur d'une
chaîne. L'exemple suivant est pour <tt>zsh</tt>&nbsp;:
<tscreen><verb>
case $TERM in
    hpterm)
        str="\e]0;%n@%m: %~\a"
	precmd () {print -Pn "\e&amp;f0k${#str}D${str}"}
   	precmd () {print -Pn "\e&amp;f-1k${#str}D${str}"}
	;;
esac
</verb></tscreen>


<sect>Annexe&nbsp;: exemples dans d'autres langages

<p>
Il peut être utile d'écrire des bouts de codes pour changer le titre de la
fenêtre à l'aide des séquences <tt>xterm</tt>. Voici quelques exemples&nbsp;:


<sect1>C

<p>
<tscreen><verb>
#include <stdio.h>

int main (int argc, char *argv[]) {
  printf("%c]0;%s%c", '\033', argv[1], '\007');
  return(0);
}
</verb></tscreen>


<sect1>Perl

<p>
<tscreen><verb>
#!/usr/bin/perl
print "\033]0;@ARGV\007";
</verb></tscreen>


<sect>Crédits
<p>
Merci aux personnes suivantes pour leur contribution à ce document.

<p>
Paul D. Smith <tt>&lt;psmith@BayNetworks.COM&gt;</tt> et Christophe Martin
<tt>&lt;cmartin@ipnl.in2p3.fr&gt;</tt> ont tous les deux remarqué que j'avais
interverti les guillemets dans le <tt>PROMPT_COMMAND</tt> pour
<tt>bash</tt>. Les avoir dans le bon ordre garantit que les variables sont
évaluées dynamiquement.

<p>
Paul D. Smith <tt>&lt;psmith@BayNetworks.COM&gt;</tt> a proposé de protéger
les caractères non-imprimables dans l'invite de <tt>bash</tt>.

<p>
Christophe Martin <tt>&lt;cmartin@ipnl.in2p3.fr&gt;</tt> a donné la
solution pour ksh.

<p>
Keith Turner <tt>&lt;keith@silvaco.com&gt;</tt> a donné les séquences
d'échappement pour les <tt>cmdtool</tt> et <tt>shelltool</tt> de Sun.

<p>
Jean-Albert Ferrez <tt>&lt;ferrez@dma.epfl.ch&gt;</tt>
a signalé un manque de cohérence dans l'utilisation de "<tt>PWD</tt>"
et "<tt>$PWD</tt>", ainsi que de "<tt>\</tt>" et "<tt>\\</tt>".

<p>
Bob Ellison <tt>&lt;papillo@hpellis.fc.hp.com&gt;</tt> et
Jim Searle <tt>&lt;jims@broadcom.com&gt;</tt> ont testé <tt>dtterm</tt>
sur HP-UX.

<p>
Teng-Fong Seak <tt>&lt;seak@drfc.cad.cea.fr&gt;</tt> a suggéré l'option
<tt>-s</tt> de <tt>hostname</tt>, l'utilisation de <tt>`pwd`</tt>, et de
<tt>echo</tt> sous <tt>csh</tt>.

<p>
Trilia <tt>&lt;trilia@nmia.com&gt;</tt> a suggéré les exemples dans
d'autres langages.

<p>
Brian Miller <tt>&lt;bmiller@telstra.com.au&gt;</tt> a fourni les séquences 
d'échappement et les exemples pour <tt>hpterm</tt>.

<p>
Lenny Mastrototaro <tt>&lt;lenny@click3x.com&gt;</tt> a expliqué
l'utilisation des séquences xterm dans les émulateurs de terminaux Irix.

<p>
Paolo Supino <tt>&lt;paolo@init.co.il&gt;</tt> a suggéré l'utilisation de
<tt>\\$</tt> dans le prompt de <tt>bash</tt>.

</article>
