Как сменить заголовок xterm

Ric Lister

ric@giccs.georgetown.edu

Перевод: Павел Гашев, SWSoft Pte Ltd.

версия 2.0, 27 октябрь 1999

Этот документ описывает, как изменять заголовки окон и подписи иконок в xterm. Даны примеры для различных оболочек, а в приложении представлены escape-последовательности для различных типов терминалов.


Содержание
1. Где можно найти этот документ
2. Статические заголовки
3. Динамические заголовки
3.1. escape-последовательности XTerm
3.2. Вывод escape-последовательностей
4. Примеры для различных оболочек
4.1. zsh
4.2. tcsh
4.3. bash
4.4. ksh
4.5. csh
5. Вывод имени текущей задачи
5.1. zsh
5.2. Другие оболочки
6. Приложение: escape-последовательности для других терминалов
6.1. IBM aixterm
6.2. SGI wsh, xwsh и winterm
6.3. Sun cmdtool и shelltool
6.4. CDE dtterm
6.5. HPterm
7. Приложение: примеры на других языках
7.1. C
7.2. Perl
8. Благодарности
9. Авторские права

1. Где можно найти этот документ

Этот документ является частью Linux HOWTO и находится по адресу http://sunsite.unc.edu/LDP/HOWTO/mini/Xterm-Title.html.

Последняя версия этого документа в различных форматах находится по адресу http://www.giccs.georgetown.edu/~ric/howto/Xterm-Title/.

Этот документ предшествует оригинальному HOWTO, который написал Winfried Trümper.


2. Статические заголовки

Статический заголовок для xterm, color-xterm или rxvt, может быть установлен при помощи ключей -T и -n:

xterm -T "Мой заголовок XTerm" -n "Мой заголовок иконки XTerm"


3. Динамические заголовки

Для большинства людей более полезны заголовки, отражающие динамическую информацию, такую как имя пользователя или текущий каталог.


3.1. escape-последовательности XTerm

Заголовок окна или имя иконки могут быть изменены при помощи escape-последовательностей:

  • ESC]0;строкаBEL -- Устанавливает строку в качестве имени иконки и заголовка окна

  • ESC]1;строкаBEL -- Устанавливает имя иконки

  • ESC]2;строкаBEL -- Устанавливает текст заголовка окна

где ESC - это символ escape (\033), а BEL - это символ bell (\007).

Вывод этой последовательности на терминал xterm приведет к изменению заголовка окна или иконки.

Примечание: эти последовательности относятся к терминалу xterm и его производным, таким как nxterm, color-xterm и rxvt. Другие типы терминалов часто используют другие последовательности; см. приложение. Полный список escape-последовательностей для xterm см. в файле ctlseq2.txt, поставляемом вместе с дистрибутивом xterm; или в xterm.seq, поставляемом с дистрибутивом rxvt.


3.2. Вывод escape-последовательностей

Для вывода информации, не меняющейся в течении всего сеанса работы - такой, как имя машины или имя пользователя, достаточно поместить в rc-файл следующую строчку:

echo -n "\033]0;${USER}@${HOST}\007"
которая установит заголовок окна в имя_пользователя@имя_машины, если переменные $USER и $HOST установлены правильно. Требуемые опции команды echo зависят от оболочки (см. примеры ниже).

Если в течении сеанса заголовок окна должен меняться (напр. текущий каталог), escape-последовательности должны выводиться каждый раз, когда изменяется приглашение оболочки. Некоторые оболочки позволяют вставлять такие последовательности прямо в строку приглашения. Это иллюстрируется в следующем разделе.


4. Примеры для различных оболочек

Ниже представлены примеры для большинства оболочек - начиная с zsh, который предоставляет для этого специальные средства, и далее в порядке увеличения сложности.

Чтобы убедиться в том, что мы находимся в xterm, мы проверяем переменную $TERM на предмет $TERM=xterm*; шаблон необходим, потому что в некоторых случаях (например для rxvt) она может быть установлена $TERM=xterm-color.

Заметим также, что в производных C-shell, таких как tcsh и csh, неопределенные переменные вызывают фатальную ошибку. Таким образом, перед тем как проверить содержимое переменной $TERM, мы должны проверить ее наличие. Чтобы добиться этого, мы должны использовать:

  if ($?TERM) then
      ...
  endif
(По нашему мнению, это одна из причин, почему не надо использовать C-shell. См. Csh Programming Considered Harmful).

Эти примеры можно использовать: просто вставьте их в соответствующий файл инициализации, выполняемый во время запуска интерактивной оболочки. В большинстве случаев он выглядит, примерно как .shellrc (например .zshrc, .tcshrc и т.д.).


4.1. zsh

zsh предоставляет несколько функций и расширений, которые мы будем использовать:

precmd ()   функция, выполняемая перед выводом каждого приглашения
chpwd ()    функция, выполняемая после смены текущего каталога
\e          escape-последовательность для символа ESC
\a          escape-последовательность для символа BEL
%n          $USERNAME
%m          имя машины до первой '.'
%~          путь к текущему каталогу, начиная с домашнего
Существует также много других расширений man zshmisc.

Таким образом, следующее меняет заголовок XTerm на "имя_пользователя@имя_машины: каталог":

case $TERM in
    xterm*)
        precmd () {print -Pn "\e]0;%n@%m: %~\a"}
        ;;
esac
То же самое достигается использованием chpwd() вместо precmd(). Встроенная команда print работает так же, как и echo, но обеспечивает доступ к %-командам.


4.2. tcsh

tcsh обладает похожими функциями:

precmd ()   функция, выполняемая перед выводом каждого приглашения
cwdcmd ()   функция, выполняемая после смены текущего каталога
%n          имя пользователя
%m          имя машины
%~          путь к текущему каталогу, начиная с домашнего
%#	    '%' для обычных пользователей, '#' для root'а
%{...%}     включает строчку как последовательность escape-сиволов

К сожалению, у tcsh нет аналога zsh-команды print, так что нам придется пользоваться обычными переменными. Для ˜/.tcshrc):

switch ($TERM)
    case "xterm*":
        alias precmd 'echo -n "\033]0;${HOST}:$cwd\007"'
        breaksw
endsw
Тем не менее, это дает нам полный путь к текущему каталогу, а не через ˜. Вместо этого в приглашение можно поместить свою строку:
switch ($TERM)
    case "xterm*":
        set prompt="%{\033]0;%n@%m:%~\007%}tcsh%# "
        breaksw
    default:
        set prompt="tcsh%# "
        breaksw
endsw
которая устанавливает приглашение "tcsh% ", а в xterm устанавливает заголовок "имя_пользователя@имя_машины: каталог". Заметим, что вокруг escape-последовательности стоят символы "%{...%}" (приглашение не должно заканчиваться этим: man tcsh).


4.3. bash

bash поддерживает переменную $PROMPT_COMMAND, содержащую команду, запускаемую перед выводом приглашения. Этот пример устанавливает заголовок окна имя_пользователя@имя_машины: каталог:

PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
где \033 - код символа ESC, а \007 - BEL.

Заметим, что кавычки здесь очень важны: значения переменных вставляются в "...", и не вставляются в '...'. Так что переменная $PROMPT_COMMAND устанавливается без подстановки переменных, которая происходит во время выполнения $PROMPT_COMMAND.

Тем не менее, $PWD дает полный путь к каталогу. Если вы хотите, чтобы он начинался с ˜, можете воспользоваться следующими расширениями:

\u          $USERNAME
\h          имя машины до первой '.'
\w          каталог, начиная с '~'
\$	    '$' для обычных пользователей, '#' для root
\[...\]     вставляет последовательность непечатаемых символов

Таким образом, следующее устанавливает приглашение bash$, а в заголовке XTerm имя_пользователя@имя_машины: каталог:

case $TERM in
    xterm*)
        PS1="\[\033]0;\u@\h: \w\007\]bash\\$ "
        ;;
    *)
        PS1="bash\\$ "
        ;;
esac
Замечу, что используется последовательность \[...\], которая говорит bash, во время вычисления ширины приглашения игнорировать символы, содержащиеся внутри. Иначе могут возникнуть проблемы с позиционированием курсора во время редактирования строки.


4.4. ksh

ksh дает не много возможностей для наших целей, так что нам придется вставить escape-последовательности прямо в приглашение. Следующий пример устанавливает заголовок окна имя_пользователя@имя_машины: каталог и приглашение ksh$.

case $TERM in
    xterm*)
        HOST=`hostname`
        PS1='^[]0;${USER}@${HOST}: ${PWD}^Gksh$ '
        ;;
    *)
        PS1='ksh$ '
        ;;
esac
$PWD выдает полный путь к каталогу. При помощи ${...##...} мы можем убрать префикс $HOME/ из каталога. Можно также укоротить имя машины через ${...%%...}:
HOST=`hostname`
HOST=${HOST%%.*}
PS1='^[]0;${USER}@${HOST}: ${PWD##${HOME}/}^Gksh$ '
Заметим, что ˆ[ и ˆG в строке приглашения - это просто символы ESC и BEL (они могут быть введены в emacs при помощи C-q ESC и C-q C-g).


4.5. csh

В csh это все достаточно сложно:

switch ($TERM)
    case "xterm*":
        set host=`hostname`
        alias cd 'cd \!*; echo -n "^[]0;${user}@${host}: ${cwd}^Gcsh% "'
        breaksw
    default:
        set prompt='csh% '
        breaksw
endsw
где мы переопределяем команду cd для того, чтобы она посылала escape-последовательности. Заметим, что ˆ[ и ˆG - символы ESC и BEL (они могут быть введены в emacs при помощи C-q ESC и C-q C-g).

Заметим, что на некоторых системах команда hostname -s выдает короткое имя машины, вместо длинного, а некоторые пользователи могут использовать `pwd` (обратные кавычки запускают команду pwd), вместо $cwd, чтобы получить более точный путь.


5. Вывод имени текущей задачи

Пользователь часто запускает "долгоиграющие" задачи, такие как top, текстовый редактор, почтовый клиент и т.д., и хочет видеть название задачи в заголовке окна. Это более сложная задача, и она может быть легко решена только в zsh.


5.1. zsh

zsh предоставляет идеальную встроенную функцию для этих целей:

preexec()   функция, выполняемая прямо перед запуском команды
$*,$1,...   аргументы, передающиеся в preexec()
Таким образом, мы можем вставить в заголовок имя текущей задачи:
case $TERM in
    xterm*)
      preexec () {
        print -Pn "\e]0;$*\a"
      }
    ;;
esac
Заметим, что функуция preexec() появилась в zsh 3.1.2, так что, возможно, вам придется обновить версию.


5.2. Другие оболочки

В других оболочках, не имеющих аналога функции preexec(), это осуществить не просто. Если кто-то это сделал, пошлите пример автору этого текста.


6. Приложение: escape-последовательности для других терминалов

Большинство современных терминалов являются производными xterm или rxvt и поддерживают те же escape-последовательности, которыми мы пользовались раньше. Некоторые фирменные терминалы, идущие вместе с различными версиями Unix, имеют свои собственные escape-последовательности.


6.1. IBM aixterm

aixterm понимает escape-последовательности xterm.


6.2. SGI wsh, xwsh и winterm

Эти терминалы устанавливают $TERM=iris-ansi и используют escape-последовательности:

  • ESCP1.yстрокаESC\ Устанавливает заголовок окна

  • ESCP3.yстрокаESC\ Устанавливает имя иконки

Для полного списка escape-последовательностей xwsh: man 1G xwsh.

Терминалы Irix также поддерживают последовательности xterm для установки заголовка окна и имени иконки раздельно, но не для установки и того и другого вместе.


6.3. Sun cmdtool и shelltool

cmdtool и shelltool устанавливают $TERM=sun-cmd и используют последовательности:

  • ESC]lстрокаESC\ Устанавливает заголовок окна

  • ESC]LстрокаESC\ Устанавливает имя иконки

Это ужасная программа - пользуйтесь чем-нибудь другим.


6.4. CDE dtterm

dtterm устанавливает $TERM=dtterm и понимает как последовательности xterm, так и Sun cmdtool (проверено на Solaris 2.5.1, Digital Unix 4.0, HP-UX 10.20).


6.5. HPterm

hpterm устанавливает $TERM=hpterm и использует последовательности:

  • ESC&f0kдлинаDстрока Устанавливает строку длиной в качестве заголовка окна

  • ESC&f-1kдлинаDстрока Устанавливает строку длиной в качестве имени иконки

Простая программа на C, вычисляющая длину строки и выводящая ее, выглядит примерно так:

#include <string.h>
int main(int argc, char *argv[])
{
    printf("\033&f0k%dD%s", strlen(argv[1]), argv[1]);
    printf("\033&f-1k%dD%s", strlen(argv[1]), argv[1]);
    return(0);
}

Можно написать простой скрипт, использующий ${#string} (zsh, bash, ksh) или ${%string} (tcsh) для вычисления длины строки. Для zsh:

case $TERM in
    hpterm)
        str="\e]0;%n@%m: %~\a"
	precmd () {print -Pn "\e&f0k${#str}D${str}"}
   	precmd () {print -Pn "\e&f-1k${#str}D${str}"}
	;;
esac


7. Приложение: примеры на других языках

Может быть полезно написать маленькую программу, вставляющую аргумент в заголовок. Ниже представлены несколько примеров.


7.1. C

#include <stdio.h>

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


7.2. Perl

#!/usr/bin/perl
print "\033]0;@ARGV\007";


8. Благодарности

Хочу выразить благодарность следующим людям, давшим советы, нашедшим опечатки и предоставившим примеры для этого документа.

Paul D. Smith <psmith@BayNetworks.COM> и Christophe Martin <cmartin@ipnl.in2p3.fr> , отметившим неправильные кавычки вокруг $PROMPT_COMMAND в bash. Благодаря этому теперь переменные подставляются правильно.

Paul D. Smith <psmith@BayNetworks.COM> , предложивший использовать \[...\] в приглашении bash для непечатаемых символов.

Christophe Martin <cmartin@ipnl.in2p3.fr> , предоставивший решение для ksh.

Keith Turner <keith@silvaco.com> , предоставивший escape-последовательности для Sun cmdtool и shelltool.

Jean-Albert Ferrez <ferrez@dma.epfl.ch> , указавший на некоторые несовместимости в использовании "PWD" и "$PWD", и использовании "\" с "\\".

Bob Ellison <papillo@hpellis.fc.hp.com> и Jim Searle <jims@broadcom.com>, проверившие dtterm на HP-UX.

Teng-Fong Seak <seak@drfc.cad.cea.fr>, предложивший опцию -s для hostname, использование `pwd`, и использование echo в csh.

Trilia <trilia@nmia.com>, предложивший примеры на других языках.

Brian Miller <bmiller@telstra.com.au>, предложивший escape-последовательности и примеры для hpterm.

Lenny Mastrototaro <lenny@click3x.com>, объяснивший, что терминалы Irix используют последовательности xterm.

Paolo Supino <paolo@init.co.il>, предложивший использовать \\$ в приглашении bash.


9. Авторские права

Авторские права на русский перевод этого текста принадлежат © 2000 SWSoft Pte Ltd. Все права зарезервированы.

Этот документ является частью проекта Linux HOWTO.

Авторские права на документы Linux HOWTO принадлежат их авторам, если явно не указано иное. Документы Linux HOWTO, а также их переводы, могут быть воспроизведены и распространены полностью или частично на любом носителе, физическом или электронном, при условии сохранения этой заметки об авторских правах на всех копиях. Коммерческое распространение разрешается и поощряется; но, так или иначе, автор текста и автор перевода желали бы знать о таких дистрибутивах.

Все переводы и производные работы, выполненные по документам Linux HOWTO, должны сопровождаться этой заметкой об авторских правах. Это делается в целях предотвращения случаев наложения дополнительных ограничений на распространение документов HOWTO. Исключения могут составить случаи получения специального разрешения у координатора Linux HOWTO, с которым можно связаться по адресу приведенному ниже.

Мы бы хотели распространить эту информацию по всем возможным каналам. Но при этом сохранить авторские права и быть уведомленными о всех планах распространения HOWTO. Если у вас возникли вопросы, пожалуйста, обратитесь к координатору проекта Linux HOWTO по электронной почте: или к координатору русского перевода Linux HOWTO компании SWSoft Pte Ltd. по адресу