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

Ric Lister

Перевод: Павел Гашев, ASPLinux

Аннотация

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


Содержание
Где можно найти этот документ
Статические заголовки
Динамические заголовки
Примеры для различных оболочек
Вывод имени текущей задачи
Приложение: escape-последовательности для других терминалов
Приложение: примеры на других языках
Благодарности
Авторские права

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

Этот документ является частью 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.


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

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


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

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


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.


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

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

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


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

Ниже представлены примеры для большинства оболочек - начиная с 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 и т.д.).


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, но обеспечивает доступ к %-командам.


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).


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, во время вычисления ширины приглашения игнорировать символы, содержащиеся внутри. Иначе могут возникнуть проблемы с позиционированием курсора во время редактирования строки.


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).


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, чтобы получить более точный путь.


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

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


zsh

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


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

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


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

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


IBM aixterm

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


SGI wsh, xwsh и winterm

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

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

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

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

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


Sun cmdtool и shelltool

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

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

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

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


CDE dtterm

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


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


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

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


C

#include <stdio.h>

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


Perl

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


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

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

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.


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

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

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

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

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

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