Карты клавиш для преобразования последовательностей событий
Когда функция read-key-sequence считывает последовательность клавиш (см. раздел Ввод последовательностей клавиш), она использует карты трансляции клавиш для преобразования одних последовательностей событий в другие. Карты трансляции клавиш — это input-decode-map, local-function-key-map и key-translation-map (в порядке приоритета).
Карты трансляции клавиш имеют ту же структуру, что и другие карты клавиш, но используются иначе: они задают преобразования, выполняемые при считывании последовательностей клавиш, а не привязки для полных последовательностей клавиш. По мере считывания каждой последовательности клавиш она проверяется по каждой карте трансляции. Если одна из карт трансляции клавиш связывает k с вектором v, то всякий раз, когда k встречается как подпоследовательность в любом месте последовательности клавиш, эта подпоследовательность заменяется событиями из v.
Например, терминалы VT100 отправляют ESC O P при нажатии клавиши клавиатуры PF1. На таких терминалах Emacs должен преобразовать эту последовательность событий в одно событие pf1. Для этого в input-decode-map последовательность ESC O P связывается с [pf1]. Таким образом, когда вы вводите C-c PF1 в терминале, терминал отправляет последовательность символов C-c ESC O P, а read-key-sequence преобразует её обратно в C-c PF1 и возвращает как вектор [?\C-c pf1].
Карты трансляции начинают действовать только после того, как Emacs декодирует ввод с клавиатуры (с помощью системы кодирования ввода, заданной в keyboard-coding-system). См. раздел Кодирование ввода-вывода терминала.
- Переменная: input-decode-map
-
Эта переменная содержит карту клавиш, описывающую последовательности символов, отправляемые функциональными клавишами обычного посимвольного терминала.
Значение
input-decode-mapобычно задаётся автоматически в соответствии с записью терминала в Terminfo или Termcap, однако иногда для этого требуются файлы Lisp, специфичные для данного терминала. Emacs поставляется с файлами для многих распространённых терминалов; их основное назначение — добавлять записи вinput-decode-map, которые нельзя вывести из Termcap и Terminfo. См. раздел Инициализация для конкретного терминала.
- Переменная: local-function-key-map
-
Эта переменная содержит карту клавиш, подобную
input-decode-map, но описывающую последовательности клавиш, которые следует преобразовывать в альтернативные интерпретации, обычно предпочтительные. Она применяется послеinput-decode-mapи доkey-translation-map.Записи в
local-function-key-mapигнорируются, если они конфликтуют с привязками в картах клавиш второстепенных режимов, локальной или глобальной карте. Иными словами, переназначение применяется только в том случае, если исходная последовательность клавиш иначе не имела бы никакой привязки.local-function-key-mapнаследуется отfunction-key-map. Последнюю следует изменять только в том случае, если привязка должна применяться во всех терминалах, поэтому почти всегда предпочтительнее использовать первую.
- Переменная: key-translation-map
-
Эта переменная представляет собой ещё одну карту клавиш, которая используется так же, как
input-decode-map, для преобразования входных событий в другие события. Она отличается отinput-decode-mapтем, что начинает действовать после завершения работыlocal-function-key-map, а не до неё; она получает результаты преобразования, выполненного с помощьюlocal-function-key-map.Как и
input-decode-map, но в отличие отlocal-function-key-map, эта карта клавиш применяется независимо от того, имеет ли входная последовательность клавиш обычную привязку. Однако обратите внимание, что фактические привязки клавиш могут влиять наkey-translation-map, даже если эта карта имеет приоритет над ними. Действительно, фактические привязки клавиш имеют приоритет надlocal-function-key-mapи поэтому могут изменить последовательность клавиш, которую получаетkey-translation-map. Очевидно, лучше избегать таких ситуаций.Предполагается, что
key-translation-mapбудет использоваться для преобразования одного набора символов в другой, в том числе обычных символов, обычно привязанных кself-insert-command.
С помощью input-decode-map, local-function-key-map и key-translation-map можно задавать не только простые псевдонимы: для преобразования клавиши можно использовать функцию вместо последовательности клавиш. В этом случае для вычисления преобразования этой клавиши вызывается функция.
Функция преобразования клавиш получает один аргумент — подсказку, заданную в read-key-sequence, или nil, если последовательность клавиш считывается циклом команд редактора. В большинстве случаев значение подсказки можно игнорировать.
Если функция сама считывает ввод, она может изменить следующее за ним событие. Например, вот как определить C-c h, чтобы следующий символ стал символом Hyper:
(defun hyperify (prompt)
(let ((e (read-event)))
(vector (if (numberp e)
(logior (ash 1 24) e)
(if (memq 'hyper (event-modifiers e))
e
(add-event-modifier "H-" e))))))
(defun add-event-modifier (string e)
(let ((symbol (if (symbolp e) e (car e))))
(setq symbol (intern (concat string
(symbol-name symbol))))
(if (symbolp e)
symbol
(cons symbol (cdr e)))))
(keymap-set local-function-key-map "C-c h" 'hyperify)
Функции преобразования клавиш может понадобиться менять своё поведение в зависимости от параметров событий внутри последовательности клавиш, содержащей события, не являющиеся клавишами (см. раздел Входные события). Эти сведения доступны через переменную current-key-remap-sequence, которой присваивается подпоследовательность клавиш, преобразуемая в ходе вызовов функций преобразования клавиш.
Взаимодействие с обычными картами клавиш
Конец последовательности клавиш определяется, когда эта последовательность либо привязана к команде, либо Emacs определяет, что никакое дополнительное событие не может привести к последовательности, привязанной к команде.
Это означает, что, хотя input-decode-map и key-translation-map применяются независимо от того, имела бы исходная последовательность клавиш привязку или нет, такая привязка всё же может помешать преобразованию. Например, вернёмся к приведённому выше примеру с VT100 и добавим в глобальную карту привязку для C-c ESC; теперь, когда пользователь нажмёт C-c PF1, Emacs не сможет декодировать C-c ESC O P как C-c PF1, поскольку прекратит считывать клавиши сразу после C-c ESC, оставив O P на потом. Это необходимо на случай, если пользователь действительно нажал C-c ESC; тогда Emacs не должен ждать следующую клавишу, чтобы определить, действительно ли пользователь нажал ESC или PF1.
По этой причине лучше не привязывать команды к последовательностям клавиш, если конец последовательности является префиксом преобразуемой последовательности клавиш. Основные проблемные суффиксы/префиксы — это ESC, M-O (то есть ESC O) и M-[ (то есть ESC [).
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Translation-Keymaps.html