Глобальное переопределение привязки ключей в Emacs
Как я могу установить привязку ключа, которая глобально переопределяет и имеет приоритет над всеми другими привязками для этого ключа? Я хочу переопределить все карты основных / второстепенных режимов и убедиться, что моя привязка действует всегда.
Это, конечно, не работает:
(global-set-key "\C-i" 'some-function)
Работает в text-mode
, но когда я использую lisp-mode
, C-i
отскок к lisp-indent-line
,
Я могу пройти и переопределить эту привязку в lisp-mode
и в любом другом режиме индивидуально, но должен быть более легкий путь. Каждый раз, когда я устанавливаю новый режим для нового типа файла, я должен был возвращаться и проверять, чтобы убедиться, что все мои привязки клавиш не переопределяются новым режимом.
Я хочу сделать это, потому что я хочу подражать привязкам, которые я уже изучил и укоренил в других редакторах.
9 ответов
Я использую второстепенный режим для всех моих "переопределенных" привязок клавиш:
(defvar my-keys-minor-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-i") 'some-function)
map)
"my-keys-minor-mode keymap.")
(define-minor-mode my-keys-minor-mode
"A minor mode so that my key settings override annoying major modes."
:init-value t
:lighter " my-keys")
(my-keys-minor-mode 1)
Это дает дополнительное преимущество, заключающееся в том, что я могу отключить все мои модификации одним махом (просто отключить второстепенный режим) в случае, если кто-то другой управляет клавиатурой или если мне нужно посмотреть, как работает связывание клавиш по умолчанию.
Обратите внимание, что вам может потребоваться отключить это в минибуфере:
(defun my-minibuffer-setup-hook ()
(my-keys-minor-mode 0))
(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)
В качестве дополнения к ответу Скоттфразера я написал следующее, чтобы мои сочетания клавиш сохраняли приоритет, даже если загруженные впоследствии библиотеки вводят новые собственные сочетания клавиш.
Поскольку таблицы ключей могут быть сгенерированы во время компиляции, load
казалось лучшим местом для этого.
(add-hook 'after-load-functions 'my-keys-have-priority)
(defun my-keys-have-priority (_file)
"Try to ensure that my keybindings retain priority over other minor modes.
Called via the `after-load-functions' special hook."
(unless (eq (caar minor-mode-map-alist) 'my-keys-minor-mode)
(let ((mykeys (assq 'my-keys-minor-mode minor-mode-map-alist)))
(assq-delete-all 'my-keys-minor-mode minor-mode-map-alist)
(add-to-list 'minor-mode-map-alist mykeys))))
Устанавливать use-package
, eval и все готово:
(require 'bind-key)
(bind-key* "C-i" 'some-function)
Я нашел этот вопрос при поиске "emacs undefine org modebbindings", потому что я хотел отсоединить существующее поведение Cc Cb, чтобы моя глобальная карта могла скрыть буфер для работы в буфере org.
Это оказалось самым простым решением для меня:
(add-hook 'org-mode-hook
(lambda ()
(local-unset-key (kbd "C-c C-b"))))
Хотя ответ Скоттфразера именно то, что вы просили, я упомяну для потомков другое решение.
"Не определяйте букву Cc как ключ в программах на Лиспе. Последовательности, состоящие из Cc и буквы (в верхнем или нижнем регистре), зарезервированы для пользователей; это единственные последовательности, зарезервированные для пользователей, поэтому не блокируйте их".
Если вы связываете свои личные глобальные привязки с Cc плюс буквой, то вы "должны" быть в безопасности. Тем не менее, это всего лишь соглашение, и любой режим все еще может переопределять ваши привязки.
Если вы хотите "всегда использовать привязки клавиш на карте, если я не переопределю их явно для конкретной карты режимов", и при условии, что вы используете подход scottfrazier, вам нужно:
(defun locally-override (key cmd)
(unless (local-variable-p 'my-keys-minor-mode-map)
(set (make-variable-buffer-local 'my-keys-minor-mode-map)
(make-sparse-keymap))
(set-keymap-parent my-keys-minor-mode-map
(default-value 'my-keys-minor-mode-map)))
(define-key my-keys-minor-mode-map key cmd))
Так
(locally-override "\C-i" nil)
следует удалить привязку "\Ci" из второстепенного режима только в текущем буфере. Предупреждение: это полностью не проверено, но кажется правильным подходом. Точка установки родителя, а не просто копирование глобального значения my-keys-minor-mode-map, заключается в том, что любые последующие изменения глобального значения автоматически отражаются в локальном значении.
Если вы действительно не хотите делать это самостоятельно, вы должны проверить и посмотреть, если кто-то еще уже сделал это.
Существует пакет для Emacs, который дает ваши сочетания клавиш в стиле Windows. Вы должны быть в состоянии найти его через Google.
Я не думаю, что ты можешь. Это примерно эквивалентно тому, что вы хотите определить глобальную переменную, которая не может быть скрыта объявлениями локальных переменных в функциях. Сфера просто так не работает.
Однако может быть способ написать функцию elisp для просмотра списка режимов и переназначить его для каждого из вас.
В Emacs 27 есть
override-global-map
. Затем вы можете сделать что-то вроде этого:(define-key override-global-map (kbd "M-h") 'backward-kill-word)
Это неверный ответ, извините.