Làm cách nào để liên kết các khóa của bạn với các keymap chưa được tải?


9

Tôi sử dụng use-packageđể quản lý các gói đã cài đặt và bind-keygán các hành động cho các khóa tùy chỉnh mà tôi thích.

Tôi ghi đè hầu hết các liên kết phím mặc định của Emacs (ví dụ: C-ntrở thành M-k, C-ptrở thành M-i), nhưng tôi ổn với các chế độ khác ghi đè lên sơ đồ liên kết phím của tôi. Tuy nhiên, đôi khi tôi muốn khóa phím của tôi vẫn tồn tại. Tôi muốn M-kcó ý nghĩa khác, hơn là mặc định Gnus hoặc Helm.

Tuy nhiên, tất cả chúng xung đột với nhau khi khởi động Emacs, vì tôi không thể thêm ràng buộc vào sơ đồ phím, nếu nó không tồn tại (vì use-packageđôi khi trì hoãn việc tải gói). Ví dụ: các lệnh sau ném lỗi (ví dụ (void-variable helm-map)), vì Helm và Gnus chưa được tải đầy đủ.

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

Tôi có tất cả các use-packageyêu cầu của mình trong một tệp và bind-keycho các phím bấm tùy chỉnh trong một tệp khác. Tôi không muốn đưa các ràng buộc vào use-packagecác cuộc gọi, bởi vì có lẽ tôi muốn xuất bản lược đồ liên kết khóa tùy chỉnh của mình dưới dạng một gói độc lập. Điều gì sẽ xảy ra nếu tôi muốn ai đó cài đặt lược đồ của mình có khóa phím cục bộ Helm và Gnus quá mức?

Làm cách nào để tôi quản lý các khóa phím cục bộ bằng cách sử dụng bind-key, sao cho tất cả các khóa được đặt ngay cả khi các gói được tải gần đây và tất cả các cài đặt khóa nằm trong một tệp?

Câu trả lời:


20

Bạn có thể sử dụng with-eval-after-loadđể trì hoãn ràng buộc khóa cho đến khi một mô-đun nhất định được tải (và do đó xác định sơ đồ bàn phím):

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

Sử dụng C-h v helm-mapđể tìm mô-đun mà sơ đồ bàn phím được xác định, và do đó, những gì cần đặt trong chuỗi trên dòng đầu tiên.


with-eval-after-loadđã được giới thiệu trong Emacs 24.4. Nếu bạn có phiên bản Emacs trước đó, bạn cần sử dụng eval-after-loadthay thế và đặt một trích dẫn trước bind-keycuộc gọi:

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

Nếu bạn muốn thực hiện một số bind-keycuộc gọi trong biểu mẫu này, với with-eval-after-loadbạn chỉ cần thực hiện từng cuộc gọi khác, nhưng với eval-after-loadbạn cần phải gói tất cả chúng trong một 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

Giải pháp

Để thực thi công cụ sau khi một gói nhất định được tải, bạn cần đặt nó sau khi :configvào use-package.

Đây là một ví dụ sử dụng đoạn trích trong câu hỏi của bạn:

Đoạn trích số 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))

Giải trình

Bạn có thể có 2 đoạn mã dưới đây ở các vị trí khác nhau trong emacs của bạn init.elhoặc trong bất kỳ tệp lồng nhau nào được tải / yêu cầu.

Đoạn trích số 2

(use-package gnus)

Đoạn số 3

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

Lý do là không có vấn đề gì trong số 2 đoạn trên được thực hiện trước.

Đây là lý do tại sao .. dưới đây là những gì Snippet # 3 mở rộng.

Bạn nhận được bên dưới bằng cách thực hiện M-x pp-macroexpand-last-sexpkhi điểm (con trỏ) nằm sau dấu ngoặc đơn đóng cuối cùng của đoạn mã đó.

Đoạn số 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)

Đoạn mã trên về cơ bản có nghĩa là

  • gnusđược yêu cầu đầu tiên và sau đó bind-keybiểu mẫu được thực thi.
  • Nếu gnuskhông tìm thấy thì bạn sẽ thấy một thông báo trong bộ đệm * Tin nhắn * nói rằng gói đó không thể được tải.
  • Nó sẽ ném lỗi nếu có bất kỳ vấn đề trong việc thực thi (bind-key "M-s" #'other-window gnus-summary-mode-map)

Ngoài ra, nếu Snippet # 2gnus đã yêu cầu ở trên và được Snippet # 3 yêu cầu lại , điều đó không quan trọng vì không tải lại gói nếu nó đã được tải.require


Tài liệu tham khảo

Từ những use-packageđiều cơ bản trên github của nó,

:configcó thể được sử dụng để thực thi mã sau khi gói được tải. Trong trường hợp tải được thực hiện một cách lười biếng (xem thêm về tự động tải bên dưới), việc thực thi này được hoãn lại cho đến sau khi quá trình tự động tải xảy ra:

Đoạn số 5

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

Ở trên thực hiện :initphần ( (setq foo-variable t)) trước khi foo gói được tải. Nhưng (foo-mode 1)trong :configphần được thực hiện sau khi foo được tải.


3

Ngược lại với các câu trả lời khác, tôi đã luôn sử dụng móc cho việc này:

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

Tôi cũng vậy, tôi nghĩ rằng đây là cách làm ưa thích.
Tên người dùng có ý nghĩa

2

Vì bạn đã sử dụng khóa liên kết, trực tiếp từ tài liệu về bind-key.el:

Nếu bạn muốn khóa phím ghi đè tất cả các chế độ nhỏ cũng có thể liên kết cùng khóa, hãy sử dụng biểu mẫu `bind-key * ':

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

Để hủy liên kết một khóa trong sơ đồ bàn phím (ví dụ: để ngăn chế độ chính yêu thích của bạn thay đổi một ràng buộc mà bạn không muốn ghi đè ở mọi nơi), hãy sử dụng khóa không ràng buộc:

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

Biểu mẫu cuối cùng bị hỏng nếu sơ đồ bàn phím hiện chưa được xác định do tệp xác định some-other-mode-mapchưa được tải. Vì vậy, bạn có thể đặt cái này trong một use-packagefor some-other-mode(gói xác định some-other-mode-map) hoặc sử dụng with-eval-after-load:

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

Một cách khác sẽ là xác định chế độ nhỏ của riêng bạn chứa tất cả các ràng buộc không bị ghi đè bởi các chế độ chính:

(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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.