Способ переназначить клавишу — изменить её запись в клавиатурной карте. Если вы
измените привязку в глобальной клавиатурной карте, изменение будет действовать во всех
буферах (хотя оно не оказывает прямого влияния в буферах, которые переопределяют
глобальную привязку локальной). Если вы измените локальную карту текущего буфера,
это обычно влияет на все буферы, использующие тот же основной режим. Функции
keymap-global-set и keymap-local-set являются удобными интерфейсами
для этих операций (см. Команды для привязки клавиш). Вы также можете
использовать keymap-set — более общую функцию; тогда вы должны явно указать
карту для изменения.
При выборе последовательностей клавиш для переназначения в программах на Lisp, пожалуйста, следуйте соглашениям Emacs относительно использования различных клавиш (см. Соглашения о привязке клавиш).
Функции, приведённые ниже, сигнализируют об ошибке, если keymap не является клавиатурной картой или если key не является допустимой клавишей.
key — это строка, представляющая одну клавишу или серию нажатий клавиш,
и должна удовлетворять условию key-valid-p. Нажатия клавиш разделяются
одиночным пробелом.
Каждое нажатие клавиши — это либо одиночный символ, либо имя события, заключённое в угловые скобки. Кроме того, любому нажатию клавиши может предшествовать один или несколько модификаторов. Наконец, ограниченное число символов имеет специальный сокращённый синтаксис. Вот несколько примеров последовательностей клавиш:
Клавиша f.
Трёхклавишная последовательность клавиш S, o и m.
Двухклавишная последовательность: клавиша c с модификатором Control, а затем клавиша o.
Клавиша с именем left с модификатором Hyper.
Клавиша return с модификатором Meta.
Клавиша space с модификаторами Control и Meta.
Единственные клавиши, имеющие специальный сокращённый синтаксис: NUL, RET, TAB, LFD, ESC, SPC и DEL.
Модификаторы должны быть указаны в алфавитном порядке: ‘A-C-H-M-S-s’, что означает ‘Alt-Control-Hyper-Meta-Shift-super’.
Эта функция устанавливает привязку для key в keymap. (Если
key содержит более одного события, изменение фактически вносится
в другую клавиатурную карту, достижимую из keymap.) Аргумент
binding может быть любым объектом Lisp, но осмысленны только определённые
типы. (Список осмысленных типов см. в Поиск по клавишам.)
Значение, возвращаемое keymap-set, равно binding.
Если key — это <t>, то устанавливается привязка по умолчанию в keymap. Когда событие не имеет собственной привязки, командный цикл Emacs использует привязку по умолчанию клавиатурной карты, если таковая имеется.
Каждый префикс key должен быть префиксной клавишей (т.е. быть привязанным
к клавиатурной карте) или неопределённым; в противном случае сигнализируется
ошибка. Если некоторый префикс key не определён, то keymap-set
определяет его как префиксную клавишу, чтобы остальная часть key могла
быть определена, как указано.
Если ранее в keymap не было привязки для key, новая привязка добавляется в начало keymap. Порядок привязок в клавиатурной карте не влияет на ввод с клавиатуры, но имеет значение для меню-клавиатурных карт (см. Клавиатурные карты меню).
Эта функция является обратной к keymap-set, она отменяет привязку
для key в keymap, что равносильно установке привязки в
nil. Чтобы полностью удалить привязку, укажите remove как
не nil. Это имеет значение только в том случае, если у keymap
есть родительская клавиатурная карта: если вы просто отмените клавишу
в дочерней карте, она всё равно будет переопределять ту же клавишу
в родительской карте; использование remove позволит использовать
клавишу из родительской клавиатурной карты.
Примечание: использование keymap-unset с remove, не равным
nil, предназначено для пользователей, чтобы помещать его в свой
инициализационный файл; пакеты Emacs должны по возможности избегать его
использования, поскольку они и так полностью контролируют свои собственные
клавиатурные карты и не должны изменять карты других пакетов.
В этом примере создаётся разрежённая клавиатурная карта и в ней делается несколько привязок:
(setq map (make-sparse-keymap))
⇒ (keymap)
(keymap-set map "C-f" 'forward-char)
⇒ forward-char
map
⇒ (keymap (6 . forward-char))
;; Создать разрежённую подкарту для C-x и привязать f в ней.
(keymap-set map "C-x f" 'forward-word)
⇒ forward-word
map
⇒ (keymap
(24 keymap ; C-x
(102 . forward-word)) ; f
(6 . forward-char)) ; C-f
;; Привязать C-p кctl-x-map. (keymap-set map "C-p" ctl-x-map) ;;ctl-x-map⇒ [nil … find-file … backward-kill-sentence]
;; Привязать C-f к foo в ctl-x-map.
(keymap-set map "C-p C-f" 'foo)
⇒ 'foo
map
⇒ (keymap ; Обратите внимание на foo в ctl-x-map.
(16 keymap [nil … foo … backward-kill-sentence])
(24 keymap
(102 . forward-word))
(6 . forward-char))
Обратите внимание, что сохранение новой привязки для C-p C-f фактически
работает путём изменения записи в ctl-x-map, и это приводит к изменению
привязок как C-p C-f, так и C-x C-f в глобальной карте по умолчанию.
keymap-set — это основной рабочий инструмент для определения клавиши
в клавиатурной карте. Однако при написании режимов вам часто приходится
привязывать большое количество клавиш одновременно, и использование
keymap-set для всех них может быть утомительным и чреватым ошибками.
Вместо этого вы можете использовать define-keymap, которая создаёт
клавиатурную карту и привязывает несколько клавиш. Подробности см. в
Создание клавиатурных карт.
Функция substitute-key-definition просматривает клавиатурную карту
в поисках клавиш, имеющих определённую привязку, и переназначает их на другую
привязку. Другая возможность, которая чище и часто может дать те же результаты —
это перенаправить одну команду в другую (см. Переназначение команд).
Эта функция заменяет olddef на newdef для любых клавиш
в keymap, которые были привязаны к olddef. Другими словами,
olddef заменяется на newdef везде, где он встречается.
Функция возвращает nil.
Например, это переопределяет C-x C-f, если вы делаете это в Emacs со стандартными привязками:
(substitute-key-definition 'find-file 'find-file-read-only (current-global-map))
Если oldmap не равен nil, это изменяет поведение
substitute-key-definition: привязки в oldmap определяют,
какие клавиши переназначать. Переназначения по-прежнему происходят
в keymap, а не в oldmap. Таким образом, вы можете изменить
одну карту под управлением привязок в другой. Например,
(substitute-key-definition 'delete-backward-char 'my-funny-delete my-map global-map)
помещает специальную команду удаления в my-map для тех клавиш,
которые глобально привязаны к стандартной команде удаления.
Вот пример, показывающий клавиатурную карту до и после замены:
(setq map (list 'keymap
(cons ?1 olddef-1)
(cons ?2 olddef-2)
(cons ?3 olddef-1)))
⇒ (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1))
(substitute-key-definition 'olddef-1 'newdef map) ⇒ nil
map ⇒ (keymap (49 . newdef) (50 . olddef-2) (51 . newdef))
Эта функция изменяет содержимое полной клавиатурной карты keymap
путём переназначения self-insert-command на команду undefined
(см. Переназначение команд). Это приводит к отмене определения всех
печатаемых символов, делая обычный ввод текста невозможным.
suppress-keymap возвращает nil.
Если nodigits равен nil, то suppress-keymap определяет
цифры для выполнения digit-argument, а - — для выполнения
negative-argument. В противном случае они остаются неопределёнными,
как и остальные печатаемые символы.
Функция suppress-keymap не делает невозможным изменение буфера,
поскольку она не подавляет такие команды, как yank
и quoted-insert. Чтобы предотвратить любое изменение буфера,
сделайте его доступным только для чтения (см. Буферы только для чтения).
Поскольку эта функция изменяет keymap, обычно её используют
на только что созданной клавиатурной карте. Работа с существующей
клавиатурной картой, которая используется для других целей, вероятно,
вызовет проблемы; например, подавление global-map сделает
невозможным использование большей части Emacs.
Эта функция может использоваться для инициализации локальной клавиатурной
карты основного режима, в котором вставка текста нежелательна. Но обычно
такой режим должен быть производным от special-mode (см. Базовые основные режимы); тогда его клавиатурная карта будет автоматически
наследовать от special-mode-map, которая уже подавлена. Вот как
определяется special-mode-map:
(defvar special-mode-map
(let ((map (make-sparse-keymap)))
(suppress-keymap map)
(keymap-set map "q" 'quit-window)
…
map))