Глобальное переопределение привязки ключей в Emacs

Как установить привязку ключей, которая глобально переопределяет и имеет приоритет над всеми другими связями для этого ключа? Я хочу переопределить все карты основных/второстепенных режимов и убедиться, что привязка всегда действует.

Это, конечно, не работает:

(global-set-key "\C-i" 'some-function)

Он работает в text-mode, но когда я использую lisp-mode, C-i отскакивает до lisp-indent-line.

Я могу пройти и переопределить это привязку в lisp-mode и в каждом другом режиме по отдельности, но должен быть более простой способ. Каждый раз, когда я устанавливаю новый режим для нового типа файла, мне придется вернуться и проверить, чтобы все мои привязки клавиш не были переопределены в новом режиме.

Я хочу сделать это, потому что я хочу эмулировать привязки, которые я уже изучил и укоренил из других редакторов.

Ответ 1

Я использую второстепенный режим для всех моих привязок ключей "override":

(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)

Ответ 2

Как дополнение к ответу scottfrazer, я написал следующее, чтобы мои привязки клавиш сохраняли приоритет, даже если впоследствии загруженные библиотеки вносят новые собственные раскладки клавиатуры.

Поскольку во время компиляции можно создавать карты клавиатуры, 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))))

Ответ 3

Я нашел этот вопрос во время поиска "emacs undefine org mode keybindings", потому что я хотел отменить существующее C-c поведение C-b, чтобы позволить моей глобальной карте бури-буфера работать в буфере org.

Это оказалось самым простым решением для меня:

(add-hook 'org-mode-hook
      (lambda ()
        (local-unset-key (kbd "C-c C-b"))))

Ответ 4

Установите use-package, eval и вы закончите:

(require 'bind-key)
(bind-key* "C-i" 'some-function)

Ответ 5

Несмотря на то, что ответ scottfrazer - это именно то, о чем вы просили, я упомянул для потомков другое решение.

Из Руководство Emacs:

"Не определяйте букву Cc в качестве ключа в программах Lisp. Последовательности, состоящие из Cc и буквы (верхнего или нижнего регистра), зарезервированы для пользователей, они являются единственными последовательностями, зарезервированными для пользователей, поэтому не выполняйте блокировать их."

Если вы привязываете свои личные глобальные привязки к C-c плюс письмо, тогда вы "должны" быть в безопасности. Однако это просто соглашение, и любой режим все еще может переопределить ваши привязки.

Ответ 6

Если вы хотите "всегда использовать привязки клавиш на карте, если я явно не переопределяю их для определенной карты режима", и если вы используете подход 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))

So

(locally-override "\C-i" nil)

следует удалить привязку "\ C-i" из второстепенного режима только в текущем буфере. Предупреждение: это полностью непроверено, но похоже на правильный подход. Точка установки родительского объекта, а не просто преодоление глобального значения my-keys-minor-mode-map, так что любые последующие изменения глобального значения автоматически отражаются в локальном значении.

Ответ 7

Я не думаю, что ты можешь. Это примерно эквивалентно утверждению, что вы хотите определить глобальную переменную, которая не может быть скрыта локальными объявлениями переменных в функциях. Сфера просто не работает.

Однако, может быть способ написать функцию elisp, чтобы пройти через список режимов и переназначить ее в каждом из них для вас.

Ответ 8

Если вы действительно не захотите сделать это самостоятельно, вы должны проверить и посмотреть, сделал ли кто-нибудь еще это.

Существует пакет для Emacs, который дает ваши окна-подобные привязки. Вы можете найти его через google.