Як прив’язати ваші ключі до ще не завантажених карт?


9

Я використовую use-packageдля управління встановленими пакунками та bind-keyдля призначення дій спеціальним клавішам, які мені подобаються.

Я перекриваю більшість замовчувань Emacs за замовчуванням (наприклад, C-nстає M-k, C-pстає M-i), але я в порядку з іншими режимами, що змінюють мою схему введення клавіш. Іноді, однак, я хочу, щоб мої клавіші зберігалися. Я хочу M-kмати на увазі щось інше, ніж за замовчуванням Gnus або Helm.

Однак всі вони конфліктують між собою під час запуску Emacs, тому що я не можу додати прив'язку до мапі клавіш, якщо її немає (бо use-packageіноді відкладається завантаження пакета). Наприклад, наступні команди видають помилки (наприклад (void-variable helm-map)), тому що Helm та Gnus ще не повністю завантажені.

(bind-key "M-Y" 'helm-end-of-buffer helm-map)
(bind-key "M-k" 'helm-next-line helm-find-files-map)
(bind-key "M-s" 'other-window gnus-summary-mode-map)

У мене всі use-packageвиклики в одному файлі, а в інших bind-key- власні вкладки ключів. Я не хочу вкладати прив'язки до use-packageдзвінків, тому що, можливо, я хочу опублікувати власну власну схему вкладки клавіш як окремий пакет. Що робити, якщо я хочу, щоб хтось, хто встановлював мою схему, також перекрив місцеві клавіатурні зв'язки Helm та Gnus?

Як я можу керувати локальними режимами клавіш за допомогою bind-key, щоб усі клавіші були встановлені, навіть якщо пакети завантажуються останнім часом, а всі параметри клавіш знаходяться всередині одного файлу?

Відповіді:


20

Ви можете використовувати with-eval-after-loadдля відкладання прив'язки клавіш до тих пір, поки певний модуль не буде завантажений (і таким чином визначено карту клавіш):

(with-eval-after-load "helm"
  (bind-key "M-Y" #'helm-end-of-buffer helm-map))

Використовуйте C-h v helm-mapдля того, щоб знайти, в якому модулі визначено карту клавіш , і тим самим, що слід розмістити в рядку в першому рядку.


with-eval-after-loadбула представлена ​​в Emacs 24.4. Якщо у вас є більш рання версія Emacs, вам потрібно скористатися eval-after-loadзамість цього і поставити одну bind-keyрозмову перед викликом:

(eval-after-load "helm"
  '(bind-key "M-Y" #'helm-end-of-buffer helm-map))

Якщо ви хочете надіслати кілька bind-keyдзвінків у цій формі, with-eval-after-loadви просто покладіть їх один за одним, але разом із ними eval-after-loadпотрібно обгорнути їх у progn:

(eval-after-load "helm"
  '(progn
     (bind-key "M-Y" #'helm-end-of-buffer helm-map)
     (bind-key "M-k" #'helm-next-line helm-find-files-map)))

9

Рішення

Для того , щоб виконати речі після завантаження даного пакета, ви повинні покласти , що після того, як :configв use-package.

Ось приклад використання фрагмента у вашому запитанні:

Фрагмент №1

(use-package helm
  :config
  (progn
    (bind-key "M-Y" #'helm-end-of-buffer helm-map)
    (bind-key "M-k" #'helm-next-line helm-find-files-map)))

(use-package gnus
  :config
  (bind-key "M-s" #'other-window gnus-summary-mode-map))

Пояснення

Добре, щоб у ваших emacs- init.elфайлах або в будь-якому з вкладених файлів завантажувались / потрібні файли нижче двох фрагментів .

Фрагмент №2

(use-package gnus)

Фрагмент №3

(use-package gnus
  :config
  (bind-key "M-s" #'other-window gnus-summary-mode-map))

Причина полягає в тому, що не має значення, який із наведених вище фрагментів виконується першим.

Ось чому .. нижче - до чого розширюється фрагмент №3.

Ви отримуєте нижченаведене, виконуючи, M-x pp-macroexpand-last-sexpколи точка (курсор) знаходиться після останнього закриття дужок цього фрагмента.

Фрагмент №4

(if (not (require 'gnus nil t))
    (ignore (message (format "Could not load %s" 'gnus)))
  (condition-case-unless-debug err
      (bind-key "M-s" #'other-window gnus-summary-mode-map)
    (error
     (ignore
      (display-warning 'use-package
                       (format "%s %s: %s" "gnus" ":config"
                               (error-message-string err))
                       :error))))
  t)

Вищенаведений фрагмент в основному означає це

  • gnusспочатку потрібно, а потім bind-keyвиконується форма.
  • Якщо gnusйого не знайдено, ви побачите повідомлення в буфері * Messages * про те, що цей пакет не вдалося завантажити.
  • Він видасть помилку, якщо є якась проблема у виконанні (bind-key "M-s" #'other-window gnus-summary-mode-map)

Також, якщо gnusцього вже вимагає Snippet №2, і він знову вимагається Snippet №3 , це не має значення, оскільки requireвін не завантажує пакет знову, якщо він уже завантажений.


Довідково

З use-packageоснов його github,

:configможе використовуватися для виконання коду після завантаження пакета. У випадках, коли завантаження проводиться ліниво (див. Докладніше про автоматичне завантаження нижче), це виконання відкладається, поки не відбудеться автоматичне завантаження:

Фрагмент №5

(use-package foo
  :init
  (setq foo-variable t)
  :config
  (foo-mode 1))

Вище виконує :initрозділ ( (setq foo-variable t)) перед foo завантаженням пакету. Але (foo-mode 1)в :configрозділі виконується після foo завантаження.


3

З іншого боку, я завжди використовував гачки для цього:

(defun my-company-maps()
  (define-key company-active-map "\C-x\M-h" 'company-show-doc-buffer)
  (define-key company-active-map "\C-n" 'company-select-next)
  (define-key company-active-map "\C-p" 'company-select-previous)
  (define-key company-active-map "\C-h" 'delete-backward-char))

(add-hook 'company-mode-hook 'my-company-maps)

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

2

Оскільки ви вже використовуєте bind-key, прямо з документації bind-key.el:

Якщо ви хочете, щоб прив'язка клавіш заміняла всі незначні режими, які також можуть пов'язувати один і той же ключ, скористайтеся формою `bind-key * ':

(bind-key* "<C-return>" 'other-window)

Щоб від’єднати ключ у картці (наприклад, для того, щоб улюблений основний режим не міняв прив'язку, яку ви не хочете переосмислювати скрізь), використовуйте клавішу unbind:

(unbind-key "C-c x" some-other-mode-map)

Остання форма руйнується, якщо в даний час параметр клавіш не визначений, оскільки визначення файлу some-other-mode-mapще не завантажено. Таким чином, ви можете поставити це в use-packageдля some-other-mode(визначає пакет some-other-mode-map) або скориставшись with-eval-after-load:

(with-eval-after-load 'some-other-mode
  (unbind-key "C-c x" some-other-mode-map))

Іншою альтернативою може бути визначення вашого власного другорядного режиму, що містить усі прив’язки, які не повинні перекривати основні режими:

(defvar my-very-own-keymap (make-keymap) "my very own keymap.")

(define-key my-very-own-keymap (kbd "M-i") 'my-foo)

(define-minor-mode my-very-own-keys-minor-mode
  "Minor mode with my very own keybindings."
  t " my-own-keys" my-very-own-keymap)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.