У глобальному масштабі перекриття прив’язки ключів у Emacs


100

Як я можу встановити прив'язку ключів, яка глобально перекриває та має перевагу над усіма іншими прив’язками для цього ключа? Я хочу змінити всі основні / другорядні карти режимів і переконатися, що моє прив'язка завжди діє.

Це, звичайно, не працює:

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

Він працює text-mode, але коли я його використовую lisp-mode, C-iвідновлюється lisp-indent-line.

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

Я хочу це зробити, тому що я хочу наслідувати прив’язки, про які я вже дізнався і вписався в інші редактори.

Відповіді:


149

Я використовую мінорний режим для всіх моїх прив'язок клавіш:

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

1
Це здається гарною ідеєю. Чи є спосіб переконатися, що ваш другорядний режим не бореться з іншими другорядними режимами?
Брайан Карпер

3
Переконайтеся, що ваш другорядний режим є першим у списку мінорних карт-списків.
Трей Джексон

2
Трей правильно. Зазвичай вистачає цього в кінці вашого .emacs достатньо. Крім того, більшість прив’язок, які ви перекриєте, були б тими, які встановлюють основні режими ... незначні режими, як правило, залишаються поза дорогою.
scottfrazer

Я дотримувався цього підходу, але потім зрозумів, що все, що я пов’язую з Ci, також прив'язується до ключа TAB. Будь-які пропозиції?
Стів

3
Брайан Carper: Ось розширення , щоб мати справу з послідовно-навантаженими режимами мінорними: stackoverflow.com/questions/683425 / ...
Филс

30

Як додаток до відповіді скоттфраззера , я написав наступне, щоб мої клавіатурні зв'язки зберігали перевагу, навіть якщо бібліотеки, що завантажуються згодом, вводять нові власні карти клавіш.

Оскільки ключові карти можна створити під час компіляції, 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))))

Я вставив ваш сценарій, але це ніяк не вплинуло :(
alper

@alper Я пропоную надіслати запитання з усіма відповідними деталями, включаючи код, який ви фактично використовуєте, та конкретний приклад / рецепт для відтворення проблеми.
філс

21

Встановіть use-package, eval, і ви закінчите:

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

5
Для випадку використання достатньо встановити лише ключ зв’язку, хоча пакет використання залежить від ключа-прив’язки.
xuchunyang

2
Цей пакет («прив’язаний ключ») здається найзручнішим рішенням; Дякую, що поділились.
олигіло

Я не зміг знайти матч для use-package:Install package: use-package [No Match]
alper

14

Я знайшов це питання під час пошуку "emacs undefine org mode keybindings", тому що я хотів відключити існуючу поведінку Cc Cb, щоб дозволити моїй глобальній карті закопувати буфер для роботи в org буфері.

Це для мене стало найпростішим рішенням:

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

1
Це специфічно для режиму і не стосується більшої картини, навіть якщо це працює для вашого окремого випадку використання.
RichieHH

12

Хоча відповідь Scottfrazer - це саме те, про що ви просили, я згадаю для нащадків інше рішення.

З посібника Emacs :

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

Якщо ви прив’язуєте свої особисті глобальні посилання на Cc плюс лист, то ви "повинні" бути в безпеці. Однак це лише умова, і будь-який режим все ще може перекрити ваші прив’язки.


3
Я не сподівався, що в усіх режимах org-mode буде порушено це правило. `Cc Ch 'говорить мені, що Cc a, b, c і l зобов'язані відповідно до org-порядку денця, org-iswitchb, org-capture і org-store-link.
Нейт Парсонс

7
Afaik, прив'язуючи їх, це перший крок org-mode пропонує для його використання, але користувач повинен визначити їх сам (тобто це не робиться за замовчуванням), і може вибрати будь-який інший, роблячи це. (також тому, що ці прив'язки повинні бути глобальними, а не пов'язані з основним режимом org)
Nikana Reklawyks

3

Якщо ви хочете "завжди використовувати в'язки клавіш на карті, якщо я явно не перекриваю їх для конкретного режиму карти", і припускаючи, що ви використовуєте підхід 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, тому будь-які пізніші зміни глобального значення автоматично відображаються в локальному значенні.


2

Я не думаю, що ти можеш. Це приблизно рівнозначно тому, що ви хочете визначити глобальну змінну, яку не можна приховати локальними оголошеннями змінної у функціях. Обсяг просто не працює таким чином.

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


Ця ідея визначення масштабу є технічно правильною, але overriding-local-mapспеціально розроблена для зміни всіх інших карт. Однак користуватися ним небезпечно.
event_jr

2

Якщо ви дійсно не хочете зробити це самостійно, вам слід оглянутись і побачити, чи ще хтось це зробив.

Є пакет для Emacs, який надає ваші Windows схожі клавіші. Ви повинні знайти його через Google.


4
Пакет, про який ви думаєте, мабуть cua-mode.
Дрю

1
Так, це пакет.
JesperE
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.