Когда функция read-key-sequence считывает последовательность клавиш
(см. Ввод последовательности клавиш), она использует таблицы перевода для
перевода определенных последовательностей событий в другие. Таблицы перевода
это input-decode-map, local-function-key-map и
key-translation-map (в порядке приоритета).
Таблицы перевода имеют ту же структуру, что и другие таблицы клавиш, но используются по-другому: они определяют переводы, которые необходимо выполнить при считывании последовательностей клавиш, а не привязки для полных последовательностей клавиш. При считывании каждой последовательности клавиш она проверяется по каждой таблице перевода. Если одна из таблиц перевода привязывает k к вектору v, то всякий раз, когда k появляется как подпоследовательность где-либо в последовательности клавиш, эта подпоследовательность заменяется событиями из v.
Например, терминалы VT100 отправляют ESC O P при нажатии
клавиши на клавиатуре PF1. В таких терминалах Emacs должен
перевести эту последовательность событий в одно событие pf1.
Это делается путем привязки ESC O P к [pf1] в
input-decode-map. Таким образом, когда вы нажимаете C-c PF1
на терминале, терминал испускает последовательность символов C-c
ESC O P, и read-key-sequence переводит это обратно в
C-c PF1 и возвращает его как вектор [?\C-c pf1].
Таблицы перевода вступают в силу только после того, как Emacs декодирует
ввод с клавиатуры (с помощью системы кодирования ввода, указанной в
keyboard-coding-system). См. Кодирование ввода/вывода терминала.
Эта переменная содержит таблицу клавиш, описывающую последовательности символов, отправляемые функциональными клавишами на обычном символьном терминале.
Значение input-decode-map обычно настраивается автоматически
в соответствии с записью Terminfo или Termcap терминала, но иногда для этого
требуется помощь файлов Lisp, специфичных для терминала. Emacs поставляется с
файлами, специфичными для терминалов, для многих распространенных терминалов; их
основная цель — добавить записи в input-decode-map, которые
не могут быть выведены из Termcap и Terminfo. См. Инициализация, специфичная для терминала.
Эта переменная содержит таблицу клавиш, похожую на input-decode-map,
за исключением того, что она описывает последовательности клавиш, которые следует
перевести в альтернативные интерпретации, которые обычно предпочтительнее. Она
применяется после input-decode-map и до key-translation-map.
Записи в local-function-key-map игнорируются, если они конфликтуют
с привязками, сделанными в режиме, в локальной или глобальной таблице клавиш.
То есть, переназначение применяется только в том случае, если исходная последовательность
клавиш в противном случае не имела бы привязки.
local-function-key-map наследуется от function-key-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 для преобразования следующего символа в гиперсимвол:
(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 [).