Настройка

В этой главе обсуждаются различные вопросы, относящиеся к простой адаптации поведения 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 являются нормальными ловушками. Эти переменные содержат списки функций, которые вызываются без аргументов. Причина того, что большинство ловушек являются нормальными, заключается в том, чтобы вы могли использовать их одинаковым способом. В Emacs каждая переменная, чье имя оканчивается на `-hook', является нормальной ловушкой.

Большинство основных режимов запускают ловушки на последней стадии инициализации. Это облегчает настройку поведения режима путем перекрытия локальных переменных, значения которых уже были присвоены данным режимом. Но ловушки также могут использоваться в другом контексте. Например, ловушка suspend-hook запускается непосредственно перед приостановкой Emacs (смотрите раздел Выход из Emacs).

Для добавления функции к нормальной ловушке рекомендуется вызывать функцию 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'). Не используйте список локальных переменных для навязывания вашего вкуса всем остальным.

"Переменная" coding не сработает из списка локальных переменных; coding реализована особым образом, и она работает только в конструкции `-*-'.

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

Перепривязка кнопок мыши

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 "coon@yoyodyne.com")
    
    Различные пакеты 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'; иначе, он находит начальный каталог в системной базе данных о пользователях.

Назад |  Вперед |  Содержание



Распространение материалов сайта означает, что распространитель принял условия лицензионного соглашения.
Идея и реализация: © Владимир Довыденков и Анатолий Камынин,  2004-2024