Добавить в избранное | Сделать стартовой страницей

Большая Linux библиотека для пользователей OS Linux и ПО для нее
Есть что сказать? Нужен совет? Посети наш форум.


-


Руководство по GNU Emacs. часть 5

Сборка и тестирование программ

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

Запуск компиляторов в Emacs

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

M-x compile
Асинхронно запускает компилятор под управлением Emacs, выводя сообщения об ошибках в буфер `*compilation*'.
M-x grep
Асинхронно запускает grep под управлением Emacs, перечисляя совпавшие строки в буфере `*grep*'.
M-x grep-find
Запускает grep через find с предоставленными пользователем аргументами, направляя вывод в буфер `*grep*'.
M-x kill-compilation
M-x kill-grep
Уничтожает работающие подпроцессы компиляции или grep.

Чтобы запустить make или другую команду компиляции, выполните M-x compile. Эта команда считывает командную строку оболочки, используя минибуфер, и затем выполняет эту командную строку в подчиненной оболочке, помещая вывод в буфер с именем `*compilation*'. В качестве рабочего каталога для выполнения этой команды используется каталог по умолчанию текущего буфера, следовательно, компиляция производится в этом каталоге.

Когда считывается командная строка оболочки, появляется минибуфер, содержащий командную строку по умолчанию; это команда, которую вы использовали при последнем применении M-x compile. Если вы наберете просто RET, то снова будет использована та же самая командная строка. Для первой M-x compile по умолчанию используется `make -k'. Значение по умолчанию берется из переменной compile-command; если соответствующая команда компиляции для файла является чем-то другим, не `make -k', то может быть полезно иметь для этого файла локальное значение compile-command (смотрите раздел Локальные переменные в файлах).

Запуск компиляции показывает буфер `*compilation*' в другом окне, но не выбирает его. Строка режима этого буфера сообщает вам, закончилась ли компиляция, при помощи слов `run' или `exit' в круглых скобках. Вы не обязаны держать этот буфер видимым, компиляция продолжается в любом случае. Пока компиляция продолжается, в строках режима всех буферов появляется слово `Compiling'. Если это слово исчезает, компиляция закончена.

Если вы хотите видеть протокол компиляции по мере его появления, переключитесь в буфер `*compilation*' и переместите точку в его конец. Когда точка расположена в конце, новый вывод процесса компиляции вставляется перед точкой, и она остается в конце. Если точка не находится в конце этого буфера, она остается на своем месте, тогда как дальнейший вывод компиляции добавляется в конец буфера.

Если вы установите переменную compilation-scroll-output в значение, отличное от nil, то буфер компиляции всегда прокручивается, чтобы показывать вывод по мере его появления.

Чтобы прекратить процесс компиляции, выполните команду M-x kill-compilation. Когда процесс компиляции будет прерван, строка режима буфера `*compilation*' изменится, и в ней будет слово `signal' вместо `run'. Запуск новой компиляции также уничтожает любую работающую компиляцию, так как в одно время может существовать только одна. Однако M-x compile требует подтверждения перед фактическим уничтожением уже запущенной компиляции.

Поиск с Grep под Emacs

Точно так же, как вы запускаете из Emacs компилятор, и затем обращаетесь к строкам, где были ошибки компиляции, вы можете запустить grep и затем обратиться к строкам, где были найдены совпадения. Это работает путем интерпретации сообщений о совпадениях от grep как сообщений об "ошибках".

Чтобы сделать это, наберите M-x grep и введите командную строку, указывающую, как нужно запускать grep. Используйте те же аргументы, которые вы дали бы grep при обычном запуске: регулярное выражение в формате grep (обычно в одиночных кавычках, чтобы отменить особый смысл специальных символов оболочки), за которым следуют имена файлов, в которых можно использовать шаблоны. Вывод из grep идет в буфер `*compilation*'. Вы можете обратиться к совпавшимстрокам при помощи C-x ` и RET, как к ошибкам компиляции.

Если вы зададите для M-x grep префиксный аргумент, она найдет в окрестности точки тег (смотрите раздел Таблицы тегов) и поместит его в команду grep по умолчанию.

Команда M-x grep-find похожа на M-x grep, но предлагает другую командную строку по умолчанию -- строку, которая запускает find и grep, так что поиск производится в каждом файле дерева каталогов. Смотрите также команду find-grep-dired, раздел Dired и find.

Режим Compilation

В буфере `*compilation*' используется особый основной режим, режим Compilation, основная цель которого -- предоставить удобный способ просмотреть строку исходного текста, где случилась ошибка.

C-x `
Обратиться к позиции следующего сообщения об ошибке компиляции или совпадения, найденного grep.
RET
Обратиться к позиции сообщения об ошибке, в которой находится точка. Эта команда применяется в буфере компиляции.
Mouse-2
Обратиться к позиции сообщения об ошибке, на котором вы щелкнули.

Вы можете обратиться к исходному тексту для любого конкретного сообщения об ошибке, переместив точку в буфере `*compilation*' к этому сообщению и нажав RET (compile-goto-error). Или щелкните на этом сообщении об ошибке Mouse-2; тогда вам не обязательно сначала переключаться в буфер `*compilation*'.

Чтобы последовательно сделать грамматический разбор сообщений компилятора об ошибках, набирайте C-x ` (next-error). Знак, стоящий после C-x -- это обратная кавычка или "акцент грав", а не обычная одиночная кавычка. Эта команда доступна во всех буферах, а не только в буфере `*compilation*'; она показывает следующее сообщение об ошибке вверху одного окна и текст, в котором находится эта ошибка, в другом окне.

Когда C-x ` используется первый раз после начала компиляции, она передвигается к положению первой ошибки. Последующие использования C-x ` продвигают вниз к следующим ошибкам. Если вы обратились к файлу по какому-то сообщению об ошибке с помощью RET или Mouse-2, последующие команды C-x ` продвигаются с этого места. Когда C-x ` доходит до конца буфера и не может найти больше сообщений, она завершается неуспехом и Emacs выдает ошибку.

C-u C-x ` начинает просмотр буфера `*compilation*' сначала. Это один из способов еще раз обработать один и тот же набор ошибок.

Режим Compilation также переопределяет ключи SPC и DEL для прокрутки по целому экрану, а M-n и M-p -- для перемещения к следующему или предыдущему сообщению об ошибке. Вы также можете использовать M-{ и M-} для перемещения вверх и вниз к сообщению об ошибке для другого исходного файла.

Возможности режима Compilation также доступны во второстепенном режиме, называемом Compilation Minor. Он позволяет вам разбирать сообщения об ошибках в любом буфере, а не только в обычном буфере для вывода протокола компиляции. Для включения этого второстепенного режима наберите M-x compilation-minor-mode. Это определит ключи RET и Mouse-2 как в основном режиме Compilation.

Второстепенный режим Compilation работает в любом буфере, если содержимое этого буфера имеет понятный ему формат. В буфере Rlogin (смотрите раздел Оболочка на удаленной машине), второстепенный режим Compilation автоматически получает удаленные исходные файлы по FTP (смотрите раздел Имена файлов).

Подоболочки для компиляции

Emacs использует для команды компиляции оболочку, но ей указывается, что она должна быть неинтерактивной. В частности, это означает, что оболочка начинается без подсказки. Если вы обнаружите, что буфер `*compilation*' уродуют ваши обычные подсказки оболочки, то это значит, что вы сделали ошибку в вашем файле инициализации оболочки, установив подсказку, не учитывая условий, когда она не должна появляться. (Файл инициализации может называться `.bashrc', `.profile', `.cshrc', `.shrc' или еще как-нибудь в зависимости от используемой вами оболочки.) Файл инициализации оболочки должен устанавливать подсказку, только если подсказка уже есть. Покажем, как это нужно делать в csh:

if ($?prompt) set prompt = ...

А так это делается в bash:

if [ "${PS1+set}" = set ]
then PS1=...
fi

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

"Операционная система" MS-DOS не поддерживает асинхронные подпроцессы; чтобы как-то обойти этот недостаток, M-x compile в MS-DOS запускает команду компиляции синхронно. Как следствие, вы должны дождаться завершения этой команды до того, как сможете сделать что-то в Emacs. Смотрите раздел Emacs и MS-DOS.

Запуск отладчиков в Emacs

Библиотека GUD (Grand Unified Debugger(8)) предоставляет интерфейс к различным символьным отладчикам из Emacs. Мы рекомендуем отладчик GDB, который распространяется свободно, но вы также можете запускать DBX, SDB или XDB, если они у вас есть. GUD может также служить интерфейсом к отладочному режиму Perl, отладчику Python PDB и JDB, отладчику Java.

Запуск GUD

Существует несколько команд для запуска отладчика, каждая соответствует конкретной программе-отладчику.

M-x gdb RET файл RET
Запускает GDB как подпроцесс Emacs. Эта команда создает буфер для ввода и вывода GDB и переключает в него. Если буфер GDB уже существует, она просто переключает в этот буфер.
M-x dbx RET файл RET
Аналогично, но запускает DBX вместо GDB.
M-x xdb RET файл RET
Аналогично, но запускает XDB, а не GDB. Используйте переменную gud-xdb-directories для задания каталогов поиска исходных файлов.
M-x sdb RET файл RET
Аналогично, но запускает SDB, а не GDB. Некоторые версии SDB не называют в своих сообщениях имена исходных файлов. Когда вы используйте их, у вас должна быть создана правильная таблица тегов (смотрите раздел Таблицы тегов), чтобы GUD мог найти функции в исходных файлах. Если вы не обращались к таблице тегов или таблица тегов не содержит одну из функций, вы получите сообщение, говорящее `The sdb support requires a valid tags table to work'.(9) Если это случилось, создайте в рабочем каталоге правильную таблицу тегов и попробуйте снова.
M-x perldb RET файл RET
Запускает интерпретатор Perl в отладочном режиме для отладки файла, программы на Perl.
M-x jdb RET файл RET
Запускает для отладки файла отладчик Java.
M-x pdb RET файл RET
Запускает для отладки файла отладчик Python.

Каждая из этих команд принимает один аргумент: командную строку для вызова отладчика. В простейшем случае, задайте просто имя исполняемого файла, который вы хотите отлаживать. Вы также можете использовать ключи, поддерживаемые вашим отладчиком. Однако шаблоны и переменные оболочки недопустимы. GUD предполагает, что первый аргумент, не начинающийся с `-', является именем исполняемого файла.

Emacs может запустить только один отладочный процесс в одно время.

Управление отладчиком

Когда вы запустили отладчик с помощью GUD, он использует буфер Emacs для обычного ввода и вывода. Этот буфер называется буфером GUD. Отладчик показывает строки исходных файлов, обращаясь к ним в буферах Emacs. Стрелка (`=>') в одном из буферов указывает на исполняемую в данный момент строку. Перемещение точки в буфере не изменяет положения стрелки.

Вы можете в любое время начать редактировать исходные файлы в тех буферах, которые их показывают. Стрелка не является частью текста файла; она появляется лишь на экране. Если вы действительно изменяете исходный файл, помните, что удаление или вставка строк собьет положение стрелки; GUD не может определить, какая строка строка соответствовала номеру строки в сообщении отладчика до вашего изменения. Кроме того, чтобы ваши изменения нашли отражение в таблицах отладчика, вам обычно придется перекомпилировать и перезапустить программу.

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

Команды GUD

Буфер диалога с GUD использует вариант режима Shell, так что вам доступны команды этого режима (смотрите раздел Режим Shell). Режим GUD также предоставляет команды для установки и сброса контрольных точек, для выбора фреймов стека и для пошагового прохода по программе. Эти команды доступны как в буфере GUD, так и глобально, но с разными привязками.

Команды управления контрольными точками обычно используются в буферах, обращающихся к файлам, потому что они дают способ указать где поставить или убрать контрольную точку. Вот глобальные привязки для установки контрольных точек:

C-x SPC
Устанавливает контрольную точку в исходной строке, где находится точка.

Это другая специальная команда, предоставляемая GUD. Ключи, начинающиеся с C-c, доступны только в буфере диалога с GUD. Привязки ключей, начинающиеся с C-x C-a, доступны и в буфере диалога с GUD, и в исходных файлах.

C-c C-l
C-x C-a C-l
Отображает в другом окне последнюю строку, на которую появилась ссылка в буфере GUD (то есть строку, указанную в последнем сообщении о позиции в программе). Это запускает команду gud-refresh.
C-c C-s
C-x C-a C-s
Исполняет одну строку кода (gud-step). Если строка содержит вызов функции, выполнение останавливается после входа в нее.
C-c C-n
C-x C-a C-n
Исполняет одну строку кода, проходя через вызовы функций без остановки (gud-next).
C-c C-i
C-x C-a C-i
Исполняет одну машинную инструкцию (gud-stepi).
C-c C-r
C-x C-a C-r
Продолжает исполнение с неопределенной точкой останова. Программа продолжит работу до тех пор, пока не попадет на контрольную точку, завершится или получит сигнал, проверяемый отладчиком (gud-cont).
C-c C-d
C-x C-a C-d
Удаляет контрольную точку (одну или несколько) в текущей строке исходного текста, если они поставлены (gud-remove). Если вы вызовите эту команду в буфере диалога с GUD, она применяется к строке, на который в последний раз остановилась программа.
C-c C-t
C-x C-a C-t
Устанавливает временную контрольную точку на текущей исходной строке, если такая есть в данный момент. Если вы вызовите эту команду в буфере диалога с GUD, она применяется к строке, на которой программа остановилась в последний раз.

Перечисленные выше команды относятся ко всем поддерживаемым отладчикам. Если вы пользуетесь GDB или DBX (некоторыми версиями), доступны такие дополнительные команды:

C-c <
C-x C-a <
Выбирает следующий внешний фрейм стека (gud-up). Это эквивалентно команде `up'.
C-c >
C-x C-a >
Выбирает следующий внутренний фрейм стека (gud-down). Это эквивалентно команде `down'.

Если вы пользуетесь GDB, доступны следующие привязки:

TAB
Завершает имя символа (gud-gdb-complete-command). Этот ключ доступен только в буфере диалога с GUD и требует GDB версии 4.13 или более поздней.
C-c C-f
C-x C-a C-f
Исполняет программу до тех пор, пока не произойдет возврат из выбранного фрейма стека (или пока программа не остановится по другой причине).

Эти команды интерпретируют числовой аргумент как счетчик повторений, если это имеет смысл.

Так как TAB служит командой завершения, вы не можете использовать ее для набора знака табуляции в качестве ввода для программы, которую вы отлаживаете в GDB. Вместо этого, чтобы ввести знак табуляции, набирайте C-q TAB.

Настройка GUD

Во время запуска GUD выполняет одну из следующих ловушек: gdb-mode-hook, если вы пользуетесь GDB; dbx-mode-hook, если вы пользуетесь DBX; sdb-mode-hook, если вы пользуетесь SDB; xdb-mode-hook, если вы пользуетесь XDB; perldb-mode-hook для отладочного режима Perl; jdb-mode-hook для PDB; jdb-mode-hook для JDB. Вы можете использовать эти ловушки для определения ваших собственных привязок ключей для буфера диалога с отладчиком. Смотрите раздел Ловушки.

Вот удобный способ определить команду, которая посылает отладчику некоторую командную строку и устанавливает для нее привязку в буфере диалога с отладчиком:

(gud-def функция командная-строка привязка док-строка)

Это определит команду с именем функция, которая посылает процессу отладчика командную-строку, и даст ей строку описания док-строка. Вы можете использовать определенную таким образом команду в любом буфере. Если привязка не равна nil, gud-def также привязывает эту команду к C-c привязка в режиме буфера GUD и к C-x C-a привязка глобально.

Командная строка может содержать определенные `%'-последовательности, которые обозначают данные, подставляемые во время вызова функции:

`%f'
Имя текущего исходного файла. Если текущим является буфер GUD, то "текущий исходный файл" -- это файл, в котором программа остановилась.
`%l'
Номер текущей исходной строки. Если текущим является буфер GUD, то "текущая исходная строка" -- это строка, на которой остановилась программа.
`%e'
Текст lvalue языка Си или выражения вызова функции, в котором или рядом с которым находится точка.
`%a'
Текст шестнадцатиричного адреса, в котором или рядом с которым находится точка.
`%p'
Числовой аргумент вызванной функции в виде десятичного числа. Если эта команда используется без числового аргумента, `%p' будет пустой строкой. Если вы не использовали `%p' в командной строке, определяемая вами команда будет игнорировать любой числовой аргумент.

Исполнение лисповских выражений

В Emacs есть несколько основных режимов для языков Лисп и Scheme. В них используются одни и те же команды редактирования, но разные команды для исполнения выражений Лиспа. У каждого режима свое предназначение.

Режим Emacs-Lisp
Режим для редактирования исходных файлов программ, запускаемых в Emacs Lisp. Этот режим определяет C-M-x для вычисления текущего определения функции. Смотрите раздел Библиотеки Лисп-программ для Emacs.
Режим Lisp Interaction
Режим для диалогового сеанса с Emacs Lisp. Он определяет C-j для вычисления s-выражения перед точкой и вставки его значения в буфер. Смотрите раздел Буферы диалога с Лиспом.
Режим Lisp
Режим для редактирования исходных файлов программ, которые запускают в Лиспах, отличных от Emacs Lisp. Этот режим определяет C-M-x так, чтобы он посылал текущее определение функции подчиненному Лисп-процессу. Смотрите раздел Запуск внешнего Лиспа.
Режим Inferior Lisp
Режим для диалогового сеанса с подчиненным процессом Лиспа. Этот режим объединяет специальные средства режима Lisp и режима Shell (смотрите раздел Режим Shell).
Режим Scheme
Подобен режиму Lisp, но для программ на Scheme.
Режим Inferior Scheme
Режим для диалогового сеанса с подчиненным процессом Scheme.

Большинство команд редактирования для работы с программами на Лиспе на самом деле доступны глобально. Смотрите раздел Редактирование программ.

Библиотеки Лисп-программ для Emacs

Лисп-программы для команд редактирования хранятся в файлах, чьи имена традиционно оканчиваются на `.el'. Это окончание сообщает Emacs, что редактировать их следует в режиме Emacs-Lisp (смотрите раздел Исполнение лисповских выражений).

Чтобы выполнить файл с кодом на Emacs Lisp, используйте M-x load-file. Эта команда считывает имя файла, используя минибуфер, и затем выполняет содержимое этого файла как Лисп-программу. Для этого нет необходимости сначала обращаться к файлу, в любом случае эта команда считывает файл таким, каким он находится на диске, а не как текст в буфере Emacs.

Если файл Лисп-программы установлен в каталогах с библиотеками Emacs Lisp, пользователи могут загрузить его, используя M-x load-library. Программы могут загрузить его, вызывая load-library, или с помощью load, более низкоуровневой функции, которая похожа на эту, но допускает некоторые дополнительные аргументы.

M-x load-library отличается от M-x load-file тем, что она просматривает последовательность каталогов и пробует три имени в каждом из них. Предположим, ваш аргумент -- это lib; три этих имени --- это `lib.elc', `lib.el' и наконец просто `lib'. Если существует файл `lib.elc', по соглашению это файл, получаемый в результате компиляции; лучше загрузить скомпилированный файл, так как он загружается и работает быстрее.

Если load-library обнаружит, что `lib.el' новее, чем `lib.elc', она напечатает сообщение, потому что это похоже на то, что кто-то внес изменения в `.el'-файл и забыл его перекомпилировать.

Так как аргумент для load-library обычно не является сам по себе действительным именем файла, то завершение имени файла недоступно. Действительно, используя эту команду, вы не знаете точно, какое имя файла будет использовано.

Последовательность каталогов, просматриваемых M-x load-library, определяется переменной load-path, списком строк, являющихся именами каталогов. По умолчанию значение этого списка содержит каталог, где хранится Лисп-код самого Emacs. Если у вас есть свои собственные библиотеки, поместите их в один каталог и добавьте этот каталог к load-path. nil в этом списке означает текущий каталог по умолчанию, но скорее всего, ставить в список nil -- не самая лучшая идея. Если вы сами решили, что хотите иметь nil в этом списке, то наиболее вероятно, что в действительности вы хотите в этот раз использовать M-x load-file.

Часто вы не должны давать никакой команды, чтобы загрузить какую-нибудь библиотеку, так как определенные в ней команды настроены таким образом, что выполняют автозагрузку этой библиотеки. Попытка запуска любой из этих команд приводит к вызову load для загрузки нужной библиотеки. Это меняет определения автозагрузки на действительные определения из библиотеки.

Код на Emacs Lisp может быть откомпилирован в байт-код, который загружается быстрее, занимает после загрузки меньше памяти и быстрее выполняется. Смотрите раздел `Byte Compilation' в the Emacs Lisp Reference Manual. По соглашению, скомпилированный код библиотеки помещается в отдельный файл, чье имя состоит из имени исходного файла библиотеки с добавленным `c'. Таким образом, скомпилированный код для `foo.el' попадает в `foo.elc'. Поэтому load-library сначала ищет `.elc'-файлы.

Вычисление выражений Emacs-Lisp

Программы на Лиспе, предназначенные для запуска в Emacs, нужно редактировать в режиме Emacs-Lisp. Это происходит автоматически для файлов, чьи имена кончаются на `.el'. В противоположность этому, сам режим Lisp используется для редактирования Лисп-программ, предназначенных для других Лисп-систем. Чтобы перейти в режим Emacs-Lisp, используете команду M-x emacs-lisp-mode.

Для проверки программ на Лиспе, предназначенных для запуска в Emacs, часто полезно вычислять какую-нибудь часть программы в том виде, как она находится в буфере Emacs. Например, после изменения текста определения лисповской функции, вычисление определения устанавливает это изменение для будущих вызовов функции. Вычисление лисповских выражений также удобно при любом редактировании для запуска неинтерактивных функций (функций, которые не являются командами).

M-:
Считывает одно лисповское выражение в минибуфере, вычисляет его и печатает его значение в эхо-области (eval-expression).
C-x C-e
Вычисляет лисповское выражение, находящееся перед точкой, и печатает его значение в эхо-области (eval-last-sexp).
C-M-x
Вычисляет определение функции, содержащее точку или находящееся после нее, и печатает его значение в эхо-области (eval-defun).
M-x eval-region
Вычисляет все лисповские выражения в области.
M-x eval-current-buffer
Вычисляет все лисповские выражения в этом буфере.

M-: (eval-expression) -- это самая основная команда для интерактивного вычисления лисповских выражений. Она считывает выражение, используя минибуфер, так что вы можете выполнить любое выражение в любом буфере, независимо от того, что этот буфер содержит. Когда выражение вычислено, то текущим буфером опять является тот, который был текущим, когда вы набирали M-:.

В режиме Emacs-Lisp ключ C-M-x привязан к команде eval-defun, которая анализирует определение функции, следующее за точкой или содержащее ее, как выражение Лиспа и вычисляет его. Значение печатается в эхо-области. Эта команда удобна для установки в среде Лиспа изменений, которые вы только что сделали в тексте определения функции.

C-M-x обрабатывает выражения defvar особо. Обычно вычисление выражения defvar не делает ничего, если определяемая им переменная уже имеет значение. Но C-M-x всегда переустанавливает эту переменную в начальное значение, заданное выражением defvar. Эта особенность удобна для отладки программ на Лиспе.

Команда C-x C-e (eval-last-sexp) вычисляет лисповское выражением, находящееся в этом буфере перед точкой, и показывает его значение в эхо-области. Она доступна во всех основных режимах, а не только в режиме Emacs-Lisp. Она не обрабатывает defvar особо.

Если командам C-M-x, C-x C-e или M-: задан числовой аргумент, то они вставляют значение в текущий буфер в позиции точки, а не в печатают эхо-области. Значение аргумента не играет роли.

Самой общей командой для вычисления Лисп-выражений из буфера является eval-region. M-x eval-region анализирует текст из области как одно или несколько лисповских выражений, вычисляя их одно за другим. M-x eval-current-buffer похожа на предыдущую, но вычисляет весь буфер. Это оправданный способ установки Лисп-кода из файла, который вы как раз готовы проверить. После нахождения и исправления ошибки используйте C-M-x в каждой функции, которую вы изменяете. Это сохранит соответствие между миром Лиспа и исходным файлом.

Буферы диалога с Лиспом

Буфер `*scratch*', выбираемый в момент запуска Emacs, предназначен для интерактивного вычисления Лисп-выражений внутри Emacs.

Простейший способ использования буфера `*scratch*' -- вставлять лисповские выражения, оканчивая каждое из них вводом C-j. Эта команда считывает Лисп-выражение перед точкой, вычисляет его и вставляет его значение в печатном представлении перед точкой. Результатом будет полный протокол вычисленных вами выражений и их значений.

Основной режим буфера `*scratch*' называется Lisp Interaction; он во всем эквивалентен режиму Emacs-Lisp, за исключением привязки для C-j.

Целесообразность этого свойства состоит в том, что у Emacs должен быть буфер в момент запуска, но этот буфер неудобен для редактирования файлов, так как новый буфер создается для каждого файла, к которому вы обращаетесь. Я думаю, что самое полезное, что может делать начальный буфер, -- это вести протокол интерпретатора Лиспа. M-x lisp-interaction-mode переведет любой буфер в режим Lisp Interaction.

Альтернативный способ интерактивного вычисления выражений Emacs Lisp предоставляет режим Inferior Emacs-Lisp, который имеет интерфейс, похожий скорее на интерфейс режима Shell (смотрите раздел Режим Shell). Наберите M-x ielm, чтобы создать буфер `*ielm*', использующий этот режим.

Запуск внешнего Лиспа

Emacs имеет средства для запуска программ в других Лисп-системах. Вы можете запустить Лисп-процесс как подчиненный процесс Emacs и передавать ему выражения, которые нужно вычислить. Вы также можете передать подчиненному Лисп-процессу измененные определения функций непосредственно из буферов Emacs, в которых вы редактируете программы на Лиспе.

Чтобы запустить подчиненный Лисп-процесс, наберите M-x run-lisp. Это запускает программу с именем lisp, ту же программу, которую бы вы запустили, набрав lisp как команду оболочки, с выводом и вводом, идущими через буфер Emacs с именем `*lisp*'. Следует сказать, что любой "терминальный вывод" от Лиспа пойдет в этот буфер, передвигая вперед точку, и любой "терминальный ввод" для Лиспа приходит из текста в буфере. (Вы можете изменить имя исполняемого файла Лиспа, установив переменную inferior-lisp-program.)

Чтобы дать ввод в Лисп, отправьте сь в конец буфера и наберите нужный текст, завершив его вводом RET. Буфер `*lisp*' находится в режиме Inferior Lisp, режиме, который объединяет специальные характеристики режима Lisp и большую часть свойств режима Shell (смотрите раздел Режим Shell). Определение RET как команды, посылающей строку подпроцессу, -- это одна из особенностей режима Shell.

Для запуска исходных файлов программ во внешних Лиспах используйте режим Lisp. Этот режим можно выбирать при помощи M-x lisp-mode; он используется автоматически для файлов, имена которых оканчиваются на `.l', `.lsp' или `.lisp', какие и применяются в большинстве Лисп-систем.

Когда вы редактируете функцию в программе на Лиспе, которая работает в данный момент, простейшим способом пересылки измененного определения в подчиненный Лисп-процесс является ключ C-M-x. В режиме Lisp при этом запускается функция lisp-send-defun, которая находит определение функции рядом или следом за точкой и посылает его как ввод в Лисп-процесс. (Emacs может послать ввод в любой подчиненный процесс независимо от того, какой буфер является текущим.)

Сравним значения C-M-x в режиме Lisp (для редактирования программ, запускаемых в другой Лисп-системе) и режиме Emacs-Lisp (для редактирования программ на Лиспе, предназначенных для работы в Emacs): в обоих режимах она имеет действие установки определения, в котором находится точка, но способ выполнения этого различается, согласно тому, где находится соответствующая среда Лиспа. Смотрите раздел Исполнение лисповских выражений.

Сокращения

Сокращение -- это слово, которое при вставке расшифровывается в какой-нибудь другой текст. Расшифровки сокращений определяются пользователем. Например, вы можете определить `foo' как сокращение, расшифровывающееся в `find outer otter'. Определив такое сокращение, вы получите возможность вставлять в буфер `find outer otter', набирая f o o SPC.

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

Понятия о сокращениях

Сокращение -- это слово, которое было определено как расшифровывающееся в заданную расшифровку. Когда вы вставляете после сокращения знак, разделяющий слова, сокращение раскрывается, заменяясь на расшифровку. Например, если `foo' определено как сокращение, расшифровывающееся в `find outer otter', то вы можете вставить в буфер `find outer otter.', напечатав f o o ..

Сокращения расшифровываются, только когда включен режим Abbrev (второстепенный режим). Выключение режима Abbrev не вызывает забвения определений сокращений, но они не расшифровываются, пока режим Abbrev не будет снова включен. Команда M-x abbrev-mode переключает режим Abbrev. С числовым аргументом она включает этот режим, если аргумент положительный, в противном случае -- выключает его. Смотрите раздел Второстепенные режимы. Символ abbrev-mode также является переменной; режим Abbrev включается, когда это переменная отлична от nil. Переменная abbrev-mode автоматически становится локальной для текущего буфера, как только вы ее устанавливаете.

Определения сокращений могут быть зависящими от режима, то есть действовать только в одном основном режиме. Сокращения могут также иметь глобальные определения, которые являются активными во всех основных режимах. Одни и те же сокращения могут иметь глобальное определение и различные зависящие от режима определения для разных основных режимов. Зависящее от режима определение для текущего основного режима перекрывает глобальное определение.

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

Определение сокращений

C-x a g
Определить сокращение, используя одно или несколько слов перед точкой в качестве его расшифровки (add-global-abbrev).
C-x a l
Аналогично, но определить сокращение, доступное только в текущем основном режиме (add-mode-abbrev).
C-x a i g
Определить слово в буфере как сокращение (inverse-add-global-abbrev).
C-x a i l
Определить слово в буфере как свойственное для режима сокращение (inverse-add-mode-abbrev).
M-x kill-all-abbrevs
Эта команда сбрасывает все действующие в данный момент определения сокращений, начиная всё сначала.

Обычный способ определить сокращение -- войти в текст, который вы хотите зашифровывать, установить после него точку и набрать C-x a g (add-global-abbrev). При этом само сокращение считывается в минибуфере, и затем оно определяется как сокращение для одного или более слов перед точкой. Используйте числовой аргумент для указания числа слов перед точкой, которые должны браться в качестве расшифровки. Например, чтобы определить сокращение `foo' как описано выше, вставьте текст `find outer otter' и затем наберите C-u 3 C-x a g f o o RET.

Нулевой аргумент для C-x a g означает, что в качестве расшифровки определяемого сокращения следует использовать содержимое области.

Команда C-x a l (add-mode-abbrev) похожа, но определяет сокращение, свойственное для режима. Свойственные для режима сокращения активны только в отдельном основном режиме. C-x a l определяет сокращение для основного режима, действующего в момент набора этой команды. Аргументы работают так же, как и для C-x a g.

Если находящийся в буфере текст является сокращением, а не его расшифровкой, используйте команду C-x a i g (inverse-add-global-abbrev) вместо C-x a g или C-x a i l (inverse-add-mode-abbrev) вместо C-x a l. Эти команды называются "инверсными", так как они обращают смысл двух используемых текстовых строк (одной из буфера и второй, считываемой в минибуфере).

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

Чтобы уничтожить определение сокращения, дайте команде определения сокращений отрицательный аргумент: C-u - C-x a g или C-u - C-x a l. Первая удаляет глобальное определение, а вторая --- свойственное для режима.

M-x kill-all-abbrevs уничтожает все имеющиеся определения сокращений, как глобальные, так и локальные.

Управление расшифровкой сокращения

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

Расшифровка сокращения сохраняет регистр букв; таким образом, `foo' расшифровывается в `find outer otter'; `Foo' в `Find outer otter', а `FOO' в `FIND OUTER OTTER' или в `Find Outer Otter' в зависимости от значения переменной abbrev-all-caps (значение, не равное nil, выбирает первую из двух расшифровок).

Для управления расшифровкой сокращений используются следующие команды:

M-'
Отделить приставку от последующего сокращения, которое будет расшифровываться позднее (abbrev-prefix-mark).
C-x a e
Расшифровать сокращение перед точкой (expand-abbrev). Это действует, даже когда отключен режим Abbrev.
M-x expand-region-abbrevs
Расшифровать некоторые или все сокращения в области.

Вы можете захотеть расшифровать сокращение с присоединенной приставкой; например, если `cnst' раскрывается в `construction', вы могли бы захотеть использовать его для ввода `reconstruction'. Набор `recnst' не работает, так как это не обязательно определенное сокращение. В этом случае сработает применение команды M-' (abbrev-prefix-mark) между приставкой `re' и сокращением `cnst'. Первым вставьте `re'. Затем наберите M-'; эта команда вставит в буфер дефис, чтобы показать, что она выполнила свою работу. Затем вставьте сокращение `cnst'. Теперь буфер содержит `re-cnst'. Теперь вставьте знак, не являющийся частью слова, чтобы расшифровать сокращение `cnst' в `construction'. На этом шаге раскрытия дефис, оставшийся после использования M-', удаляется. Результирующим текстом будет желаемое слово `reconstruction'.

Если вы на самом деле хотите получить в буфере текст сокращения, а не его расшифровку, вы можете достичь желаемого, вставив последующую пунктуацию с помощью C-q. Таким образом, foo C-q , оставляет в буфере `foo,'.

Если вы расшифровали сокращение по ошибке, то вы можете отменить расшифровку и вернуть само сокращение, напечатав для отмены C-_ (смотрите раздел Отмена сделанных изменений). Это также отменяет вставку знака, не являющегося частью слова, который развернул сокращение. Если вы хотите получить завершающий знак, не входящий в слово, плюс нераскрытое сокращение, то вы должны заново вставить завершающий знак, экранировав его командой C-q. Вы также можете использовать команду M-x unexpand-abbrev для отмены последнего раскрытия без удаления завершающего знака.

M-x expand-region-abbrevs ищет в области определенные сокращения и предлагает заменить каждое найденное сокращение на его расшифровку. Это команда удобна, если вы набрали текст, используя сокращения, но забыли перед этим включить режим Abbrev. Она также может быть полезной вместе со специальным набором определений сокращений для выполнения нескольких глобальных замен за один раз. Эта команда действует, даже если выключен режим Abbrev.

Расшифровка сокращения запускает ловушку pre-abbrev-expand-hook (смотрите раздел Ловушки).

Проверка и редактирование сокращений

M-x list-abbrevs
Показать перечень всех определений сокращений.
M-x edit-abbrevs
Редактировать перечень сокращений; вы можете добавить, изменить или удалить определения.

Вывод M-x list-abbrevs выглядит так:

(lisp-mode-abbrev-table)
"dk"         0    "define-key"
(global-abbrev-table)
"dfn"        0    "definition"

(Некоторые пустые строки, не имеющие смысловой значимости, и некоторые другие таблицы сокращений были опущены.)

Строка, содержащая имя в круглых скобках, -- это заголовок для сокращений из конкретной таблицы; global-abbrev-table содержит все глобальные сокращения, а другие таблицы сокращений, которые именуются в соответствии с основными режимами, содержат сокращения, специфичные для режима.

Каждая непустая строка в таблице определяет одно сокращение. Слово в начале строки -- это само сокращение. Число, стоящее далее, говорит, сколько раз сокращение было расшифровано. Emacs отслеживает это, чтобы помочь вам увидеть, какие сокращения вы действительно используете, на случай, если вы решите уничтожить те, что не используются достаточно часто. Цепочка знаков в конце строки -- это и есть расшифровка.

M-x edit-abbrevs позволяет вам добавить, изменить или уничтожить определения сокращений при помощи редактирования их списка в буфере Emacs. Этот список имеет тот же самый формат, что и описанный выше. Буфер сокращений называется `*Abbrevs*' и находится в режиме Edit-Abbrevs. Напечатайте в этом буфере C-c C-c, чтобы установить, как указано в нем, определения сокращений и удалить все не перечисленные в нем определения.

Команда edit-abbrevs -- это фактически то же самое, что и list-abbrevs, за исключением того, что она выбирает буфер `*Abbrevs*', тогда как list-abbrevs просто показывает его в другом окне.

Сохранение сокращений

Эти команды позволяют вам сохранять определения сокращений между сеансами редактирования.

M-x write-abbrev-file RET файл RET
Записать файл файл, описывающий все определенные сокращения.
M-x read-abbrev-file RET файл RET
Считать файл файл и определить сокращения так, как там описано.
M-x quietly-read-abbrev-file RET файл RET
То же самое, но не показывать сообщения о происходящем.
M-x define-abbrevs
Определить сокращения из определений в текущем буфере.
M-x insert-abbrevs
Вставить все сокращения и их расшифровки в текущий буфер.

M-x write-abbrev-file считывает имя файла, используя минибуфер, и записывает в этот файл описание всех текущих определений сокращений. Это используется для того, чтобы сохранить определения для использования в дальнейших сеансах. Хранимый в таком файле текст -- это последовательность лисповских выражений, которые при выполнении определяют такие же сокращения, какие у вас есть в данный момент.

M-x read-abbrev-file запрашивает имя файла, используя минибуфер, и затем считывает этот файл, определяя сокращения согласно его содержимому. M-x quietly-read-abbrev-file -- такая же команда, за исключением того, что она не показывает в эхо-области сообщение о своей работе; в действительности это удобно главным образом в файле `.emacs'. Если любой из этих функций передается пустой аргумент, то в качестве имени файла используется значение переменной abbrev-file-name, которая по умолчанию равна "~/.abbrev_defs".

Emacs автоматически предложит записать сокращения, если вы изменили какое-либо из них, всякий раз, когда он предлагает сохранить все файлы (для C-x s или C-x C-c). Это свойство может быть отключено установкой переменной save-abbevs в значение nil.

Команды M-x insert-abbrevs и M-x define-abbrevs похожи на предыдущие команды, но работают над текстом в буфере Emacs. M-x insert-abbrevs вставляет текст в текущий буфер перед точкой, описывая все текущие определения сокращений; M-x define-abbrevs полностью анализирует текущий буфер и соответственно определяет сокращения.

Динамическая расшифровка сокращений

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

M-/
Расшифровать слово в буфере перед точкой как динамическое сокращение при помощи поиска в буфере слов, начинающихся с этого сокращения (dabbrev-expand).
C-M-/
Завершить слово перед точкой как динамическое сокращение (dabbrev-completion).

Например, если буфер содержит `does this follow' и вы наберете f o M-/, то результатом будет вставка `follow', потому что это последнее слово в буфере, которое начинается с `fo'. Числовой аргумент для M-/ говорит, что следует брать вторую, третью и так далее отличающуюся расшифровку, найденную при просмотре в обратном направлении от точки. Повтор M-/ ищет альтернативную расшифровку путем дальнейшего просмотра назад. После того, как будет просмотрен весь текст перед точкой, просматривается текст после точки. Переменная dabbrev-limit, если не равна nil, указывает, как далеко по буферу нужно искать расшифровку.

После просмотра текущего буфера M-/ обычно просматривает другие буферы, если вы не установили dabbrev-check-all-buffers в значение nil.

Отрицательный аргумент для M-/, как C-u - M-/, говорит, что нужно искать расшифровки сначала после точки, а потом перед ней. Если вы повторяете M-/ для поиска другого раскрытия, не задавайте аргумент. При этом сначала будут попробованы все расшифровки после точки, а затем все расшифровки перед точкой.

После того, как вы расшифровали динамическое сокращение, вы можете скопировать дополнительные слова, которые идут после расшифровки в оригинальном контексте. Просто печатайте SPC M-/ для каждого слова, которое вы хотите скопировать. Промежутки и пунктуация между словами копируется вместе с ними.

Команда C-M-/ (dabbrev-completion) производит завершение динамического сокращения. Вместо того, чтобы пробовать возможные расшифровки одну за другой, она находит их все, а потом вставляет текст, который является в них общим. Если в них нет ничего общего, C-M-/ показывает перечень завершений, из которого вы можете выбрать нужное обычным способом. Смотрите раздел Завершение.

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

Настройки для динамических сокращений

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

Это средство управляется переменной dabbrev-case-fold-search. Если она равна t, регистр при поиске игнорируется; если она равна nil, то слово и расшифровка должны иметь один регистр. Если значение dabbrev-case-fold-search равно case-fold-search, что верно по умолчанию, то игнорирование регистра во время поиска расшифровок определяется переменной case-fold-search.

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

Переменная dabbrev-case-replace указывает, нужно ли сохранять образец регистра сокращения. Если она равна t, образец регистра сокращения сохраняется в большинстве случаев; если она nil, то расшифровка копируется буквально. Если значение dabbrev-case-replace равно case-replace, что истинно по умолчанию, то переменная case-replace указывает, нужно ли копировать расшифровку буквально.

Однако, если расшифровка содержит сложный набор букв разных регистров, и сокращение совпадает с этим образцом, когда доходит до него, то расшифровка копируется буквально, несмотря на значения этих переменных. Таким образом, если буфер содержит переменнуюСГлупымОбразцомРегистров, и вы напечатаете п е M-/, она скопирует расшифровку буквально, включая ее образец регистров.

Переменная dabbrev-abbrev-char-regexp, если не равна nil, указывает, какие знаки считаются частью слова для целей динамической расшифровки. Это регулярное выражение должно совпадать только с одним знаком, но никогда не с двумя или большим числом. Это же регулярное выражение определяет также, какие знаки являются частью расшифровки. Значение nil имеет особый смысл: сокращения состоят из знаков, являющихся частью слов, но расшифровки состоят из знаков, являющихся частью слов и символов.

В сценариях командного интерпретатора и Make-файлах к именам переменных иногда приставляется `$', а иногда нет. Основные режимы для такого рода текста могут настроить динамическую расшифровку, чтобы она обрабатывала необязательный префикс, установив переменную dabbrev-abbrev-skip-leading-regexp. Ее значение должно быть регулярным выражением, совпадающим с необязательным префиксом, который должен игнорироваться динамическими сокращениями.

Редактирование рисунков

Чтобы создать рисунок, составленный из текстовых знаков (например изображение деления регистра на поля в качестве комментария в программе), используйте команду M-x edit-picture для входа в режим Picture.

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

Конечно, в действительности Emacs всегда рассматривает текст как последовательность знаков, и строки на самом деле имеют концы. Но в режиме Picture наиболее часто используемые команды заменяются вариантами, которые воспроизводят квадрантную модель текста. Они делают это, вставляя пробелы или превращая в пробелы знаки табуляции.

Большинство базовых команд редактирования Emacs переопределяются режимом Picture таким образом, чтобы делать в основном те же самые вещи, но квадрантным способом. Кроме того, режим Picture определяет разные ключи, начинающиеся с префикса C-c, для запуска специальных команд редактирования изображения.

Один из этих ключей, C-c C-c, достаточно важен. Часто рисунок --- это часть большего файла, который обычно редактируется в каком-нибудь другом основном режиме. Команда M-x edit-picture записывает имя предыдущего основного режима, и затем вы можете использовать команду C-c C-c (picture-mode-exit), чтобы вернуться в этот режим. Если C-c C-c не имеет числового аргумента, она также уничтожает пробелы в концах строк.

Все команды, используемые в режиме Picture, работают и в других режимах (если только загружена библиотека `picture'), но привязаны к ключам только в режиме Picture. Дальнейшие описания говорят о движении "на один столбец" и так далее, но все команды режима Picture обращаются с числовыми аргументами так же, как и их обычные эквиваленты.

Включение режима Picture вызывает ловушку picture-mode-hook (смотрите раздел Ловушки).

Основы редактирования в режиме Picture

Большинство ключей делают в режиме Picture то же самое, что они делают обычно, но в квадрантном стиле. Например, C-f перепривязывается на запуск команды picture-forward-column, которая передвигает точку на один столбец вправо, вставляя, если это необходимо, пробел, так что действительный конец строки не играет роли. C-b перепривязывается для запуска picture-backward-column, которая всегда двигает точку влево на один столбец, превращая знак табуляции в несколько пробелов, если это необходимо. C-n и C-p перепривязываются для запуска picture-move-down и picture-move-up, которые могут либо вставить пробелы, либо превратить знаки табуляции в пробелы, как необходимо, чтобы гарантировать, что точка остается в том же самом столбце. C-e запускает picture-end-of-line, которая передвигается за последний непустой знак на строке. Здесь не надо менять C-a, так как выбор модели экрана не влияет на начала строк.

Вставка текста приспосабливается к квадрантной модели экрана посредством использования режима Overwrite (смотрите раздел Второстепенные режимы). Самовставляющиеся знаки заменяют существующий текст, столбец за столбцом, а не выталкивают его вправо. RET запускает picture-newline, которая просто сдвигает на начало следующей строки, так что новый текст заменит эту строку.

Режим Picture предоставляет стирание текста вместо удаления и уничтожения. DEL (picture-backward-clear-column) заменяет предыдущий знак пробелом, а не удаляет его; это смещает точку назад. C-d (picture-clear-column) заменяет следующий знак или знаки пробелами, но не сдвигает точку. (Если вы хотите превратить знаки в пробелы и продвинуться через них, используйте SPC.) C-k (picture-clear-line) действительно уничтожает содержимое строки, но никогда не удаляет из буфера знаки перевода строки.

Чтобы сделать действительную вставку, вы должны использовать специальные команды. C-o (picture-open-line) создает пустую строку после текущей; она никогда не разбивает строку. C-M-o (split-line) имеет смысл в режиме Picture, поэтому она не изменяется. C-j (picture-duplicate-line) вставляет ниже текущей строки другую строку с тем же самым содержимым.

Чтобы сделать в режиме Picture действительное удаление, используйте C-w или C-c C-d (которая определяется для запуска delete-char, как C-d в других режимах), или с помощью одной из команд прямоугольника для рисунков (смотрите раздел Команды прямоугольника в режиме Picture).

Управление движением после вставки

Так как "самовставляющиеся" знаки в режиме Picture перезаписывают и передвигают точку, то нет существенного ограничения на то, как точка будет передвигаться. Обычно точка перемещается вправо, но вы можете определить любое из восьми ортогональных или диагональных направлений для движения после "самовставляющегося" знака. Это удобно для рисования линий в буфере.

C-c <
Сдвинуться после вставки влево (picture-movement-left).
C-c >
Сдвинуться после вставки вправо (picture-movement-right).
C-c ^
Сдвинуться после вставки вверх (picture-movement-up).
C-c .
Cдвинуться после вставки вниз (picture-movement-down).
C-c `
Сдвинуться после вставки вверх и влево (на "северо-запад") (picture-movement-nw).
C-c '
Сдвинуться после вставки вверх и вправо (на "северо-восток") (picture-movement-ne).
C-c /
Сдвинуться после вставки вниз и влево (на "юго-запад")
(picture-movement-sw).
C-c \
Сдвинуться после вставки вниз и вправо (на "юго-восток")
(picture-movement-se).

Две команды движения передвигают, основываясь на текущем направлении вставки. Команда C-c C-f (picture-motion) передвигает в том же самом направлении, в каком выполняется движение после текущей "вставки", тогда как C-c C-b (picture-motion-reverse) двигает в противоположном направлении.

Знаки табуляции в режиме Picture

В режиме Picture предусмотрены два вида действий, подобных табуляции. Для табуляции, основанной на контексте, используйте M-TAB (picture-tab-search). Без аргумента она передвигает в точку под следующий "интересный" знак, который следует за незначащим знаком в предыдущей непустой строке. "Следующий" означает здесь "появляющийся в более дальней горизонтальной позиции, чем та, с которой точка отправлялась". С аргументом, как в C-u M-TAB, эта команда переходит к следующему такому интересному знаку в текущей строке. M-TAB не изменяет текст, она только двигает точку. "Интересные" знаки определяются переменной picture-tab-chars, которая должна задавать набор знаков. Синтаксис этой переменной похож на синтаксис, используемый внутри `[...]' в регулярном выражении, но без `[' и `]'. Ее значение по умолчанию равно "!-~".

Сама TAB запускает picture-tab, которая действует, основываясь на установленных текущих позициях табуляции; это эквивалент tab-to-tab-stop в режиме Picture. Обычно она просто двигает точку, но с числовым аргументом она стирает текст, через который передвинулась.

Формы табуляции, основанные на контексте и на позициях табуляции, объединяются вместе командой C-c TAB, picture-set-tab-stops. Эта команда устанавливает позиции табуляции, которые M-TAB считала бы значимыми в текущей строке. Использование этой команды вместе с TAB может дать эффект табуляции, основанной на контексте. Но M-TAB более удобна в тех случаях, когда ее достаточно.

Может оказаться удобным запретить использование настоящих знаков табуляции в рисунках. Например, это помешает C-x TAB испортить рисунок. Вы можете сделать так, установив переменную indent-tabs-mode в значение nil. Смотрите раздел Табуляция по сравнению с пробелами.

Команды прямоугольника в режиме Picture

Режим Picture определяет команды для работы с прямоугольными кусками текста таким способом, который подходит для квадрантной модели. Стандартные команды для прямоугольников также могут быть полезны (смотрите раздел Прямоугольники).

C-c C-k
Очистить текущую область-прямоугольник (picture-clear-rectangle). С аргументом -- удалить ее.
C-c C-w r
То же самое, но сначала сохранить содержимое прямоугольника в регистре r (picture-clear-rectangle-to-register).
C-c C-y
Скопировать последний уничтоженный прямоугольник в буфер путем перезаписи, при этом левый верхний угол находится в точке (picture-yank-rectangle). С аргументом -- вставка вместо перезаписи.
C-c C-x r
То же самое, но использовать прямоугольник из регистра r (picture-yank-rectangle-from-register).

Команды работы с прямоугольниками для рисунков, это C-c C-k (picture-clear-rectangle) и C-c C-w (picture-clear-rectangle-to-register), отличаются от стандартных команд прямоугольника тем, что они обычно очищают прямоугольник вместо его удаления; это аналогично тому, как в режиме Picture изменяется C-d.

Однако, удаление прямоугольников может быть удобным и в режиме Picture, поэтому эти команды удаляют прямоугольник, если им передан числовой аргумент. C-c C-k с числовым аргументом или без него сохраняет прямоугольник для C-c C-y.

Команды режима Picture для восстановления прямоугольников отличаются от стандартных тем, что они перезаписывают, а не вставляют. Точно так же вставка другого текста в режиме Picture отличается от вставки в других режимах. C-c C-y (picture-yank-rectangle) вставляет (при помощи перезаписи) прямоугольник, который был уничтожен самым последним, в то время как C-c C-x (picture-yank-rectangle-from-register) делает то же самое для прямоугольника, находящегося в указанном регистре.

Посылка почты

C-x m
Начать составление сообщения для пересылки (compose-mail).
C-x 4 m
Аналогично, но показать сообщение в другом окне (compose-mail-other-window).
C-x 5 m
Аналогично, но создать новый фрейм (compose-mail-other-frame).
C-c C-s
В режиме Mail, посылает сообщение (mail-send).
C-c C-c
Посылает сообщение и прячет его буфер (mail-send-and-exit).

Команда C-x m (compose-mail) выбирает буфер с именем `*mail*' и инициализирует его наброском исходящего сообщения. C-x 4 m (compose-mail-other-window) выбирает буфер `*mail*' в другом окне, оставляя предыдущий текущий буфер видимым. C-x 5 m (compose-mail-other-frame) создает для буфера `*mail*' новый фрейм.

Поскольку буфер сообщения -- это обычный буфер Emacs, во время составления письма вы можете переключаться в другие буферы и вернуться обратно позднее (или вообще не возвращаться). Если вы используете команду C-x m снова, когда вы составляли другое сообщение, но еще не послали его, от вас потребуют подтверждение, перед тем как удалить старое сообщение. Если вы ответите n, буфер `*mail*' останется выбранным со своим старым содержимым, так что вы сможете закончить прежнее сообщение и послать его. C-u C-x m -- это другой способ сделать то же самое. Пересылка сообщения помечает буфер `*mail*' как "немодифицированный", что устраняет необходимость подтверждения при следующем использовании C-x m.

Если вы составляете сообщение в буфере `*mail*' и хотите послать еще одно сообщение до завершения первого, переименуйте буфер `*mail*' с помощью M-x rename-uniquely (смотрите раздел Разнообразные операции над буфером). Затем вы можете использовать C-x m или ее варианты, описанные выше, чтобы создать новый буфер `*mail*'. Если вы сделаете так, то сможете работать с каждым буфером с сообщением независимо.

Формат буфера с почтовым сообщением

Кроме текста, или тела, сообщение имеет поля заголовка, которые говорят, кто послал его, когда, кому, зачем и так далее. Некоторые поля заголовка, такие как `Date' (дата) и `Sender' (отправитель), создаются автоматически, когда вы посылаете сообщение. Другие же, например имена получателей, должны быть заданы вами, чтобы сообщение было отослано правильно.

Режим Mail предусматривает несколько команд, помогающих вам отредактировать некоторые поля заголовка, и некоторые поля в этом буфере иногда инициализируются автоматически. Вы можете вставить или отредактировать любые поля заголовка, используя обычные команды редактирования.

Строка в буфере, которая гласит

--text follows this line--

--- это специальный ограничитель, отделяющий заданные вами заголовки от самого текста. Все, что следует за этой строкой, -- это текст сообщения, а заголовки предшествуют ей. Сама разделяющая строка не появляется в реальном посылаемом сообщении. Используемый для строки-ограничителя текст задается переменной mail-header-separator.

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

To: [email protected]
CC: [email protected], [email protected]
Subject: The Emacs Manual
--Text follows this line--
Please ignore this message.

Поля заголовка сообщения

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

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

`To'
Это поле содержит почтовые адреса, на которые посылается сообщение. Если вы перечисляете более одного адреса, используйте для их разделения запятые, а не пробелы.
`Subject'
Содержанием поля `Subject' должен быть фрагмент текста, который указывает, о чем будет сообщение. Смысл полей `Subject' в том, что большинство программ чтения почты могут предоставлять обзорный перечень сообщений, печатая только тему каждого сообщения, а не весь текст.
`CC'
Это поле, как и поле `To', содержит дополнительные почтовые адреса, по которым нужно отправить сообщение, но эти читатели не должны рассматривать это сообщение как адресованное им.
`BCC'
Это поле содержит дополнительные почтовые адреса, по которым отправляется сообщение, но они не должны появляться в заголовке фактически посланного сообщения. Посланные таким образом копии называются слепыми копиями. Чтобы вам посылалась слепая копия каждого исходящего сообщения, установите переменную mail-self-blind равной t.
`FCC'
Это поле содержит имя файла, оно велит Emacs добавить после отправки копию этого сообщения в заданный файл. Если это файл в формате Rmail, Emacs записывает сообщение в формате Rmail; в противном случае -- в системном формате почтовых файлов. Чтобы каждый раз, когда вы начинаете редактирование исходящего сообщения, в поле `FCC' помещалось фиксированное имя файла, установите переменную mail-archive-file-name равной имени этого файла. Если вы не удалите поле `FCC' перед посылкой, сообщение будет записано в этот файл.
`From'
Используйте поле `From', чтобы назвать себя, когда вы отправляете почту, войдя в систему под чужим именем. Содержимое поля `From' должно быть правильным почтовым адресом, поскольку обычно ответы направляются по этому адресу. Если вы не задали поле `From' сами, Emacs использует значение user-mail-address в качестве значения по умолчанию.
`Reply-to'
Используйте это поле, чтобы направлять ответы по адресам, отличным от вашего собственного. Большинство программ чтения почты (включая Rmail) автоматически посылают ответы по адресу `Reply-to'; он имеет приоритет перед адресом `From'. Добавляя в заголовок поле `Reply-to', вы можете избавиться от любых проблем, которые может вызывать при ответе ваш адрес `From'. Чтобы какой-то адрес для `Reply-to' помещался в каждое исходящее сообщение, установите переменную mail-default-reply-to равной этом адресу (в виде строки). Тогда mail инициализирует сообщения с заданным адресом `Reply-to'. Вы можете удалить или изменить это поле заголовка перед отправкой сообщения, если хотите. Когда Emacs начинает работу, mail-default-reply-to инициализируется по переменной среды `REPLYTO', если она установлена.
`In-reply-to'
Это поле содержит фрагмент текста, описывающий сообщение, на которое вы отвечаете. Некоторые почтовые системы могут использовать эту информацию для соотношения связанных между собой фрагментов почты. Обычно это поле заполняется самим Rmail, когда вы отвечаете на сообщение из него, и вам никогда не придется думать об этом (смотрите раздел Чтение почты с помощью Rmail).
`References'
В этом поле перечисляются ID предыдущих сообщений, связанных с этим. Rmail устанавливает это поле автоматически, когда вы отвечаете на какое-то сообщение.

Поля заголовка `To', `CC', `BCC' и `FCC' могут использоваться любое число раз, и каждое из этих полей может содержать несколько адресов, разделенных запятыми. Поля `To', `CC' или `BCC' могут также иметь строки продолжения: одна или несколько строк, начинающиеся с пробельных знаков и следующие за строкой, на которой начинается поле, рассматриваются как часть этого поля. Вот пример поля `To' со строкой продолжения:

To: [email protected], [email protected],
  [email protected]

При посылке сообщения, если вы не написали поле `From' сами, Emacs сделает это за вас. Формат этого поля управляется переменной mail-from-style:

nil
Только почтовый адрес, как `[email protected]'.
parens
И почтовый адрес, и полное имя, как `[email protected] (Elvis Parsley)'.
angles
То же, но как `Elvis Parsley '.
system-default
Позволить системе самой вставить поле `From'.

Почтовые псевдонимы

Вы можете определить почтовые псевдонимы в файле с именем `~/.mailrc'. Это короткие мнемонические имена, обозначающие почтовые адреса или группы адресов. Подобно многим другим почтовым программам, Emacs раскрывает псевдонимы, когда они появляются в полях `To', `From', `CC', `BCC' и `Reply-to' и в их вариантах с `Resent-'.

Чтобы определить псевдоним в `~/.mailrc', напишите одну строку в таком формате:

alias короткий-адрес полные-адреса

Здесь полные-адреса означает один или более почтовых адресов, в которые раскрывается короткий-адрес. Разделяйте адреса пробелами; если адрес содержит пробел, заключайте весь адрес в двойные кавычки.

Например, чтобы сделать так, чтобы maingnu обозначало ваш собственный местный адрес и [email protected], поместите такую строку:

alias maingnu [email protected] local-gnu

Emacs также распознает в файлах `.mailrc' команды включения. Они выглядят так:

source имя-файла

Файл `~/.mailrc' в основном используется другими программами для чтения почты; он может содержать различные другие команды. Emacs игнорирует все, кроме определений псевдонимов и команд включения.

Есть другой способ определить почтовый псевдоним, но только внутри Emacs -- с помощью команды define-mail-alias. Она запрашивает псевдоним и затем полный адрес. Вы можете использовать ее для определения псевдонимов в вашем файле `.emacs', следующим образом:

(define-mail-alias "maingnu" "[email protected]")

define-mail-alias записывает псевдонимы, добавляя их к переменной, называемой mail-aliases. Если вы умеете обращаться со списками в Лиспе, вы можете установить mail-aliases напрямую. Первоначальное значение переменной mail-aliases равно t, что означает, что для получения правильного значения Emacs должен считать `.mailrc'.

Вы можете задать вместо `~/.mailrc' файл с другим именем, установив переменную mail-personal-alias-file.

Обычно Emacs раскрывает псевдонимы, когда вы отсылаете сообщение. Вам не обязательно раскрывать псевдонимы до отсылки сообщения, но вы можете раскрыть их, если хотите увидеть, куда пойдет это письмо. Чтобы сделать это, используйте команду M-x expand-mail-aliases; она раскрывает все почтовые псевдонимы, присутствующие в данный момент в полях заголовка с адресами.

Если хотите, вы можете сделать так, чтобы почтовые псевдонимы раскрывались как сокращения, по мере того как вы их набираете (смотрите раздел Сокращения). Чтобы включить эту возможность, выполните следующее:

(add-hook 'mail-setup-hook 'mail-abbrevs-setup)

Это можно написать в файле `.emacs'. Смотрите раздел Ловушки. Если вы пользуетесь этим методом, вы должны использовать define-mail-abbrev, а не define-mail-alias; последняя команда не работает с этим пакетом. Обратите внимание, пакет для сокращений почтовых адресов использует переменную mail-abbrevs вместо mail-aliases, и все псевдонимы преобразуются к нижнему регистру.

Пакет для сокращений почтовых адресов также предоставляет команду C-c C-a (mail-interactive-insert-alias), которая считывает псевдоним (с завершением) и вставляет его определение в точке. Это полезно при редактировании самого текста сообщения или поля вроде `Subject', где Emacs обычно не раскрывает псевдонимы.

Заметьте, что сокращения раскрываются, только если вы после вставили разделитель слов. Однако, вы можете перепривязать C-n и M-> так, чтобы они еще и производили раскрытие. Это можно сделать следующим образом:

(add-hook 'mail-setup-hook
          '(lambda ()
             (substitute-key-definition
               'next-line 'mail-abbrev-next-line
               mail-mode-map global-map)
             (substitute-key-definition
               'end-of-buffer 'mail-abbrev-end-of-buffer
               mail-mode-map global-map)))

Режим Mail

Основной режим, используемый в буфере сообщения -- это режим Mail, который очень похож на режим Text за исключением того, что в нем предоставляются различные специальные команды на префиксе C-c. Все эти команды должны производить различные операции с редактируемым или посылаемым сообщением. Кроме того, режим Mail определяет знак `%' как разделитель слов; это полезно при использовании команд, работающих со словами, для редактирования почтовых адресов.

Режим Mail обычно используется в буферах, автоматически подготовленных командой mail или родственными командами. Однако, вы можете также переключиться в режим Mail в буфере, обращающемся к файлу. Это полезно делать, если вы сохранили в файле черновик сообщения.

Отправка почты

В режиме Mail есть две команды для отправки сообщения, которое вы редактировали:

C-c C-s
Послать это сообщение и оставить буфер с ним выбранным (mail-send).
C-c C-c
Послать это сообщение и выбрать какой-то другой буфер (mail-send-and-exit).

C-c C-s (mail-send) отсылает сообщение и помечает буфер с этим сообщением как немодифицированный, но при этом оставляет этот буфер выбранным, так что вы можете изменить это сообщение (возможно с новыми получателями) и послать его снова.

C-c C-c (mail-send-and-exit) отсылает сообщение, а затем удаляет окно или переключает в другой буфер. Эта команда устанавливает для буфера с сообщением самый низкий приоритет для повторного выбора, так как вы перестали его использовать. Это обычный способ отправки сообщения.

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

Когда вы отправляете сообщение, которое содержит знаки, не входящие в ASCII, эти знаки необходимо перевести в какую-то систему кодирования (смотрите раздел Системы кодирования). Обычно она устанавливается вашей языковой средой (смотрите раздел Языковые среды). Вы можете явно указать систему кодирования для исходящей почты, устанавливая переменную sendmail-coding-system.

Если определяемая таким образом система кодирования не может обработать знаки в каком-то сообщении, Emacs просит вас выбрать систему кодирования самим, показывая список возможных вариантов.

Редактирование заголовка сообщения

Режим Mail предоставляет специальные команды для передвижения к определенным полям заголовка и для завершения адресов.

C-c C-f C-t
Перейти к полю заголовка `To', создавая его, если его еще нет (mail-to).
C-c C-f C-s
Перейти к полю заголовка `Subject', создавая его, если его еще нет (mail-subject).
C-c C-f C-c
Перейти к полю заголовка `CC', создавая его, если его еще нет (mail-cc).
C-c C-f C-b
Перейти к полю заголовка `BCC', создавая его, если его еще нет (mail-bcc).
C-c C-f C-f
Перейти к полю заголовка `FCC', создавая его, если его еще нет (mail-fcc).
M-TAB
Завершить почтовый адрес (mail-complete).

Есть пять команд для перемещения точки к отдельным полям заголовка, и все они базируются на префиксе C-c C-f (`C-f' означает "field".(10) Они перечислены в таблице выше. Если требуемое поле не существует, эти команды создают его. Мы предоставляем специальные команды для перемещения именно к таким полям, потому что чаще всего пользователи хотят редактировать именно их.

При редактировании полей заголовка, которые содержат почтовые адреса, таких как `To:', `CC:' и `BCC:', вы можете завершить адрес, введя M-TAB (mail-complete). Эта команда вставляет полное имя, соответствующее этому адресу, если она может его определить. Переменная mail-complete-style говорит, нужно ли вставлять полное имя и какой стиль следует использовать; стиль задается как в mail-from-style (смотрите раздел Поля заголовка сообщения).

При завершении правильными почтовыми адресами считаются имена локальных пользователей и определенные вами почтовые псевдонимы. Вы можете задать дополнительные источники правильных адресов; используйте буфер настройки, чтобы просмотреть возможные варианты.

Если вы напечатаете M-TAB в теле сообщения, она вызовет ispell-complete-word, как в режиме Text.

Цитирование почты

В режиме Mail также есть команды для восстановления или цитирования всего или части сообщения, на которое вы отвечаете. Эти команды активны, только когда вы начали отправку сообщения с использованием команды Rmail.

C-c C-y
Восстановить выбранное сообщение из Rmail (mail-yank-original).
C-c C-r
Восстановить область из буфера Rmail (mail-yank-region).
C-c C-q
Заполнить все абзацы, процитированные из другого сообщения (mail-fill-yanked-message).

Если отправка почты запускается из программы чтения почты Rmail с использованием команды Rmail, то внутри буфера сообщения может использоваться команда C-c C-y для вставки текста сообщения, на которое вы отвечаете. Обычно она сдвигает каждую строку этого сообщения на три пробела и удаляет большинство полей заголовка. Числовой аргумент указывает количество пробелов для отступа. Просто C-u говорит о том, что делать отступ и удалять что-либо не надо. C-c C-y всегда использует текущее сообщение из буфера Rmail, так что можно вставить несколько старых сообщений, выбирая нужное в Rmail, переключаясь в `*mail*' и восстанавливая его, а затем снова переключаясь в Rmail, чтобы выбрать еще одно.

Вы можете задать текст, который команда C-c C-y будет вставлять в начале каждой строки: установите mail-yank-prefix равной желаемой строке. (Значение nil означает, что следует делать отступ; это используется по умолчанию.) Однако, C-u C-c C-y никогда не добавляет ничего в начало вставляемых строк, несмотря на значение mail-yank-prefix.

Чтобы вставить только часть пришедшего сообщения, установите в Rmail область вокруг нужного фрагмента; затем перейдите в буфер `*mail*' и напечатайте C-c C-r (mail-yank-region). В каждой копируемой строке делается отступ или добавляется префикс в соответствии с mail-yank-prefix.

После использования C-c C-y или C-c C-r вы можете набрать C-c C-q, чтобы заполнить абзацы восстановленного старого сообщения или сообщений. Однократным использованием C-c C-q заполняются все такие абзацы, причем каждый отдельно. Чтобы заполнить один абзац процитированного сообщения, используйте M-q. Если заполнение не обрабатывает используемый вами стиль префикса для цитат автоматически, попробуйте установить префикс заполнения явно. Смотрите раздел Заполнение текста.

Другие возможности режима Mail

C-c C-t
Перемещает к началу текста тела сообщения (mail-text).
C-c C-w
Вставляет файл `~/.signature' в конец текста сообщения (mail-signature).
C-c C-i файл RET
Вставляет содержимое файла в конец исходящего сообщения (mail-attach-file).
M-x ispell-message
Производит проверку правописания в тексте сообщения, но не в цитатах из других сообщений.

C-c C-t (mail-text) перемещает точку к позиции сразу после строки-разделителя заголовка, то есть к началу текста тела сообщения.

C-c C-w (mail-signature) добавляет в конец сообщения стандартный кусок текста, где вы можете подробнее рассказать с себе. Этот текст берется из файла `~/.signature' в вашем начальном каталоге. Чтобы подпись вставлялась автоматически, установите переменную mail-signature в значение t; тогда при создании почтового сообщения содержимое вашего файла `~/.signature' будет вставляться автоматически. Если вы не хотите ставить подпись в конкретном сообщении, удалите ее из буфера перед отсылкой.

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

Вы можете проверить орфографию в тексте написанного сообщения с помощью команды M-x ispell-message. Если вы восстанавливали пришедшие сообщения в набросок отправляемого, эта команда пропускает восстановленные места, но проверяет текст, который вставили вы сами. (Она просматривает величину отступа или значение переменной mail-yank-prefix, чтобы отличить процитированные строки от введенных вами.) Смотрите раздел Поиск и исправление орфографических ошибок.

Чтобы включить в отправляемое сообщение файл, вы можете использовать C-x i, обычную команду для вставки файла в текущий буфер. Но чаще удобнее использовать особую команду, C-c C-i (mail-attach-file). Эта команда вставляет содержимое заданного файла в конец буфера после подписи, если она есть, с разделяющей строкой, включающей имя этого файла.

Включение режима Mail (что C-x m делает автоматически) запускает обычные ловушки text-mode-hook и mail-mode-hook. Инициализация нового исходящего сообщения запускает обычную ловушку mail-setup-hook; используйте эту ловушку, если вы хотите добавить к вашему почтовому заголовку особые поля или сделать другие изменения в представлении буфера сообщения. Смотрите раздел Ловушки.

Основное различие между этими ловушками состоит только в том, в какое время они вызываются. Когда вы набираете M-x mail, запускается mail-mode-hook, как только будет создан буфер `*mail*'. Затем функция mail-setup помещает в этот буфер его начальное содержимое по умолчанию. После этого запускается mail-setup-hook.

Как сбить с толку NSA

M-x spook добавляет в отправляемое сообщение строку случайно выбранных ключевых слов. Эти ключевые слова выбираются из списка слов, которые предполагают, что вы обсуждаете что-то .

За этой возможностью стоит идея, что NSA(11) просматривает электронную почту, содержащую ключевые слова, которые они могут найти интересными. (NSA говорит, что они этого не делают, но они должны так говорить.) Идея состоит в том, что если многие люди добавляют к своим сообщениям подозрительные слова, NSA будет настолько занято подделками, что вынуждено будет совсем прекратить просмотр.

Вот как автоматически вставлять зловещие ключевые слова, когда вы начинаете набирать сообщение:

(add-hook 'mail-setup-hook 'spook)

Смущает это NSA или нет, по крайней мере это развлекает людей.

Способы составления сообщений

Эта глава описывает обычный режим Emacs для редактирования и отправки почты -- режим Mail. В Emacs есть иные способы для этого, включая режимы MH-E и Message, не описанные в этом руководстве. Вы можете выбрать любой из них в качестве своего предпочтительного способа. Команды C-x m, C-x 4 m и C-x 5 m используют тот агент, который вы задали. Так же делают и другие команды и программы Emacs, посылающие почту.

Чтобы указать ваш способ составления сообщений, установите переменную mail-user-agent. На данный момент допустимые значения включают sendmail-user-agent, mh-e-user-agent и message-user-agent.

Если вы выбрали другой способ составления сообщений, информация о буфере `*mail*' и режиме Mail из этой главы не относится к вашему случаю; другие методы могут использовать совершенно иные команды с иным форматом в иначе называемом буфере.

Чтение почты с помощью Rmail

Rmail -- это подсистема Emacs для чтения и размещения получаемой вами почты. Rmail хранит почтовые сообщения в файлах, называемых Rmail-файлами. Чтение сообщений в Rmail-файле осуществляется в специальном основном режиме, режиме Rmail, который переопределяет большинство букв для запуска команд управления почтой. Команда rmail-mode используется для входа в режим Rmail, она запускает ловушку rmail-mode-hook, как обычно; но не выполняйте эту команду вручную, она не может делать ничего существенного, если этот буфер не обращается к правильному Rmail-файлу.

Основные понятия Rmail

При простейшем использовании Rmail, у вас есть один Rmail-файл `~/RMAIL', в котором сохраняется вся ваша почта. Этот файл называется первичным Rmail-файлом. Команда M-x rmail считывает ваш первичный Rmail-файл, вставляет в него новую почту из ваших входных файлов, отображает первое непрочитанное сообщение и позволяет вам начать чтение. Переменная rmail-file-name задает имя первичного Rmail-файла.

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

В пределах Rmail-файла сообщения расположены последовательно в порядке поступления; вы можете использовать другие способы сортировки. Сообщениям присваиваются последовательные целые числа в качестве их номеров сообщений. Номер текущего сообщения показывается в строке режима Rmail, за ним идет общее число сообщений в файле. Вы можете перейти на сообщение, задавая его номер с помощью ключа j (смотрите раздел Перемещение по сообщениям).

Следуя обычным правилам Emacs, изменения в Rmail-файле становятся постоянными только после сохранения этого файла. Вы можете осуществить это с помощью команды s (rmail-save), которая также сперва вычеркивает удаляемые сообщения из файла (смотрите раздел Удаление сообщений). Для записи файла без вычеркивания следует использовать C-x C-s. Rmail также сохраняет Rmail-файл при поступлении новой почты из входного почтового файла (смотрите раздел Rmail-файлы и входные почтовые ящики).

Выйти из Rmail можно с помощью q (rmail-quit), при этом Rmail-файл очищается и сохраняется, и происходит переход в другой буфер. Но формально нет необходимости `выходить'. Если вы переключились из Rmail к редактированию в других буферах и больше не возвращались обратно, на самом деле вы вышли. (Команда Rmail b делает это для вас.) Достаточно просто убедиться, что вы сохранили Rmail-файл (как и любой другой измененный вами файл). Достаточно удобный способ сделать это предоставляет команда C-x s (смотрите раздел Сохранение файлов).

Прокрутка в сообщении

Когда Rmail показывает сообщение, не помещающееся на экране, вам придется прокручивать это сообщение, чтобы прочитать оставшуюся часть. Вы могли бы сделать это с помощью C-v, M-v и M-<, но в Rmail прокруткой приходится пользоваться настолько часто, что ее команды заслуживают более простого набора.

SPC
Прокручивает вперед (scroll-up).
DEL
Прокручивает назад (scroll-down).
.
Прокручивает к началу сообщения (rmail-beginning-of-message).

Так как во время чтения сообщения наиболее частой процедурой является прокрутка по целому экрану, Rmail делает SPC и DEL синонимами C-v (scroll-up) и M-v (scroll-down).

Команда . (rmail-begining-of-message) прокручивает к началу выбранного сообщения. Это не совсем то же, что и M-<: во-первых, она не оставляет метку, а во-вторых, она переустанавливает границы буфера до пределов текущего сообщения, если вы их изменили.

Перемещение по сообщениям

Самое основное, что вы можете сделать с сообщением -- прочитать его. В Rmail вы можете прочитать сообщение, сделав его текущим. Обычно при этом последовательно перемещаются по файлу, так как сообщения в нем расположены в порядке получения. При входе в Rmail вы попадаете на первое сообщение, которое никогда еще не было текущим (это первое сообщения, имеющее атрибут `unseen'; смотрите раздел Атрибуты в Rmail). Чтобы увидеть другие новые сообщения, двигайтесь вперед, для повторного просмотра старых двигайтесь назад.

n
Перейти к следующему неудаленному сообщению, пропуская все промежуточные удаленные сообщения (rmail-next-undeleted-message).
p
Перейти к предыдущему неудаленному сообщению (rmail-previous-undeleted-message).
M-n
Перейти к следующему сообщению, включая удаленные (rmail-next-message).
M-p
Перейти к предыдущему сообщению, включая удаленные (rmail-previous-message).
j
Перейти к первому сообщению. С аргументом n -- перейти к сообщению с номером n (rmail-show-message).
>
Перейти к последнему сообщению (rmail-last-message).
<
Перейти к первому сообщению (rmail-first-message).
M-s regexp RET
Перейти к следующему сообщению, содержащему совпадение с регулярным выражением regexp (rmail-search).
- M-s regexp RET
Перейти к предыдущему сообщению, содержащему совпадение с regexp.

n and p -- это обычный способ перемещения по сообщениям в Rmail. Они перемещают по сообщениям последовательно, но пропускают удаленные сообщения, что обычно вы и хотели бы делать. Эти команды называются rmail-next-undeleted-message и rmail-previous-undeleted-message. Если вы не хотите пропускать удаленные сообщения, например, если вы хотите переместиться к сообщению, чтобы отменить его удаление, используйте варианты M-n и M-p (rmail-next-message и rmail-previous-message). Числовой аргумент в любой из этих команд используется как счетчик повторов.

В Rmail вы можете задать числовой аргумент, набрав только цифру. При этом не требуется сначала набирать C-u.

Команда M-s (rmail-search) -- это версия поиска для Rmail. Обычная команда наращиваемого поиска C-s работает в Rmail, но она осуществляет поиск только в пределах текущего сообщения. Цель команды M-s -- поиск другого сообщения. Она считывает регулярное выражение (смотрите раздел Синтаксис регулярных выражений) без наращивания и затем осуществляет поиск совпадения, начиная с начала следующего сообщения. Потом она выбирает сообщение, содержащее совпадение. Если regexp пусто, M-s использует регулярное выражение, заданное при предыдущем поиске.

Чтобы найти в файле другое сообщения в обратном направлении, задайте команде M-s отрицательный аргумент. В Rmail это можно сделать как - M-s.

Также возможен поиск сообщения по метке. Смотрите раздел Метки.

Для передвижения к сообщению, задаваемому абсолютным номером, используйте команду j (rmail-show-message) с номером сообщения в качестве аргумента. Без аргумента, команда j выбирает первое сообщение. < (rmail-first-message) также выбирает первое сообщение. Команда > (rmail-last-message) выбирает последнее.

Удаление сообщений

Когда вам больше не нужно хранить какое-то сообщение, его можно удалить. При этом удаляемое сообщение метится как возможно игнорируемое и некоторые команды Rmail не будут замечать его присутствия, но тем не менее оно продолжает существовать в Rmail-файле и сохраняет свой номер.

Вычеркивание в Rmail-файле (или его очистка) действительно уничтожает удаленные сообщения. Остальные сообщения последовательно перенумеровываются. Вычеркивание -- это единственное действие, кроме разбора дайджеста (смотрите раздел Сообщения-дайджесты), которое изменяет номера сообщений.

d
Удалить текущее сообщение и перейти к следующему неудаленному (rmail-delete-forward).
C-d
Удалить текущее сообщение и перейти к предыдущему неудаленному (rmail-delete-backward).
u
Отменить удаление текущего сообщения или перейти назад к удаленному сообщению и отменить его удаление (rmail-undelete-previous-message).
x
Очистить Rmail-файл (rmail-expunge).

Существуют две команды Rmail для удаления сообщений. Обе они удаляют текущее сообщение и выбирают другое. Команда d (rmail-delete-forward) переходит к следующему сообщению, пропуская уже удаленные, в то время как C-d (rmail-delete-backward) передвигает к предыдущему неудаленному сообщению. Если же нет неудаленного сообщения, к которому можно перейти в указанном направлении, то текущим остается сообщение, которое было только что удалено. Числовой аргумент меняет направление движения после удаления.

Всякий раз, когда Rmail удаляет сообщение, он вызывает функции, перечисленные в rmail-delete-message-hook. Когда вызываются функции этой ловушки, сообщение уже помечено как удаленное, но все еще является текущим в этом буфере Rmail.

Для того чтобы все удаленные сообщения окончательно исчезли из Rmail-файла, надо набрать x (rmail-expunge). Пока это не сделано, есть возможность отмены удаления сообщений. Команда отмены удаления, u (rmail-undelete-previous-message), предназначена для отмены действия команды d в большинстве случаев. Она отменяет удаление текущего сообщения, если оно было удалено. В противном случае она двигается к предыдущему сообщению до тех пор, пока не будет найдено удаленное сообщение, и производит отмену удаления этого сообщения.

Обычно вы можете отменить действие d с помощью команды u, так как u передвигает назад и отменяет удаление сообщения, произведенное командой d. Но это не работает, когда d пропускает несколько уже удаленных сообщений, которые следуют за удаляемым сообщением; в этом случае команда u будет отменять удаление последнего сообщения из тех, что были пропущены. Не существует совершенного способа обойти эту проблему. Однако, повторяя команду u, можно в конце концов вернуться к сообщению, для которого вы собирались отменить удаление. Можно также добраться до этого сообщения с помощью команды M-p и затем набрать u.

Удаленное сообщение имеет атрибут `deleted', и как результат при удалении текущего сообщения в строке режима появляется слово `deleted'. На самом деле, удаление или отмена удаления сообщения --- это не более чем добавление или уничтожение этого атрибута. Смотрите раздел Атрибуты в Rmail.

Rmail-файлы и входные почтовые ящики

Операционная система помещает приходящую вам почту в файл, который мы называем вашим входным почтовым ящиком. Когда вы запускаете Rmail, он выполняет написанную на Си программу movemail, чтобы скопировать новые сообщения из входного почтового ящика в первичный Rmail-файл, который также содержит другие сообщения, сохранившиеся от предыдущих сеансов Rmail. Именно в этом файле находится та корреспонденция, которую вы читаете с помощью Rmail. Эта процедура называется получением новой почты. В любой момент она может быть повторена в Rmail с помощью команды g.

Переменная rmail-primary-inbox-list содержит список имен файлов, являющихся входными почтовыми ящиками вашего первичного Rmail-файла. Если вы не установили эту переменную явно, она инициализируется значением переменной среды `MAIL', или, в крайнем случае, устанавливается в значение nil, что означает использование входного почтового ящика по умолчанию; это могут быть файлы `/var/mail/имя-пользователя', `/usr/mail/имя-пользователя' или `/usr/spool/mail/имя-пользователя' в зависимости от вашей операционной системы.

Чтобы узнать значение по умолчанию для вашей системы, используйте C-h v rmail-primary-inbox RET. Вы можете указать входной файл (или файлы) для любого Rmail-файла с помощью команды set-rmail-inbox-list; смотрите раздел Множество почтовых файлов.

Есть две причины для разделения Rmail-файлов и входных почтовых ящиков.

  1. Формат входных почтовых файлов изменяется от одной операционной системы к другой и зависит от других почтовых программ. Только одна часть Rmail должна знать об этих альтернативах и должна лишь понимать, как преобразовывать их все к собственному формату Rmail.
  2. Обеспечение доступа в файл входного почтового ящика без возникновения опасности потери почты -- очень громоздкая вещь, поскольку требует взаимных блокировок с доставкой почты. Кроме того, различные операционные системы используют разную технику блокировок. Стратегия перемещения почты из входного почтового ящика раз и навсегда в отдельный Rmail-файл устраняет необходимость блокировки всего остального в Rmail, так как только Rmail работает с Rmail-файлом.

Rmail был написан с использованием Babyl в качестве внутреннего формата. С тех пор мы поняли, что обычный для систем Unix и GNU формат входных почтовых ящиков подходит для этой цели, и мы планируем изменить Rmail, чтобы он использовал этот формат. Однако, Rmail-файл все так же будет отдельным от входного файла, даже на системах, где их форматы одинаковы.

Множество почтовых файлов

По умолчанию Rmail действует в вашем первичном Rmail-файле, называемом `~/RMAIL', и получает вашу приходящую почту из системного входного почтового файла. Но вы можете также иметь другие Rmail-файлы и редактировать их с помощью Rmail. Эти файлы могут получать почту через их собственные файлы входных почтовых ящиков, или вы можете перемещать в них сообщения с помощью явных команд Rmail (смотрите раздел Копирование сообщений в файлы).

i файл RET
Считать файл в Emacs и запустить в нем Rmail (rmail-input).
M-x set-rmail-inbox-list RET файлы RET
Задать имена входных почтовых файлов, откуда будет получать почту текущий Rmail-файл.
g
Получить новую почту из входных почтовых ящиков текущего Rmail-файла (rmail-get-new-mail).
C-u g файл RET
Получить новую почту из входного почтового ящика файл.

Чтобы запустить Rmail для файла, отличного от вашего первичного почтового файла, можно использовать в Rmail команду i (rmail-input). Она обращается к этому файлу в режиме Rmail. Вы также можете использовать команду M-x rmail-input, даже не находясь в Rmail.

Файл, считываемый с помощью команды i, как правило, должен быть правильным Rmail-файлом. Если это не так, Rmail пытается преобразовать его в поток сообщений в нескольких известных форматах. Если это удается, он преобразует весь этот файл в Rmail-файл. Если вы задали имя несуществующего файла, i инициализирует новый буфер для создания нового Rmail-файла.

Вы также можете выбрать Rmail-файл из меню. Сначала выберите пункт меню Classify, из меню Classify выберите пункт Input Rmail File; затем выберите нужный вам файл. Переменные rmail-secondary-file-directory и rmail-secondary-file-regexp указывают, какие файлы предлагает это меню: первая переменная говорит, в каком каталоге их искать; вторая говорит, какие файлы в этом каталоге предлагать (все, чьи имена соответствуют регулярному выражению). Эти переменные также относятся к выбору файла для вывода (смотрите раздел Копирование сообщений в файлы).

Каждый Rmail-файл может содержать список имен файлов входных почтовых ящиков; вы можете задать этот список с помощью M-x set-rmail-inbox-list RET files RET. Аргумент может содержать любое число имен файлов, разделенных запятыми. Он может быть также пустым, и это означает, что этот файл не должен иметь входных почтовых ящиков. Как только указан список входных почтовых ящиков, Rmail-файл запоминает его и сохраняет до тех пор, пока он явно не будет изменен.

Как особое исключение, если ваш первичный Rmail-файл не указывает входных почтовых файлов, он использует стандартный системный.

Команда g (rmail-get-new-mail) вносит почту в текущий Rmail-файл из его входных файлов. Если у этого Rmail-файла нет входных файлов, g ничего не делает. Команда M-x rmail также вносит новую почту в ваш первичный Rmail-файл.

Чтобы перенести почту из файла, не являющегося обычным входным почтовым ящиком, задайте ключу g числовой аргумент, как в C-u g. Тогда он считает имя файла и перенесет почту из него. Когда g используется с аргументом, файл входного почтового ящика ни в коем случае не удаляется и не изменяется. Поэтому это основной способ переноса одного файла сообщений в другой.

Копирование сообщений в файлы

Эти команды копируют сообщения из Rmail-файла в другой файл.

o файл RET
Добавить копию текущего сообщения в конец файла, по умолчанию в формате Rmail-файлов (rmail-output-to-rmail-file).
C-o файл RET
Добавить копию текущего сообщения в конец файла, по умолчанию в формате системных почтовых ящиков (rmail-output).
w файл RET
Вывести только тело сообщения в файл, по умолчанию имя файла берется из поля `Subject'.

Команды o и C-o копируют текущее сообщение в указанный файл. Это может быть Rmail-файл или файл в формате системных почтовых ящиков; команды вывода выясняют формат этого файла и записывают копируемое сообщение в этом формате.

При копировании сообщения в файл в формате Unix, эти команды включают все поля заголовков, которые видимы в данный момент. Если хотите, используйте сначала команду t, чтобы указать, какие заголовки показывать (и копировать).

Команды o и C-o различаются с двух сторон: каждая предлагает свое имя файла по умолчанию и каждая задает свой выбор формата, когда файл еще не существует. Команда o использует при создании нового файла формат Rmail, тогда как C-o использует для нового файла системный формат. По умолчанию o использует имя файла, заданное последней o, а C-o -- последней C-o.

Если к выходному Rmail-файлу в данный момент обращается какой-нибудь буфер, команды вывода копируют сообщение в этот буфер. Нужно ли действительно сохранять буфер в его файл решаете вы.

Иногда вы можете получить сообщение, чье тело несет содержимое файла. Вы можете сохранить его тело в файл (исключая заголовки сообщения) с помощью команды w (rmail-output-body-to-file). Часто эти сообщения содержат имя целевого файла в поле `Subject', поэтому команда w использует это поле как имя выходного файла по умолчанию. Однако, имя файла считывается из минибуфера, поэтому при желании вы можете указать другое имя.

Вы также можете вывести сообщение в Rmail-файл, выбранный из меню. Сначала выберите пункт меню Classify, из меню Classify выберите пункт Output Rmail File; затем выберите нужный вам пункт меню. Это выведет текущее сообщение в указанный файл, как команда o. Переменные rmail-secondary-file-directory и rmail-secondary-file-regexp указывают, какие файлы предлагает это меню: первая переменная говорит в каком каталоге их искать; вторая говорит, какие файлы в этом каталоге предлагать (все, чьи имена соответствуют регулярному выражению).

Копирование сообщения придает его исходной копии атрибут `filed', так что когда такое сообщение становится текущим, в строке режима появляется слово `filed'. Если вы хотите хранить только одну копию каждого почтового сообщения, установите переменную rmail-delete-after-output равной t; тогда команды o и C-o после копирования удаляют оригинал. (Впоследствии вы можете отменить удаление оригинального сообщения, если захотите.)

При копировании в файлы в системном формате почтовых ящиков используются поля заголовка, которые показаны в это время в Rmail. Таким образом, если вы используете команду t для просмотра всего заголовка и затем скопируете сообщение, скопируется весь заголовок. Смотрите раздел Отображение сообщений.

Переменная rmail-output-file-alist позволяет вам указать интеллектуальные значения по умолчанию для выходного файла, основанные на содержимом текущего сообщения. Ее значением должен быть список, чьи элементы имеют такую форму:

(regexp . имя)

Если в текущем сообщении есть совпадение с regexp, то по умолчанию именем выходного файла будет имя. Если совпадения найдены для нескольких элементов, то имя файла по умолчанию определяется первым совпавшим элементом. Подвыражение имя может быть константной строкой, дающей имя файла, или, в более общем случае, любым лисповским выражением, возвращающим имя файла в виде строки. rmail-output-file-alist относится как к o, так и к C-o.

Метки

У каждого сообщения могут быть различные метки, приписываемые ему в качестве средства классификации. Метка имеет имя; разные имена означают разные метки. Любая данная метка либо присутствует, либо отсутствует в конкретном сообщении. Ряд имен меток имеют стандартные значения и присваиваются сообщениям в Rmail автоматически в нужный момент; такие специальные метки называются атрибутами.

Все другие метки приписываются пользователем.

a метка RET
Приписать метку текущему сообщению (rmail-add-label).
k метка RET
Удалить метку из текущего сообщения (rmail-kill-label).
C-M-n метки RET
Передвинуться на следующее сообщение, которое имеет одну из меток (rmail-next-labeled-message).
C-M-p метки RET
Передвинуться на предыдущее сообщение, которое имеет одну из меток (rmail-previous-labeled-message).
C-M-l метки RET
Cделать резюме всех сообщений, содержащих какую-либо из меток (rmail-summary-by-labels).

Команды a (rmail-add-label) и k (rmail-kill-label) позволяют вам приписывать или удалять любую метку из текущего сообщения. Если аргумент метка пустой, то это означает приписывание или удаление той самой метки, которая была приписана или удалена самой последней.

Как только вы присвоили сообщениям метки, чтобы классифицировать их так, как вам хочется, появляются два способа использования этих меток: в перемещении и в резюме.

Команда C-M-n метки RET (rmail-next-labeled-message) передвигает к следующему сообщению, которое имеет одну из меток. Аргумент метки -- это одно или несколько имен меток, разделенных запятыми. C-M-p (rmail-previous-labeled-message) -- аналогичная команда, но передвигает назад к предыдущим сообщениям. Числовой аргумент в этих командах работает как счетчик повторов.

Команда C-M-l метки RET (rmail-summary-by-labels) показывает резюме, содержащее только сообщения, имеющие по крайней мере одну из описанного набора меток. Аргумент метки -- это одно или более имен меток, разделенных запятыми. Смотрите раздел Резюме, для получения информации о резюме.

Если аргумент метки для C-M-n, C-M-p или C-M-l пустой, то это предполагает использование последнего набора меток, указанного для какой-либо из этих команд.

Атрибуты в Rmail

Некоторые метки, такие, как `deleted' и `filed', имеют встроенные значения и приписываются сообщениям или удаляются из них автоматически в соответствующее время; эти метки называются атрибутами. Ниже приводится список атрибутов Rmail.

`unseen'
Означает, что сообщение никогда не было текущим. Приписывается сообщениям, когда они поступают из файла входного почтового ящика, и удаляется, когда сообщение становится текущим. Когда вы запускаете Rmail, он изначально показывает первое сообщение с этим атрибутом.
`deleted'
Означает, что сообщение удаляется. Приписывается командами удаления и уничтожается командами отмены удаления (смотрите раздел Удаление сообщений).
`filed'
Означает, что сообщение было скопировано в какой-нибудь другой файл. Приписывается командами вывода файла (смотрите раздел Множество почтовых файлов).
`answered'
Означает, что вы послали ответ на это сообщение. Приписывается командой r (rmail-reply). Смотрите раздел Посылка ответов.
`forwarded'
Означает, что вы перенаправляли сообщение другим. Приписывается командой f (rmail-forward). Смотрите раздел Посылка ответов.
`edited'
Означает, что вы редактировали текст сообщения внутри Rmail. Смотрите раздел Редактирование внутри сообщения.
`resent'
Означает, что вы пересылали это сообщение. Приписывается командой M-x rmail-resend. Смотрите раздел Посылка ответов.

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

Посылка ответов

Rmail имеет ряд команд, которые используют режим Mail для посылки исходящей корреспонденции. Смотрите раздел Посылка почты, для справок по использованию режима Mail, включая некоторые средства, предназначенные для работы с Rmail. А в этом разделе описываются специальные команды Rmail для входа в режим Mail. Следует отметить, что обычные команды для посылки почты, C-x m и C-x 4 m, применимы в режиме Rmail и работают точно так же, как обычно.

m
Послать сообщение (rmail-mail).
c
Продолжить редактирование уже начатого выходного сообщения (rmail-continue).
r
Послать ответ на текущее сообщение Rmail (rmail-reply).
f
Перенаправить текущее сообщение другим пользователям (rmail-forward).
C-u f
Переслать сообщение другим пользователям (rmail-resend).
M-m
Попробовать послать отскочившее письмо еще раз (rmail-retry-failure).

Самая распространенная причина посылки сообщения во время пребывания в Rmail -- это необходимость ответа на сообщение, которое вы читаете. Чтобы сделать это, наберите r (rmail-reply). Это вызовет появление буфера `*mail*' в другом окне, что очень похоже на C-x 4 m, но при этом заранее инициализируются поля заголовка `Subject', `To', `CC' и `In-reply-To', основываясь на сообщении, на которое формируется ответ. Полю `To' присваивается имя отправителя этого сообщения, а в поле `CC' помещаются имена всех остальных его получателей.

Вы можете предотвратить появление некоторых адресов в поле `CC', используя переменную rmail-dont-reply-to-names. Ее значением должно быть регулярное выражение (в виде строки): все получатели, чьи адреса совпадают с этим регулярным выражением, будут исключены из поля `CC'. По умолчанию она соответствует вашему собственному имени и любому имени, начинающемуся с `info-'. (Эти имена исключаются, потому что есть соглашение об использовании их для больших списков рассылки для широкой публикации анонсов.)

Чтобы полностью опустить поле `CC' в каком-то ответе, введите команду ответа с числовым аргументом: C-u r или 1 r.

После того, как буфер `*mail*' проинициализирован, редактирование и отправка почты идет как обычно (смотрите раздел Посылка почты). Если с вашей точки зрения ранее подготовленные поля заголовка неправильны, то их можно отредактировать. Вы также можете использовать команды режима Mail (смотрите раздел Режим Mail), включая C-c C-y, которая вставляет сообщение, на которое вы отвечаете. Вы можете вернуться в буфер Rmail, выбрать там другое сообщение, переключиться назад и вставить новое текущее сообщение.

Иногда сообщения не доходят по назначению. Почтовые программы обычно возвращают вам это письмо, заключив его в сообщение об отказе. Команда Rmail M-m (rmail-retry-failure) подготавливает этого же сообщение к повторной посылке: она создает буфер `*mail*' с тем же телом и полями заголовка, какие были раньше. Если вы сразу нажмете C-c C-c, вы пошлете сообщение точно таким же, каким оно было в первый раз. Иначе, вы можете отредактировать его текст или заголовки и затем отправить. Переменная rmail-retry-ignored-headers, в том же формате, что и rmail-ignored-headers (смотрите раздел Отображение сообщений), контролирует, какие заголовки будут удалены из сообщения об отказе при попытке повторной отправки; по умолчанию она равна nil.

Еще одна достаточно частая причина отправки почты в Rmail заключается в необходимости перенаправить текущее сообщение другим пользователям. Команда f (rmail-forward) облегчает это, заранее инициализируя буфер `*mail*' текстом текущего сообщения и указывая в поле `Subject', что это перенаправленное письмо. От вас требуется только записать получателей и отправить. Когда вы перенаправляете сообщение, адресаты получают его "от вас", а его содержимым является оригинальное сообщение.

Перенаправленное сообщение заключается между двумя разделительными строками. Кроме этого, все строки в нем, начинающиеся с дефисов, изменяются добавлением `- ' в начало. Когда вы получаете перенаправленное сообщение, если оно содержит что-то кроме обычного текста -- исходный код программы, например -- вы можете счесть удобным проделать обратное преобразование. Вы можете сделать это, выбрав перенаправленное сообщение и напечатав M-x unforward-rmail-message. Эта команда извлекает оригинальное сообщение, удаляя вставленные строки `- ', и вставляет его в Rmail-файл как отдельное сообщение сразу после текущего.

Пересылка -- это вариант, похожий на перенаправление; разница в том, что при пересылке письмо отправляется "от начального посылателя", таким же, каким оно пришло к вам, но с добавлением полей заголовка `Resent-from' и `Resent-to', чтобы обозначить, что оно исходит от вас. Чтобы переслать сообщение в Rmail, используйте C-u f. (f запускает rmail-forward, которая запрограммирована так, чтобы вызывать rmail-resend, если вы задали числовой аргумент.)

Команда m (rmail-mail) используется для начала редактирования исходящего сообщения, которое не является ответом. Она оставляет поля заголовка пустыми. Единственное отличие ее от C-x 4 m состоит в том, что она обеспечивает доступность буфера Rmail для C-c C-y, так же, как это делает r. Таким образом, m может быть использована для отправки ответа на сообщение или для перенаправления; она может делать все, что делают команды r и f.

Команда c (rmail-continue) возобновляет редактирование буфера `*mail*', чтобы вы могли завершить сообщение, которое уже составляли, а также для изменения сообщения, которое вы отправили.

Если вы установите переменную rmail-mail-new-frame в значение, не равное nil, то все команды Rmail для начала отправки сообщения будут создавать для его редактирования новый фрейм. Этот фрейм удаляется, когда вы отсылаете сообщение, или когда вы используете пункт `Don't Send' в меню `Mail'.

Все команды Rmail для отправки сообщения используют тот метод составления, который вы выбрали (смотрите раздел Способы составления сообщений).

Резюме

Резюме -- это буфер, который содержит по одной строке на сообщение и дает вам возможность обзора почты в Rmail-файле. В каждой такой строке показан номер сообщения, его отправитель, метки и тема. Почти все команды Rmail можно использовать также и в буфере резюме; они относятся к сообщению, описанному на текущей строке. Перемещение точки в буфере резюме выбирает другие сообщения, когда вы переходите к их строкам.

Каждый буфер резюме относится только к одному Rmail-файлу; если редактируется множество Rmail-файлов, то они имеют отдельные буферы резюме. Имя буфера резюме создается добавлением `-summary' в конец имени буфера Rmail. Как правило, в один и тот же момент показывается только один буфер резюме.

Создание резюме

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

h
C-M-h
Создает резюме всех сообщений (rmail-summary).
l метки RET
C-M-l метки RET
Создает резюме сообщений, которые имеют одну или несколько указанных меток (rmail-summary-by-labels).
C-M-r получатели RET
Создает резюме сообщений, отправленных одному или нескольким из указанных получателей (rmail-summary-by-recipients).
C-M-t тема RET
Создает резюме сообщений, которые имеют совпадение с регулярным выражением тема в полях заголовка `Subject' (rmail-summary-by-topic).

Команда h или C-M-h (rmail-summary) заполняет буфер резюме для текущего Rmail-файла перечнем всех сообщений из этого файла. Потом она показывает и выбирает этот буфер резюме в другом окне.

C-M-l метки RET (rmail-summary-by-labels) делает частичное резюме, упоминающее только сообщения, которые имеют одну или несколько меток. Метки должны содержать имена меток, разделенные запятыми.

C-M-r получатели RET (rmail-summary-by-recipients) делает частичное резюме, упоминающее только сообщения, которые имеют одного или нескольких получателей. Аргумент получатели должен содержать почтовые адреса, разделенные запятыми.

C-M-t тема RET (rmail-summary-by-topic) создает частичное резюме, упоминающее только сообщения, чьи поля `Subject' имеют совпадения с регулярным выражением тема.

Следует отметить, что для любого Rmail-файла существует только один буфер резюме; создание резюме одного вида отменяет любое ранее сделанное резюме.

Переменная rmail-summary-window-size говорит, сколько строк должно использовать окно резюме. Переменная rmail-summary-line-count-flag указывает, должны ли строки резюме содержать число, показывающее количество строк в сообщении.

Редактирование резюме

Вы можете делать в буфере резюме Rmail практически все, что вы можете делать в самом буфере Rmail. На самом деле, если у вас есть буфер резюме, нет необходимости переключаться назад в буфер Rmail.

Вы можете выбирать и просматривать различные сообщения в буфере Rmail из буфера резюме просто перемещая в нем точку к разным строкам. Не играет роли, какую именно команду Emacs вы используете для перемещения точки; на какой строке окажется точка после команды, то сообщение и будет выбрано в буфере Rmail.

Почти все команды Rmail работают и в буфере резюме, также как и в буфере Rmail. А именно, d в буфере резюме удаляет текущее сообщение, u отменяет удаление, а x вычеркивает. o и C-o выводят текущее сообщение в файл; r позволяет написать ответ. Вы можете прокручивать текущее сообщение, оставаясь в буфере резюме, с помощью SPC и DEL.

Команды Rmail для передвижения по сообщениям работают также и в буфере резюме, но с особенностью: они перемещают по тем сообщениям, которые перечислены в резюме. Они также убеждаются, что буфер Rmail появляется на экране (в отличие от команд движения курсора, которые обновляют содержимое буфера Rmail, но не показывают его в окне, если он уже не виден). Вот перечень этих команд:

n
Перейти к следующей строке, пропуская удаленные, и выбрать ее сообщение.
p
Перейти к предыдущей строке, пропуская удаленные, и выбрать ее сообщение.
M-n
Перейти к следующей строке и выбрать ее сообщение.
M-p
Перейти к предыдущей строке и выбрать ее сообщение.
>
Перейти к последней строке и выбрать ее сообщение.
<
Перейти к первой строке и выбрать ее сообщение.
M-s образец RET
Производит поиск образца в сообщениях начиная с текущего; выбирает найденное сообщение и перемещает точку в буфере резюме к его строке.

Удаление, отмена удаления, получение новой почты и даже выбор другого сообщения -- все обновляют буфер резюме, когда вы делаете эти операции в буфере Rmail. Если переменная rmail-redisplay-summary не равна nil, эти действия также возвращают буфер резюме на экран.

Когда вы завершили использование резюме, наберите Q (rmail-summary-wipe), чтобы удалить окно буфера резюме. Вы также можете выйти из Rmail, находясь в буфере резюме: q (rmail-summary-quit) удаляет окно резюме, а затем выходит из Rmail, записывая Rmail-файл и переключая в другой буфер.

Сортировка Rmail-файла

M-x rmail-sort-by-date
Сортирует сообщения текущего Rmail-файла по дате.
M-x rmail-sort-by-subject
Сортирует сообщения текущего Rmail-файла по теме.
M-x rmail-sort-by-author
Сортирует сообщения текущего Rmail-файла по имени автора.
M-x rmail-sort-by-recipient
Сортирует сообщения текущего Rmail-файла по именам получателей.
M-x rmail-sort-by-correspondent
Сортирует сообщения текущего Rmail-файла по имени другого корреспондента.
M-x rmail-sort-by-lines
Сортирует сообщения текущего Rmail-файла по размеру (числу строк).
M-x rmail-sort-by-keywords RET метки RET
Сортирует сообщения текущего Rmail-файла по меткам. Аргумент метки должен быть списком меток, разделенных запятыми. Порядок этих меток определяет порядок сообщений; сообщения с первой меткой идут первыми, сообщения со второй меткой идут вторыми, и так далее. Сообщения, не имеющие ни одну из этих меток, идут последними.

Команды Rmail для сортировки производят устойчивую сортировку: если нет причины предпочитать одно из двух сообщений, их порядок не изменяется. Вы можете использовать это для сортировки по нескольким критериям. Например, если вы применили rmail-sort-by-date и затем rmail-sort-by-author, сообщения от одного автора появятся в порядке возрастания даты.

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

Отображение сообщений

Rmail переформатирует заголовок каждого сообщения перед его показом. При этом удаляются неинтересные поля заголовков, чтобы уменьшить беспорядок. Чтобы посмотреть заголовок целиком или повторить операцию переформатирования, вы можете использовать команду t (rmail-toggle-headers).

t
Включает или выключает показ полного заголовка (rmail-toggle-header).

При переформатировании удаляются большинство полей заголовка, поскольку они не представляют интереса. Переменная rmail-ignored-headers содержит регулярное выражение, указывающее какие поля надо скрывать таким способом -- если оно соответствует началу поля, то это поле скрывается.

Rmail сохраняет полные исходные заголовки перед переформатированием; чтобы посмотреть их, используйте команду t (rmail-toggle-headers). Она сбрасывает переформатированные заголовки текущего сообщения и показывает его с исходными заголовками. Повтор команды t снова переформатирует сообщение. Повторный выбор сообщения тоже приводит к переформатированию.

Одно из последствий этого состоит в том, что если вы редактировали переформатированный заголовок (с помощью e; смотрите раздел Редактирование внутри сообщения), последующее использование t сбросит ваши изменения. С другой стороны, если вы использовали e после t, чтобы редактировать первоначальный (не переформатированный) заголовок, эти изменения останутся.

Когда команде t дан префиксный аргумент, положительный аргумент обозначает показ переформатированного заголовка, а нулевой или отрицательный -- полного.

При использовании в оконной системе, которая поддерживает несколько шрифтов, Rmail подсвечивает некоторые поля заголовка, которые особенно интересны -- по умолчанию это поля `From' и `Subject'. Переменная rmail-highlighted-headers хранит регулярное выражение, задающее поля заголовка, которые нужно подсвечивать; если оно соответствует началу поля, все это поле подсвечивается.

Если вы зададите необычные цвета для текста и фона, то цвета, используемые для подсветки, могут с ними плохо смотреться. В таком случае задайте другие цвета для начертания highlight. Это стоит сделать, потому что начертание highlight используется и других видах выделения. Смотрите раздел Использование разных начертаний, чтобы узнать, как это сделать.

Чтобы полностью выключить подсветку в Rmail, установите rmail-highlighted-headers равной nil.

Редактирование внутри сообщения

Большинство обычных команд Emacs доступны в режиме Rmail, хотя некоторые, такие как C-M-n и C-M-h, переопределяются в Rmail для других целей. Однако обычно буфер Rmail предназначен только для чтения, и большинство букв переопределены как команды Rmail. Если вы хотите отредактировать текст сообщения, вы должны использовать команду Rmail e.

e
Редактировать текущее сообщение как обычный текст.

Команда e (rmail-edit-current-message) переключает из режима Rmail в режим Rmail Edit, другой основной режим, практически эквивалентный режиму Text. Это изменение отображается в строке режима.

В режиме Rmail Edit буквы вставляют себя как обычно, а команды Rmail недоступны. Когда вы закончите редактирование сообщения и будете готовы вернуться в Rmail, наберите команду C-c C-c, которая переключит вас назад в режим Rmail. С другой стороны, можно вернуться в режим Rmail, но отменить все сделанные изменения, набрав C-c C-].

Вход в режим Rmail Edit вызывает ловушку text-mode-hook, а затем ловушку rmail-edit-mode-hook (смотрите раздел Ловушки). При этом в сообщению присваивается атрибут `edited'. Она также показывает полный заголовок сообщения, так что вы можете редактировать как тело, так и заголовки сообщения, и ваши изменения в заголовках останутся навсегда.

Сообщения-дайджесты

Сообщение-дайджест -- это сообщение, которое создано для передачи нескольких других сообщений. Дайджесты используются в некоторых списках рассылки с ведущим; все сообщения, которые пришли для рассылки в течение какого-то периода времени, например одного дня, помещаются в единый дайджест, который затем рассылается подписчикам. Пересылка одного такого дайджеста занимает гораздо меньше машинного времени, чем пересылка отдельных сообщений, хоть и при одинаковом общем объеме, поскольку затраты ресурсов на одно сообщение при передаче почты по сети довольно значительны.

При получении сообщения-дайджеста наиболее удобным способом для его прочтения является разброшюровка: обратное разделение его на несколько отдельных сообщений. После этого можно читать и удалять отдельные сообщения как вам угодно.

Чтобы сделать это, необходимо выбрать сообщение-дайджест и затем набрать команду M-x undigestify-rmail-message. Она извлекает каждое подсообщение как отдельное сообщение Rmail и вставляет их вслед за дайджестом. Само сообщение-дайджест помечается как удаленное.

Преобразование Rmail-файла в системный формат

Команда M-x unrmail преобразует файл в формате Rmail в формат входных почтовых ящиков (также известный как системный почтовый формат), чтобы вы могли использовать его с другими программами для редактирования почты. Вы должны указать два аргумента, имя Rmail-файла и имя для преобразованного файла. M-x unrmail не изменяет сам Rmail-файл.

Чтение сообщений в Rot13

Сообщения из списков рассылки, которые могут оскорбить некоторых читателей, иногда кодируются простым методом, называемым rot13 --- потому что он сдвигает алфавит на 13 букв. Этот код служит не для секретности, он не предоставляет ее; скорее, он позволяет тем, кто может быть оскорблен, избежать возможности даже увидеть настоящий текст сообщения.

Чтобы просмотреть буфер, использующий код rot13, запустите команду M-x rot13-other-window. Она показывает текущий буфер в другом окне, применяя код при отображении текста.

movemail и POP

При получении новой почты Rmail сначала копирует ее из входного файла в Rmail-файл; затем он записывает Rmail-файл; затем усекает входной файл. Таким образом, сбой в системе может вызвать дублирование почты во входном файле и в Rmail-файле, но не может вызвать потери. Если rmail-preserve-inbox не равна nil, то Rmail будет копировать новую почту из входного файла в Rmail-файл, не усекая входной файл. Вы можете сделать такую установку, например, на портативном компьютере, который вы используете для проверки почты через POP во время путешествий, чтобы ваша почта оставалась на сервере, и вы могли сохранить ее позднее на своей рабочей станции.

В некоторых случаях Rmail копирует новую почту из входного файла не прямым путем. Сначала он запускает программу movemail, чтобы переместить почту из входного файла в промежуточный файл, называемый `~/.newmail-входной-файл'. Затем Rmail вносит новую почту из этого файла, сохраняет Rmail-файл и только затем удаляет промежуточный файл. Если в неподходящий момент случится фатальный сбой, этот файл останется на месте, и Rmail будет использовать его в следующий раз при получении новой почты из этого входного файла.

Если Rmail по какой-то причине не может преобразовать данные из файла `~/.newmail-входной-файл' в формат Babyl, он переименовывает его в `~/RMAILOSE.n' (n -- это целое число, выбранное так, чтобы оно было уникальным), так что Rmail не будет иметь проблем с этими данными снова. Вам стоит просмотреть этот файл, найти сообщение, которое сбивает с толку Rmail (вероятно, оно содержит знак control-подчерк, восьмеричный код 037), и удалить его. Тогда вы можете использовать 1 g, чтобы получить почту из исправленного файла.

Некоторые системы используют для доступа к данным почтовых ящиков пользователей метод, называемый POP, вместо записи этих данных в почтовые файлы. movemail может работать с POP, если вы скомпилировали ее с определенным макросом MAIL_USE_POP. (Вы можете получить это, задав ключ `--with-pop', когда запускаете configure во время установки Emacs.) movemail работает только с POP3, но не с более ранними версиями POP.

В предположении, что вы правильно скомпилировали и установили movemail, вы можете указать входной почтовый ящик POP, написав "имя файла" в форме `po:имя-пользователя' в списке входных почтовых ящиков Rmail-файла. movemail обрабатывает такие имена путем установки соединения с POP-сервером. Переменная среды `MAILHOST' задает машину, на которой будет производиться поиск сервера.

Для доступа к почте через POP может потребоваться пароль. Если переменная rmail-pop-password отлична от nil, то она задает пароль для использования с POP. Иначе, если rmail-pop-password-required не равна nil, то Rmail спрашивает пароль у вас.

Если вам нужно передать movemail дополнительные флаги командной строки, установите переменную rmail-movemail-flags равной списку желаемых флагов. Не используйте эту переменную для передачи флага -p, который предотвращает затирание содержимого входного файла; пользуйтесь вместо этого переменной rmail-preserve-inbox.

Установленная в вашей системе программа movemail может поддерживать аутенфикацию Kerberos. Если она поддерживается, то это будет использоваться по умолчанию всегда, когда вы будете пытаться получить почту через POP при неустановленных rmail-pop-password и rmail-pop-password-required.

Некоторые POP-серверы хранят сообщения в обратном порядке. Если ваш сервер делает так, а вам хотелось бы читать почту в том порядке, в каком она поступала, вы можете велеть movemail перевернуть очередность загружаемых сообщений, добавив к rmail-movemail-flags флаг -r.

Dired, редактор каталогов

Dired создает буфер Emacs, содержащий распечатку каталога и, возможно, некоторых его подкаталогов. Вы можете использовать обычные команды Emacs, чтобы передвигаться по этому буферу, и специальные команды Dired, чтобы производить различные действия над файлами.

Вход в Dired

Чтобы запустить Dired, выполните C-x d или M-x dired. Эта команда считывает имя каталога или шаблон имени файла как аргумент минибуфера, чтобы определить, какие файлы нужно перечислить. Команда dired отличается от list-directory тем, что она переводит буфер в режим Dired, так что в нем становятся доступными специальные команды Dired.

Переменная dired-listing-switches задает ключи для передачи ls при создании распечатки каталога; эта строка должна содержать `-l'. Если вы используете с командой dired числовой аргумент, вы можете указать в минибуфере ключи для ls до того, как введете имя каталога.

Чтобы показать буфер Dired в другом окне, а не в выбранном, вместо C-x d используется C-x 4 d (dired-other-window). C-x 5 d (dired-other-frame) использует для показа буфера Dired отдельный фрейм.

Команды, действующие в буфере Dired

Буфер Dired помечен как "предназначенный только для чтения", и вставлять в него текст бесполезно, так что обычные печатные знаки, такие как d и x, используются для команд Dired. Одни команды Dired устанавливают флаг на текущем файле (это файл на текущей строке) или помечают его; другие команды выполняют действия над помеченными файлами или файлами с установленным флагом.

Все обычные команды движения курсора в Emacs доступны и в буферах Dired. Также предусмотрены некоторые специальные команды. Ключи C-n и С-p переопределены так, что они устанавливают курсор в начало имени файла на строке, а не в начало самой строки.

Для большего удобства, SPC и n в Dired эквивалентны C-n. p эквивалентен C-p. (Движение по строкам делается в Dired настолько часто, что оно заслуживает того, чтобы набор его был облегчен.) DEL (передвинуться вверх и убрать флаг) часто бывает полезным просто для движения вверх.

Удаление файлов с помощью Dired

Прежде всего Dired используется, чтобы установить флаг для удаления на некоторых файлах, а потом удалить файлы, ранее помеченные флагом.

d
Установить флаг удаления для этого файла.
u
Убрать флаг удаления на этой строке.
DEL
Передвинуть точку на строку выше и убрать на этой строке флаг удаления.
x
Удалить файлы, помеченные флагом удаления.

Вы можете установить на файле флаг, переместившись на строку, описывающую файл, и набрав на ней d (dired-flag-file-deletion). Флаг удаления выглядит как `D' в начале строки. Эта команда передвигает точку в начало следующей строки, таким образом, повторение команды d помечает для удаления последующие файлы. Числовой аргумент служит в качестве счетчика повторов.

Файлы помечаются для удаления, а не удаляются немедленно, чтобы уменьшить опасность случайного удаления файла. До тех пор, пока вы прямо не укажете Dired удалить помеченный файл, вы можете убрать флаги, используя команды u или DEL. u (dired-unmark работает точно так же, как d, но удаляет флаги, а не создает их. DEL (dired-unmark-backward) двигается вверх, убирая флаги; это подобно u с аргументом -1.

Чтобы удалить файлы с установленным флагом, наберите x (dired-expunge). Эта команда покажет сначала список всех имен файлов, помеченных для удаления, и потребует подтверждения вводом yes. Если вы подтверждаете, то все помеченные флагом файлы уничтожаются и их строки удаляются из текста буфера Dired. Сокращенный буфер Dired остается выбранным.

Если при запросе подтверждения вы ответите no или выйдите с помощью C-g, вы немедленно вернетесь в Dired; все флаги удаления останутся в буфере, и файлы не будут удалены.

Установка флага на несколько файлов одновременно

#
Помечает флагом удаления все файлы, которые появились при самосохранении (файлы, чьи имена начинаются и кончаются на `#') (смотрите раздел Самосохранение: защита от гибели).
~
Помечает флагом удаления все резервные файлы (файлы, чьи имена кончаются на `~') (смотрите раздел Резервные файлы).
&
Помечает флагом удаления все файлы с определенными типами имен, предполагающими, что вы легко сможете их снова создать.
. (Точка)
Помечает флагом удаления излишние резервные файлы. Сохраняются только несколько самых старых и самых новых резервных копий; промежуточные помечаются флагом.
% d регулярное-выражение RET
Помечает флагом удаления все файлы, чьи имена соответствуют заданному регулярному-выражению.

Команды #, ~, & и . устанавливают флаг для нескольких файлов, основываясь на их именах. Эти команды полезны именно потому, что сами по себе они не удаляют файлы; вы можете убрать флаги удаления с любых помеченных файлов, которые вы в действительности хотите сохранить.

& (dired-flag-garbage-files) устанавливает флаг удаления для файлов, чьи имена соответствуют регулярному выражению, заданному переменной dired-garbage-files-regexp. По умолчанию ей соответствуют определенные файлы, производимые TeX, и файлы `.orig' и `.rej', производимые программой patch.

# (dired-flag-auto-save-files) устанавливает флаг удаления для всех файлов, чьи имена выглядят как имена самосохраненных файлов (смотрите раздел Самосохранение: защита от гибели) -- это файлы с именами, начинающимися и заканчивающимися на `#'. ~ (dired-flag-backup-files) устанавливает флаг удаления для всех файлов, чьи имена говорят, что это резервные копии (смотрите раздел Резервные файлы) -- это файлы с именами, заканчивающимися на `~'.

. (точка, dired-clean-directory) устанавливает флаг удаления лишь для некоторых резервных копий: для всех, кроме самых старых и самых новых резервных копий одного файла. Обычно dired-kept-versions (не kept-new-versions; эта переменная применяется при сохранении) задает число самых новых сохраняемых версий каждого файла, а kept-old-versions задает число самых старых сохраняемых версий.

Точка с положительным числовым аргументом, как в C-u 3 ., указывает число оставляемых новых версий, перекрывая значение dired-kept-versions. Отрицательный числовой аргумент перекрывает kept-old-versions, используя число, противоположное заданному, для указания числа оставляемых старых версий каждого файла.

Команда % d устанавливает флаг удаления для всех файлов, чьи имена соответствуют заданному регулярному выражению (dired-flag-files-regexp). При поиске используется имя файла с исключенной частью, определяющей каталог. Для привязки регулярного выражения к началу или концу имени вы можете использовать `^' и `$'. Подкаталоги вы можете исключить, скрыв их (смотрите раздел Скрывание подкаталогов).

Обращение к файлам в Dired

Есть несколько команд Dired для обращения к файлам, перечисленным в буфере Dired, или просмотра их содержимого. Все они применяются к файлу на текущей строке; если этот файл на самом деле является каталогом, эти команды вызывают в нем Dired (создавая отдельный буфер Dired).

f
Обращается к файлу, описанному на текущей строке; подобна вводу C-x C-f и заданию имени этого файла (dired-find-file). Смотрите раздел Обращение к файлам.
RET
Эквивалент f.
o
Как f, но использует для отображения буфера этого файла отдельное окно (dired-find-file-other-window). Буфер Dired остается видимым в первом окне. Это подобно использованию C-x 4 C-f для обращения к этому файлу. Смотрите раздел Множество окон.
C-o
Обращается к файлу, описанному на текущей строке, и отображает его буфер в отдельном окне, но не выбирает это окно (dired-display-file).
Mouse-2
Обращается к файлу в строке, на которой вы щелкнули (dired-mouse-find-file-other-window). Эта команда использует для показа файла другое окно, как команда o.
v
Обращается к файлу, описанному на текущей строке, в режиме просмотра, как M-x view-file (dired-view-file). Просмотр файла похож на обращение к нему, но этот режим делает акцент на предоставление большего удобства для перемещения по файлу и не позволяет изменять его. Смотрите раздел Разнообразные действия над файлами.

Пометки Dired vs. флаги

Вместо установки для файла флага с помощью `D' вы можете установить на этом файле метку с помощью какого-либо другого знака (обычно `*'). Большинство команд Dired для работы с файлами, кроме "вычеркивания" (x), действуют на файлы, помеченные звездочкой `*'.

Вот некоторые команды для пометки с помощью `*', для снятия метки или для произведения каких-либо действий над метками. (Смотрите раздел Удаление файлов с помощью Dired, для получения информации о командах для установки и снятия флагов на файлах.)

m
* m
Помечает текущий файл звездочкой `*' (dired-mark). С числовым аргументом n, помечает следующие n файлов начиная от текущего. (Если n отрицателен, помечает -n предыдущих файлов.)
* *
Помечает все исполняемые файлы звездочкой `*' (dired-mark-executables). С числовым аргументом, убирает метки со всех таких файлов.
* @
Помечает все символьные ссылки звездочкой (dired-mark-symlinks). С числовым аргументом, убирает метки со всех таких файлов.
* /
Помечает звездочкой все файлы, которые являются в действительности каталогами, исключая `.' и `..' (dired-mark-directories). С числовым аргументом, убирает метки со всех этих файлов.
* s
Помечает все файлы в текущем подкаталоге, кроме `.' и `..' (dired-mark-subdir-files).
u
* u
Убирает любую метку на этой строке (dired-unmark).
DEL
* DEL
Перемещает точку на предыдущую строку и убирает любую метку на этой строке (dired-unmark-backward).
* !
Убирает все метки со всех файлов в этом буфере Dired (dired-unmark-all-files-no-query).
* ? знак-метки
Убирает все метки, использующие знак знак-метки (dired-unmark-all-files). Аргументом должен быть один знак --- не используете для его завершения RET. С числовым аргументом, эта команда запрашивает подтверждение на снятие метки для каждого помеченного файла. Вы можете ответить y для подтверждения, n для отказа или ! для снятия меток со всех остальных файлов без запроса о них.
* C-n
Перемещает вниз к следующему помеченному файлу (dired-next-marked-file). Файл считается "помеченным", если на нем есть метки любого вида.
* C-p
Перемещает вверх к предыдущему помеченному файлу (dired-prev-marked-file)
* t
Переключает все метки (dired-do-toggle): файлы, помеченные `*' становятся непомеченными, а непомеченные файлы метятся знаком `*'. Файлы, помеченные другим способом, не затрагиваются.
* c старый новый
Заменяет все метки, использующие знак старый на метки со знаком новый (dired-change-marks). Эта команда дает основной метод создания или использования меток, отличных от `*' или `D'. Аргументами должны быть одиночные знаки -- не используйте RET для их завершения. С помощью этой команды вы можете использовать почти любой знак в качестве знака метки для разделения различных классов файлов. Если старый знак -- это пробел (` '), то эта команда действует на все непомеченные файлы; если новый знак является пробелом, эта команда убирает метку с файлов, на которые она действует. Чтобы продемонстрировать мощь этой команды, мы покажем способ установить метку `D' на все файлы, которые не были помечены, в то же время снимая метку со всех файлов, имевших метку `D':
* c D t  * c SPC D  * c t SPC
Здесь предполагается, что ни один из файлов не помечен флагом `t'.
% m regexp RET
* % regexp RET
Помечает (знаком `*') все файлы, чьи имена соответствуют регулярному выражению regexp (dired-mark-files-regexp). Эта команда похожа на % d, но она помечает файлы звездочкой `*', а не устанавливает флаг `D'. Смотрите раздел Установка флага на несколько файлов одновременно. Для поиска совпадений используется только та часть имени файла, которая не задает каталог. Для привязки регулярного выражения к началу или концу имени вы можете использовать `^' и `$'. Подкаталоги вы можете исключить, скрыв их (смотрите раздел Скрывание подкаталогов).
% g regexp RET
Помечает (знаком `*') все файлы, чье содержимое включает совпадения с регулярным выражением regexp (dired-mark-files-containing-regexp). Эта команда похожа на % m, но она просматривает содержимое файлов, а не их имена.
C-_
Отменяет изменения в буфере Dired, такие как добавление или снятие меток (dired-undo).

Действия над файлами

Этот раздел описывает основные команды Dired для произведения различных действий над несколькими файлами. Все эти команды являются заглавными буквами; все они используют минибуфер, либо для считывания аргументов, либо для запрашивания подтверждения перед совершением действий. Все они дают вам некоторые способы указания, какие файлы должны быть обработаны:

  • Если вы даете команде числовой аргумент n, она действует на n следующих файлов, начиная с текущего. (Если n отрицательно, то эта команда действует на -n файлов, предшествующих текущей строке.)
  • Иначе, если какие-то файлы помечены с помощью `*', команда действует на все эти файлы.
  • Иначе эта команда действует только на текущий файл.

Вот команды для манипуляций над файлами, действующие таким способом. (Некоторые другие команды Dired, такие как ! и `%', также придерживаются этих соглашений для принятия решения о выборе файлов для работы.)

C новый RET
Копирует указанные файлы (dired-do-copy). Аргумент новый --- это каталог, в который нужно копировать, или (при копировании единственного файла) новое имя. Если dired-copy-preserve-time не равна nil, то при копировании с помощью этой команды время изменения нового файла устанавливается таким же, как у старого файла.
D
Удаляет указанные файлы (dired-do-delete). Подобно остальным командам в этом разделе, эта команда действует на помеченные файлы или на n следующих файлов. Напротив, x (dired-expunge) удаляет все файлы с установленным флагом.
R новый RET
Переименовывает указанные файлы (dired-do-rename). Аргумент новый -- это каталог, в который нужно переименовывать, или (при переименовании единственного файла) новое имя. Dired автоматически изменяет имена файлов, к которым вы обращаетесь, для связанных с этими переименованным файлами буферов так, чтобы они отражали новые имена.
H новый RET
Создает жесткие ссылки на указанные файлы (dired-do-hardlink). Аргумент новый -- это каталог, в котором нужно создавать ссылки, или (при создании ссылки на единственный файл) имя этой ссылки.
S новый RET
Создает символьные ссылки на указанные файлы (dired-do-symlink). Аргумент новый -- это каталог, в котором нужно создавать ссылки, или (при создании ссылки на единственный файл) имя этой ссылки.
M режим RET
Изменяет режим (также называемый "битами прав доступа") указанных файлов (dired-do-chmod). Эта команда использует программу chmod, потому режим может быть любым аргументом, который chmod способен обработать.
G новая-группа RET
Заменяет группу владельцев указанных файлов на новую-группу (dired-do-chgrp).
O новый-владелец RET
Заменяет владельца указанных файлов на нового-владельца (dired-do-chown). (На большинстве систем это может делать только привилегированный пользователь.) Переменная dired-chown-program задает имя программы, используемой для этих задач (различные системы помещают chown в разные места).
P команда RET
Печатает указанные файлы (dired-do-print). Вы должны указать команду печати, но в минибуфере сразу появляется подходящая предполагаемая строка, полученная с помощью переменных lpr-command и lpr-switches (эти же переменные использует lpr-buffer ; смотрите раздел Вывод твердой копии).
Z
Сжимает указанные файлы (dired-do-compress). Если оказывается, что какой-то файл уже сжат, эта команда наоборот раскрывает его.
L
Загружает указанные файлы Emacs Lisp (dired-do-load). Смотрите раздел Библиотеки Лисп-программ для Emacs.
B
Байт-компилирует указанные файлы на Emacs Lisp (dired-do-byte-compile). Смотрите раздел `Byte Compilation' в The Emacs Lisp Reference Manual.
A regexp RET
Производит поиск регулярного выражения regexp во всех указанных файлах (dired-do-search). Эта команда -- вариант команды tags-search. Поиск останавливается при первом найденном совпадении; чтобы продолжить поиск и найти следующее совпадение, нажмите M-,. Смотрите раздел Поиск и замена при помощи таблиц тегов.
Q старое RET новое RET
Производит query-replace-regexp в каждом из указанных файлов, заменяя совпадения старого (регулярного выражения) на строку новое (dired-do-query-replace). Эта команда -- вариант tags-query-replace. Если вы выйдите из цикла замены с подтверждением, вы можете использовать M-, для продолжения поиска и замены дальнейших совпадений. Смотрите раздел Поиск и замена при помощи таблиц тегов.

Одна особая команда для работы с файлами -- это + (dired-create-directory). Она считывает имя каталога и создает его, если каталог с таким именем еще не существует.

Команды оболочки в Dired

Команда Dired ! (dired-do-shell-command) считывает в минибуфере командную строку оболочки и запускает эту команду оболочки для всех указанных файлов. Вы можете задать обрабатываемые файлы обычными методами, как для команд Dired (смотрите раздел Действия над файлами). Есть два способа применить команду оболочки к нескольким файлам:

  • Если вы используете в команде оболочки `*', то эта команда запускается один раз, а `*' заменяется списком имен файлов. Имена файлов передаются в том же порядке, в каком они появляются в буфере Dired. Таким образом, ! tar cf foo.tar * RET запускает tar для всего списка имен файлов, помещая их все в один tar-файл `foo.tar'.
  • Если командная строка не содержит `*', она запускается один раз для каждого файла с добавленным в конце именем этого файла. Например, ! uudecode RET запускает для каждого файла команду uudecode.

Что если вы хотите выполнить команду оболочки один раз для каждого файла, но с именем файла, вставленным в середине? Или если вы хотите использовать имена файлов более сложным образом? Используйте циклы оболочки. Например, такая команда оболочки запустила бы uuencode для каждого заданного файла, записывая вывод в соответствующий `.uu'-файл:

for file in *; do uuencode $file $file >$file.uu; done

Рабочим каталогом команды оболочки служит каталог верхнего уровня буфера Dired.

Команда ! не пытается обновить буфер Dired, чтобы показать новые или измененные файлы, потому что на самом деле она не понимает команд оболочки и не знает, какие имена изменились. Для обновления буфера Dired используйте команду g (смотрите раздел Обновление буфера Dired).

Преобразование имен файлов в Dired

Вот команды, которые изменяют имена файлов систематическим образом:

% u
Изменяет имя каждого из выбранных файлов на имя, написанное заглавными буквами (dired-upcase). Если старыми именами файлов были `Foo' и `bar', то новыми будут `FOO' и `BAR'.
% l
Изменяет имя каждого из выбранных файлов на имя, написанное строчными буквами (dired-downcase). Если старыми именами файлов были `Foo' и `bar', то новыми будут `foo' и `bar'.
% R старое RET новое RET
% C старое RET новое RET
% H старое RET новое RET
% S старое RET новое RET
Эти четыре команды переименовывают, копируют, создают жесткие и символьные ссылки, вычисляя в каждом случае новое имя путем подстановки в регулярном выражении, задающем имя старого файла.

Эти четыре команды подстановки в регулярном выражении в действительности производят поиск и замену в именах выбранных файлов в буфере Dired. Они принимают два аргумента: регулярное выражение старое и образец подстановки новое.

Эти команды сравнивают каждое "старое" имя файла с регулярным выражением старое и затем заменяют совпавшую часть на новое. Вы можете использовать в строке новое обозначения `\&' и `\цифра', чтобы сослаться на весь или на часть совпавшего образца в старом имени файла, как в replace-regexp (смотрите раздел Замена регулярных выражений). Если в имени файла есть более одного совпадения с регулярным выражением, заменяется только первое.

Например, % R ^.*$ RET x-\& RET переименовывает каждый выбранный файл, добавляя `x-' в начало имени. Обратная процедура, удаление `x-' из начала каждого имени файла, также возможна: один способ -- набрать % R ^x-\(.*\)$ RET \1 RET; другой -- это % R ^x- RET RET. (Используйте `^' и `$' для привязки регулярных выражений к началу или концу имени.)

Обычно при замене не затрагиваются имена каталогов, которым принадлежат файлы; обрабатываются только файлы в этом каталоге. Если вы зададите числовой аргумент, равный нулю, при замене будут обрабатываться полные абсолютные имена файлов, включая имена каталогов.

Часто вы можете захотеть выбрать набор обрабатываемых файлов с помощью того же регулярного выражения regexp, что будет использоваться для их обработки. Чтобы сделать так, пометьте эти файлы командой % m regexp RET, а затем примените это же регулярное выражение в команде обработки. Для облегчения этого, команды обработки файлов, начинающиеся на %, используют по умолчанию последнее регулярное выражение, заданное любой команде %.

Сравнение файлов в Dired

В Dired есть две команды, которые сравнивают заданные файлы с помощью программы diff.

=
Сравнивает текущий файл (файл в позиции точки) с другим файлом (файлом в позиции метки), используя программу diff (dired-diff). Файл в позиции метки -- это первый аргумент diff, а файл в позиции точки -- второй.
M-=
Сравнивает текущий файл с его последней резервной копией (dired-backup-diff). Если текущий файл сам является резервной копией, сравнивает его с оригиналом; таким образом вы можете сравнить файл с любой его резервной версией по вашему выбору. Первым аргументом diff передается резервная копия.

Подкаталоги в Dired

В обычном случае буфер Dired показывает только один каталог; но вы также можете включить в список и его подкаталоги.

Простейший способ включить несколько подкаталогов в один буфер Dired --- задать для запуска ls ключи `-lR'. (Если при вызове Dired вы зададите числовой аргумент, вы сможете написать эти ключи в минибуфере.) Это произведет рекурсивный список каталога, показывающий все подкаталоги всех уровней.

Но обычно всех подкаталогов бывает слишком много; чаще вы предпочли бы включить только конкретные подкаталоги. Вы можете сделать это с помощью команды i:

i
Вставляет содержимое подкаталога ниже в этом буфере.

Применяйте команду i (dired-maybe-insert-subdir) на строке, описывающей файл, который является каталогом. Она вставляет содержимое этого каталога в этот же буфер Dired и перемещает к нему. Вставленное содержимое подкаталога следует после каталога верхнего уровня данного буфера Dired, как в выводе `ls -lR'.

Если содержимое подкаталога уже находится в этом буфере, команда i просто перемещает к нему.

В обоих случаях i до перемещения устанавливает метку Emacs, так что C-u C-SPC возвращает вас к предыдущей позиции в буфере (к строке, описывающей подкаталог).

Используйте команду l (dired-do-redisplay) для обновления содержимого подкаталога. Для удаления подкаталога вы можете применить команду k. Смотрите раздел Обновление буфера Dired.

Перемещение по подкаталогам

Когда буфер Dired перечисляет подкаталоги, вы можете использовать команды перемещения по страницам C-x [ и C-x ] для перехода через целые каталоги.

Следующие команды передвигают в пределах одного уровня, вверх или вниз по дереву каталогов в одном буфере Dired. Они перемещают к строкам заголовков каталогов; это строки, сообщающие имя каталога, они выводятся перед его содержимым.

C-M-n
Переходит к строке заголовка следующего подкаталога, независимо от его уровня (dired-next-subdir).
C-M-p
Переходит к строке заголовка предыдущего подкаталога, независимо от его уровня (dired-prev-subdir).
C-M-u
Переходит к строке заголовка родительского подкаталога (dired-tree-up).
C-M-d
Переходит вниз по дереву каталогов, к строке заголовка первого подкаталога (dired-tree-down).
<
Перемещает вверх к предыдущей строке файла-каталога (dired-prev-dirline). Это строки, описывающие каталог как файл в его родительском каталоге.
>
Перемещает к следующей строке файла-каталога (dired-prev-dirline).

Скрывание подкаталогов

Скрыть подкаталог -- значит сделать невидимым его содержимое, за исключением строки заголовка, средствами выборочного показа (смотрите раздел Выборочный показ).

$
Скрывает или открывает подкаталог, на котором находится точка, и перемещает точку к следующему подкаталогу (dired-hide-subdir). Числовой аргумент служит в качестве счетчика повторов.
M-$
Скрывает все подкаталоги в этом буфере Dired, оставляя только их строки заголовков (dired-hide-all). Или, если какой-нибудь подкаталог уже скрыт, делает все подкаталоги снова видимыми. Вы можете использовать эту команду, чтобы получить обзор очень глубоких деревьев каталогов или чтобы быстро переместиться к далеким подкаталогам.

Обычные команды Dired никогда не затрагивают файлы в скрытых подкаталогах. Например, команды, работающие с помеченными файлами, игнорируют файлы в скрытых каталогах, даже если они помечены. Следовательно, вы можете использовать скрывание, чтобы временно исключить подкаталоги из области действия различных операций, не убирая при этом метки.

Команды скрывания подкаталогов переключают; это значит, что они скрывают то, что было видимо, и показывают то, что было скрыто.

Обновление буфера Dired

Этот раздел описывает команды для обновления буфера Dired, чтобы он отражал внешние (сделанные не в Dired) изменения в буферах и файлах, и для удаления части буфера Dired.

g
Обновляет все содержимое буфера Dired (revert-buffer).
l
Обновляет указанные файлы (dired-do-redisplay).
k
Удаляет заданные строки файлов -- не сами файлы, а только строки в буфере (dired-do-kill-lines).
s
Переключает между сортировкой в алфавитном порядке и по дате/времени (dired-sort-toggle-or-edit).
C-u s переключатели RET
Обновляет буфер Dired, используя переключатели в качестве dired-listing-switches.

Наберите g (revert-buffer), чтобы содержимое буфера Dired обновилось, основываясь на сделанных в перечисленных файлах и каталогах изменениях. Эта команда сохраняет все метки, кроме меток, стоявших на удаленных файлах. Скрытые подкаталоги обновляются, но остаются скрытыми.

Чтобы обновить только некоторые файлы, наберите l (dired-do-redisplay). Эта команда применяется к следующим n файлам, или к помеченным файлам, если такие есть, или к текущему файлу. Обновление их означает считывание нового статуса из файловой системы и обновление буфера для правильного отображения состояния этих файлов.

Если вы примените l на строке заголовка подкаталога, она обновит содержимое этого подкаталога.

Чтобы удалить заданные строки файлов -- не сами файлы, только их строки -- напечатайте k (dired-do-kill-lines). Запущенная с числовым аргументом n, эта команда применяется к следующим n файлам; иначе она применяется к помеченным файлам.

Если вы уничтожите строку для файла, являющегося каталогом, содержимое этого каталога также будет удалено из буфера. Другой способ удалить подкаталог из буфера Dired -- набрать C-u k на строке заголовка этого подкаталога.

Команда g возвращает все строки, уничтоженные таким методом, но не возвращает подкаталоги -- вы должны использовать i, чтобы снова вставить каждый подкаталог.

Файлы в буферах Dired обычно перечисляются в алфавитном порядке по именам. Или Dired может отсортировать их по дате и времени. Команда Dired s (dired-sort-toggle-or-edit) переключает между этими двумя режимами сортировки. Строка режима в буфере Dired показывает, по какому признаку в данный момент отсортированы файлы: по имени или по дате.

C-u s переключатели RET позволяет вам задать новое значение для dired-listing-switches.

Dired и find

Вы можете задать набор файлов для показа в буфере Dired более гибким способом, используя для выбора файлов утилиту find.

Чтобы найти все файлы, чьи имена соответствуют заданному шаблону, запустите M-x find-name-dired. Эта команда считывает аргументы каталог и образец и выбирает все файлы в каталоге или его подкаталогах, чьи имена соответствуют образцу.

Выбранные таким способом файлы отображаются в буфере Dired, в котором доступны обычные команды Dired.

Если вы хотите проверять содержимое файлов, а не их имена, используйте M-x find-grep-dired. Эта команда считывает в минибуфере два аргумента, каталог и regexp; она выбирает все файлы в каталоге или его подкаталогах, которые содержат совпадения с регулярным выражением regexp. Для этого она запускает программы find и grep. Смотрите также M-x grep-find, раздел раздел Запуск компиляторов в Emacs. Помните, что регулярное выражение задается для grep, а не для Emacs.

Наиболее общая команда в этой серии -- команда M-x find-dired, которая позволяет вам указать любое условие, которое может проверить find. Эта команда принимает два аргумента минибуфера, каталог и аргументы-find; она запускает find в каталоге, передавая аргументы-find, чтобы сообщить, какие условия должна проверить find. Чтобы использовать эту команду, вы должны уметь пользоваться программой find.

Формат распечатки, производимой этими командами, управляется переменной find-ls-option; ее значение по умолчанию велит использовать для ls ключи `-ld'. Если ваши распечатки повреждены, вам может понадобиться изменить значение этой переменной.

Календарь и дневник

Emacs может работать как настольный календарь с ежедневником для планируемых и прошедших событий. Чтобы войти в календарь, наберите M-x calendar; это покажет календарь на три месяца, отцентрированный на текущем месяце, а точка будет находиться на текущей дате. С числовым аргументом, как в C-u M-x calendar, эта команда запрашивает у вас месяц и год, которые должны оказаться в центре трехмесячного календаря. Календарь использует свой собственный буфер c основным режимом Calendar.

Mouse-2 в календаре выводит меню операций для даты; C-Mouse-3 выводит меню часто используемых средств календаря, которые не зависят от конкретной даты. Чтобы выйти из календаря, введите q. Смотрите раздел `Calendar' в The Emacs Lisp Reference Manual, для получения информации о настройке календаря и дневника.

Перемещение по календарю

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

Перемещение по обычным календарным единицам

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

C-f
Перемещает на день вперед (calendar-forward-day).
C-b
Перемещает на день назад (calendar-backward-day).
C-n
Перемещает на неделю вперед (calendar-forward-week).
C-p
Перемещает на неделю назад (calendar-backward-week).
M-}
Перемещает на месяц вперед (calendar-forward-month).
M-{
Перемещает на месяц назад (calendar-backward-month).
C-x ]
Перемещает на год вперед (calendar-forward-year).
C-x [
Перемещает на год назад (calendar-backward-year).

Команды для перемещения по дням и неделям -- это естественные аналоги обычных команд Emacs для перемещения по знакам или строкам. Так же, как C-n обычно перемещает к тому же столбцу в следующей строке, в режиме Calendar она перемещает к тому же дню следующей недели. А C-p перемещает к тому же дню предыдущей недели.

Курcорные стрелки эквивалентны C-f, C-b, C-n и C-p, как и в других режимах.

Команды для перемещения по месяцам и годам работают так же, как команды для недель, но переносят на большие расстояния. Команды для месяцев M-} и M-{ перемещают вперед или назад на целый месяц. Команды для лет C-x ] и C-x [ перемещают вперед или назад на целый год.

Простейший способ запомнить эти команды -- рассматривать месяцы и годы как аналоги абзацев и страниц, соответственно. Но сами команды не вполне аналогичны. Обычные команды Emacs для абзацев передвигают к началу или концу абзаца, тогда как эти команды для месяцев и лет перемещают по целому месяцу или году, что обычно подразумевает переход за конец месяца или года.

Все эти команды принимают числовой аргумент в качестве счетчика повторов. Для удобства, в режиме Calendar цифры и знак минус задают числовой аргумент даже без модификатора Meta. Например, 100 C-f перемещает точку на 100 дней вперед от ее текущей позиции.

Начало или конец недели, месяца или года

Неделя (или месяц, или год) -- это не просто некоторое количество дней; мы полагаем, что недели (месяцы, года) начинаются с определенных дат. Поэтому режим Calendar предоставляет команды для перехода к началу или концу недели, месяца или года:

C-a
Переход к началу недели (calendar-beginning-of-week).
C-e
Переход к концу недели (calendar-end-of-week).
M-a
Переход к началу месяца (calendar-beginning-of-month).
M-e
Переход к концу месяца (calendar-end-of-month).
M-<
Переход к началу года (calendar-beginning-of-year).
M->
Переход к концу года (calendar-end-of-year).

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

По умолчанию недели начинаются с воскресенья. Чтобы сделать так, чтобы они начинались с понедельника, установите переменную calendar-week-start-day в значение 1.

Указанные даты

Режим Calendar предоставляет команды для перехода к конкретной дате, которую можно задать многими способами.

g d
Перемещает точку к указанной дате (calendar-goto-date).
o
Центрирует календарь вокруг указанного месяца (calendar-other-month).
.
Перемещает к сегодняшней дате (calendar-goto-today).

g d (calendar-goto-date) запрашивает год, месяц и день месяца, а затем перемещает к этой дате. Поскольку календарь включает все даты от начала нашей эры, вы должны вводить год полностью; то есть пишите `1990', а не `90'.

o (calendar-other-month) запрашивает месяц и год, а затем центрирует трехмесячный календарь вокруг этого месяца.

Вы можете вернуться к сегодняшней дате с помощью команды . (calendar-goto-today).

Прокрутка календаря

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

C-x <
Прокручивает календарь на один месяц вперед (scroll-calendar-left).
C-x >
Прокручивает календарь на один месяц назад (scroll-calendar-right).
C-v
NEXT
Прокручивает календарь на три месяца вперед (scroll-calendar-left-three-months).
M-v
PRIOR
Прокручивает календарь на три месяца назад (scroll-calendar-right-three-months).

Самые основные команды прокрутки календаря прокручивают по одному месяцу за раз. Это означает, что между отображением до команды и отображением после делается два месяца перекрытия. C-x < прокручивает содержимое календаря на месяц влево; то есть она перемещает вид вперед по времени. C-x > прокручивает содержимое календаря вправо, что перемещает назад во времени.

Команды C-v и M-v прокручивают календарь по целым экранам --- по три месяца -- по аналогии с обычным значением этих команд. C-v делает видимыми более поздние даты, а M-v -- более ранние. Эти команды принимают числовой аргумент в качестве счетчика повторов; в частности, так как C-u умножает следующую команду на четыре, набор C-u C-v прокручивает календарь на год вперед, а C-u M-v прокручивает на год назад.

Функциональные клавиши NEXT и PRIOR эквивалентны C-v и M-v, как и в других режимах.

Посчет дней

M-=
Выводит число дней в текущей области (calendar-count-days-region).

Чтобы определить число дней в области, наберите M-= (calendar-count-days-region). Количество дней выводится включительно; то есть дни, указываемые точкой и меткой, учитываются.

Другие команды календаря

p d
Выводит номер дня в году (calendar-print-day-of-year).
C-c C-l
Заново генерирует окно календаря (redraw-calendar).
SPC
Прокручивает следующее окно (scroll-other-window).
q
Выходит из календаря (exit-calendar).

Чтобы напечатать число дней, прошедших с начала года или остающихся до конца года, наберите команду p d (calendar-print-day-of-year). Она покажет оба этих числа в эхо-области. Количество прошедших дней включает выбранную дату. Число оставшихся дней не включает ее.

Если окно календаря окажется испорчено, наберите C-c C-l (redraw-calendar) чтобы его перерисовать. (Такое может случиться, только если вы используете команды редактирования не из режима Calendar.)

В режиме Calendar вы можете использовать SPC (scroll-other-window) для прокрутки другого окна. Это удобно, если вы смотрите в другом окне список праздников или записи ежедневника.

Чтобы выйти из календаря, наберите q (exit-calendar). Эта команда прячет все буферы, связанные с календарем, и выбирает другие буферы. (Если фрейм содержит специально назначенное окно календаря, выход из календаря минимизирует этот фрейм.)

LaTeX и календарь

Команды календаря для работы с LaTeX генерируют буфер с LaTeX-кодом, который печатает календарь. В зависимости от использованой команды напечатанный календарь покрывает день, неделю, месяц или год, в котором находится точка.

t m
Генерирует календарь на один месяц (cal-tex-cursor-month).
t M
Генерирует горизонтальный календарь на один месяц (cal-tex-cursor-month-landscape).
t d
Генерирует календарь на один день (cal-tex-cursor-day).
t w 1
Генерирует одностраничный календарь на одну неделю (cal-tex-cursor-week).
t w 2
Генерирует двухстраничный календарь на одну неделю (cal-tex-cursor-week2).
t w 3
Генерирует календарь в стиле ISO на одну неделю (cal-tex-cursor-week-iso).
t w 4
Генерирует календарь на одну неделю, начинающуюся с понедельника (cal-tex-cursor-week-monday).
t f w
Генерирует двухнедельный календарь на одной странице в стиле Filofax (cal-tex-cursor-filofax-2week).
t f W
Генерирует недельный календарь на одной странице в стиле Filofax (cal-tex-cursor-filofax-week).
t y
Генерирует календарь на один год (cal-tex-cursor-year).
t Y
Генерирует горизонтальный календарь на один год (cal-tex-cursor-year-landscape).
t f y
Генерирует календарь на один год в стиле Filofax (cal-tex-cursor-filofax-year).

Некоторые из этих команд печатают календарь горизонально (в "ландшафтном режиме"), поэтому его ширина может быть больше длины. Некоторые из них используют размер бумаги Filofax (3.75 на 6.75 дюймов). Все эти команды принимают префиксный аргумент, задающий число печатаемых дней, недель, месяцев или лет (всегда начиная от текущего).

Если переменная cal-tex-holidays не равна nil (это значение по умолчанию), то печатаемые календари показывают праздники из calendar-holidays. Если переменная cal-tex-diary отлична от nil (по умолчанию это nil), также включаются записи из дневника (только в недельные и месячные календари). Если отлична от nil переменная cal-tex-rules (по умолчанию nil), то в тех стилях распечатки календаря, где достаточно места, страницы разлинованы.

Праздники

Календарь Emacs знает обо всех больших и о многих малых праздниках и может их отображать.

h
Показать праздники, приходящиеся на выбранную дату (calendar-cursor-holidays).
Mouse-2 Holidays
Показать все праздники для даты, на которой вы щелкнули.
x
Пометить праздники (mark-calendar-holidays).
u
Снять метки в окне календаря (calendar-unmark).
a
Перечислить в другом окне все праздники для показанных трех месяцев (list-calendar-holidays).
M-x holidays
Перечислить в другом окне все праздники для трех месяцев вокруг текущей даты.
M-x list-holidays
Перечислить в другом окне праздники для заданного промежутка лет.

Чтобы узнать, не приходится ли на данную дату праздников, расположите точку на этой дате в окне календаря и используйте команду h. Или щелкните на этой дате Mouse-2 и затем выберите из появившегося меню пункт Holidays. В обоих случаях выводятся праздники для заданной даты, в эхо-области, если они там умещаются, или в отдельном окне.

Чтобы просмотреть распределение праздников для всех показанных в календаре дат, используйте команду x. Она отображает праздничные дни другим начертанием (или помещает после этих дат значок `*', если множественные начертания недоступны). Эта команда применяется и к месяцам, видимым в данный момент, и к тем, что станут впоследствии видимыми при прокрутке. Чтобы выключить разметку и стереть текущие метки, наберите u, что также стирает метки дневника (смотрите раздел Дневник).

Чтобы получить еще более подробную информацию, используйте команду a, которая показывает отдельный буфер, содержащий список всех праздников в текущем трехмесячном диапазоне. Вы можете использовать SPC в окне календаря для прокрутки этого списка.

Команда M-x holidays выводит список праздников для текущего, предыдущего и следующего месяца; она работает, даже если у вас нет окна календаря. Если вы хотите получить перечень праздников, центрированный вокруг другого месяца, используйте C-u M-x holidays, которая спрашивает месяц и год.

Известные Emacs праздники включают праздники США и основные христианские, иудейские и исламские праздники; также он знает о солнцестояниях и равноденствиях.

Команда M-x list-holidays выводит список праздников для нескольких лет. Эта функция запрашивает у вас начальный и конечный год и позволяет выбрать все праздники или одну из их категорий. Вы можете использовать эту команду, даже если у вас нет окна календаря.

Emacs использует для праздников даты, основанные на текущей практике, а не на исторических фактах. К примеру, исторически момент сезонного перевода времени и даже само его существование изменялось от года к году, но текущий закон США говорит, что время переводится в первое воскресенье апреля. Когда правила сезонного перевода времени установлены по американским нормам, Emacs всегда использует текущее определение, даже если оно было неправильно в некоторые прошлые годы.

Время восхода и заката Солнца

Особые команды календаря могут сообщить вам с точностью до минуты-двух времена восхода и заката Солнца для любой даты.

S
Показывает времена восхода и заката Солнца для выбранной даты (calendar-sunrise-sunset).
Mouse-2 Sunrise/Sunset
Показывает времена восхода и заката Солнца для даты, на которой вы щелкнули.
M-x sunrise-sunset
Показывает времена восхода и заката Солнца для сегодняшней даты.
C-u M-x sunrise-sunset
Показывает времена восхода и заката Солнца для заданной даты.

Чтобы просмотреть в эхо-области местное время восхода и заката Солнца, находясь в календаре, переместите точку к желаемой дате и нажмите S. Или щелкните на этой дате Mouse-2 и выберите из появившегося меню пункт Sunrise/Sunset. Команда M-x sunrise-sunset, доступная извне календаря, показывает эту информацию для текущей или указанной даты. Чтобы задать отличную от сегодняшней дату, используйте команду C-u M-x sunrise-sunset, которая спросит год, месяц и день.

Вы можете просмотреть время восхода и заката Солнца для любой местности и даты с помощью C-u C-u M-x sunrise-sunset. Эта команда запрашивает вас широту, долготу, разницу от универсального координированного времени и дату, а затем сообщает вам времена восхода и заката для этого места и этой даты.

Поскольку время восхода и заката Солнца зависит от положения на Земле, перед использованием этих команд вы должны сказать Emacs вашу широту, долготу и название местности. Вот пример задаваемых значений:

(setq calendar-latitude 40.1)
(setq calendar-longitude -88.2)
(setq calendar-location-name "Urbana, IL")

Задавайте значения calendar-latitude и calendar-longitude с точностью до одной десятой.

Ваш часовой пояс также влияет на время восхода и заката. Обычно Emacs получает информацию о часовом поясе от операционной системы, но если это не те значения, которые вы хотите (или если операционная система их не предоставляет), вы должны установить их сами. Вот пример:

(setq calendar-time-zone -360)
(setq calendar-standard-time-zone-name "CST")
(setq calendar-daylight-time-zone-name "CDT")

Значение calendar-time-zone -- это разница между вашим местным стандартным и универсальным координированным (гринвичским) временем, выраженная в минутах. Значения calendar-standard-time-zone-name и calendar-daylight-time-zone-name -- это сокращения, принятые для обозначения вашего часового пояса. Emacs показывает время восхода и заката в с учетом сезонного перевода часов. Смотрите раздел Сезонный перевод времени, о том, как определяется сезонная поправка.

Как пользователь, вы можете счесть удобным установить переменные календаря для задания вашего обычного физического местонахождения в вашем файле `.emacs'. А когда вы устанавливаете Emacs на машине, вы можете создать файл `default.el', который будет правильно их устанавливать для типичного местонахождения большинства пользователей этой машины. Смотрите раздел Файл инициализации, `~/.emacs'.

Фазы Луны

Эти команды календаря показывают даты и времена лунных фаз (новолуние, первая четверть, полнолуние, последняя четверть). Эта возможность полезна при отладке проблем, которые "зависят от фазы Луны".

M
Выводит даты и времена всех четвертей Луны для показанного трехмесячного периода (calendar-phases-of-moon).
M-x phases-of-moon
Выводит даты и времена четвертей Луны для трех месяцев вокруг сегодняшней даты.

Внутри календаря, для показа в отдельном буфере фаз Луны для текущего трехмесячного периода используется команда M. Перечислямые даты и времена точны до нескольких минут.

Вне календаря, для показа фаз Луны для текущего, предыдущего и следующего месяца используйте команду M-x phases-of-moon. Чтобы получить сведения для какого-то другого месяца, используйте C-u M-x phases-of-moon, она спросит вас о месяце и годе.

Даты и времена лунных фаз даются в местном времени (с учетом сезонных поправок, если это необходимо); но если переменная calendar-time-zone не определена, используется универсальное координированное время (гринвичский часовой пояс). Смотрите раздел Сезонный перевод времени.

Преобразование в другие календарные системы и из них

В Emacs всегда показывается григорианский календарь, иногда называемый календарем "нового стиля", который в наши дни применяется почти везде. Однако, этот календарь не существовал до шестнадцатого столетия и не использовался широко до восемнадцатого; только в начале девятнадцатого века он полностью вытеснил юлианский календарь и получил всемирное признание. Календарь Emacs может отобразить любой месяц начиная от января первого года нашей эры, но всегда показывает григорианский календарь, даже для дат, когда его еще не существовало.

Хотя Emacs не может показывать другие календари, он умеет преобразовавать даты из нескольких других календарных систем.

Поддерживаемые календарные системы

Коммерческий календарь ISO используется в основном в Европе.

Юлианский календарь, названный в честь Юлия Цезаря, использовался в Европе в средние века и во многих других странах вплоть до девятнадцатого века.

Астрономы используют простой подсчет дней, истекших от полудня понедельника, первого января, 4713-го года до нашей эры по юлианскому календарю. Число прошедших дней называется юлианским или астрономическим номером дня.

Иудейский календарь по традиции используется в еврейской религии. Календарная программа Emacs использует иудейский календарь для определения дат еврейских праздников. Даты иудейского календаря начинаются и завершаются при заходе Солнца.

Исламский календарь используется во многих мусульманских странах. Emacs использует его для определения дат исламских праздников. В исламском мире нет всеобщей договоренности о календаре; в Emacs применяется широко распространенная версия, но точные даты исламского календаря часто основываются на высказываниях религиозных авторитетов, а не на вычислениях. Как следствие, действительные даты наблюдения могут слегка отличаться от вычисленных в Emacs. Даты исламского календаря начинаются и завершаются при заходе Солнца.

Календарь французской революции был создан якобинцами после революции 1789-го года для введения более светского и основанного на представлениях о природе взгляда на годовой цикл и для установления десятидневной недели, более рационалистической, как метрическая система. Французское правительство официально отменило этот календарь в конце 1805-го года.

Центральноамериканские Майя использовали три разные, перекрывающиеся календарные системы, долгий счет, тцолкин и хааб. Emacs знает обо всех трех календарях. Эксперты обсуждают точное соответствие между календарем Майя и нашим календарем; Emacs использует для вычислений корреляцию Гудмана-Мартинеса-Томсона.

Копты используют календарь, основанный на древнеегипетском солнечном календаре. Он состоит из двенадцати тридцатидневных месяцев, за которым идет дополнительный пятидневный период. Раз в четыре года к этому периоду добавляется шестой, високосный день. Эфиопский календарь обладает такой же структурой, но в нем другие номера лет и названия месяцев.

Персы используют солнечный календарь, основанный на разработках Омара Хайама. Их календарь состоит из двенадцати месяцев, первые шесть из которых содержат 31 дней, следующие пять -- 30 дней, а в последнем 29 дней в обычные года и 30 дней в високосные. Високосные года случаются по сложному образцу каждые четыре или пять лет.

Китайский календарь -- это сложная система лунных месяцев, скомбинированных с солнечными годами. Годы проходят по циклам из шестидесяти лет, обычный год содержит 12 месяцев, високосный -- 13; в каждом месяце либо 29, либо 30 дней. Каждый год, обычный месяц и день именуется комбинацией одного из десяти "небесных стеблей" и одной из двенадцати "земных ветвей", в общей сложности есть шестьдесят имен, которые проходят по кругу.

Преобразование в другой календарь

Следующие команды описывают выбранную дату (дату, в которой находится точка) в различных календарных системах:

Mouse-2 Other Calendars
Выводит дату, на которой вы щелкнули, выраженную через различные другие календари.
p c
Выводит эквивалент выбранного дня в коммерческом календаре ISO (calendar-print-iso-date).
p j
Выводит юлианскую дату для выбранного дня (calendar-print-julian-date).
p a
Выводит астрономический (юлианский) номер дня для выбранной даты (calendar-print-astro-day-number).
p h
Показывает иудейскую дату для выбранного дня (calendar-print-hebrew-date).
p i
Показывает исламскую дату для выбранного дня (calendar-print-islamic-date).
p f
Показывает французскую революционную дату для выбранного дня (calendar-print-french-date).
p C
Показывает китайскую дату для выбранного дня (calendar-print-chinese-date).
p k
Показывает коптскую дату для выбранного дня (calendar-print-coptic-date).
p e
Показывает эфиопскую дату для выбранного дня (calendar-print-ethiopic-date).
p p
Показывает дату персидского календаря для выбранного дня (calendar-print-persian-date).
p m
Показывает дату календаря Майя для выбранного дня (calendar-print-mayan-date).

Если вы используете X, простейший способ перевести дату в другие календари -- щелкнуть на ней Mouse-2 и выбрать из появившегося меню пункт Other Calendars. Это покажет в виде меню эквивалентные формы для данной даты во всех календарях, которые понимает Emacs. (Выбор альтернатив из этого меню не делает ничего -- оно используется только для показа.)

Переместите точку к желаемой дате в григорианском календаре и нажмите подходящие клавиши. p -- это мнемоника для "print", поскольку Emacs "печатает" эквивалентную дату в эхо-области.

Преобразование из другого календаря

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

g c
Переход к дате, заданной в коммерческом календаре ISO (calendar-goto-iso-date).
g j
Переход к дате, заданной в юлианском календаре (calendar-goto-julian-date).
g a
Переход к дате, заданной астрономическим (юлианским) номером дня (calendar-goto-astro-day-number).
g h
Переход к дате, заданной в иудейском календаре (calendar-goto-hebrew-date).
g i
Переход к дате, заданной в исламском календаре (calendar-goto-islamic-date).
g f
Переход к дате, заданной во французском революционном календаре (calendar-goto-french-date).
g C
Переход к дате, заданной в китайском календаре (calendar-goto-chinese-date).
g p
Переход к дате, заданной в персидском календаре (calendar-goto-persian-date).
g k
Переход к дате, заданной в коптском календаре (calendar-goto-coptic-date).
g e
Переход к дате, заданной в эфиопском календаре (calendar-goto-ethiopic-date).

Эти команды запрашивают у вас дату из другого календаря, перемещают точку к эквивалентной дате григорианского календаря и показывают дату другого календаря в эхо-области. При считывании названия месяца Emacs использует строгое завершение (смотрите раздел Завершение), поэтому вам не нужно беспокоиться о правильности написания иудейских, исламских или французских названий.

Один из вопросов, часто возникающих в связи с иудейским календарем, --- вычисление годовщины смерти, называемой "yahrzeit". Календарь Emacs включает средства для таких вычислений. Если вы находитесь в календаре, команда M-x list-yahrzeit-dates спрашивает вас о промежутке лет и затем показывает для этого промежутка список yahrzeit для даты в точке. Если вы не в календаре, эта команда сначала спросит о дате смерти и промежутке лет, а затем покажет список дат yahrzeit.

Преобразование из календаря Майя

Это команды для выбора дат, оснаванных на календаре Майя:

g m l
Переходит к дате, заданной календарем долгого счета (calendar-goto-mayan-long-count-date).
g m n t
Переходит к следующему появлению некоторого места в календаре тцолкин (calendar-next-tzolkin-date).
g m p t
Переходит к предыдущему появлению некоторого места в календаре тцолкин (calendar-previous-tzolkin-date).
g m n h
Переходит к следующему появлению некоторого места в календаре хааб (calendar-next-haab-date).
g m p h
Переходит к предыдущему появлению некоторого места в календаре хааб (calendar-previous-haab-date).
g m n c
Переходит к следующему появлению некоторого места в календарном круге (calendar-next-calendar-round-date).
g m p c
Переходит к предыдущему появлению некоторого места в календарном круге (calendar-previous-calendar-round-date).

Чтобы понять эти команды, вы должны понимать календари Майя. Долгий счет -- это подсчет дней в следующих единицах:

1 кин = 1 день   1 уинал = 20 кин   1 тун = 18 уинал
1 катун = 20 тун   1 бактун = 20 катун

Таким образом, дата 12.16.11.16.6 в долгом счете означает 12 бактун, 16 катун, 11 тун, 16 уинал и 6 кин. Календарь Emacs может обрабатывать майянские даты долгого счета от 7.17.18.13.1, но не более ранние. Когда вы используете команду g m l, набирайте майянскую дату долгого счета, разделяя бактун, катун, тун, уинал и кин точками.

Майянский календарь тцолкин -- это цикл из 260 дней, формируемый парой независимых циклов из 13 и 20 дней. Поскольку этот цикл повторяется бесконечно, Emacs предоставляет команды для перемещения назад и вперед к предыдущей или следующей точке цикла. Наберите g m p t, чтобы перейти к предыдущей дате в тцолкин; Emacs спросит у вас дату в тцолкин и переместит точку к предыдущему появлению этой даты. Аналогично, наберите g m n t, чтобы перейти к следующему появлению даты в тцолкин.

Майянский календарь хааб -- это цикл из 365 дней, собранный из 18 месяцев по 20 в каждом, за которыми следует пятидневный период без месяца. Подобно циклу тцолкин, этот цикл повторяется бесконечно, и есть команды для перехода назад и вперед к предыдущей или следующей точке этого цикла. Наберите g m p h, чтобы перейти к предыдущей дате хааб; Emacs спросит у вас дату в хааб и переместит точку к предыдущему появлению этой даты. Аналогично, наберите g m n h, чтобы перейти к следующему появлению даты в хааб.

Майя также использовали комбинацию дат тцолкин и хааб. Эта комбинация --- цикл примерно в 52 года, назыавемый календарным кругом. Если вы наберете g m p c, Emacs спросит у вас даты хааб и тцолкин и затем переместит точку к предыдущему появлению этой комбинации. Используйте g m n c для перемещения точки к следующему появлению комбинации. Эти команды сообщают об ошибке, если набранная вами комбинация дат хааб/тцолкин невозможна.

При запросе майянской даты Emacs использует строгое завершение (смотрите раздел Строгое завершение), поэтому вам не нужно беспокоиться о правильности написания.

Дневник

С помощью дневника Emacs можно прослеживать назначенные встречи и другие события на ежедневной основе и в совокупности с календарем. Чтобы воспользоваться этими возможностями, вы должны сначала создать файл дневника, содержащий перечень событий и их дат. Тогда Emacs сможет автоматически подобрать и показать вам события на сегодняшний день, на ближайшее будущее или для указанной даты.

По умолчанию в качестве файла дневника Emacs использует файл `~/diary'. Это тот же самый файл, что применяеися в утилите calendar. Вот пример файла `~/diary':

12/22/1988  Twentieth wedding anniversary!!
&1/1.       Happy New Year!
10/22       Ruth's birthday.
* 21, *:    Payday
Tuesday--weekly meeting with grad students at 10am
         Supowit, Shen, Bitner, and Kapoor to attend.
1/13/89     Friday the thirteenth!!
&thu 4pm    squash game with Lloyd.
mar 16      Dad's birthday
April 15, 1989 Income tax due.
&* 15       time cards due.

В данном примере для выравнивания описаний в большинстве вхождений событий использованы пробелы. Такое форматирование полностью является делом вкуса.

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

Команды для просмотра записей в дневнике

После того как вы создали файл `~/diary', вы можете просматривать его из календаря. Вы также можете просмотреть список сегодняшних событий извне режима Calendar.

d
Показывает все записи дневника для выбранной даты (view-diary-entries).
Mouse-2 Diary
Показывает все записи дневника для даты, на которой вы щелкнули.
s
Показывает весь файл дневника (show-all-diary-entries).
m
Помечает все видимые даты, для которых есть записи в дневнике (mark-diary-entries).
u
Убирает метки из окна календаря (calendar-unmark).
M-x print-diary-entries
Печатает твердую копию отображаения дневника в том виде, в каком он есть на экране.
M-x diary
Показывает все вхождения дневника для сегодняшней даты.
M-x diary-mail-entries
Отправляет вам по почте напоминание о предстоящих событиях.

Отображение записей дневника с помощью d показывает в отдельном окне вхождения дневника для выбранной в календаре даты. Строка режима нового окна показывает дату для этих записей и все выпадающие на нее праздники. Если вы зададите для d числовой аргумент, она покажет все записи дневника на указанное число дней. То есть, 2 d покажет все записи для выбранной даты и для следующего дня.

Другой способ просмотреть записи дневника для какой-либо даты --- щелкнуть на этой дате Mouse-2, а затем выбрать из появившегося меню пункт Diary.

Чтобы получить более широкий обзор упомянутых в календаре дней, используйте команду m. Она показывает даты, для которых в дневнике есть записи, другим начертанием (или помещает после них знак `+', если дисплей не может отобразить несколько начертаний). Эта команда применяется как к видимым в данный момент месяцам, так и к остальным, которые становятся видимыми при последующей прокрутке. Чтобы выключить разметку и стереть текущие метки, нажмите u, что выключает также и метки праздников (смотрите раздел Праздники).

Чтобы увидеть файл дневника полностью, а не только некоторые его вхождения, используйте команду s.

При выводе избранных записей дневника применяется средство выборочного показа, чтобы скрыть ненужные записи.

Буфер дневника в той форме, как вы его видите -- это иллюзия, поэтому простая его печать не даст то, что вы видите на экране. Для получения твердой копии буфера дневника таким, каким он виден, есть особая команда; это команда M-x print-diary-entries. Она посылает данные непосредственно на принтер. Вы можете настраивать ее, как lpr-region (смотрите раздел Вывод твердой копии).

Команда M-x diary показывает записи дневника для текущей даты, независимо от того, виден ли календарь, и кроме того, возможно, для нескольких следующих дней; переменная number-of-diary-entries задает число включаемых дней. Смотрите раздел `Calendar' в The Emacs Lisp Reference Manual.

Если вы поместите в ваш файл `.emacs' строку (diary), то при входе в Emacs вам будет автоматически показываться окно с записями дневника на сегодняшний день. Строка режима этого окна показывает дату и выпадающие на нее праздники.

Многим пользователям нравится получать напоминания о событиях из ежедневника по почте. Чтобы послать себе такие сообщения, используйте команду M-x diary-mail-entries. Префиксный аргумент указывает, сколько дней (начиная с сегодняшнего) следует проверять; иначе число дней определяется по переменной diary-mail-days.

Файл дневника

Ваш файл дневника -- это файл, в котором записаны события, связанные с определенными датами. Имя этого файла задается переменной diary-file; по умолчанию это `~/diary'. Программа calendar поддерживает подмножество формата, допускаемого средствами дневника в Emacs, так что вы можете использовать эту утилиту для просмотра файла дневника с разумными результатами, если не считать вхождений, которые она не понимает.

Каждая запись в файле дневника описывает одно событие и состоит из одной или нескольких строк. Запись всегда начинается со спецификации даты с левого края. Остальная часть записи -- это просто текст, описывающий событие. Если запись содержит более одной строки, то строки после первой должны начинаться с отступа, как указание на то, что они продолжают предыдущее вхождение. Строки, которые не начинаются с правильной даты и не продолжают предыдущее вхождение, игнорируются.

Вы можете подавить разметку определенных записей из дневника в окне календаря; чтобы сделать так, вставьте в начале записи перед датой знак `&'. Это не влияет на отображение записи в окне дневника; это затрагивает только метки дат в окне календаря. Запрет пометки записи особенно полезен для обобщенных вхождений, которые иначе пометили бы слишком много разных дней.

Если первая строка записи состоит только из даты или названия дня недели, и после нее нет пропусков или пунктуации, то такая строка не выводится в окне дневника; там появляются только строки продолжения. Например, такая запись:

02/11/1989
      Bill B. visits Princeton today
      2pm Cognitive Studies Committee meeting
      2:30-5:30 Liz at Lawrenceville
      4:00pm Dentist appt
      7:30pm Dinner at George's
      8:00-10:00pm concert

появляется в окне дневника без строки с датой в начале. Такой стиль записей выглядит красивее, если вы просматриваете вхождения для одного дня, но может запутать, если вы попросите показать записи для нескольких дней.

Вы можете редактировать записи дневника в том виде, как они появляются в окне, но важно помнить, что этот показанный буфер содержит полный файл дневника, но некоторые его части скрыты из вида. Это означает в частности, что команда C-f (forward-char) может поместить точку в таком месте, которое кажется концом строки, но на самом деле это середина какой-то скрытой строки.

Будьте внимательны при редактировании записей дневника! Вставка новых строк или добавление/удаление знаков в середине видимой строки не могут причинить проблем, но редактирование в конце строки может делать не то, что вы ожидаете. Удаление строки может удалить другие невидимые записи, которые следуют за ней. Перед редактированием дневника лучше всего отобразить файл полностью с помощью команды s (show-all-diary-entries).

Формат дат

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

4/20/93  Switch-over to new tabulation system
apr. 25  Start tabulating annual results
4/30  Results for April are due
*/25  Monthly cycle finishes
Friday  Don't leave without backing up files

Первая запись появляется только один раз, 20 апреля 1993 года. Вторая и третья появляются каждый год в заданные дни, а четвертая использует для месяца символ подстановки (звездочку), поэтому она появляется 25-го числа каждого месяца. Последняя запись появляется каждую неделю в пятницу.

Для выражения даты вы можете использовать только числа, как `месяц/день' или `месяц/день/год'. После этого должна идти не-цифра. В самой дате, месяц и день должны быть однозначными или двузначными числами. Необязательный год -- это тоже число, его можно сокращать до последних двух цифр; то есть вы можете писать как `11/12/1989', так и `11/12/89'.

Даты также можно записывать в формате `название-месяца день' или `название-месяца день, год', где название месяца можно писать полностью или сокращать до трех букв (с точкой или без). Регистр значения не имеет.

Дата может быть обобщенной, то есть частично недоопределенной. Тогда она применяется ко всем датам, соответствующим спецификации. Если дата не содержит год, то она обобщенная и относится ко всем годам. Или же месяц, день или год могут быть знаком `*'; это соответствует любому месяцу, дню или году. Таким образом, вхождение дневника `3/*/*' соответствует любому дню марта в каждом году; то же и для `march *'.

Если вы предпочитаете европейский стиль написания дат -- когда день идет перед месяцем -- наберите в календаре M-x european-calendar или установите переменную european-calendar-style в значение t перед использованием любой команды календаря или дневника. Этот режим интерпретирует все даты в дневнике в европейском стиле, а также применяет европейский стиль при отображении дат дневника. (Заметьте, что после названия-месяца в европейском стиле нет запятой.) Чтобы вернуться к американскому (принимаемому по умолчанию) стилю написания дат, наберите M-x american-calendar.

Вы можете использовать название дня недели в качестве обобщенной даты, которая относится к любой дате, приходящейся на этот день недели. Названия дней недели можно сокращать до трех букв (с точкой или без) или писать полностью; регистр значения не имеет.

Команды для добавления к дневнику

Когда вы находитесь в календаре, вам доступны несколько команд для создания записей в дневнике:

i d
Добавляет в дневник запись для выбранной даты (insert-diary-entry).
i w
Добавляет в дневник запись для выбранного дня недели (insert-weekly-diary-entry).
i m
Добавляет в дневник запись для выбранного дня месяца (insert-monthly-diary-entry).
i y
Добавляет в дневник запись для выбранного дня года (insert-yearly-diary-entry).

Вы можете создать в дневнике запись для конкретной даты, выбрав эту дату в окне календаря и выполнив команду i d. Эта команда показывает конец вашего файла дневника в другом окне и вставляет дату; затем вы можете напечатать остальную часть записи.

Если вы хотите сделать в дневнике запись, которая относится к какому-то дню недели, выберите этот день (можно любое его появление) и наберите i w. Это вставит название дня недели как обобщенную дату; потом вы можете ввести остальную часть записи. Таким же способом вы можете создать ежемесячную запись. Выберите день месяца, примените команду i m и введите остаток записи. Аналогично вы можете вставить ежегодную запись при помощи команды i y.

Все описанные выше команды по умолчанию создают помечаемые записи. Чтобы сделать в дневнике непомечаемую запись, дайте команде числовой аргумент. Например, C-u i w создает в дневнике непомечаемую еженедельную запись.

Когда вы измените файл дневника, убедитесь, что вы сохранили его перед выходом из Emacs.

Особые записи дневника

Помимо вхождений, основанных на календарных датах, файл дневника может содержать sexp-вхождения для регулярных событий, таких как годовщины. Такие записи основаны на лисповских выражениях (s-выражениях), которые Emacs выполняет по мере сканирования файла дневника. Вместо даты sexp-вхождение содержит строку `%%', за которой идет лисповское выражение, заключенное в круглые скобки. Это выражение определяет, к каким датам относится данная запись.

Режим Calendar предоставляет команды для вставки некоторых часто используемых sexp-вхождений:

i a
Добавляет в дневник запись о годовщине события для текущей даты (insert-anniversary-diary-entry).
i b
Добавляет блочную запись дневника для текущей области (insert-block-diary-entry).
i c
Добавляет циклическую запись дневника, начинающуюся от текущей даты (insert-cyclic-diary-entry).

Если вы хотите создать в дневнике запись, которая относится к годовщине какой-то даты, переместите точку к этой дате и используйте команду i a. Это покажет конец вашего файла дневника в другом окне и вставит описание годовщины; затем вы можете набрать остальную часть записи. Запись выглядит так:

%%(diary-anniversary 10 31 1948) Arthur's birthday

Эта запись относится к 31 октября каждого года после 1948; `10 31 1948' задает дату. (Если вы используете европейский стиль календаря, месяц и день меняются местами.) Причина того, что это выражение требует указания начального года, состоит в том, что продвинутые функции календаря могут использовать его для подсчета истекших лет.

Блочная запись дневника применяется к заданному промежутку последовательных дат. Вот блочная запись, которая относится ко всем датам от 24 июня 1990 до 10 июля 1990 года.

%%(diary-block 6 24 1990 7 10 1990) Vacation

`6 24 1990' обозначает начальную дату, а `7 10 1990' --- конечную. (Опять же, если вы используете европейский стиль календаря, месяц и день меняются местами.)

Чтобы вставить блочную запись, поместите точку и метку на двух датах, которые начинают и завершают промежуток, и наберите i b. Эта команда показывает конец вашего файла дневника в другом окне и вставляет описание блока; потом вы можете напечатать остальную часть записи.

Циклические записи дневника повторяются после фиксированного интервала дней. Чтобы создать такую запись, выберите начальную дату и используйте команду i c. Эта команда спросит у вас длину интервала, а затем вставит запись, выглядящую следующим образом:

%%(diary-cyclic 50 3 1 1990) Renew medication

Эта запись относится к 1 марта 1990 года и к каждому 50-ому последующему дню; `3 1 1990' задает начальную дату. (Если вы используете европейский стиль календаря, месяц и день меняются местами.)

Все три эти команды создают помечаемые записи. Чтобы вставить непомечаемую запись, дайте команде числовой аргумент. Например, C-u i a создает непомечаемую запись для годовщины некоторого события.

Пометка sexp-вхождений дневника в календаре чрезвычайно требовательна ко времени, поскольку должна быть отдельно проверена каждая видимая в окне календаря дата. Поэтому лучше делать sexp-вхождения дневника непомечаемыми (с `&'), если возможно.

Другой, усложненный вид sexp-вхождения, плавающая запись, задает регулярно случающееся событие по сдвигу, выраженному в днях, неделях и месяцах. Ее можно сравнить с записями crontab, интерпретируемыми утилитой cron. Вот непомечаемая плавающая запись, которая относится к последнему четвергу ноября:

&%%(diary-float 11 4 -1) American Thanksgiving

Число 11 обозначает ноябрь (одиннадцатый месяц), 4 обозначает четверг (четвертый день недели, где воскресенье считается нулем), а -1 обозначает "последний" (1 обозначало бы "первый", 2 обозначало бы "второй", -2 -- "предпоследний" и так далее). Месяц может быть единственным или списком месяцев. Таким образом, вы могли бы изменить 11 выше на `'(1 2 3)' и получить запись, относящуюся к последнему четвергу января, февраля и марта. Если месяц задан как t, запись относится ко всем месяцам года.

В самом общем виде, sexp-вхождения дневника могут производить для определения своей применимости любые вычисления. Смотрите раздел `Sexp Diary Entries' в The Emacs Lisp Reference Manual.

Напоминания о назначенных событиях

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

Чтобы включить напоминание о назначенных событиях, вы должны задействовать средство Emacs для показа времени, M-x display-time (смотрите раздел Строка режима). Вы также должны добавить к ловушке diary-hook функцию appt-make-list следующим образом:

(add-hook 'diary-hook 'appt-make-list)

Помещение такого текста в ваш файл `.emacs' делает все сразу:

(display-time)
(add-hook 'diary-hook 'appt-make-list)
(diary 0)

Если сделана такая подготовка, то когда вы отображаете дневник (с помощью команды d в окне календаря или через M-x diary), для всех записей дневника, в которых есть распознаваемые описания времени, настраивается список назначенных событий, и перед каждым из них вам делается напоминание.

Предположим например, что файл дневника содержит такие строки:

Monday
  9:30am Coffee break
 12:00pm Lunch        

Тогда по понедельникам, после того как вы отобразите дневник, вам будут напоминать в 9:20 о перерыве для кофе и в 11:50 об обеде.

Вы можете записывать время в стиле am/pm (где `12:00am' обозначает полночь, а `12:00pm' -- полдень) или в двадцатичетырехчасовом европейском/военном стиле. Необязательно быть постоянным; файл дневника может содержать смесь этих двух стилей.

Emacs автоматически обновляет список напоминаний сразу после полуночи. Это также отображает в буфере дневника записи для следующего дня, если только вы не установили appt-display-diary равной nil.

Вы также можете использовать средства напоминания о назначенных событиях в качестве будильника. Команда M-x appt-add добавляет записи в список напоминаний, не затрагивая ваш файл дневника. Для удаления записей из списка напоминаний применяется команда M-x appt-delete.

Вы можете в любое время выключить средство напоминания о назначенных событиях, установив appt-issue-message в значение nil.

Сезонный перевод времени

Emacs понимает разницу между стандартным и сезонным временем --- времена, выдаваемые для восходов и закатов Солнца, солнцестояний, равноденствий и фаз Луны, учитывают его. Правила сезонного перевода времени меняются от места к месту и кроме того колебались исторически от года к году. Чтобы делать свою работу правильно, Emacs должен знать, какое правило использовать.

Некоторые операционные системы отслеживают правила, применяющиеся в той местности, где вы находитесь; на таких системах Emacs получает необходимую информацию от системы автоматически. Если часть этой информации или вся она неизвестна, Emacs заполняет пробелы правилами, используемыми в данное время в Кембридже, Массачусетс. Если получившиеся правила -- это не то, что вы хотите, вы можете сообщить Emacs нужные правила, устанавливая определенные переменные: calendar-daylight-savings-starts и calendar-daylight-savings-ends.

Значениями этих переменных должны быть лисповские выражения, ссылающиеся на переменную year и вычисляющие григорианскую дату перехода на зимнее и летнее время в форме списка (месяц день год). Эти значения должны быть равны nil, если в вашей местности не бывает сезонного перевода времени.

Emacs использует эти выражения для определения даты перевода времени при создании списка праздников и для корректровки времени при вычислениях, связанных с Луной и Солнцем.

Для массачусетского Кембриджа эти значения таковы:

(calendar-nth-named-day 1 0 4 year)
(calendar-nth-named-day -1 0 10 year)

Это обозначает первый нулевой день недели (воскресенье) четвертого месяца (апреля) в году, задаваемом переменной year, и последнее воскресенье десятого месяца (октября) в этом же году. Если момент перевода времени сменился бы на 1 октября, вы установили бы переменную calendar-daylight-savings-starts в такое значение:

(list 10 1 year)

Если в вашей местности время не переводится, или если вы хотите получать всегда стандартное время, установите calendar-daylight-savings-starts и calendar-daylight-savings-ends равными nil.

Переменная calendar-daylight-time-offset задает разницу во времени после перевода, измеряемую в минутах. Для массачусетского Кембриджа это 60.

Переменные calendar-daylight-savings-starts-time и calendar-daylight-savings-ends-time задают число минут после полуночи по местному времени, когда происходит перевод часов. Для массачусетского Кембриджа значения обоих этих переменных равны 120.

Разнообразные команды

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

Gnus

Gnus -- это пакет Emacs, разработанный в первую очередь для чтения и отправки новостей Usenet. Его также можно использовать для чтения и написания ответов на сообщения из многих других источников -- почты, удаленных каталогов, дайджестов и других.

Здесь мы даем введение в Gnus и описываем некоторые основные возможности. Для получения подробной информации о Gnus наберите M-x info и выберите затем руководство по Gnus.

Чтобы запустить Gnus, напечатайте M-x gnus RET.

Буферы Gnus

В противоположность большинству обычных пакетов Emacs, Gnus использует для показа информации и получения команд несколько разных буферов. Большую часть времени пользователи проводят в трех буферах: буфере групп, буфере резюме и буфере статьи.

Буфер групп содержит перечень групп. Это первый буфер, который Gnus показывает после запуска. Обычно в нем показаны только те группы, на которые вы подписаны, и в которых есть непрочтенные статьи. Используйте этот буфер для выбора конкретной группы.

Буфер резюме построчно перечисляет статьи одной группы. По умолчанию для каждой статьи показываются автор, заголовок и число строк, но это можно настроить по своему вкусу, как и большую часть того, что отображает Gnus. Буфер резюме создается, когда вы выбираете группу в буфере групп, и уничтожается, когда вы покидаете эту группу. Используйте этот буфер для выбора статьи.

Буфер статьи показывает саму статью. При обычном использовании Gnus вы не выбираете этот буфер -- все полезные команды, предназначенные для действий над статьей, работают из буфера резюме. Но вы можете выбрать буфер статьи и выполнять все команды Gnus из него, если хотите.

Когда Gnus запускается

При запуске Gnus считывает ваш файл инициализации новостей `.newsrc' и пытается установить связь с локальным сервером новостей, который служит хранилищем статей. Сервер новостей не обязан быть тем же компьютером, на который вы вошли.

Если вы запустили Gnus и соединились с сервером, но не видите в буфере групп ни одной группы, наберите L или A k, чтобы получить перечень всех групп. Затем нажимайте u, чтобы переключать подписку на группы.

Когда вы запускаете Gnus первый раз, он подписывает вас на несколько избранных групп. Все остальные группы сначала уничтожены с вашей точки зрения; вы можете получить их перечень с помощью A k. Все новые группы, появляющиеся в дальнейшем на сервере, становятся для вас зомбированными; наберите A z, чтобы получить их перечень. Вы можете подписаться на группы, показанные в этих списках, используя команду u.

Когда вы покидаете Gnus при помощи q, он автоматически записывает в ваших файлах инициализации `.newsrc' и `.newsrc.eld' статус подписки всех групп. Обычно вам не стоит редактировать эти файлы вручную, но вы можете это делать, если знаете как.

Обзор команд Gnus

Чтение новостей -- это двухшаговый процесс:

  1. Выберите группу в буфере групп.
  2. Выбирайте статьи в буфере резюме. Каждая выбранная статья показывается в буфере статьи в большом окне под буфером резюме в маленьком окне.

Каждый буфер Gnus имеет свои особые команды; однако, смысл любого данного ключа в различных буферах Gnus обычно аналогичен, даже если и различается. Вот команды буферов групп и резюме:

q
В буфере групп, обновляет файл инициализации `.newsrc' и покидает Gnus. В буфере резюме, покидает текущую группу и возвращает в буфер групп. Таким образом, дважды нажав q, вы выйдете из Gnus.
L
В буфере групп, перечисляет все доступные группы на вашем сервере новостей (кроме тех, что вы уничтожили). Это может быть длинный список!
l
В буфере групп, перечисляет только те группы, на которые вы подписаны, и которые содержат непрочтенные статьи.
u
В буфере групп, отменяет подписку (или устанавливает ее) на группу, перечисленную в строке, в которой находится точка. Когда вы выходите из Gnus, нажав q, Gnus перечисляет в вашем файле `.newsrc' те группы, на которые вы подписаны. При следующем запуске Gnus вы не увидите эту группу, потому что обычно Gnus показывает только группы, на которые вы подписаны.
C-k
В буфере групп, "уничтожает" группу на текущей строке -- даже не перечисляет ее отныне в `.newsrc'. Это затрагивает как текущий сеанс Gnus, так и последующие. Когда вы покидаете Gnus при помощи q, Gnus записывает информацию в файле `.newsrc', описывая все группы, кроме тех, что вы "уничтожили".
SPC
В буфере групп, выбирает группу на строке под курсором и показывает первую непрочтенную статью в этой группе. В буфере резюме,
  • Выбирает статью под курсором, если ни одна еще не выбрана.
  • Прокручивает текст текущей статьи (если такая есть).
  • Выбирает следующую непрочтенную статью, если текущая статья кончилась.
Таким образом, вы можете пройти по всем статьям, последовательно нажимая SPC.
DEL
В буфере групп, перемещает точку к предыдущей группе, содержащей непрочтенные статьи. В буфере резюме, прокручивает текст статьи назад.
n
Перемещает точку к следующей непрочитанной группе или выбирает следующую непрочитанную статью.
p
Перемещает точку к предыдущей непрочитанной группе или выбирает предыдущую непрочитанную статью.
C-n
C-p
Перемещает точку к следующему или предыдущему пункту, даже если он помечен как прочтенный. Это не выбирает группу или статью на той строке.
s
В буфере резюме, начинает наращиваемый поиск в тексте текущего буфера статьи, точно так же, как если бы вы переключились в буфер статьи и набрали C-s.
M-s regexp RET
В буфере резюме, производит поиск статей, содержащих совпадение с regexp.

Запуск команд оболочки из Emacs

В Emacs есть команды для передачи одиночных командных строк подчиненным процессам оболочки. Существует возможность интерактивного запуска оболочки с вводом и выводом в буфер Emacs с именем `*shell*'.

M-! кмд RET
Запустить командную строку оболочки кмд и показать ее вывод (shell-command).
M-| кмд RET
Запустить командную строку оболочки кмд с содержимым области в качестве ввода; возможна замена содержимого области выводом команды (shell-command-on-region).
M-x shell
Запустить подоболочку с вводом и выводом через буфер Emacs. Затем вы можете задавать команды интерактивно.

Отдельные команды оболочки

M-! (shell-command) считывает в минибуфере строку текста и выполняет ее как команду оболочки в подоболочке, созданной только для этой команды. Стандартный ввод команде поступает из нулевого устройства. Если команда оболочки производит какой-либо вывод, то он поступает в буфер Emacs с именем `*Shell Command Output*', который отражается не в выбранном, а в другом окне. Числовой аргумент, как в M-1 M-!, велит команде вставить весь вывод в текущий буфер. В этом случае точка остается перед выводом, а метка устанавливается за ним.

Если командная строка оболочки завершается на `&', она выполняется асинхронно. Для синхронной команды оболочки shell-command возвращает выходное значение этой команды (0 обозначает успех), когда она вызывается из Лисп-программы.

M-| (shell-command-on-region) похожа на M-!, но команде оболочки передается в качестве стандартного ввода содержимое области, а не пустота. Если используется числовой аргумент, означающий вставку вывода в текущий буфер, то старая область сначала удаляется, а потом заменяется выводом. Она возвращает выходное значение команды, когда запускается из лисповской программы.

Обе команды M-! и M-| используют оболочку, указанную переменной shell-file-name. При запуске Emacs эта переменная инициализируется на основании вашей переменной среды `SHELL'. Если в имени этого файла не указывается каталог, то просматриваются каталоги в списке exec-path; этот список инициализируется при запуске Emacs по переменной среды `PATH'. Ваш файл `.emacs' может отменять либо одну, либо обе эти инициализации по умолчанию.

И M-! и M-| ожидают завершения команды оболочки. Чтобы остановить ожидание, используйте команду C-g; она завершает команду оболочки сигналом SIGINT -- тем же сигналом, который обычно генерируется оболочкой при вводе C-c. Emacs ждет, пока эта команда на самом деле завершится. Если команда оболочки не остановилась (потому что она игнорирует сигнал SIGINT), наберите C-g снова; это пошлет сигнал SIGKILL, который невозможно проигнорировать.

Чтобы указать систему кодирования для M-! или M-|, используйте команду C-x RET c непосредственно перед ними. Смотрите раздел Задание системы кодирования.

Сообщения команды об ошибках обычно перемежаются с обычным выводом. Если вы установите переменную shell-command-default-error-buffer равной строке, являющейся именем буфера, протокол ошибок будет вставляться перед точкой в буфере с этим именем.

Интерактивная подчиненная оболочка

Для запуска интерактивной подоболочки с сохранением протокола в буфере Emacs применяется M-x shell. Эта команда создает (или вновь использует) буфер с именем `*shell*' и запускает подоболочку с вводом, приходящим из этого буфера, и выводом, идущим в него. То есть, любой "терминальный ввод" для подоболочки приходит из текста в буфере, а любой "терминальный вывод" из подоболочки поступает в буфер, продвигая точку вперед. Для передачи ввода в подоболочку необходимо отправиться в конец буфера, набрать нужное и завершить набором RET.

Emacs не ждет, пока подоболочка что-либо сделает. Можно переключать окна или буферы и редактировать их, пока оболочка ожидает, или пока она выполняет команду. Вывод из подоболочки ждет до тех пор, пока у Emacs не появится время на его обработку; прием происходит всякий раз, когда Emacs ожидает ввода с клавиатуры, а также когда есть свободное время.

В качестве имени файла для загрузки подоболочки используется значение переменной explicit-shell-file-name, если оно не nil. В противном случае, используется переменная среды `ESHELL' если она установлена, или `SHELL'. Если указанное имя файла является относительным, просматриваются каталоги в списке exec-path; этот инициализируется по переменной среды `PATH' во время запуска Emacs. Ваш файл `.emacs' может перекрыть одну или обе из этих инициализаций.

Чтобы указать для оболочки систему кодирования, вы можете использовать команду C-x RET c непосредственно перед M-x shell. Вы также можете задать систему кодирования после запуска оболочки с помощью команды C-x RET p в ее буфере. Смотрите раздел Задание системы кодирования.

Как только оболочка запущена, на вход ей подается содержимое файла `~/.emacs_имя-оболочки', если этот файл существует, где имя-оболочки является именем файла, из которого загружается оболочка. Например, если вы используете bash, то ей посылается файл `~/.emacs_bash'.

Команды cd, pushd и popd, передаваемые подчиненной оболочке, отслеживаются в Emacs так, чтобы каталог по умолчанию буфера `*shell*' всегда совпадал с рабочим каталогом оболочки. Эти команды распознаются синтаксически проверкой посылаемых строк ввода. Если вы используете для этих команд псевдонимы, то вы можете указать Emacs, что их тоже следует распознавать. Например, если значение переменной shell-pushd-regexp соответствует началу командной строки оболочки, то эта строка воспринимается как команда pushd. Если для `pushd' используются псевдонимы, то необходимо изменить эту переменную. Аналогично, shell-popd-regexp и shell-cd-regexp используются для распознавания команд, обозначающих `popd' и `cd'. Причем эти команды распознаются только в начале командной строки оболочки.

Если Emacs получает ошибку при попытке обработать то, что он считает командами `cd', `pushd' или `popd', он запускает ловушку shell-set-directory-error-hook (смотрите раздел Ловушки).

Если Emacs не отслеживает правильно изменения текущего каталога подоболочки, используйте команду M-x dirs, чтобы спросить оболочку, какой у нее текущий каталог. Эта команда работает для оболочек, поддерживающих наиболее распространенный синтаксис команд; она не работает с необычными оболочками.

Вы также можете использовать M-x dirtrack-mode, чтобы включить (или выключить) альтернативный и более агрессивный метод отслеживания изменений текущего каталога.

Emacs определяет в подоболочке переменную среды `EMACS' со значением t. Сценарий оболочки может проверить эту переменную, чтобы определить, запущен ли он из подоболочки Emacs.

Режим Shell

Буферы оболочки использует режим Shell, в котором определено несколько специальных ключей, привязанных к префиксу C-c. Они выбраны так, что имитируют обычные клавиши редактирования и управления заданиями, присутствующие в оболочках вне Emacs, с той лишь разницей, что сначала вы должны набрать C-c. Ниже приведен полный список таких ключей режима Shell.

RET
В конце буфера, посылает строку в качестве ввода; в противном случае копирует текущую строку в конец буфера и посылает ее (send-shell-input). При копировании строки любой текст в ее начале, соответствующий переменной shell-prompt-pattern, пропускается; значение этой переменной должно быть регулярным выражением, которое соответствует подсказкам, используемым в вашей оболочке.
TAB
Завершает имя команды или файла перед точкой в буфере оболочки (comint-dynamic-complete). TAB также завершает ссылки на историю (смотрите раздел Ссылки на историю оболочки) и имена переменных среды. Переменная shell-completion-fignore задает список расширений файлов, которые должны игнорироваться при завершении в режиме Shell. Установка по умолчанию игнорирует имена файлов, заканчивающиеся на `~', `#' или `%'. Другие родственные с Comint режимы используют переменную comint-completion-fignore.
M-?
Временно показывает список возможных завершений имени файла перед точкой в буфере оболочки (comint-dynamic-list-filename-completions).
C-d
Либо удаляет один знак, либо посылает EOF (comint-delchar-or-maybe-eof). Набранный в конце буфера оболочки, C-d посылает подоболочке EOF. Набранный в любой другой позиции в этом буфере, C-d удаляет один знак, как обычно.
C-c C-a
Перемещает в начало строки, но после подсказки, если она есть (comint-bol). Если вы наберете эту команду два раза подряд, на второй раз она возвращает к метке процесса, то есть к началу ввода, который вы еще не послали подоболочке. (Обычно это одно и то же место --- конец подсказки в текущей строке -- но после C-c SPC метка процесса может оказаться на предыдущей строке.)
C-c SPC
Накапливает несколько строк ввода, и потом посылает их вместе. Эта команда вставляет перед точкой перевод строки, но не посылает предшествующий текст на вход подоболочки -- по крайней мере не сейчас. Обе строки, и та, что перед переводом строки, и та, что после, будут посланы вместе (и с разделяющим их переводом строки), когда вы нажмете RET.
C-c C-u
Уничтожает весь текст, который еще не был послан в качестве ввода (comint-kill-input).
C-c C-w
Уничтожает слово перед точкой (backward-kill-word).
C-c C-c
Прерывает оболочку или ее текущее подзадание, если оно существует (comint-interrupt-subjob). Эта команда уничтожает также весь предназначенный для ввода текст, который еще не был послан.
C-c C-z
Останавливает оболочку или ее текущее подзадание, если оно существует (comint-stop-subjob). Эта команда уничтожает также весь текст, который еще не был послан в качестве ввода.
C-c C-\
Посылает сигнал выхода оболочке или ее текущему подзаданию, если оно существует (comint-quit-subjob). Эта команда уничтожает также весь предназначенный для ввода текст, который еще не был послан.
C-c C-o
Уничтожает последнюю порцию вывода от команды оболочки (comint-kill-output). Это полезно, если команда оболочки извергает много текста, который только мешает.
C-c C-r
C-M-l
Прокручивает окно так, чтобы начало последней порции вывода оказалось вверху; также перемещает туда курсор (comint-show-output).
C-c C-e
Прокручивает окно, чтобы начало последней порции вывода оказалось внизу (comint-show-maximum-output).
C-c C-f
Перемещает вперед на одну команду оболочки, но в пределах текущей строки (shell-forward-command). Переменная shell-command-regexp указывает, как распознать конец команды.
C-c C-b
Перемещает назад на одну команду оболочки, но в пределах текущей строки (shell-backward-command).
C-c C-l
Показывает историю команд оболочки этого буфера в другом окне (comint-dynamic-list-input-ring).
M-x dirs
Спрашивает оболочку о текущем каталоге, чтобы Emacs скоординировался с оболочкой.
M-x send-invisible RET текст RET
Считывает текст и посылает его на вход оболочки без эхо. Это полезно, когда команда оболочки запускает программу, спрашивающую пароль. Или вы можете сообщить Emacs, как распознавать запросы пароля и выключать для них эхо:
(add-hook 'comint-output-filter-functions
          'comint-watch-for-password-prompt)
M-x comint-continue-subjob
Возобновляет процесс оболочки. Это полезно, если вы нечаянно приостановили процесс оболочки.(12)
M-x comint-strip-ctrl-m
Убирает все знаки control-M из текущей порции вывода оболочки. Наиболее удобный способ использовать эту команду -- запускать ее автоматически, когда вы получаете вывод от подоболочки. Чтобы сделать так, вычислите следующее лисповское выражение:
(add-hook 'comint-output-filter-functions
          'comint-strip-ctrl-m)
M-x comint-truncate-buffer
Эта команда усекает буфер оболочки до определенного максимального числа строк, задаваемого переменной comint-buffer-maximum-size. Это можно сделать автоматически каждый раз при получении вывода от подоболочки таким способом:
(add-hook 'comint-output-filter-functions
          'comint-truncate-buffer)

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

Режим Shell происходит от режима Comint, режима общего назначения для общения с интерактивными подпроцессами. Большинство возможностей режима Shell в действительности дает режим Comint, как вы можете понять из имен перечисленных выше команд. Особые средства режима Shell включают выбор регулярного выражения для распознавания подсказки, средство отслеживания каталогов и несколько пользовательских команд.

Другие средства Emacs, использующие варианты режима Comint, включают GUD (смотрите раздел Запуск отладчиков в Emacs) и M-x run-lisp (смотрите раздел Запуск внешнего Лиспа).

Вы можете использовать M-x comint-run для выполнения любой программы по вашему выбору в неизмененном режиме Comint -- без особенностей режима Shell.

История команд оболочки

Буферы оболочки поддерживают три способа повторения более ранних команд. Вы можете использовать те же ключи, что используются в минибуфере; они работают во многом так же, как в минибуфере, вставляя текст предыдущих команд, всегда оставляя точку в конце буфера. Вы можете переместиться по буферу назад к предыдущим командам в их начальной позиции и затем снова послать их или скопировать в конец. Или вы можете использовать знак `!' для ссылок на старые команды.

Список истории оболочки

M-p
Извлекает следующую более старую команду оболочки.
M-n
Извлекает следующую более новую команду оболочки.
M-r regexp RET
M-s regexp RET
Производит поиск команды оболочки, соответствующей регулярному выражению regexp, вперед или назад.
C-c C-x (режим Shell)
Извлекает следующую команду в списке истории.

Буферы оболочки предоставляют историю ранее введенных команд. Чтобы снова использовать команды оболочки, сохраненные в истории, используйте команды редактирования M-p, M-n, M-r и M-s. Они работают так же, как команды истории минибуфера, за тем лишь исключением, что действуют на текст в конце буфера оболочки, где вы вставляли бы текст для отправки оболочке.

M-p вставляет более раннюю команду оболочки в буфер оболочки. Последовательное применение M-p извлекает последовательно все более ранние команды оболочки, каждый раз замещая любой текст, уже существовавший в качестве потенциального ввода для оболочки. M-n работает похоже, но последовательно находит более поздние команды оболочки из этого буфера.

Команды поиска в истории, M-r и M-s, считывают регулярное выражение и производят поиск совпадающей команды в истории. Кроме предоставления выбора, какую именно команду вы хотите извлечь, они работают точно так же, как M-p и M-r. Если вы введете пустое регулярное выражение, будет использовано то регулярное выражение, которое вы предоставили в последний раз.

Когда вы нашли желаемый предыдущий ввод, вы можете снова послать его, нажав RET, или сначала отредактировать и затем послать, если хотите.

Часто бывает полезно заново выполнить несколько последовательных команд оболочки, которые ранее выполнялись по порядку. Чтобы сделать это, сначала найдите и выполните первую команду в последовательности. Затем наберите C-c C-x; это извлечет следующую команду -- ту, которая шла за только что повторенной. Затем нажмите RET, чтобы заново выполнить эту команду. Вы можете повторить несколько последовательных команд, набирая C-c C-x RET снова и снова.

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

Некоторые оболочки сохраняют истории их команд в файлах, чтобы вы могли сослаться на старые команды из предыдущих сеансовx. Emacs считывает файл истории команд для выбранной вами оболочки, чтобы проинициализировать свою собственную историю команд. Этот файл называется `~/.bash_history' в bash, `~/.sh_history' в ksh и `~/.history' в других оболочках.

Копирование истории оболочки

C-c C-p
Перемещает точку к предыдущей подсказке (comint-previous-prompt).
C-c C-n
Перемещает точку к следующей подсказке (comint-next-prompt).
C-c RET
Копирует команду ввода, в которой находится точка, вставляя ее копию в конец буфера (comint-copy-old-input). Это полезно, если вы переместили точку назад к предыдущей команде. После того, как вы скопировали эту команду, вы можете послать копию в качестве ввода, нажав RET. Если вы хотите, вы можете отредактировать копию перед отправлением.

Перемещение к предыдущему вводу и последующее его копирование с помощью C-c RET дает тот же результат -- то же содержимое буфера -- какой вы получили бы применением M-p достаточное число раз, чтобы извлечь эту старую команду из списка истории. Однако, C-c RET копирует текст из буфера, которые может отличаться от того, что находится в списке истории, если вы редактировали в буфере введенный текст после того, как он был послан.

Ссылки на историю оболочки

Различные оболочки, включая csh и bash, поддерживают ссылки на историю, которые начинаются с `!' и `^'. Режим Shell может понимать такие конструкции и делать для вас подстановку. Если вы вставили ссылку на историю и нажали TAB, это приведет к поиску совпадающей команды в истории ввода, подстановке, если она необходима, и помещению в буфер результата на место ссылки. Например, вы можете извлечь самую недавнюю команду, начинающуюся на `mv', с помощью ! m v TAB. Вы можете отредактировать эту команду, если хотите, и затем послать ее оболочке, нажав RET.

Ссылки на историю действуют только после подсказки оболочки. Переменная shell-prompt-pattern указывает, как распознать подсказку. Вообще, режимы Comint используют для определения подсказки переменную comint-prompt-regexp; режим Shell использует shell-prompt-pattern, чтобы установить локальное значение comint-prompt-regexp.

В режиме Shell есть возможность раскрывать ссылки на историю, когда вы отправляете их оболочке. Чтобы затребовать это, установите переменную comint-input-autoexpand равной input.

Вы можете сделать так, чтобы SPC производил раскрытие истории, привязав SPC к команде comint-magic-space.

Параметры режима Shell

Если переменная comint-scroll-to-bottom-on-input не равна nil, команды вставки и восстановления прокручивают выбранное окно книзу перед вставкой.

Если comint-scroll-show-maximum-output не равна nil, то прокрутка из-за поступления вывода старается разместить последнюю строку текста на нижней строке окна, чтобы вы видели как можно больше полезного текста. (Это имитирует поведение прокрутки на многих терминалах.) По умолчанию эта переменная равна nil.

Установкой comint-scroll-to-bottom-on-output вы можете сделать так, чтобы точка перескакивала в конец буфера всякий раз при поступлении вывода -- независимо от того, где точка была раньше. Если значение равно this, точка перескакивает в выбранном окне. Если значение равно all, точка перескакивает в каждом окне, показывающем этот буфер Comint. Если значение равно other, точка перескакивает во всех невыбранных окнах, показывающих текущий буфер. По умолчанию это nil, что означает, что точка не должна перемещаться в конец.

Переменная comint-input-ignoredups говорит, нужно ли сохранять в истории последовательные одинаковые строки ввода. Отличное от nil значение велит опускать ввод, идентичный предыдущему. По умолчанию эта переменная равна nil; это значит, что сохраняется любой ввод, даже если он эквивалентен предыдущему.

Завершение имен файлов управляется тремя переменными. Переменная comint-completion-addsuffix говорит, вставляет ли завершение пробел или косую черту, чтобы обозначить полностью завершенное имя файла или каталога (не-nil велит вставлять пробел или косую черту). comint-completion-recexact, если не равна nil, указывает TAB выбирать наименьшее возможное завершение, если обычный алгоритм завершения Emacs не может добавить даже одного знака. comint-completion-autolist, если не равна nil, велит перечислять все возможные завершения, когда нельзя найти точное завершение.

Команда comint-dynamic-complete-variable завершает имя переменной, используя установки переменных среды внутри Emacs. Переменные, управляющие завершением имен файлов, применяются и к завершению имен переменных. Эта команда обычно доступна через меню.

При завершении команд обычно рассматриваются только исполняемые файлы. Если вы установите shell-command-execonly равной nil, будут рассматриваться также имена и неисполняемых файлов.

Вы можете сконфигурировать поведение `pushd'. Есть переменные, которые указывают, ведет ли себя pushd, как cd, если ей не задан аргумент (shell-pushd-tohome), выталкивает ли она каталог, а не прокручивает, если ей задан числовой аргумент (shell-pushd-dextract), и добавляет ли она каталоги в стек только в том случае, если их еще нет в нем (shell-pushd-dunique). Выбранные вами значения должны, разумеется, соответствовать вашей оболочке.

Оболочка на удаленной машине

Emacs предоставляет две команды для захода на другой компьютер и общения с ним через буфер Emacs.

M-x telnet RET имя-машины RET
Устанавливает с компьютером имя-машины соединение по Telnet.
M-x rlogin RET имя-машины RET
Устанавливает с компьютером имя-машины соединение по Rlogin.

Используйте M-x telnet, чтобы установить соединение по Telnet с другим компьютером. (Telnet -- это стандартный протокол Internet для захода на удаленную систему.) Она считывает в минибуфере имя другого компьютера в качестве аргумента. Когда соединение установлено, общение с другим компьютером работает похоже на общение с подоболочкой: вы можете редактировать ввод с помощью обычных команд Emacs и посылать его построчно, набирая RET. Вывод вставляется в буфер вперемешку со вводом.

Используйте M-x rlogin для установки соединения по Rlogin. Rlogin -- это другой протокол общения с удаленной системой, во многом похожий на Telnet, но не совместимый с ним и поддерживаемый только на некоторых системах. Преимущества Rlogin состоят в том, что вы можете сделать так, чтобы вам необязательно было задавать имя пользователя и пароль при общении между часто используемыми машинами, и что вы можете установить восьмибитное соединение. (Чтобы сделать это в Emacs, установите rlogin-explicit-args равной ("-8") перед запуском Rlogin.)

M-x rlogin устанавливает каталог по умолчанию данного буфера Emacs, чтобы получать доступ к удаленной машине через FTP (смотрите раздел Имена файлов), и отслеживает команды оболочки, которые изменяют текущий каталог, так же, как режим Shell.

Есть два способа отслеживания каталогов в буфере Rlogin -- либо с помощью имен удаленных каталогов `/машина:кат/', либо с помощью локальных имен (это работает, если "удаленная" машина разделяет файловые системы с вашей начальной машиной). Вы можете использовать команду rlogin-directory-tracking-mode, чтобы переключать эти режимы. Отсутствие аргумента обозначает использование имен удаленных каталогов, положительный аргумент обозначает использование локальных имен, а отрицательный выключает отслеживание каталогов.

Использование Emacs в качестве сервера

Различные программы, такие как mail, могут вызывать выбранный вами редактор для редактирования определенного текста, например, отправляемого сообщения. По соглашению, большинство этих программ используют переменную среды `EDITOR', чтобы определить, какой редактор надо запускать. Если вы установите `EDITOR' равной `emacs', они вызовут Emacs -- но неудобным способом, запуская новый отдельный процесс Emacs. Это неудобно, потому что занимает время и потому что новый процесс Emacs не разделяет буферы с существующим процессом.

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

Во-первых, подготовка. Внутри Emacs, вызовите функцию server-start. (Ваш файл `.emacs' может делать это автоматически, если вы добавите в него выражение (server-start).) Затем, извне Emacs, установите переменную среды `EDITOR' равной `emacsclient'. (Заметьте, что некоторые программы используют другую переменную среды; например, чтобы TeX использовал `emacsclient', вам нужно установить переменную среды `TEXEDIT' равной `emacsclient +%d %s'.)

Впоследствии, когда любая программа вызывает указанную программу `EDITOR', в результате вашему главному Emacs будет отправлено сообщение, чтобы он обратился к файлу. (Программа emacsclient делает именно это.) Emacs немедленно показывает этот буфер, и вы сразу можете начать его редактирование.

Когда вы завершите редактирование этого буфера, наберите C-x # (server-edit). Это сохранит файл и пошлет программе emacsclient сообщение, приказывающее выйти. Программы, использующие `EDITOR', ожидают, пока "редактор" (на самом деле, emacsclient) не выйдет. C-x # также проверяет другие отложенные внешние запросы на редактирование различных файлов и выбирает следующий.

Вы можете переключиться в серверный буфер вручную, если хотите; необязательно попадать в него с помощью C-x #. Но C-x # дает единственный способ сказать, что "закончили" с текущим.

Если вы установите переменную server-window равной окну или фрейму, C-x # будет показывать серверный буфер в этом окне или фрейме.

Пока mail или другое приложение ожидает завершения emacsclient, emacsclient не читает терминальный ввод. Поэтому терминал, который использовала mail, как бы блокируется на это время. Чтобы редактировать в вашем главном Emacs, вам нужна возможность использовать Emacs без этого терминала. Есть два способа добиться этого:

  • Используя оконную систему, запускайте mail и главный Emacs в двух разных окнах. Пока mail ожидает emacsclient, окно, в котором она запущена, блокируется, но вы можете использовать Emacs, переключив окно.
  • Используйте для запуска других программ, таких как mail, режим Shell в Emacs; тогда emacsclient блокирует только подоболочку в Emacs, и вы можете продолжать использовать Emacs для редактирования этого файла.

Некоторые программы записывают для вашего редактирования временные файлы. После того, как вы отредактировали такой временный файл, программа считывает его и удаляет. Если сервер Emacs позже попросят отредактировать файл с тем же именем, он не должен предполагать, что этот файл имеет какое-либо отношение к предыдущему появлению этого же имени. Сервер делает это, уничтожая буфер временного файла, когда вы закончили с ним. Используйте переменную server-temp-file-regexp, чтобы указать, какие файлы являются временными в этом смысле; ее значением должно быть регулярное выражение, совпадающее с именами временных файлов.

Если вы запускаете emacsclient с ключом --no-wait, он возвращается сразу, не дожидаясь, пока вы "завершите" с буфером в Emacs.

Вывод твердой копии

Команды Emacs для создания твердой копии позволяют вам напечатать весь буфер или только его часть с заголовками или без них. Смотрите также команды печати Dired (смотрите раздел Разнообразные действия над файлами) и дневника (смотрите раздел Команды для просмотра записей в дневнике).

M-x print-buffer
Выдать распечатку текущего буфера с заголовками, содержащими имя файла и номер страницы.
M-x lpr-buffer
Выдать распечатку текущего буфера без заголовков страниц.
M-x print-region
Как print-buffer, но печатать только текущую область.
M-x lpr-region
Как lpr-buffer, но печатать только текущую область.

Все команды печати (кроме использующих Postscript) передают программе lpr дополнительные ключи, базирующиеся на значении переменной lpr-switches. Ее значение должно быть списком строк, причем каждая строка -- это ключ, начинающийся с `-'. Например, чтобы сделать ширину строк равной восьмидесяти столбцам для всех распечаток, получаемых из Emacs, установите lpr-switches так:

(setq lpr-switches '("-w80"))

Вы можете указать, какой принтер должен использоваться, установив переменную printer-name.

Переменная lpr-command задает имя используемой программы печати; значение по умолчанию зависит от типа вашей операционной системы. На большинстве систем это "lpr". Переменная lpr-headers-switches похожим образом задает дополнительные ключи для создания заголовков страниц. Переменная lpr-add-switches указывает, нужно ли передавать программе печати ключи `-T' и `-J' (подходящие для lpr): nil означает, что добавлять их не надо. lpr-add-switches должна быть равна nil, если ваша программа печати не совместима с lpr.

Печать через Postscript

Эти команды преобразуют содержимое буфера в Postscript и либо печатают его, либо оставляют в другом буфере Emacs.

M-x ps-print-buffer
Выводит распечатку текущего буфера в форме Postscript.
M-x ps-print-region
Выводит распечатку текущей области в форме Postscript.
M-x ps-print-buffer-with-faces
Выводит распечатку текущего буфера в форме Postscript, показывая использованные в тексте начертания средствами Postscript.
M-x ps-print-region-with-faces
Выводит распечатку текущей области в форме Postscript, показывая использованные в тексте начертания средствами Postscript.
M-x ps-spool-buffer
Генерирует Postscript для текста текущего буфера.
M-x ps-spool-region
Генерирует Postscript для текущей области.
M-x ps-spool-buffer-with-faces
Генерирует Postscript для текущего буфера, показывая использованные начертания.
M-x ps-spool-region-with-faces
Генерирует Postscript для текущей области, показывая использованные начертания.

Команды работы с Postscript, ps-print-buffer и ps-print-region, печатают содержимое буфера в форме Postscript. Одна команда печатает весь буфер, другая -- только область. Соответствующие команды с окончанием `-with-faces', ps-print-buffer-with-faces и ps-print-region-with-faces, используют средства Postscript для передачи начертаний (шрифтов и цветов) в свойствах печатаемого текста.

Если вы используете цветной дисплей, вы можете напечатать буфер, содержащий код программы, с цветовой подсветкой, включив в этом буфере режим Font-Lock и вызвав ps-print-buffer-with-faces.

Команды, чьи имена содержат `spool' на месте `print', генерируют вывод Postscript в буфере Emacs, а не посылают его на принтер.

Переменные, управляющие печатью в Postscript

Все команды печати через Postscript используют переменные ps-lpr-command и ps-lpr-switches, указывающие, как нужно печатать. ps-lpr-command задает имя запускаемой команды, ps-lpr-switches задает ключи командной строки, а ps-printer-name задает принтер. Если вы не установили первые две переменные сами, они получают свои начальные значения от lpr-command и lpr-switches. Если ps-printer-name равна nil, используется printer-name.

Переменная ps-print-header контролирует, будут ли эти команды добавлять строки заголовка для каждой страницы, -- установите ее равной nil, чтобы выключить заголовки. Вы можете отключить обработку цветов, установив ps-print-color-p в значение nil.

Переменная ps-paper-type указывает, для какого размера станицы нужно форматировать; допустимые значения включают a4, a3, a4small, b4, b5, executive, ledger, legal, letter, letter-small, statement, tabloid. По умолчанию это letter. Вы можете определить дополнительные размеры бумаги, изменяя переменную ps-page-dimensions-database.

Переменная ps-landscape-mode указывает ориентацию текста на странице. По умолчанию она равна nil, что обозначает "портретный" режим. Любое отличное от nil значение задает "ландшафтный" режим.

Переменная ps-number-of-columns задает число колонок; она играет роль и в "портретном", и в "ландшафтном" режиме. По умолчанию это 1.

Переменная ps-font-family указывает, какое семейство шрифтов нужно использовать при печати обычного текста. Допустимые значения включают Courier, Helvetica, NewCenturySchlbk, Palatino и Times. Переменная ps-font-size задает размер шрифта для обычного текста. По умолчанию это 8.5 пунктов.

Многие другие переменные для настройки этих команд определены и описаны в файле на Лиспе `ps-print.el'.

Сортировка текста

Emacs предоставляет несколько команд для сортировки текста в буфере. Все они оперируют с содержимым области (текстом между точкой и меткой). Эти команды разделяют текст области на большое число записей сортировки, определяют ключ сортировки для каждой записи и затем переставляют записи в порядке, определяемом ключами сортировки. Записи располагаются таким образом, чтобы их ключи находились в алфавитном или, для числовой сортировки, числовом порядке. При алфавитной сортировке все буквы верхнего регистра от `A' до `Z' идут перед `а' нижнего регистра, в соответствии с последовательностью знаков ASCII.

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

M-x sort-lines
Разделить область на строки и отсортировать в соответствии с полным текстом строки. Числовой аргумент означает сортировку по убыванию.
M-x sort-paragraphs
Разделить область на абзацы и отсортировать, сравнивая текст абзацев целиком (за исключением пустых строк в начале). Числовой аргумент означает сортировку по убыванию.
M-x sort-pages
Разделить область на страницы и отсортировать, сравнивая полный текст страниц (за исключением пустых строк в начале). Числовой аргумент означает, что сортировка производится по убыванию.
M-x sort-fields
Разделить область на строки и отсортировать, сравнивая содержимое одного поля в каждой строке. Поля разделяются пропусками, так что первый отрезок последовательных непробельных знаков в строке составляет поле 1, второй такой отрезок составляет поле 2, и так далее. Поле, по которому должна производится сортировка, указывается с помощью числового аргумента: 1 используется для сортировки по полю 1, и так далее. Отрицательный аргумент означает отсчет полей справа, а не слева; то есть минус 1 обозначает сортировку по последнему полю. Если содержание полей сортировки в нескольких строках одинаково, эти строки остаются в том же относительном порядке, в каком они были изначально.
M-x sort-numeric-fields
Эта команда подобна M-x sort-fields, за исключением того, что для каждой строки указанное поле превращается в число, и сравниваются уже эти числа. `10' предшествует `2', когда рассматривается как текст, но следует за `2', когда рассматривается как число.
M-x sort-columns
Как M-x sort-fields, за исключением того, что используемый для сравнения текст получается в пределах каждой строки из фиксированного диапазона столбцов. Объяснение приведено ниже.
M-x reverse-region
Обратить порядок строк в области. Это полезно для сортировки в порядке убывания по полям или колонкам, так как данные команды сортировки не имеют средств для этого.

Например, если буфер содержит такой текст:

On systems where clash detection (locking of files being edited) is
implemented, Emacs also checks the first time you modify a buffer
whether the file has changed on disk since it was last visited or
saved.  If it has, you are asked to confirm that you want to change
the buffer.

применение M-x sort-lines ко всему буферу даст следующее:

On systems where clash detection (locking of files being edited) is
implemented, Emacs also checks the first time you modify a buffer
saved.  If it has, you are asked to confirm that you want to change
the buffer.
whether the file has changed on disk since it was last visited or

где заглавная `O' идет перед всеми строчными буквами. Если вы вместо этого примените C-u 2 M-x sort-fields, то получите следующее:

implemented, Emacs also checks the first time you modify a buffer
saved.  If it has, you are asked to confirm that you want to change
the buffer.
On systems where clash detection (locking of files being edited) is
whether the file has changed on disk since it was last visited or

где ключами сортировки были `Emacs', `If', `buffer', `systems' и `the'.

M-x sort-columns требует более подробного объяснения. Вы указываете колонки, устанавливая точку на одном столбце, а метку -- на другом. Так как это означает, что вы не можете поставить точку или метку в начале первой строки, с которой должна начаться сортировка, то эта команда использует необычное определение `области': вся строка с точкой рассматривается как часть области, и так же все содержимое строки, в которой находится метка, и все строки между ними.

Например, для сортировки таблицы по информации, размещенной в столбцах с 10 по 15, метку можно поставить в первой строке таблицы в столбце 10, а точку в столбце 15 в последней строке таблицы и затем запустить sort-columns. Или вы можете поставить метку в столбце 15 в первой строке, а точку -- в столбце 10 в последней строке.

Это можно рассматривать как сортировку прямоугольника, заданного точкой и меткой, за исключением того, что текст в каждой строке справа и слева от прямоугольника двигается вместе с текстом внутри прямоугольника. Смотрите раздел Прямоугольники.

Многие команды сортировки игнорируют при сравнениях различие в регистре букв, если sort-fold-case не равна nil.

Сужение

Сужение означает сосредоточение на некоторой части буфера, при котором оставшаяся часть становится временно недоступной. Та часть, в которую вы все еще можете попасть, называется доступной частью. Отмена сужения и переход в состояние, когда весь буфер снова становится доступным, называется расширением. Размер действующего сужения буфера в какое-либо время называется ограничением этого буфера.

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

C-x n n
Сузить до области между точкой и меткой (narrow-to-region).
C-x n w
Расширить так, чтобы буфер снова стал полностью доступным (widen).
C-x n p
Сузить до текущей страницы (narrow-to-page).
C-x n d
Сузить до текущего определения функции (narrow-to-defun).

Когда вы сделали сужение до части буфера, эта часть -- все, что вы видите. Вы не можете видеть остальную часть, в нее невозможно перейти (команды движения не выйдут за пределы доступной части) и нельзя изменить ее никаким образом. Но она не пропала, и если вы сохраняете файл, то сохранится и недоступная часть текста. При действии сужения в строке режима появляется слово `Narrow'.

Основной командой сужения является C-x n n (narrow-to-region). Она устанавливает ограничения для текущего буфера таким образом, что остается доступным только текст текущей области, но весь текст перед областью и после нее становится недоступным. Точка и метка не изменяются.

Еще вы можете использовать C-x n p (narrow-to-page) для сужения до текущей страницы. Смотрите раздел Страницы, определение страницы. C-x n d (narrow-to-defun) сужает до определения функции, содержащего точку (смотрите раздел Определения функций).

Отмена сужения выполняется командой C-x n w (widen). Она делает весь текст буфера снова доступным.

Вы можете получить информацию о том, до какой части сужен буфер, применив команду C-x =. Смотрите раздел Информация о позиции курсора.

Поскольку сужение может легко запутать пользователя, не понимающего его, команда narrow-to-region обычно заблокирована. При попытке ее использования запрашивается подтверждение и предоставляется возможность ее включения; если вы задействовали эту команду, подтверждение больше не требуется. Смотрите раздел Блокирование команд.

Редактирование текста в две колонки

Режим Two-column позволяет вам удобно редактировать текст в две колонки. Он использует два расположенных рядом окна, каждое из которых показывает свой буфер.

Есть два способа войти в двухколоночный режим:

F2 2 или C-x 6 2
Входит в режим two-column, слева появляется текущий буфер, а справа появляется буфер, чье имя основано на имени текущего буфера (2C-two-columns). Если правый буфер еще не существует, изначально он делается пустым; содержимое текущего буфера не изменяется. Эта команда подходит, если текущий буфер пуст или содержит текст только одной колонки, и вы хотите добавить вторую.
F2 s or C-x 6 s
Разделяет текущий буфер с текстом в двух колонках на два буфера и показывает их рядом друг с другом (2C-split). Текущий буфер становится левым буфером, но текст из правой колонки перемещается в правый буфер. Текущий столбец определяет точку раздела. Разделение начинается от текущей строки и продолжается до конца буфера. Эта команда полезна, если у вас уже есть буфер с двухколоночным текстом, и вы хотите временно разделить колонки.
F2 b буфер RET
C-x 6 b буфер RET
Входит в режим two-column, используя текущий буфер в качестве левого и буфер буфер в качестве правого (2C-associate-buffer).

F2 s или C-x 6 s ищет разделитель колонок, который является строкой, стоящей между двух колонок на каждой строке. Вы можете задать ширину разделителя с помощью числового аргумента для F2 s; столько знаков, стоящих перед точкой, выразят строку-разделитель. По умолчанию ширина равна 1, поэтому разделитель колонок -- это знак перед точкой.

Когда строка содержит разделитель на своем месте, F2 s помещает текст после разделителя в правый буфер и удаляет разделитель. Строки, не имеющие разделителя колонок, оставляются неразбитыми; они остаются в левом буфере, а в правый буфер помещается для соответствия пустая строка. (Таким образом можно написать строку, которая "проходит по обеим колонкам в двухколоночном режиме": написать ее в левом буфере и сделать пустую строку в правом буфере.)

Команда C-x 6 RET или F2 RET (2C-newline) вставляет знак новой строки в оба буфера в соответствующих позициях. Это самый простой способ добавить новую строку в двухколоночном тексте, когда вы редактируете его в разных буферах.

Когда вы отредактировали оба буфера, как вам хотелось, объедините их с помощью F2 1 или C-x 6 1 (2C-merge). Это копирует текст из правого буфера как вторую колонку другого буфера. Чтобы вернуться к редактированию в две колонки, используйте F2 s.

Используйте F2 d или C-x 6 d, чтобы разъединить два буфера, оставляя каждый как есть (2C-dissociate). Если другой буфер, не текущий в момент, когда вы набрали F2 d, оказался пустым, F2 d уничтожает его.

Редактирование двоичных файлов

Существует специальный основной режим для редактирования двоичных файлов: режим Hexl. Чтобы воспользоваться им, вызовите для обращения к файлу M-x hexl-find-file вместо C-x C-f. Эта команда преобразует содержимое файла в шестнадцатиричные числа и позволяет вам редактировать их. Когда вы сохраняете этот файл, он автоматически преобразуется обратно в двоичный формат.

Вы можете также использовать M-x hexl-mode для преобразования существующего буфера в шестнадцатиричный вид. Это полезно, если вы обратились к файлу обычным способом и потом обнаружили, что это двоичный файл.

Обычные знаки в режиме Hexl перезаписывают поверх существующего текста. Это сделано для уменьшения риска нечаянной потери выравнивания данных в файле. Для вставки есть особые команды. Вот перечень команд режима Hexl:

C-M-d
Вставляет байт с введенным десятичным кодом.
C-M-o
Вставляет байт с введенным восьмиричным кодом.
C-M-x
Вставляет байт с введенным шестнадцатиричным кодом.
C-x [
Перемещает на начало 1k-байтной "страницы".
C-x ]
Перемещает на конец 1k-байтной "страницы".
M-g
Перемещает к адресу, заданному шестнадцатиричным числом.
M-j
Перемещает к адресу, заданному десятичным числом.
C-c C-c
Покидает режим Hexl, возвращаясь к тому основному режиму, который был в этом буфере до того, как вы вызвали hexl-mode.

Сохранение сеансов Emacs

Вы можете использовать библиотеку Desktop для сохранения состояния Emacs от одного сеанса к другому. Сохранение состояния означает, что Emacs запускается с тем же самым набором буферов, основных режимов, позиций в буферах и прочим, какие были в предыдущем сеансе Emacs.

Чтобы использовать Desktop, вы должны воспользоваться буфером Customization (смотрите раздел Интерфейс для простой настройки) и установить desktop-enable в отличное от nil значение или добавить такие строки в ваш файл `.emacs':

(desktop-load-default)
(desktop-read)

Первый раз, когда вы сохраняете состояние сеанса Emacs, вы должны сделать это вручную, с помощью команды M-x desktop-save. Как только вы это сделали, при выходе из Emacs состояние будет сохраняться снова -- не только в существующем сеансе Emacs, но и во всех последующих. Вы также можете записать состояние в любое время не выходя из Emacs, снова набрав M-x desktop-save.

Чтобы Emacs восстановил состояние предыдущего сеанса, вы обязаны запустить его из того же каталога, который вы использовали в прошлом сеансе. Это необходимо, потому что desktop-read просматривает в поисках файла, который она должна прочитать, именно текущий каталог. Это означает, что вы можете хранить отдельные сохраненные сеансы в разных каталогах; каталог, в котором вы запускаете Emacs, будет указывать, какой из сохраненных сеансов вы хотите восстановить.

Переменная desktop-files-not-to-save говорит, какие файлы исключаются при сохранении состояния. Ее значение -- это регулярное выражение, совпадающее с именами исключаемых файлов. По умолчанию исключаются удаленные (полученные по FTP) файлы; потому что повторное к ним обращение в последующем сеансе может быть медленным. Если вы хотите включить эти файлы в сохраненное состояние, установите desktop-files-not-to-save равной "^$". Смотрите раздел Удаленные файлы.

Уровни рекурсивного редактирования

Рекурсивное редактирование -- это ситуация, в которой вы используете команды Emacs для выполнения произвольного редактирования, находясь в середине другой команды Emacs. Например, при наборе команды C-r внутри query-replace происходит вход в рекурсивное редактирование, где можно изменить текущий буфер. Выходя из этого рекурсивного редактирования, вы возвращаетесь в query-replace.

Выход из рекурсивного редактирования означает возврат к незаконченной команде, которая продолжает выполняться. Выход производится с помощью команды C-M-c (exit-recursive-edit).

Вы можете также прервать рекурсивное редактирование. Это похоже на выход, но при этом происходит также и незамедлительный выход из незаконченной команды. Прерывание рекурсивного редактирования производится по команде C-] (abort-recursive-edit). Смотрите раздел Выход и аварийное завершение.

Строка режима показывает вам, что вы находитесь в рекурсивном редактировании, при помощи квадратных скобок вокруг круглых скобок, которые всегда окружают названия основного и второстепенных режимов. Строка режима каждого окна показывает это таким же образом, поскольку нахождение в рекурсивном редактировании относится к Emacs в целом, а не к какому-либо отдельному окну или буферу.

Возможно пребывание в рекурсивных редактированиях внутри рекурсивных редактирований. Например, после набора команды C-r в query-replace можно набрать команду, которая входит в отладчик. Это начинает уровень рекурсивного редактирования для отладчика внутри уровня рекурсивного редактирования для C-r. Строки режима показывают пару квадратных скобок для каждого работающего в данный момент уровня рекурсивного редактирования.

Выход из внутреннего рекурсивного редактирования (например, с помощью команды c отладчика) возобновляет команду одним уровнем выше. По окончанию этой команды можно использовать C-M-c, чтобы выйти из еще одного уровня рекурсивного редактирования, и так далее. Выход относится только к самому внутреннему уровню. Прерывание тоже приводит к выходу лишь из одного уровня рекурсивного редактирования: происходит немедленный возврат на уровень команды предыдущего рекурсивного редактирования. Если хотите, то можете затем прервать и следующий уровень.

Напротив, команда M-x top-level прерывает все уровни рекурсивного редактирования, возвращаясь непосредственно на верхний командный уровень.

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

В основном мы стараемся минимизировать использование уровней рекурсивного редактирования в GNU Emacs. Это так, потому что они обязывают вас "возвращаться" в определенном порядке -- от самого внутреннего уровня к верхнему уровню. Если возможно, мы представляем различные виды деятельности в разных буферах, чтобы вы могли переключаться между ними, как вам нравится. Некоторые команды переключают в новый основной режим, который предоставляет команду для переключения назад. Эти методы дают вам большую гибкость для возврата к незаконченным занятиям в том порядке, в каком вы пожелаете.

Эмуляция

GNU Emacs может быть запрограммирован для эмуляции (в большей или меньшей степени) большинства других редакторов. Стандартные средства могут эмулировать следующее:

EDT (редактор DEC VMS)
Эмуляция EDT включается с помощью команды M-x edt-emulation-on. Команда M-x edt-emulation-off восстанавливает обычные для Emacs привязки. Большинство команд эмуляции EDT являются ключами вспомогательной клавиатуры, и большинство стандартных привязок ключей в Emacs остаются доступными. Перепривязки при эмуляции EDT выполняются в глобальной таблице ключей, таким образом, при нахождении в режиме эмуляции EDT нет проблемы переключения буферов или основных режимов.
vi (редактор Беркли)
Viper -- новейший эмулятор vi. Он реализует несколько уровней эмуляции: уровень 1 ближе всех к vi, тогда как уровень 5 отходит от строгой эмуляции, чтобы воспользоваться возможностями Emacs. Чтобы вызвать Viper, наберите M-x viper-mode; это проведет вас по остальному пути и спросит об уровне эмуляции. Смотрите Info файл `viper', нода `Top'.
vi (другой эмулятор)
M-x vi-mode входит в основной режим, который заменяет прежде установленный режим. Все команды vi, которые в настоящем vi входят в режим "ввода", запрограммированы для возврата в предыдущий основной режим. Таким образом, обычный Emacs служит режимом "ввода" для vi. Поскольку эмуляция vi работает через основные режимы, переключать буфера в процессе эмуляции нельзя. Сначала необходимо вернуться в обычный Emacs. Если вы планируете часто использовать эмуляцию vi, то, вероятно, появится желание привязать ключ к команде vi-mode.
vi (еще один эмулятор)
M-x vip-mode вызывает еще один эмулятор vi, про который говорят, что он соответствует настоящему vi более полно, чем M-x vi-mode. Режим "ввода" в этом эмуляторе отличается от обычного Emacs, так что для возврата в режим эмуляции vi можно использовать ESC. Для возврата из режима эмуляции vi в обычный Emacs необходимо набрать C-z. Этот режим эмуляции не работает через основные режимы, что обеспечивает возможность различных вариантов переключения буферов внутри эмулятора. Приписывать ключ команде vip-mode нет так необходимо, как в случае vi-mode, поскольку завершение режима вставки не использует ее. Смотрите Info файл `vip', нода `Top', для получения полной информации.

Диссошиэйтед Пресс

M-x dissociated-press -- это команда для перемешивания текстового файла слово за словом или знак за знаком. Имея в начале буфер с нормальным текстом, она формирует крайне забавный вывод. Ввод производится из текущего буфера Emacs. Диссошиэйтед Пресс записывает свой вывод в буфер с именем `*Dissociation*', при этом, чтобы облегчить его постепенное чтение, через каждую пару строк (примерно) содержимое буфера показывается заново.

Диссошиэйтед Пресс время от времени спрашивает, продолжать ли действие. Для остановки необходимо ответить n. Остановить можно также в любое время с помощью C-g. Диссоциированная выдача сохраняется в буфере `*Dissosiation*', чтобы по желанию можно было скопировать ее в другое место.

Диссошиэйтед Пресс в процессе работы совершает беспорядочные прыжки из одной точки буфера в другую. Для получения правдоподобного вывода, а не тарабарщины, она соблюдает некоторое перекрытие между концом одного отрезка последовательности слов или знаков и началом следующего. Так, если только что она напечатала слово `президент' и теперь решает прыгнуть в другую точку файла, то она может заметить `ент' в слове `пентагон' и продолжить вывод отсюда, выдавая в результате `президентагон'.(13) Наилучшие результаты получаются на длинных выборках.

Положительный аргумент M-x dissociated-press велит ей работать познаково и определяет число перекрывающихся знаков. Отрицательный аргумент заставляет ее действовать слово за словом и определяет количество перекрывающихся слов. В этом режиме целые слова, а не знаки, трактуются как переставляемые элементы. Отсутствие аргумента эквивалентно аргументу, равному двум. К сновашему сведению, вывод осуществляется только в буфер `*Dissociation*'. Буфер, с которого вы начали, не изменяется.

Диссошиэйтед Пресс производит примерно те же результаты, что и марковская цепь, основанная на частотной таблице, построенной по выборочному тексту. Однако, этот метод является независимым, игноригинальным изобретением. Диссошиэйтед Пресс повсеметодически копирует несколько последовательных знаков из выборки от прыжка к прыжку, тогда как цепь Маркова делала бы случайный выбор для каждого слова или знака. В итоге все это работает быстрее и придает результату более благозвучный вид.

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

Другие развлечения

Если вы немного заскучали, можете попробовать M-x hanoi. Если вам очень скучно, то задайте ей численный аргумент. Если вам очень-очень скучно, то попробуйте задать аргумент 9. Откиньтесь на спинку кресла и наблюдайте.

Если вам хочется больше личного участия, попробуйте команду M-x gomoku, которая сыграет с вами в пять-в-ряд.

M-x blackbox и M-x mpuz -- это две головоломки. blackbox предлагает вам определить с помощью томографии положение объектов внутри черного ящика. mpuz показывает задачу на умножение, где цифры заменены буквами, а как, вы должны догадаться. Чтобы сделать предположение, наберите букву, а затем цифру, которая, как вы думаете, обозначена этой буквой.

M-x dunnet запускает приключенческую игру; это большая головоломка.

Если вас расстроили, запустите знаменитую программу Eliza. Наберите просто M-x doctor. Каждый ввод заканчивайте двойным набором RET.

Когда вам будет не по себе, наберите M-x yow.

Настройка

В этой главе обсуждаются различные вопросы, относящиеся к простой адаптации поведения Emacs. Чтобы узнать, как сделать большие изменения, смотрите книгу The Emacs Lisp Reference Manual.

Все виды настройки воздействуют только на тот сеанс Emacs, в котором вы их делаете. Они полностью исчезают при завершении работы с Emacs и не действуют на другие сеансы Emacs, которые могут быть запущены в то же самое время или позже. Только в одном случае сеанс работы с Emacs может повлиять на что-либо вне его самого -- при записи файла. В частности, чтобы сделать настройку "постоянной", существует единственный путь --- поместить нечто в ваш файл `.emacs' или другой подходящий файл, что будет выполнять настройку в каждом сеансе. Смотрите раздел Файл инициализации, `~/.emacs'.

Второстепенные режимы

Второстепенные режимы -- это необязательные возможности, которые вы можете включать и выключать. Например, режим Auto Fill -- это второстепенный режим, в котором SPC разрывает строки на границе слов по мере того, как вы набираете. Все второстепенные режимы независимы друг от друга и от выбранного основного режима. Большинство второстепенных режимов сообщают, что они включены, в строке режима; например, надпись `Fill' в строке режима означает, что включен режим Auto Fill.

Для получения имени командной функции, включающей или выключающей второстепенный режим, добавьте к имени второстепенного режима слово -mode. Таким образом, команда запуска или выключения режима Auto Fill называется M-x auto-fill-mode. Подобные команды обычно запускаются через M-x, но при желании к ним можно привязать ключи. Без аргумента эти команды включают режим, если он был выключен, и выключают, когда он был включен. Эта техника известна как переключение. Положительный аргумент всегда включает режим, а явный нулевой или отрицательный аргумент всегда выключает его.

Включение или выключение некоторых второстепенных режимов применяется только к текущему буферу; каждый буфер независим от других. Следовательно, вы можете включить режим в одних буферах и выключить в других. К второстепенным режимам, которые могут так работать, относятся режим Abbrev, режим Auto Fill, режим Auto Save, режим Font-Lock, режим Hscroll, режим ISO Accents, второстепенный режим Outline, режим Overwrite и режим Binary Overwrite.

Режим Abbrev позволяет вам определить сокращения, которые автоматически расшифровываются при наборе. Например, `amd' может раскрываться в `abbrev mode'. Смотрите раздел Сокращения, для получения полной информации.

Режим Auto Fill позволяет вводить заполненный текст без явного прерывания строк. Emacs вставляет перевод строки, когда это нужно, чтобы строка не стала слишком длинной. Смотрите раздел Заполнение текста.

Режим Auto Save заставляет Emacs периодически сохранять содержимое буфера, чтобы уменьшить возможный объем потерянной работы в случае краха системы. Смотрите раздел Самосохранение: защита от гибели.

Режим Enriched позволяет редактировать и сохранять форматированный текст. Смотрите раздел Редактирование форматированного текста.

Режим Flyspell автоматически подсвечивает неправильно набранные слова. Смотрите раздел Поиск и исправление орфографических ошибок.

Режим Font-Lock автоматически подсвечивает определенные текстовые единицы, используемые в программах, такие как комментарии, строки и имена определенных функций. Для этого требуется оконная система, которая может отображать разные шрифты. Смотрите раздел Использование разных начертаний.

Режим Hscroll выполняет автоматическую горизонтальную прокрутку экрана, чтобы точка всегда была видна. Смотрите раздел Горизонтальная прокрутка.

Режим ISO Accents компонует знаки ``', `'', `"', `^', `/' и `~' со следующий буквой в букву с акцентом из набора знаков ISO Latin-1. Смотрите раздел Поддержка однобайтных европейских знаков.

Второстепенный режим Outline обеспечивает те же возможности, что и основной режим, называемый Outline; но поскольку он является второстепенным режимом, то вы можете использовать его вместе с любым основным. Смотрите раздел Режим Outline.

Режим Overwrite заменяет существующие знаки при вводе новых вместо обычной вставки со сдвигом вправо. Например, если точка находится перед `B' в слове `FOOBAR', то в режиме Overwrite ввод G изменяет это слово на `FOOGAR', вместо `FOOGBAR', как это делается обычно. В режиме Overwrite, команда C-q вставляет знак, каким бы он не был, даже если это цифра, -- это дает вам способ вставки знака вместо замены существующего.

Режим Binary Overwrite -- это вариант режима Overwrite для редактирования двоичных файлов; он обрабатывает знаки новой строки и табуляции точно также, как и другие знаки, так что они могут заменять другие знаки и сами могут быть заменены другими знаками.

Следующие второстепенные режимы обычно применяются ко всем буферам сразу. Поскольку каждый из них включается или выключается с помощью установки значения переменной, вы можете установить их по-разному для отдельных буферов, явно делая эти переменные локальными для этих буферов. Смотрите раздел Локальные переменные.

Режим Icomplete показывает возможность завершения, когда вы находитесь в минибуфере и завершение активно. Смотрите раздел Параметры завершения.

Режим Line Number постоянно отображает номер текущей строки в строке режима. Смотрите раздел Строка режима.

Режим Resize-Minibuffer заставляет минибуфер расширяться так, чтобы он мог вместить весь текст, который вы в него помещаете. Смотрите раздел Редактирование в минибуфере.

Режим Scroll Bar прикрепляет к каждому окну полоску прокрутки (смотрите раздел Полоски прокрутки). Режим Menu Bar прикрепляет к каждому фрейму полоску меню (смотрите раздел Полоски меню). Оба этих режима по умолчанию включены при использовании X Window System.

В режиме Transient Mark, каждое изменение содержимого буфера "деактивирует" метку, так что команды, которые оперируют с областью, буду выдавать ошибку. Это означает, что вы должны либо установить пометку, либо явно "активировать" ее перед каждой командой, которая работает с областью. Преимущество режима Transient Mark в том, что Emacs может отрисовывать область подсвеченной (в настоящее время только при работе в X). Смотрите раздел Установка метки.

Для большинства второстепенных режимов, имя команды также совпадает с именем переменной, которая контролирует данный режим. Режим включается, когда значение переменной устанавливается в не-nil, и команда установки второстепенного режима работает путем установки этой переменной. Например, команда outline-minor-mode работает, устанавливая значение outline-minor-mode как переменной; именно эта переменная непосредственно включает и выключает второстепенный режим Outline. Чтобы проверить, работает ли некий второстепенный режим таким способом, используйте C-h v, чтобы запросить документацию на имя переменной.

Переменные второстепенных режимов обеспечивают хороший способ включения и выключения второстепенных режимов для программ на Лиспе; они также полезны в списках локальных переменных файлов. Но пожалуйста, дважды подумайте, прежде чем устанавливать второстепенные режимы через список локальных переменных, потому что большинство второстепенных режимов являются предметом предпочтений пользователя -- другие пользователи, которые будут редактировать этот же файл, могут не захотеть использовать те же режимы, что предпочитаете вы.

Переменные

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

Лисп позволяет хранить в любой переменной любой вид значения, но большинство используемых в Emacs переменных требуют значение определенного типа. Зачастую значение должно всегда быть строкой или всегда числом. Иногда мы говорим, что некоторое свойство включено, если некая переменная "отлична от nil", подразумевая, что если значение переменной равно nil, то это свойство выключено, но оно включено для любого другого значения. Поскольку при установке переменной вам нужно выбрать одно определенное значение, для включения свойства принято использовать значение t.

Как и всякая программа на Лиспе, Emacs использует много лисповских переменных для хранения внутренних записей. Но большинство переменных, которые представляют для вас интерес, -- это те, что существуют ради настройки. Emacs (обычно) не меняет значения этих переменных, вместо этого вы сами устанавливаете значения, тем самым изменяя и управляя поведением некоторых команд Emacs. Эти переменные называются пользовательскими параметрами. Большинство параметров описаны в этом руководстве и приведены в указателе переменных (смотрите раздел Указатель переменных).

Примером переменной, являющейся пользовательским параметром, служит fill-column; она определяет позицию правого края (как число знаков от левого края), которая используется командами заполнения (смотрите раздел Заполнение текста).

Просмотр и установка переменных

C-h v пер RET
Показывает значение переменной пер и документацию по ней (describe-variable).
M-x set-variable RET пер RET значение RET
Изменяет значение переменной пер на значение.

Чтобы посмотреть значение отдельной переменной, используется команда C-h v (describe-variable), которая считывает в минибуфере имя переменной с возможностью завершения. Эта команда печатает и значение переменной, и документацию по ней. Например,

C-h v fill-column RET

выведет примерно следующее:

fill-column's value is 75

Documentation:
*Column beyond which automatic line-wrapping should happen.
Automatically becomes buffer-local when set in any fashion.

Звездочка в начале описания показывает, что эта переменная является пользовательским параметром. C-h v не ограничивается только пользовательскими параметрами, она принимает имя любой переменной.

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

M-x set-variable RET fill-column RET 75 RET

устанавливает fill-column равной 75.

Действие M-x set-variable ограничено пользовательскими параметрами, но вы можете установить значение любой переменной с помощью выражения на языке Лисп, используя функцию setq. Вот выражение для установки значения переменной fill-column через setq:

(setq fill-column 75)

Чтобы выполнить выражение, подобное этому, переключитесь в буфер `*scratch*', наберите выражение и затем нажмите C-j. Смотрите раздел Буферы диалога с Лиспом.

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

Интерфейс для простой настройки

Удобный способ найти желаемые параметры и изменить их предоставляет команда M-x customize. Она создает буфер настройки, где вы можете просмотривать пользовательские параметры Emacs, представленные логически организованной структурой, редактировать их и устанавливать их значения. Вы также можете использовать буфер настройки для постоянного сохранения этих установок. (Пока в эту структуру включены не все пользовательские параметры Emacs, но мы добавляем оставшиеся.)

Группы настройки

В целях настройки пользовательские параметры собраны в группы, чтобы их было проще найти. Группы собраны в еще большие группы, и так до самой верхней группы, названной Emacs.

Команда M-x customize создает буфер настройки, который показывает группу верхнего уровня Emacs и группы, которые лежат на уровень ниже. Это выглядит примерно так, показана часть:

/- Emacs group: ---------------------------------------------------\
      [State]: visible group members are all at standard settings.
   Customization of the One True Editor.
   See also [Manual].

Editing group: [Go to Group] 
Basic text editing facilities.

External group: [Go to Group] 
Interfacing to external utilities.

еще группы второго уровня

\- Emacs group end ------------------------------------------------/

Это означает, что буфер показывает содержимое группы Emacs. Другие группы перечислены здесь, поскольку они являются ее содержимым. Но они перечислены иначе, без отступов и тире, потому что их содержимое сюда не включено. Каждая группа имеет однострочное описание; у группы Emacs также есть строка `[State]'.

Большинство текста в буфере настройки находится в режиме только для чтения, но обычно в него включено несколько редактируемых полей, которые вы можете изменять. Существуют также активные поля; это означает, что они делают что-то, когда вы активизируете их. Для активизации активного поля либо щелкните на нем кнопкой Mouse-1, или установите на нем точку и нажмите RET.

Например, фраза `[Go to Group]', появляющая в группе второго уровня, -- активное поле. Активизация поля `[Go to Group]' для группы создает новый буфер настройки, который показывает эту группу и ее содержимое. Это поле является чем-то вроде гиперссылки на другую группу.

Сама группа Emacs не включает ни одного пользовательского параметра, но они есть в других группах. Исследуя разные группы, вы в конце концов найдете нужные вам параметры и начертания. Затем вы можете использовать буфер настройки, чтобы установить их.

Вы можете просмотреть структуру групп настройки в укрупненном виде, используя команду M-x customize-browse. Эта команда создает особый вид буфера настройки, который показывает только имена групп (а также параметры и начертания) и их структуру.

В этом буфере вы можете просматривать содержимое группы, активизируя кнопку `[+]'. Когда показывается содержимое группы, эта кнопка меняется на `[-]'; активизация этой кнопки прячет содержимое группы.

Имя каждой группы, параметра или начертания в этом буфере имеет активное поле, в котором написано `[Group]', `[Option]' или `[Face]'. При активизации этого активного поля создается обычный буфер настройки, показывающий только эту группу с ее содержимым, или только этот параметр или только это начертание. Таким способом устанавливают значения.

Изменение параметра

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

Kill Ring Max: [Hide] 30
   [State]: this option is unchanged from its standard setting.
Maximum length of kill ring before oldest elements are thrown away.

Текст, следующий за `[Hide]', -- в нашем случае это `30' --- показывает текущее значение параметра. Если вместо `[Hide]' вы видите `[Show]', то это означает, что значение скрыто; буфер настройки сначала скрывает значения, которые занимают несколько строк. Нажмите на `[Show]', чтобы открыть значение.

Строка, следующая за именем параметра, показывает состояние настройки для данного параметра: в вышеприведенном примере, она сообщает, что вы еще не изменили этот параметр. Слово `[State]' в начале строки является активным; вы можете получить меню разных операций, нажав на ней Mouse-1 или RET. Эти операции являются существенными для настройки переменной.

Строка после строки `[State]' показывает начало описания данного параметра. Если документация занимает несколько строк, то эта строка оканчивается кнопкой `[More]'; вы можете выбрать ее для того, чтобы посмотреть более полное описание.

Для того чтобы ввести новое значение для `Kill Ring Max', переместите точку к значению и отредактируйте его как обычный текст. Например, вы можете набрать M-d и ввести затем другое число.

Когда вы начинаете редактировать текст, вы увидите, что строка `[State]' изменилась, сообщая, что вы поменяли значение:

[State]: you have edited the value as text, but not set the option.

Изменение значения в действительности не устанавливает значение переменной. Для этого вы должны установить данный параметр. Чтобы сделать это, активизируйте кнопку `[State]' и выберите `Set for Current Session'.

Когда вы установите параметр, его состояние визуально изменится:

[State]: you have set this option, but not saved it for future sessions.

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

При редактировании значения поля, которое является именем файла, каталога, команды или чем-нибудь еще, для чего определено завершение, вы можете нажимать M-TAB (widget-complete), чтобы произвести завершение.

Некоторые параметры имеют небольшой фиксированный набор возможных значений. Эти параметры не позволяют вам редактировать значения как текст. Вместо этого перед значением появляется активное поле `[Value Menu]'; активизируйте это поле для изменения значения. Для логического значения "вкл/выкл" активное поле показывает надпись `[Toggle]', и оно переключает это значение. `[Value Menu]' и `[Toggle]' изменяют буфер; изменения вступают в силу, когда вы используете операцию `Set for Current Session'.

Некоторые параметры имеют значения со сложной структурой. Например, значение переменной load-path является списком каталогов. Здесь показано, как оно изображается в буфере настройки:

Load Path:
[INS] [DEL] [Current dir?]: /usr/local/share/emacs/20.3/site-lisp
[INS] [DEL] [Current dir?]: /usr/local/share/emacs/site-lisp
[INS] [DEL] [Current dir?]: /usr/local/share/emacs/20.3/leim
[INS] [DEL] [Current dir?]: /usr/local/share/emacs/20.3/lisp
[INS] [DEL] [Current dir?]: /build/emacs/e20/lisp
[INS] [DEL] [Current dir?]: /build/emacs/e20/lisp/gnus
[INS]
   [State]: this item has been changed outside the customization buffer.
List of directories to search for files to load....

Каждый каталог в этом списке изображается на отдельной строке, а каждая строка имеет несколько редактируемых или активных полей.

Вы можете изменять любое из имен каталогов. Для того чтобы удалить каталог из списка, выберите кнопку `[DEL]' в его строке. Для того чтобы вставить в список новый каталог, выберите кнопку `[INS]' в той точке, куда вы хотите вставить имя.

Вы также можете выбрать поле `[Current dir?]', чтобы переключиться между включением в путь конкретного указанного каталога или значения nil. (nil в пути поиска означает "попробовать текущий каталог").

Две специальные команды, TAB и S-TAB, полезны для перемещения по буферу настройки. TAB (widget-forward) перемещает вперед на следующее активное или редактируемое поле; S-TAB (widget-backward) перемещает в обратном направлении на предыдущее активное или редактируемое поле.

Нажимая RET на редактируемом поле, вы также перемещаетесь на следующее поле, аналогично действию TAB. Причина этого заключается в том, что люди часто нажимают RET по завершении редактирования поля. Если вам понадобится вставить в редактируемое поле перевод строки, используйте C-o или C-q C-j.

Установка параметра изменяет его значение в текущем сеансе Emacs; сохранение значения изменяет его и для будущих сеансов. Это работает путем записи кода в ваш файл `~/.emacs', так что значения параметров будут устанавливаться каждый раз, когда вы запускаете Emacs. Для того чтобы сохранить параметр, активизируйте кнопку `[State]' и выберите операцию `Save for Future Sessions'.

Вы также можете восстановить стандартные значения параметров, активизируя кнопку `[State]' и выбирая операцию `Reset to Standard Settings'. В действительности существует три стандартных операции восстановления:

`Reset'
Если вы внесли некоторые изменения и не установили параметр, то эта операция восстанавливает текст буфера настройки, чтобы он соответствал текущему значению.
`Reset to Saved'
Эта операция восстанавливает значение параметра в последнее сохраненное значение и соответственно обновляет текст.
`Reset to Standard Settings'
Эта операция устанавливает параметр в его стандартное значение и соответственно обновляет текст. Эта операция также уничтожает любое сохраненное значение для данного параметра, так что в будущих сеансах работы с Emacs вы будете получать стандартное значение.

Состояние группы показывает, было ли что-нибудь в этой группе изменено, установлено или сохранено. Вы можете выбрать операции `Set for Current Session', `Save for Future Sessions' и различные виды операции `Reset' для данной группы; эти операции над группой применяются сразу ко всем настройкам в группе и ее подгруппах.

В начале буфера настройки находятся две строки, содержащие несколько активных полей:

 [Set for Current Session] [Save for Future Sessions]
 [Reset] [Reset to Saved] [Reset to Standard]   [Bury Buffer]

Активизация кнопки `[Bury Buffer]' скрывает буфер настройки. Каждое из остальных полей выполняет операции -- установку, сохранение или восстановление -- над каждым из пунктов в буфере, которые могут быть установлены, сохранены или восстановлены.

Настройка начертаний

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

Custom Changed Face: (sample)
   [State]: this face is unchanged from its standard setting.
Face used when the customize item has been changed.
Attributes: [ ] Bold: [toggle] off
            [X] Italic: [toggle] on
            [ ] Underline: [toggle] off
            [ ] Inverse-Video: [toggle] on
            [ ] Foreground: black (sample)
            [ ] Background: white (sample)
            [ ] Stipple:  

Каждый атрибут начертания располагается на отдельной строке. Поле `[x]' перед именем атрибута показывает, включен ли этот атрибут; знак `X' обозначает, что включен. Вы можете включать или выключать атрибут, выбирая данное поле. Когда атрибут включен, вы можете изменить его значение обычными способами.

На черно-белом дисплее вам доступны для использования в качестве фона следующие цвета: `black', `white', `gray', `gray1' и `gray3'. Emacs поддерживает эти оттенки серого, используя вместо цвета штрихование фона с помощью масок.

Установка, сохранение и сброс начертания работает точно также, как и с пользовательскими параметрами (смотрите раздел Изменение параметра).

Начертание может задавать разный вид для разных типов дисплеев. Например, начертание может сделать текст красным на цветном дисплее, а на монохромном отображать этот текст жирным шрифтом. Для того чтобы указать разный вид для данного начертания, выберите пункт `Show Display Types' из меню, которое появляется при выборе кнопки `[State]'.

Другой, более общий способ установить атрибуты заданного начертания --- использовать команду M-x modify-face. Эта команда считывает имя начертания и атрибуты, один за другим. Для атрибутов, задающих цвета и маски, текущим значением атрибута будет значение по умолчанию -- просто нажмите RET, если вы не хотите изменять этот атрибут. Наберите `none' в том случае, когда вы хотите очистить данный атрибут.

Настройка отдельных пунктов

Вместо того чтобы находить параметр, который вы хотите изменить, перемещаясь сквозь дерево групп, вы можете указать, какой конкретно параметр, начертание или группу вы хотите настроить.

M-x customize-option RET параметр RET
Создать буфер настройки только для одного параметра.
M-x customize-face RET начертание RET
Создать буфер настройки только для одного начертания.
M-x customize-group RET группа RET
Создать буфер настройки только для одной группы.
M-x customize-apropos RET regexp RET
Создать буфер настройки для всех параметров, начертаний и групп, которые соответствуют regexp.
M-x customize-changed-options RET версия RET
Создать буфер настройки для всех параметров, начертаний и групп, чей смысл изменился начиная с указанной версии Emacs.
M-x customize-saved
Создать буфер настройки, содержащий все параметры и начертания, которые вы сохранили с помощью буферов настройки.
M-x customize-customized
Создать буфер настройки, содержащий все параметры и начертания, которые вы изменили, но не сохранили.

Если вы хотите изменить конкретный пользовательский параметр с помощью буфера настройки, и вы знаете его имя, то вы можете использовать команду M-x customize-option и указать имя этого параметра. Это создает буфер настройки только для одного параметра -- для того, который вы запросили. Изменение, установка и сохранение значения работает точно так же, как описано выше, но только для указанного параметра.

Таким же образом вы можете изменить параметры конкретного начертания, выбранного по имени. Для этого используйте команду M-x customize-face.

Вы также можете создать буфер настройки для отдельной группы, используя команду M-x customize-group. В этом буфере появится непосредственное содержимое выбранной группы, в том числе переменные-параметры, начертания и другие группы. Однако содержимое подгрупп изначально будет скрыто. Вы можете просмотреть их содержимое обычным способом, выбрав кнопку `[Show]'.

Для более точного указания того, что вы хотите настроить, вы можете использовать команду M-x customize-apropos. В качестве аргумента вы указываете регулярное выражение; затем в созданном буфере настройки отображаются все параметры, начертания и группы, чьи имена удовлетворяют этому регулярного выражению. Если вы укажете пустое регулярное выражение, то буфер настройки будет включать все группы, параметры и начертания (но это займет длительное время).

Когда вы устанавливаете новую версию Emacs, вы можете захотеть настроить новые параметры, а также те параметры, чей смысл или значения по умолчанию были изменены. Чтобы сделать это, воспользуйтесь командой M-x customize-changed-options и укажите в минибуфере номер предыдущей версии Emacs. Эта команда создаст буфер настройки, который покажет вам все параметры (и группы), чье определение изменилось по сравнению с указанной версией.

Если вы изменили значения параметров и затем решили, что сделали это по ошибке, то у вас есть две специальные команды для того, чтобы пересмотреть предыдущие изменения. Используйте команду customize-saved, чтобы посмотреть на параметры и начертания, которые вы уже сохранили. А команду M-x customize-customized используйте для того, чтобы посмотреть на параметры и начертания, которые вы установили, но еще не сохранили.

Ловушки

Ловушки -- это важный механизм настройки Emacs. Ловушкой называют лисповскую переменную, содержащую список функций, которые вызываются в некоторой определенной ситуации. (Это называется запуском ловушки.) Отдельные функции в этом списке называются функциями этой ловушки. За редкими исключениями, сразу после запуска ловушки в Emacs пустые, так что все функции в любой ловушке --- это явно помещенные туда вами для настройки.

Большинство основных режимов запускают на последнем этапе инициализации одну или более ловушек режима. Это облегчает настройку поведения режима путем перекрытия локальных переменных, значения которых уже были присвоены данным режимом. Но ловушки также используются в других контекстах. Например, ловушка suspend-hook запускается непосредственно перед тем, как Emacs приостанавливает свою работу смотрите раздел Выход из Emacs).

Большинство ловушек в Emacs являются нормальными ловушками. Это означает, что запуск такой ловушки действует путем безусловного вызова всех ее функций без аргументов. Мы старались сохранить большую часть ловушек нормальными, чтобы вы могли использовать их одним и тем же способом. Каждая переменная в Emacs, чье имя оканчивается на `-hook', является нормальной ловушкой.

Также есть несколько аномальных ловушек. Имена этих переменных оканчиваются на `-hooks' или `-functions', а не на `-hook'. Аномальность этих ловушек заключается в том, что их функции вызываются с какой-то особенностью -- возможно, им передаются аргументы, а может возвращаемое ими значение как-то используется. Например, find-file-not-found-hooks (смотрите раздел Обращение к файлам) --- аномальная ловушка, потому что как только одна из ее функций возвращает отличное от nil значение, остальные функции не вызываются совсем. В документации на каждую аномальную ловушку подробно описано, в чем состоит ее особенность.

Для добавления функции к ловушке (как нормальной, так и аномальной) рекомендуется вызывать функцию add-hook. Вы можете использовать любую правильную функцию языка Лисп как функцию ловушки, при условии, что она может обработать правильное число аргументов (нуль в случае нормальной ловушки). Конечно, не всякая лисповская функция полезна в каждой конкретной ловушке.

Например, вот как установить ловушку для включения режима Auto Fill при входе в режим Text и в другие режимы, основанные на режиме Text:

(add-hook 'text-mode-hook 'turn-on-auto-fill)

Следующий пример показывает, как использовать ловушки для настройки отступов в программах на Си. (Люди часто отдают строгое предпочтение одному формату по сравнению с другим). Приводимая здесь функция ловушки является анонимным лямбда-выражением.

(setq my-c-style
  '((c-comment-only-line-offset . 4)
    (c-cleanup-list . (scope-operator
                       empty-defun-braces
                       defun-close-semi))
    (c-offsets-alist . ((arglist-close . c-lineup-arglist)
                        (substatement-open . 0)))))

(add-hook 'c-mode-common-hook
  (function (lambda ()
    (c-add-style "my-style" my-c-style t))))

Лучше всего проектировать функции ловушек таким образом, чтобы порядок выполнения не играл роли. Создавать любую зависимость от порядка вызова --- "напрашиваться на проблемы". Однако, порядок предсказуем: функции, добавленные последними, выполняются первыми.

Локальные переменные

M-x make-local-variable RET пер RET
Сделать переменную пер локальной в текущем буфере.
M-x kill-local-variable RET пер RET
Сделать так, что переменная пер использовала в текущем буфере свое глобальное значение.
M-x make-variable-buffer-local RET пер RET
Пометить переменную пер так, чтобы ее установка делала ее локальной для текущего в тот момент буфера.

Почти любая переменная может быть сдалана в локальной для определенного буфера Emacs. Это означает, что ее значение в этом буфере не зависит от ее значения в других буферах. Несколько переменных всегда являются локальными в каждом буфере. Любая другая переменная Emacs имеет глобальное значение, которое действует во всех буферах, в которых эта переменная не сделана локальной.

Команда M-x make-local-variable считывает имя переменной и делает ее локальной для данного буфера. Будущие изменения в данном буфере не затронут другие буферы, а будущие изменения глобального значения не затронут значения для данного буфера.

M-x make-variable-buffer-local считывает имя переменной и изменяет будущее ее поведение таким образом, что при установке она автоматически становится локальной. Точнее, если переменная помечается таким способом, то обычные способы установки переменной сначала будут автоматически выполнять make-local-variable. Такие переменные мы называем переменными буфера.

Основные режимы (смотрите раздел Основные режимы) всегда делают переменные локальными для буфера до их установки. Поэтому изменение основного режима в одном буфере не влияет на другие буферы. Второстепенные режимы также работают путем установки переменных -- обычно каждый второстепенный режим имеет одну управляющую переменную, которая отлична от nil, когда данный режим включен (смотрите раздел Второстепенные режимы). Для большинства второстепенных режимов управляющая переменная является переменной буфера.

Emacs содержит некоторое количество переменных, которые всегда являются переменными буфера. Сюда включаются abbrev-mode, auto-fill-function, case-fold-search, comment-column, ctl-arrow, fill-column, fill-prefix, indent-tabs-mode, left-margin, mode-line-format, overwrite-mode, selective-display-ellipses, selective-display, tab-width и truncate-lines. Некоторые другие переменные также всегда являются локальными для текущего буфера, но они используются для внутренних целей.

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

Команда M-x kill-local-variable считывает из минибуфера имя переменной и прекращает ее существование как локальной для текущего буфера. С этого момента в этом буфере начинает действовать глобальное значение переменной. Установка основного режима уничтожает все локальные переменные буфера за исключением нескольких, специально отмеченных как постоянно локальные.

Для установки глобального значения переменной, независимо от того, имеет ли она локальное значение в текущем буфере, можно использовать функцию Лиспа setq-default. Она работает аналогично setq, но устанавливает глобальные значения переменных, а не локальные (если они есть). Если в текущем буфере действительно существует локальное значение, то новое глобальное значение может быть невидимо до тех пор, пока вы не переключитесь в другой буфер. Вот пример:

(setq-default fill-column 75)

setq-default -- это единственный способ установки глобального значения переменной, которая была помечена функцией make-variable-buffer-local.

Программы на Лиспе могут посмотреть на значение некоторой переменной по умолчанию с помощью функции default-value. Эта функция принимает в качестве аргумента символ и возвращает его значение по умолчанию. Аргумент вычисляется; обычно вы должны явно поставить перед ним кавычку. Например, вот как можно получить значение по умолчанию для переменной fill-column:

(default-value 'fill-column)

Локальные переменные в файлах

Файл может указывать список значений локальных переменных, которые должны использоваться при редактировании этого файла в Emacs. Обращение к файлу проверяет список локальных переменных, при этом каждая из этих переменных делается локальной для буфера, и для нее устанавливается значение, указанное в файле.

Есть два способа указания локальных переменных: в первой строке или с помощью списка локальных переменных. Здесь мы покажем, как задать переменные в первой строке:

-*- mode: имя-режима; пер: значение; ... -*-

Таким способом вы можете написать любое количество пар переменная/значение, каждая пара разделяется двоеточием и точкой с запятой, как показано выше. mode: имя-режима; задает основной режим; эта пара должна быть первой в строке. Значения не вычисляются, а используются буквально. Вот пример, который задает режим Lisp и устанавливает две переменные с числовыми значениями:

;; -*-mode: Lisp; fill-column: 75; comment-column: 50; -*-

Этим способом вы можете также указать систему кодирования для данного файла: просто задайте значение для "переменной" с именем coding. Значением должно быть имя системы кодирования, которое Emacs может распознать. Смотрите раздел Системы кодирования.

Список локальных переменных находится в конце файла, на последней странице. (Часто бывает лучше всего поместить его на отдельную страницу.) Список локальных переменных начинается со строки, содержащей `Local Variables:', и оканчивается строкой, содержащей `End:'. Между ними идут имена переменных и их значения, по одному на строке, в виде `переменная: значение'. Значения не вычисляются, они используются буквально. Если в файле используются и список локальных переменных, и строка `-*-', то Emacs обрабатывает сначала все в строке `-*-', а затем все в списке локальных переменных.

Вот пример списка локальных переменных:

;;; Local Variables: ***
;;; mode:lisp ***
;;; comment-column:0 ***
;;; comment-start: ";;; "  ***
;;; comment-end:"***" ***
;;; End: ***

Как вы видите, каждая строка начинается с префикса `;;; ' и заканчивается суффиксом ` ***'. Emacs распознает их как префикс и суффикс, основываясь на первой строке списка, так как они окружают магическую строку `Local Variables:'; затем они автоматически исключаются из остальных строк списка.

Обычно префиксы и/или суффиксы используются для встраивания списка локальных переменных в комментарии, чтобы он не смущал другие программы, на вход которым подается этот файл. Пример выше написан для языка, где комментарий начинается с `;;; ' и заканчивается на `***'; значения локальных переменных comment-start и comment-end настраивают Emacs на понимание этого необычного синтаксиса. Не используйте префикс или суффикс, если они вам не нужны.

Два "имени переменных" имеют особый смысл в списке локальных переменных: значение для переменной mode в действительности устанавливает основной режим, а значение для переменной eval просто вычисляется как выражение, а его значение игнорируется. mode и eval не являются настоящими переменными; установка переменных с именами mode и eval в любом другом контексте не имеет особого смысла. Если mode используется для установки основного режима, то она должна быть первой "переменной" в списке.

Вы можете использовать "переменную" mode для установки второстепенных режимов точно так же, как и основных режимов; в действительности, вы можете использовать ее несколько раз, сначала для установки основного режима, а затем для установки второстепенных режимов, которые будет действовать для выбранного буфера. Но большинство второстепенных режимов не стоит никак указывать в файле, поскольку они представляют предпочтения пользователя.

Например, у вас можете появиться искушение включить режим Auto Fill с помощью списка локальных переменных. Это будет ошибкой. Использовать режим Auto Fill или нет -- это дело личного вкуса, а не свойство содержимого файла. Если вы хотите использовать режим Auto Fill, то установите ловушки основных режимов в вашем файле `.emacs', чтобы он включался (когда нужно) только для вас (смотрите раздел Файл инициализации, `~/.emacs'). Не используйте список локальных переменных для навязывания вашего вкуса всем остальным.

Список локальных переменных должен начинаться не далее, чем за 3000 знаков от конца файла, и он должно находиться на последней странице, если файл поделен на страницы. Иначе Emacs не заметит его там. Цель этого в том, чтобы случайная `Local Variable:', появившаяся не на последней странице, не путала Emacs, и чтобы при обращении к длинному файлу, который полностью является одной страницей и не имеет списка локальных переменных, не тратилось время на просмотр всего файла.

Используйте команду normal-mode для переустановки локальных переменных и основного режима данного буфера соответственно имени файла и его содержимого, включая списки локальных переменных, если они есть. Смотрите раздел Как выбираются основные режимы.

Переменная enable-local-variables говорит, нужно ли обрабатывать локальные переменные в файлах, и таким образом дает вам шанс перекрыть их. По умолчанию ее значение равно t, что означает обработку локальных переменных в файлах. Если вы установите значение переменной равным nil, то Emacs просто будет игнорировать локальные переменные в файлах. Любое другое значение велит делать запрос у пользователя о каждом файле, в котором имеются локальные переменные, показывая определения локальных переменных, чтобы вы могли принять решение.

"Переменная" eval и некоторые настоящие переменные создают некий риск; когда вы обращаетесь к чужим файлам, определения локальных переменных для них могут произвольно воздействовать на ваш Emacs. Поэтому параметр enable-local-eval контролирует, будет ли Emacs обрабатывать переменные eval, а так же переменные, чьи имена оканчиваются на `-hook', `-hooks', `-function' или `-functions', а также некоторые другие переменные. Существует три возможных значения для данного параметра: t, nil и что-нибудь другое, точно так же, как и для enable-local-variables. Значением по умолчанию является maybe, это не t и не nil, так что обычно Emacs спросит подтверждение об установке этих переменных.

Клавиатурные макросы

Клавиатурный макрос -- это определенная пользователем команда, обозначающая другую последовательность ключей. Например, если вы обнаружили, что вам нужно набрать C-n C-d сорок раз, то вы можете ускорить работу, определив клавиатурный макрос для C-n C-d и вызвав его со счетчиком повторений 40.

C-x (
Начать определение клавиатурного макроса (start-kbd-macro).
C-x )
Закончить определение клавиатурного макроса (end-kbd-macro).
C-x e
Выполнить самый последний клавиатурный макрос (call-last-kbd-macro).
C-u C-x (
Заново выполнить последний клавиатурный макрос и затем добавить дополнительные ключи к его определению.
C-x q
Когда достигается эта точка при выполнении макроса, сделать запрос о подтверждении (kbd-macro-query).
M-x name-last-kbd-macro
Задать имя команды (на время текущего сеанса) для последнего определенного клавиатурного макроса.
M-x insert-kbd-macro
Вставить в буфер определение клавиатурного макроса как код на Лиспе.
C-x C-k
Отредактировать ранее определенный клавиатурный макрос (edit-kbd-macro).
M-x apply-macro-to-region-lines
Запустить последний клавиатурный макрос на каждой полной строке в области.

Клавиатурные макросы отличаются от обычных команд Emacs тем, что они написаны на командном языке Emacs, а не на Лиспе. Это облегчает их написание для новичков и делает их более удобными в качестве временных хаков. Однако, мощности командного языка Emacs как языка программирования недостаточно, чтобы он был удобным для написания чего-либо умного или универсального. Для таких вещей надо использовать Лисп.

Вы определяете клавиатурные макросы во время выполнения команд, являющихся определением. Говоря другими словами, во время определения клавиатурного макроса его определение выполняется в первый раз. Таким образом, вы можете видеть, каково действие ваших команд, так что вы не должны просчитывать его в уме. Когда вы кончили, макрос клавиатуры определен, а также один раз фактически выполнен. После этого вы можете снова и снова выполнять все целиком, вызывая макрос.

Основы использования

Для начала определения клавиатурного макроса наберите команду C-x ( (start-kbd-macro). Начиная с этого момента ваши нажатия на клавиши по-прежнему выполняются, но также становятся частью определения макроса. В строке режима появляется слово `Def', чтобы напомнить вам о том, что происходит. Когда вы закончите, команда C-x ) (end-kbd-macro) закончит определение макроса (но не станет его частью!). Например,

C-x ( M-f foo C-x )

определяет макрос для перемещения вперед на слово и вставки `foo'.

Определенный таким образом макрос может запускаться снова с помощью команды C-x e (call-last-kbd-macro), в качестве числового аргумента которой можно задать счетчик повторов для многократного выполнения макроса. Команде C-x ) также можно задать счетчик повторов в качестве аргумента, в этом случае именно столько раз она повторяет макрос сразу после его определения, но само определение макроса засчитывается как первое повторение (так как оно выполняется в то время, как вы его определяете). Таким образом, C-x ) с аргументом 4 приводит к непосредственному выполнению макроса еще 3 раза. Аргумент 0 для C-x e или C-x ) означает повторение макроса бесконечное число раз (пока он не получит ошибку, или вы не наберете C-g или, в MS-DOS, C-BREAK).

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

После того как вы завершили определение макроса, вы можете добавить что-либо в его конец, набрав C-u C-x ). Это эквивалентно обычной C-x (, за которой следует повторный набор всего имевшегося до сих пор определения. Как следствие этого, она повторно выполнит макрос, как было определено ранее.

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

Одна из вещей, которая не всегда правильно работает в клавиатурных макросах, -- это команда C-M-c (exit-recursive-edit). Когда эта команда выводит из рекурсивного редактирования, которое было начато внутри макроса, то она работает так, как вы ожидали. Но если вы выходите из рекурсивного редактирования, которое было начато до того, как вы запустили клавиатурный макрос, то также происходит выход из клавиатурного макроса как из части этого процесса.

Вы можете отредактировать уже существующий клавиатурный макрос, используя C-x C-k (edit-kbd-macro). Затем вы должны ввести то, что вы будете использовать для вызова макроса -- C-x e или M-x имя или какую-то другую последовательность ключей. Это форматирует определение макроса в буфере и входит в специальный основной режим для его редактирования. Наберите в этом буфере C-h m, чтобы получить подробности о редактировании макроса. Когда вы закончите редактирование, нажмите C-c C-c.

Команда M-x apply-macro-to-region-lines повторяет последний определенный клавиатурный макрос для каждой полной строки внутри текущей области. Она делает это строка за строкой, перемещая точку в начало строки и выполняя затем макрос.

Именование и сохранение клавиатурных макросов

Если вы хотите сохранить макрос клавиатуры дольше, чем до следующего определения, то вы должны дать ему имя, используя M-x name-last-kbd-macro. Эта команда считывает имя как аргумент, используя минибуфер, и определяет это имя для выполнения макроса. Имя макроса --- это лисповский символ, а определение его таким способом делает его допустимым именем команды для вызова при помощи M-x или для привязывания ключа с помощью global-set-key (смотрите раздел Таблицы ключей). Если вы укажете имя, уже имеющее определение, отличное от макроса клавиатуры, то печатается сообщение об ошибке, и ничего не изменяется.

Когда макрос получает имя команды, вы можете записать его определение в файл. Потом его можно будет использовать в другом сеансе редактирования. Сначала обратитесь к файлу, в котором хотите записать определение. Затем используйте эту команду:

M-x insert-kbd-macro RET имя-макро RET

Это вставляет Лисп-код, который, будучи выполнен позднее, определит тот же самый макрос с тем же самым определением, которое он имеет сейчас. (Чтобы сделать это, вам не нужно разбираться в Лисп-коде, так как insert-kbd-macro напишет его за вас.) Затем сохраните файл. Позже вы можете загрузить этот файл с помощью load-file (смотрите раздел Библиотеки Лисп-программ для Emacs). Если файл, в который вы записываете, является вашим файлом инициализации `~/.emacs' (смотрите раздел Файл инициализации, `~/.emacs'), то макрос будет определяться каждый раз, когда вы запускаете Emacs.

Если вы зададите команде insert-kbd-macro числовой аргумент, то она создаст дополнительный Лисп-код для записи ключей (если они есть), которые вы привязали к макросу клавиатуры; таким образом, когда вы загрузите файл, макрос будут вновь привязан к тем же самым ключам.

Выполнение макроса с вариациями

Используя C-x q (kbd-macro-query), вы можете достигнуть эффекта, сходного с действием query-replace, когда макрос каждый раз запрашивает у вас, должен ли он производить изменения. Во время определения макроса наберите C-x q в той точке, где вы хотите получать запрос. При определении макроса эта команда ничего не делает, но когда вы запускаете макрос, то C-x q произведет интерактивный запрос о продолжении действий.

Правильными ответами на запрос от C-x q являются SPC (или y), DEL (или n), RET (или q), C-l и C-r. Ответы те же самые, что и для query-replace, хотя не все варианты ответа для query-replace имеют смысл.

Эти ответы включают SPC для продолжения, а DEL для пропуска остатка этого повторения макроса и начала нового повторения макроса. RET означает пропуск остатка данного повторения и отмены остальных повторений. C-l перерисовывает экран и снова делает запрос.

C-r входит на уровень рекурсивного редактирования, где вы можете выполнить редактирование, которое не является частью макроса. Когда вы выйдете из рекурсивного редактирования с помощью C-M-c, у вас снова спросят о том, как продолжать выполнение клавиатурного макроса. Если тогда вы нажмете SPC, то будет выполнен остаток макроса.

C-u C-x q, то есть C-x q с числовым аргументом, осуществляет совершенно другую функцию. Она входит в рекурсивное редактирование, считывая ввод с клавиатуры, и когда вы набираете его во время определения макроса, и когда он выполняется из макроса. Во время определения, редактирование, которое вы делаете внутри рекурсивного редактирования, не становится частью макроса. Во время выполнения макроса рекурсивное редактирование дает вам возможность выполнить какое-либо особенное редактирование в каждом повторении. Смотрите раздел Уровни рекурсивного редактирования.

Другой способ изменить поведение клавиатурного макроса -- использовать в качестве счетчика регистр, увеличивая его при каждом повторе макроса. Смотрите раздел Хранение чисел в регистрах.

Настройка привязок ключей

Этот раздел описывает привязки ключей, которые отображают ключи в команды, и таблицы ключей, которые сохраняют привязки. Здесь также объясняется, как изменять привязки ключей для своих нужд.

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

Таблицы ключей

Привязки между последовательностями ключей и функциями-командами сохраняются в структурах данных, называемых таблицами ключей. В Emacs много таких таблиц, каждая из которых используется в особых случаях.

Напомним, что последовательность ключей (или коротко, ключ) --- это последовательность событий ввода, которая имеет смысл как одно целое. События ввода включают в себя знаки, функциональные клавиши и кнопки мыши -- все виды ввода, какие вы можете послать компьютеру с вашего терминала. Последовательность ключей получает свой смысл из привязки, которая говорит, какую команду данный ключ запускает. Назначение таблиц ключей состоит в сохранении этих привязок.

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

Например, самовставляющийся знак, такой как g, является самовставляющимся, потому что глобальная таблица ключей привязывает его к команде self-insert-command. Стандартные знаки редактирования в Emacs, такие как C-a, также получают свой стандартный смысл из глобальной таблицы ключей. Команды для перепривязки ключей, такие как M-x global-set-key, на самом деле работают путем сохранения новой привязки в соответствующем месте глобальной таблицы ключей. Смотрите раздел Интерактивное изменение привязок ключей.

Meta-знаки работают по другому; Emacs транслирует каждый Meta-знак в пары знаков, начинающиеся с ESC. Когда вы набираете знак M-a, Emacs заменяет ее на ESC a. Meta-клавиша приходит как одиночное событие ввода, но для целей привязки ключей становится двумя событиями. Это происходит по историческим причинам, и мы можем когда-нибудь это изменить.

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

На многих терминалах нажатие на функциональную клавишу в действительности посылает компьютеру последовательность знаков; точная информация о том, что это за последовательность, зависит от самой функциональной клавиши и от того, какую модель терминала вы используете. (Часто такая последовательность начинается с ESC [.) Если Emacs понимает ваш тип терминала правильно, то он распознает последовательности знаков, формирующие функциональные клавиши, в каком бы месте последовательности ключей они не встречались (не только в начале). Таким образом, для большинства целей вы можете считать, что функциональные клавиши достигают Emacs непосредственно, и игнорировать их кодирование как последовательность знаков.

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

Таблица ключей записывает определения для одиночных событий. Для интерпретации последовательности ключей, состоящей из нескольких событий, нужна цепочка таблиц ключей. Первая таблица дает определение первого события; это определение является другой таблицей ключей, которая используется для поиска второго события в последовательности, и так далее.

Последовательность ключей может содержать нажатия на функциональные и знаковые клавиши. Например, C-x SELECT имеет смысл. Если вы сделаете клавишу SELECT префиксным ключом, то SELECT C-n тоже будет иметь смысл. Вы даже можете смешивать события от мыши с событиями от клавиатуры, но мы не рекомендуем делать так, потому что такие последовательности неудобно набирать.

Как пользователь вы можете перепривязать любой ключ; но будет лучше, если вы всегда будете использовать последовательности ключей, состоящие из C-c, за которым следует буква. Эти клавиши "зарезервированы для пользователей", так что они не будут конфликтовать ни с одним правильно спроектированным расширением Emacs. Функциональные клавиши от F5 до F9 также зарезервированы для пользователей. Если вы перепривязываете какой-то другой ключ, ваше определение может быть перекрыто некоторыми расширениями или основными режимами, которые переопределяют тот же самый ключ.

Таблицы префиксных ключей

Префиксный ключ, такой как C-x или ESC, имеют собственную таблицу ключей, которая хранит определения для событий, непосредственно следующих за этим префиксом.

Определение префиксного ключа -- это обычно таблица ключей, в которой ищется следующее событие. Это определение также может быть лисповским символом, чье определение функции является следующей таблицей ключей; результат этого тот же самый, но он предоставляет для префиксного ключа командное имя, которое может быть использовано как описание того, для чего предназначен этот префиксный ключ. Таким образом, привязка C-x -- это символ Ctl-X-Prefix, чье определение функции является таблицей ключей для команд на C-x. Определения C-c, C-x, C-h и ESC как префиксных ключей появляются в глобальной таблице, так что эти префиксные ключи доступны всегда.

Помимо обычных префиксных ключей существуют фиктивные "префиксные ключи", которые представляют полоску меню; смотрите раздел `Menu Bar' в The Emacs Lisp Reference Manual, для дополнительной информации о привязках ключей полоски меню. События от кнопок мыши, которые запускают всплывающие меню, также являются префиксными ключами; смотрите раздел `Menu Keymaps' в The Emacs Lisp Reference Manual, для дополнительной информации.

Некоторые таблицы префиксных ключей хранятся в именованных переменных:

  • ctl-x-map -- это имя переменной для таблицы, используемой для знаков, следующих за C-x.
  • help-map для знаков, следующих за C-h.
  • esc-map для знаков, следующих за ESC. Таким образом, все Meta-знаки в действительности определяются этой таблицей.
  • ctl-x-4-map для знаков, следующих за C-x 4.
  • mode-specific-map для знаков, следующих за C-c.

Локальные таблицы ключей

До сих пор мы объясняли принципы работы глобальной таблицы. Основные режимы настраивают Emacs, предоставляя собственные привязки ключей в локальных таблицах ключей. Например, режим C переопределяет TAB для создания отступа текущей строки кода на Си. Куски текста в буфере могут указывать свои собственные таблицы ключей взамен таблицы основного режима этого буфера.

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

Локальные таблицы ключей для режима Lisp и некоторых других основных режимов всегда существуют, даже когда не используются. Они хранятся в переменных с именами lisp-mode-map и так далее. Для менее часто используемых основных режимов локальная таблица ключей обычно создается при первом использовании в сеансе. Это сберегает ресурсы. Если вы хотите изменить одну из этих таблиц ключей, то вы должны использовать ловушку режима -- смотрите ниже.

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

Локальная таблица ключей может локально переопределять ключ как префиксный, определяя его как префиксную таблицу ключей. Если этот ключ определен как префикс и в глобальной таблице, то его локальное и глобальное определения (из обоих таблиц ключей) эффективно комбинируется: обе они используются для поиска события, которое следует за префиксным ключом. Таким образом, если локальная таблица ключей определяет C-c как еще одну таблицу ключей, а эта таблица определяет C-z как команду, то это придает локальный смысл для C-c C-z. Это не затрагивает другие последовательности, которые начинаются с C-c; если у этих последовательностей нет собственной локальной привязки, то продолжают действовать глобальные привязки.

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

Для изменения локальных привязок основного режима вы должны изменить локальную таблицу ключей этого режима. Обычно вы должны дождаться первого использования режима, поскольку до того момента большинство режимов не создают свои таблицы ключей. Если вы хотите указать что-нибудь в вашем файле `~/.emacs' для изменения привязок основного режима, то вы должны использовать ловушку этого режима, чтобы задержать изменения до его первого использования.

Например, команда texinfo-mode для выбора режима Texinfo запускает ловушку texinfo-mode-hook. Продемонстрируем, как можно использовать эту ловушку для добавления локальных привязок (мы признаем, не слишком полезной) для клавиш C-c n и C-c p в режиме Texinfo:

(add-hook 'texinfo-mode-hook
          '(lambda ()
             (define-key texinfo-mode-map
                         "\C-cp"
                         'backward-paragraph)
             (define-key texinfo-mode-map
                         "\C-cn"
                         'forward-paragraph)
             ))

Смотрите раздел Ловушки.

Таблицы ключей минибуфера

Минибуфер имеет свой собственный набор локальных таблиц ключей; они содержат разные команды завершения и выхода.

  • minibuffer-local-map используется для обыкновенного ввода (без завершения).
  • minibuffer-local-ns-map похожа, но SPC выходит, точно так же, как RET. Это используется главным образом для совместимости с Mocklisp.
  • minibuffer-local-completion-map для свободного завершения.
  • minibuffer-local-must-match-map для строгого и осторожного завершения.

Интерактивное изменение привязок ключей

Чтобы переопределить ключ в Emacs, надо изменить ее запись в таблице ключей. Вы можете изменить глобальную таблицу ключей, тогда изменение подействует на все основные режимы (за исключением тех, в которых есть свои локальные, перекрывающие определения для того же самого ключа). Или вы можете изменить локальную таблицу ключей текущего буфера, что затронет все буферы, использующие тот же самый основной режим.

M-x global-set-key RET ключ кмд RET
Глобально определяет ключ для запуска команды кмд.
M-x local-set-key RET ключ кмд RET
Локально определяет ключ (в текущем основном режиме) для запуска команды кмд.
M-x global-unset-key RET ключ
Делает ключ неопределенным в глобальной таблице ключей.
M-x local-unset-key RET ключ
Делает ключ неопределенным в локальной таблице ключей (в текущем основном режиме).

Допустим например, что вы хотите выполнять команды в подоболочке внутри буфера Emacs, а не приостанавливать Emacs и выполнять команды в вашей входной оболочке. Обычно C-z привязан к функции suspend-emacs (когда не используется система X Windows), но вы можете изменить C-z на запуск интерактивной подоболочки внутри Emacs, привязав ее к команде shell, как показано:

M-x global-set-key RET C-z shell RET

global-set-key считывает имя команды после клавиши. После того как вы нажмете клавишу, появится примерно такое сообщение, так что вы сможете убедиться, что назначаете ту клавишу, которую хотите:

Set key C-z to command: 

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

Вы можете перепривязать ключ, который содержит больше одного события, тем же самым способом. Emacs продолжает считывать ключ для перепривязки до тех пор, пока он не станет полным ключом (то есть непрефиксным). Таким образом, если вы нажмете C-f как ключ, то на этом все закончится; вы сразу попадете в минибуфер для считывания команды кмд. Но если вы нажмете C-x, считывается еще один знак; если это 4, считывается еще один, и так далее. Например,

M-x global-set-key RET C-x 4 $ spell-other-window RET

переопределяет C-x 4 $ для запуска команды (фиктивной) spell-other-window.

Двухзнаковые ключи, состоящие из C-c и буквы, зарезервированы для пользовательской настройки. Предполагается, что программы на Лиспе не определяют эти ключи, так что ваши привязки для них будут доступны во всех основных режимах и не будут ничему мешать.

Вы можете убрать глобальное определение ключа с помощью команды global-unset-key. Это делает ключ неопределенным; если вы наберете его, Emacs просто подаст звуковой сигнал. Сходным образом local-unset-key делает ключ неопределенным в таблице ключей текущего основного режима, и в этом основном режиме вступает в действие определение (или отсутствия определения) из глобальной таблицы ключей.

Если вы переопределили (или сделали неопределенным) какой-то ключ и затем хотите отказаться от изменения, то отмена определения не будет работать -- вам необходимо переопределить ключ, используя стандартное определение. Чтобы найти имя стандартного определения ключа, перейдите в буфер с режимом Fundamental и примените C-h c. Описания ключей в данном руководстве также сообщают имена соответсвующих команд.

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

Перепривязка ключей в файле инициализации

Если у вас есть набор привязок ключей, которые вы хотите использовать всегда, вы можете указать их в вашем файле `.emacs', используя синтаксис Лиспа.

Простейший способ работает только со знаками ASCII и их Meta-вариантами. Этот метод использует для представления перепривязываемой последовательности ключей строку. Например, как привязать C-z к команде shell:

(global-set-key "\C-z" 'shell)

Этот пример использует строковую константу, содержащую один знак, C-z. Одинарная кавычка перед именем команды, shell, отмечает ее как константный символ, а не как переменную. Если вы опустите кавычку, Emacs попытается сразу вычислить shell как переменную. Это вероятно вызовет ошибку; это явно не то, что вы хотите.

Вот другой пример, который привязывает последовательность ключей из двух знаков:

(global-set-key "\C-xl" 'make-symbolic-link)

Когда последовательность ключей включает в себя функциональные клавиши, или события от кнопок мыши или не входящие в ASCII знаки, такие как C-= или H-a, вы должны использовать более общий метод перепривязки, в котором для указания последовательности ключей используется вектор.

Для того чтобы записать вектор в Emacs Lisp, необходимо заключить элементы вектора в квадратные скобки. Для разделения элементов используйте пробелы. Если элемент является символом, то просто напишите имя символа -- никаких других разделителей или пунктуации не нужно. Если элемент вектора является знаком, то пишите его как знаковую константу Лиспа: `?', за которым следует сам знак в том виде, как он появился бы в строке.

Вот примеры использования векторов для перепривязки C-= (управляющий знак, не входящий в ASCII), H-a (Hyper-знак; в ASCII вообще нет Hyper); F7 (функциональная клавиша) и C-Mouse-1 (модифицированная с клавиатуры кнопка мыши):

(global-set-key [?\C-=] 'make-symbolic-link)
(global-set-key [?\H-a] 'make-symbolic-link)
(global-set-key [f7] 'make-symbolic-link)
(global-set-key [C-mouse-1] 'make-symbolic-link)

Вы также можете использовать вектор и для простых случаев. Вот как можно переписать первые два примера, приведенные выше, с использованием векторов:

(global-set-key [?\C-z] 'shell)

(global-set-key [?\C-x ?l] 'make-symbolic-link)

Перепривязка функциональных клавиш

Последовательности ключей могут содержать функциональные клавиши, как и обычные знаки. Так же, как лисповские знаки (на самом деле целые числа) представляют знаки клавиатуры, лисповские символы представляют функциональные клавиши. Если на функциональной клавиша надписано слово, то это слово также будет именем соответствующего лисповского символа. Здесь приводятся лисповские имена для часто встречающихся функциональных клавиш:

left, up, right, down
Курсорные стрелки.
begin, end, home, next, prior
Другие клавиши перемещения курсора.
select, print, execute, backtab
insert, undo, redo, clearline
insertline, deleteline, insertchar, deletechar,
Различные функциональные клавиши.
f1, f2, ... f35
Нумерованные функциональные клавиши (расположенные сверху клавиатуры).
kp-add, kp-subtract, kp-multiply, kp-divide
kp-backtab, kp-space, kp-tab, kp-enter
kp-separator, kp-decimal, kp-equal
Клавиши дополнительной клавиатуры (справа от основной клавиатуры), с именами или знаками пунктуации.
kp-0, kp-1, ... kp-9
Клавиши дополнительной клавиатуры с цифрами.
kp-f1, kp-f2, kp-f3, kp-f4
Функциональные клавиши дополнительной клавиатуры.

Эти имена являются общепринятыми, но некоторые системы (особенно при использовании X Windows) могут использовать другие имена. Чтобы убедиться, какой символ используется для определенной функциональной клавиши на вашем терминале, наберите C-h c и затем нужную клавишу.

Последовательность ключей, которая содержит символы функциональных клавиш (или что-то другое кроме ASCII-знаков), должны быть вектором, а не строкой. Синтаксис векторов использует пробел между элементами и квадратные скобки вокруг всего вектора. Таким образом, для привязки функциональной клавиши `f1' к команде rmail, напишите следующее:

(global-set-key [f1] 'rmail)

Для привязки клавиши с правой стрелкой к команде forward-char, вы можете использовать такое выражение:

(global-set-key [right] 'forward-char)

Здесь используется лисповский синтаксис для вектора, содержащего символ right. (Эта привязка существует по умолчанию в Emacs).

Смотрите раздел Перепривязка ключей в файле инициализации, для дополнительной информации об использовании векторов для перепривязки.

В последовательности ключей вы можете смешивать функциональные клавиши и знаки. Этот пример привязывает C-x NEXT к команде forward-page.

(global-set-key [?\C-x next] 'forward-page)

где ?\C-x -- это знаковая константа Лиспа для знака C-x. Элемент вектора next является лисповским символом, и поэтому к нему не приписан вопросительный знак.

Вы можете использовать клавиши-модификаторы CTRL, META, HYPER, SUPER, ALT и SHIFT вместе с функциональными клавишами. Для представления этих модификаторов добавьте строки `C-', `M-', `H-', `s-', `A-' и `S-' в начало имени символа. Таким образом, чтобы Hyper-Meta-RIGHT перемещал вперед на слово, нужно сделать так:

(global-set-key [H-M-right] 'forward-word)

Именованные управляющие ASCII-знаки

TAB, RET, BS, LFD, ESC и DEL начали свою жизнь как имена определенных управляющих знаков ASCII, использовавшихся так часто, что для них были сделаны специальные клавиши. Позднее, пользователи сочли удобным различать в Emacs эти клавиши и "те же самые" управляющие знаки, набранными с помощью клавиши CTRL.

Emacs различает эти два типа ввода, когда используется с X Window System. Он обрабатывает эти "особые" клавиши как функциональные с именами tab, return, backspace, linefeed, escape и delete. Эти функциональные клавиши автоматически транслируются в соответствующие ASCII-знаки, если у них нет собственных привязок. В результате ни пользователи, ни программы на Лиспе не обязаны помнить об этом различии, если только им это не нужно.

Если вы не хотите различать (например) TAB и C-i, просто сделайте одну привязку для ASCII-знака TAB (восьмиричный код 011). Если вы действительно хотите различать их, то сделайте одну привязку для этого ASCII-знака, а вторую для "функциональной клавиши" tab.

На обычных ASCII-терминалах нет способа различать TAB и C-i (и аналогично для других таких пар), потому что терминал посылает один и тот же знак в обоих случаях.

Не-ASCII-знаки на клавиатуре

Если на вашей клавиатуре есть клавиши, которые посылают знаки, не входящие в ASCII, например акцентированные буквы, перепривязка их делается несколько хитро. Есть два решения. Одно -- указать систему кодирования для клавиатуры, используя set-keyboard-coding-system (смотрите раздел Задание системы кодирования). Затем вы можете привязывать эти клавиши обычным способом, но записывая

(global-set-key [?знак] 'какая-то-функция)

и подставляя знак, который вы хотите привязать

Если вы не указываете систему кодирования для клавиатуры, этот способ не сработает. Вместо этого вам нужно выяснить код, который в действительности посылает терминал. Простейший способ сделать это в Emacs -- создать пустой буфер с помощью C-x b temp RET, сделать его однобайтным, набрав M-x toggle-enable-multibyte-characters RET, а затем нажать клавишу, которая вставит в этот буфер нужный знак.

Расположите точку сразу перед этим знаком, затем наберите C-x =. Это отобразит в минибуфере сообщение, показывающее восьмиричный, шестнадцатиричный и десятичный код знака, все в круглых скобках. Используйте второе из этих трех чисел, десятичное, внутри вектора для привязки:

(global-set-key [десятичный-код] 'какая-то-функция)

Перепривязка кнопок мыши

Emacs использует лисповские символы и для обозначения кнопок мыши. Обычными событиями от мыши в Emacs являются события-щелчки; это случается, когда вы нажимаете и отпускаете кнопку без перемещения мыши. Вы можете также получить событие-проведение, когда вы перемещаете мышь, держа нажатой кнопку. События-проведения в действительности происходят, когда вы отпускаете кнопку мыши.

Символами для основных событий-щелчков являются mouse-1 для левой кнопки мыши, mouse-2 для следующей кнопки и так далее. Вот как можно переопределить вторую кнопку мыши для разделения текущего окна:

(global-set-key [mouse-2] 'split-window-vertically)

Символы для события-проведения похожи на предыдущие, но имеют префикс `drag-' перед словом `mouse'. Например, проведение с помощью первой кнопки генерирует событие drag-mouse-1.

Вы также можете определить привязки для событий, которые возникают в момент нажатия на кнопку мыши. Имена этих событий начинаются со слова `down-' вместо `drag-'. Такие события генерируются, только если они имеют привязку. Когда вы получите событие-нажатие, то за ним всегда будут следовать соответствующее событие-щелчок или проведение.

Если хотите, вы можете различать одиночные, двойные и тройные щелчки. Двойной щелчок означает щелканье кнопкой мыши дважды почти в одном и том же месте. Первый щелчок генерирует обычное событие-щелчок. Второй щелчок, если он приходит достаточно быстро, генерирует событие-двойной щелчок. Тип события для двойного щелчка начинается с `double-': например, double-mouse-3.

Это означает, что вы можете придать особый смысл второму щелчку в том же самом месте, но он должен действовать в предположении, что обычное определение одинарного щелчка уже обработалось, когда был получен первый щелчок.

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

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

Emacs также поддерживает события-тройные щелчки, чьи имена начинаются с `triple-'. Emacs не различает четвертное нажатие как тип события; щелчки свыше третьего генерируют дополнительные события-тройные щелчки. Однако полное количество щелчков сохраняется в списке событий, так что вы можете различать такие случаи, если вам это действительно нужно. Мы не рекомендуем особых значений для более чем трех щелчков, но иногда полезно, чтобы последующие щелчки проходили по циклу того же набора трех значений, так что четыре щелчка эквивалентны одному, пять эквивалентны двум, а шесть -- трем.

Emacs также записывает множественные нажатия в событиях проведения и нажатия. Например, когда вы дважды нажмете кнопку, а затем переместите мышь, держа кнопку нажатой, Emacs получит событие `double-drag-'. А когда вы нажимаете на кнопку второй раз, Emacs получит событие `double-down-' (которое игнорируется, подобно всем событиям нажатия, если у них нет привязки).

Переменная double-click-time задает промежуток времени, который может пройти между двумя щелчками, чтобы они считались парой. Ее значение измеряется в миллисекундах. Если значение равно nil, то двойной щелчок не распознается совсем. Если значение равно t, то нет никакого временного ограничения.

Символы для событий мыши также показывают статус клавиш-модификаторов, с обычными префиксами `C-', `M-', `H-', `s-', `A-' и `S-'. Они всегда стоят перед `double-' или `triple-', которые всегда предшествуют `drag-' или `down-'.

Фрейм включает области, которые не отображают текст буфера, такие как строка режима и линейка прокрутки. Вы можете судить о том, что кнопка мыши нажата на специальной области экрана, посредством префиксных псевдо-ключей. Например, если вы щелкнете мышью в строке режима, то вы получите префиксный ключ mode-line перед обычным символом, обозначающем кнопку мыши. Вот как определить щелчок первой кнопкой на строке режима для запуска scroll-up:

(global-set-key [mode-line mouse-1] 'scroll-up)

Вот полный список таких префиксных псевдо-ключей и их значений:

mode-line
Мышь находилась на строке режима окна.
vertical-line
Мышь находилась на вертикальной линии, разделяющей окна. (Если вы используете полоски прокрутки, они появляются вместо этих вертикальных линий).
vertical-scroll-bar
Мышь находилась на вертикальной полоске прокрутки. (Пока это единственная разновидность полосок прокрутки, которые поддерживает Emacs).

Вы можете поместить в последовательность ключей больше одного события от кнопок мыши, но обычно так не далают.

Блокирование команд

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

Попытка интерактивного вызова блокированной команды в Emacs отображает окно, содержащее имя команды, ее описание и некоторые рекомендации о том, что надо сделать немедленно; затем Emacs спросит у вас ввод, указывающий, нужно ли выполнять эту команду, как запрошено, разблокировать ее или отменить запрос. Если вы решите разблокировать команду, то вас спросят, выполнить ли это постоянно или только для текущего сеанса. Постоянное разблокирование производится путем автоматического редактирования вашего файла `.emacs'.

Прямой механизм блокирования команды -- помещение отличного от nil свойства disabled в лисповский символ для данной команды. Вот программа на Лиспе, которая делает это:

(put 'delete-region 'disabled t)

Если значение свойства disabled является строкой, то эта строка включается в сообщение, выводимое при использовании этой команды:

(put 'delete-region 'disabled
     "It's better to use `kill-region' instead.\n")

Вы можете блокировать команду либо непосредстенным редактированием файла `.emacs', либо с помощью команды M-x disable-command, которая радактирует файл `.emacs' за вас. Подобным образом команда M-x enable-command изменяет `.emacs' для постоянного разрешения команды. Смотрите раздел Файл инициализации, `~/.emacs'.

Блокирование команды не зависит от того, какой ключ используется для ее запуска; блокирование также действует, если команда вызывается через M-x. Блокирование не имеет эффекта при вызове команды как функции из программ на Лиспе.

Перевод клавиатуры

Некоторые клавиатуры не позволяют удобно посылать все специальные знаки, которые использует Emacs. Наиболее общим случаем этой проблемы является знак DEL. Некоторые клавиатуры не обеспечивают удобного способа для набора этого очень важного знака -- обычно потому что они спроектированы в предположении, что для удаления будет использоваться знак C-h. На таких клавиатурах, если вы нажмете клавишу, обычно используемую для удаления, то Emacs обработает C-h как префиксный ключ и предложит вам список параметров, а это не то, что вам нужно.

Вы можете обойти эту проблему внутри Emacs, подготовив перевод клавиатуры для превращения C-h в DEL и DEL в C-h, как показано:

;; Переводит C-h в DEL.
(keyboard-translate ?\C-h ?\C-?)

;; Переводит DEL в C-h.
(keyboard-translate ?\C-? ?\C-h)

Перевод клавиатуры -- это не то же самое, что и привязка ключей в таблицах ключей (смотрите раздел Таблицы ключей). Emacs содержит многочисленные таблицы ключей, которые применяются в разных ситуациях, но только один набор переводов клавиш, и он применяется к каждому знаку, который Emacs считывает с терминала. Перевод клавиатуры происходят на низшем уровне обработки ввода; ключи, поиск которых происходит в таблицах ключей, содержат знаки, появляющиеся после перевода клавиатуры.

При работе в X, клавиша с именем DELETE является функциональной клавишей, и она отличается от ASCII-знака с именем DEL. Смотрите раздел Именованные управляющие ASCII-знаки. Перевод клавиатуры затрагивает только ввод ASCII-знаков, но не функциональных клавиш; таким образом, пример выше, примененный под X, не влияет на клавишу DELETE. Однако такой перевод не является необходимым под X, потому что Emacs может также различать клавишу BACKSPACE и C-h; и обычно он рассматривает BACKSPACE как DEL.

Для более полной информации об использовании перевода клавиатуры смотрите раздел `Translating Input' в The Emacs Lisp Reference Manual.

Синтаксическая таблица

Все команды Emacs, которые разбирают слова или балансируют скобки, управляются синтаксической таблицей. Синтаксическая таблица говорит, какие знаки являются открывающими ограничителями, частями слов, кавычками строковых констант и так далее. У каждого основного режима есть своя синтаксическая таблица (хотя родственные основные режимы часто разделяют одну), которая устанавливается в любом буфере, использующем этот режим. Все команды применяют синтаксическую таблицу, установленную в текущем буфере; именно ее мы имеем в виду, когда мы говорим просто "синтаксическая таблица". Синтаксическая таблица -- это лисповский объект, таблица знаков, чьими элементами являются числа.

Чтобы вывести на экран описание содержимого текущей синтаксической таблицы, наберите C-h s (describe-syntax). Описание каждого знака включает строку, которую вы передали бы modify-syntax-entry для установки текущего синтаксиса, и небольшое объяснение этой строки на английском, если необходимо.

Для получения полной информации о синтаксических таблицах смотрите раздел `Syntax Tables' в The Emacs Lisp Reference Manual.

Файл инициализации, `~/.emacs'

Когда Emacs запускается, он обычно загружет Лисп-программу из файла `.emacs' в вашем начальном каталоге. Мы называем этот файл вашим файлом инициализации, поскольку он указывает, как инициализировать Emacs для вас. Вы можете использовать ключи командной строки -q, чтобы предотвратить загрузку файла инициализации, и -u (или --user), чтобы указать файл инициализации другого пользователя (смотрите раздел Вход и выход из Emacs).

Также может быть файл инициализации по умолчанию, это библиотека с именем `default.el', находимая по стандартному пути поиска для библиотек. В дистрибутиве Emacs нет такой библиотеки; она может быть создана на вашей системе для локальных настроек. Если эта библиотека существует, она загружается при запуске Emacs (только если вы не задали -q). Но ваш файл инициализации, если он существует, загружается первым; если он устанавливает inhibit-default-init в отличное от nil значение, то `default' не загружается.

На вашей системе также может быть системный файл запуска; он называется `site-start.el', если существует. Emacs загружает эту библиотеку до вашего файла инициализации. Чтобы подавить загрузку этой библиотеки, используйте ключ -no-site-file.

Если ваш файл `.emacs' содержит большой объем кода, вам стоит переместить его в другой файл, как `~/что-нибудь.el', скомпилировать его и сделать так, чтобы ваш файл `.emacs' загружал его через (load "~/что-нибудь"). Смотрите раздел `Byte Compilation' в the Emacs Lisp Reference Manual, для получения большей информации о компилировании программ на Emacs Lisp.

Если вы собираетесь писать настоящие программы на Emacs Lisp, которые идут дальше простой настройки, вам нужно прочитать книгу Emacs Lisp Reference Manual.

Синтаксис файла инициализации

Файл `.emacs' содержит одно или несколько лисповских выражений вызовов функций. Каждое из них состоит из имени функции, за которым следуют аргументы, всё в окружении круглых скобок. Например, (setq fill-column 60) вызывает функцию setq для установки переменной fill-column (смотрите раздел Заполнение текста) в значение 60.

Второй аргумент setq -- это выражение для нового значения переменной. Это может быть константа, переменная или вызов функции. В файле `.emacs' чаще всего используются константы. Это могут быть:

Числа:
Числа записываются в десятичной форме, с необязательным знаком минус в начале.
Строки:
Синтаксис лисповских строк такой же, как в Си, но с некоторыми дополнительными чертами. Для начала и завершения строковой константы используйте знак двойных кавычек. В строковых константах вы можете писать переводы строк и специальные знаки буквально. Но часто для ясности лучше использовать для них последовательности с обратной косой чертой: `\n' для перевода строки, `\b' для возврата на одну позицию, `\r' для возврата каретки, `\t' для табуляции, `\f' для прогона страницы (control-L), `\e' для escape, `\\' для обратной косой черты, `\"' для двойных кавычек или `\ooo' для знака с восьмиричным кодом ooo. Обратная косая черта и двойные кавычки --- это единственные знаки, для которых такие последовательности обязательны. `\C-' можно использовать как префикс для управляющего знака, как `\C-s' для ASCII control-S, а `\M-' можно применять в качестве префикса для Meta-знака, как `\M-a' для Meta-A или `\M-\C-a' для Control-Meta-A.
Знаки:
Синтаксис лисповских знаковых констант состоит из `?', за которым идет либо знак, либо последовательность, начинающаяся с `\'. Примеры: ?x, ?\n, ?\", ?\). Заметьте, что строки и знаки не взаимозаменимы в Лиспе; в некоторых контекстах требуется одно, в некоторых другое.
Истина:
t обозначает `истину'.
Ложь:
nil обозначает `ложь'.
Другие лисповские объекты:
Пишите одиночную кавычку (') и за ней желаемый лисповский объект.

Примеры файла инициализации

Вот несколько примеров выполнения часто нужных вещей с помощью лисповских выражений:

  • Сделать так, чтобы TAB в режиме C просто вставлял табуляцию, если точка находится в середине строки.
    (setq c-tab-always-indent nil)
    
    Здесь мы имеем переменную, чье значение обычно равно t, то есть `истина', а альтернатива ему -- nil, `ложь'.
  • Сделать так, чтобы поиск производился с учетом регистра (во всех буферах, которые не перекрывают это).
    (setq-default case-fold-search nil)
    
    Это устанавливает значение по умолчанию, оно распространяется на все буферы, в которых нет локальных значений для этой переменной. Установка case-fold-search с помощью setq затрагивает только локальное значение текущего буфера, а это не то, что вы, скорее всего, хотите сделать в файле инициализации.
  • Указать ваш адрес электронной почты, если Emacs не может правильно выяснить его сам.
    (setq user-mail-address "[email protected]")
    
    Различные пакеты Emacs, которым нужно знать ваш адрес, используют значение user-mail-address.
  • Сделать режим Text режимом для новых буферов по умолчанию.
    (setq default-major-mode 'text-mode)
    
    Заметьте, что используется text-mode, поскольку это команда для входа в режим Text. Одиночная кавычка перед ним делает этот символ константой; иначе text-mode рассматривался бы как имя переменной.
  • Подготовить установки по умолчанию для набора знаков Latin-1, который поддерживает большинство западноевропейских языков.
    (set-language-environment "Latin-1")
    
  • Включать режим Auto Fill автоматически в режиме Text и родственных с ним.
    (add-hook 'text-mode-hook
      '(lambda () (auto-fill-mode 1)))
    
    Это показывает, как добавить функцию-ловушку к переменной-ловушке (смотрите раздел Ловушки). Функция, которую мы предоставляем -- это список, начинающийся с lambda, с одиночной кавычкой в начале, чтобы сделать этот список константой, а не выражением. Объяснение функций Лиспа выходит за рамки данного руководства, но для этого примера достаточно знать, что действием будет вычисление (auto-fill-mode 1), когда вы входите в режим Text. При желании вы можете заменить это на другое выражение или на несколько выражений подряд. Emacs поставляется с функцией с именем turn-on-auto-fill, чье определение -- это (lambda () (auto-fill-mode 1)). Таким образом, более простой способ написать приведенное выше выражение выглядит так:
    (add-hook 'text-mode-hook 'turn-on-auto-fill)
    
  • Загрузить установленную лисповскую библиотеку с именем `foo' (на самом деле файл `foo.elc' или `foo.el' из стандартного каталога Emacs).
    (load "foo")
    
    Когда аргументом load является относительное имя файла, не начинающееся с `/' или `~', load просматривает каталоги из load-path (смотрите раздел Библиотеки Лисп-программ для Emacs).
  • Загрузить скомпилированный Лисп-файл `foo.elc' из вашего начального каталога.
    (load "~/foo.elc")
    
    Здесь использовано абсолютное имя файла, поэтому поиск не производится.
  • Перепривязать ключ C-x l на запуск функции make-symbolic-link.
    (global-set-key "\C-xl" 'make-symbolic-link)
    
    или
    (define-key global-map "\C-xl" 'make-symbolic-link)
    
    Еще раз обратите внимание, одиночная кавычка используется для ссылки на символ make-symbolic-link, а не на его значение как переменной.
  • Сделать то же самое, только для режима Lisp.
    (define-key lisp-mode-map "\C-xl" 'make-symbolic-link)
    
  • Переопределить все ключи, которые сейчас запускают next-line в режиме Fundamental, чтобы они вместо этого запускали forward-line.
    (substitute-key-definition 'next-line 'forward-line
                               global-map)
    
  • Сделать C-x C-v неопределенным.
    (global-unset-key "\C-x\C-v")
    
    Одна из причин для удаления определения ключа состоит в том, чтобы вы могли сделать его префиксом. Просто определение C-x C-v что-угодно сделает C-x C-v префиксом, но сначала нужно лишить C-x C-v его обычного непрефиксного определения.
  • Присвоить `$' синтаксическую категорию пунктуации в режиме Text. Обратите внимание на использование знаковой константы для `$'.
    (modify-syntax-entry ?\$ "." text-mode-syntax-table)
    
  • Разрешить использование команды narrow-to-region без подтверждения.
    (put 'narrow-to-region 'disabled nil)
    

Инициализация терминала

Для каждого типа терминала может быть библиотека, загружаемая в Emacs, когда он запускается на этом типе терминала. Для типа терминала с именем тип-терм эта библиотека называется `term/тип-терм', и она находится, как обычно, путем поиска в каталогах load-path, при этом пробуются окончания `.elc' и `.el'. Обычно она появляется в подкаталоге `term' из каталога, где хранится большинство библиотек Emacs.

Обычное назначение специфичной для терминала библиотеки --- отображение escape-последовательностей, используемых функциональными клавишами терминала, в более осмысленные имена с помощью функции function-key-map. Пример того, как это делается, смотрите в файле `term/lk201.el'. Многие функциональные клавиши отображаются автоматически в соответсвтии с базой данных Termcap; в специфичной для терминала библиотеке нужно описать только те функциональные клавиши, которые на указаны в Termcap.

Когда тип терминала содержит дефис, при выборе имени библиотеки имеет значение только часть перед первым дефисом. Таким образом, типы терминалов `aaa-48' и `aaa-30-rv' оба используют библиотеку `term/aaa'. Код библиотеки может применять (getenv "TERM") для выяснения полного имени типа терминала.

Имя библиотеки конструируется конкатенацией значения переменной term-file-prefix и типа терминала. Ваш файл `.emacs' может предотвратить загрузку специфичной для терминала библиотеки, устанавливая term-file-prefix равной nil.

В конце инициализации, когда считаны и ваш файл `.emacs', и любая специфичная для терминала библиотека, Emacs запускает ловушку term-setup-hook. Добавьте к этой ловушке функции, если вы хотите перекрыть часть специфичной для терминала библиотеки или определить инициализацию для терминалов, к которым нет библиотеки. Смотрите раздел Ловушки.

Как Emacs находит файл инициализации

Обычно для поиска файла `.emacs' Emacs использует переменную среды `HOME'; знак `~' в имени файла обозначает именно это. Но если вы сделали su, Emacs пытается найти ваш собственный `.emacs', а не того пользователя, за кого вы себя сейчас выдаете. Идея в том, чтобы вы получали свои собственные настройки редактора, даже если работаете как привелигированный пользователь.

Более точно, Emacs сначала определяет, файл инициализации какого пользователя нужно использовать. Он получает имя пользователя из переменных среды `LOGNAME' и `USER'; если ни одна из них не существует, берется эффективный ID пользователя. Если имя пользователя соответствует реальному пользовательскому ID, то Emacs использует `HOME'; иначе, он находит начальный каталог в системной базе данных о пользователях.


Бери в аренду VPS сервер, широкий список тарифов.