Ghi đè toàn cầu liên kết khóa trong Emacs


100

Làm cách nào để tôi có thể đặt một liên kết khóa ghi đè toàn cục và được ưu tiên hơn tất cả các ràng buộc khác cho khóa đó? Tôi muốn ghi đè tất cả các bản đồ chế độ chính / phụ và đảm bảo rằng ràng buộc của tôi luôn có hiệu lực.

Tất nhiên điều này không hoạt động:

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

Nó hoạt động trong text-mode, nhưng khi tôi sử dụng lisp-mode, C-ibị phục hồi lisp-indent-line.

Tôi có thể xem qua và ghi đè ràng buộc này trong lisp-modevà trong mọi chế độ khác riêng lẻ, nhưng phải có một cách dễ dàng hơn. Mỗi khi tôi cài đặt một chế độ mới cho một loại tệp mới, tôi phải quay lại và kiểm tra để đảm bảo rằng tất cả các ràng buộc chính của tôi không bị chế độ mới ghi đè.

Tôi muốn làm điều này vì tôi muốn mô phỏng các ràng buộc mà tôi đã học và hiểu sâu từ các trình soạn thảo khác.

Câu trả lời:


149

Tôi sử dụng một chế độ nhỏ cho tất cả các ràng buộc khóa "ghi đè" của mình:

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

Điều này có thêm lợi ích là có thể tắt tất cả các sửa đổi của tôi trong một lần rơi (chỉ cần tắt chế độ nhỏ) trong trường hợp ai đó đang điều khiển bàn phím hoặc nếu tôi cần xem ràng buộc phím mặc định làm gì.

Lưu ý rằng bạn có thể cần phải tắt tính năng này trong bộ đệm nhỏ:

(defun my-minibuffer-setup-hook ()
  (my-keys-minor-mode 0))

(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)

1
Đây có vẻ là một ý kiến ​​hay. Có cách nào để đảm bảo chế độ phụ của bạn không chiến đấu với các chế độ phụ khác không?
Brian Carper

3
Đảm bảo rằng chế độ nhỏ của bạn nằm đầu tiên trong danh sách chế độ nhỏ-chế độ bản đồ-alist.
Trey Jackson

2
Trey nói đúng. Thường đặt cái này gần cuối .emac của bạn là đủ. Ngoài ra, hầu hết các ràng buộc mà bạn ghi đè sẽ là những ràng buộc mà các chế độ chính đang thiết lập ... các chế độ phụ thường không có lợi.
scottfrazer

Tôi đã làm theo cách tiếp cận này, nhưng sau đó tôi nhận ra rằng bất cứ thứ gì tôi liên kết với Ci cũng bị ràng buộc với khóa TAB. Bất kỳ đề xuất?
Steve

3
Brian Carper: Đây là một cải tiến để đối phó với các chế độ nhỏ được tải sau đó: stackoverflow.com/questions/683425/…
phils

30

Như một phần bổ sung cho câu trả lời của scottfrazer , tôi đã viết phần sau để các keybinding của tôi vẫn được ưu tiên, ngay cả khi các thư viện được tải sau đó mang đến các keymap mới của riêng chúng.

Bởi vì sơ đồ bàn phím có thể được tạo tại thời điểm biên dịch, loadcó vẻ như đây là nơi tốt nhất để làm điều này.

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

Tôi dán kịch bản của bạn nhưng nó không thực hiện bất kỳ ảnh hưởng :(
Alper

@alper Tôi khuyên bạn nên đăng một câu hỏi với tất cả các chi tiết liên quan, bao gồm mã bạn đang thực sự sử dụng và một ví dụ / công thức cụ thể để tái tạo vấn đề.
phils

20

Cài đặt use-package, đánh giá và bạn đã hoàn tất:

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

5
Chỉ cài đặt bind-key là đủ cho trường hợp sử dụng, mặc dù use-package phụ thuộc vào bind-key.
xuchunyang

2
Đây (gói 'bind-key') dường như là giải pháp thuận tiện nhất; cám ơn vì đã chia sẻ.
oligilo

Tôi không thể tìm thấy kết quả phù hợp cho use-package:Install package: use-package [No Match]
alper

14

Tôi đã tìm thấy câu hỏi này trong khi tìm kiếm "emacs undefine keybindings chế độ tổ chức", vì tôi muốn hủy liên kết hành vi Cc Cb hiện có để cho phép bản đồ toàn cầu của tôi chôn bộ đệm hoạt động trong bộ đệm tổ chức.

Đây là giải pháp đơn giản nhất đối với tôi:

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

1
Đây là chế độ cụ thể và không giải quyết bức tranh lớn hơn mặc dù nó hoạt động cho trường hợp sử dụng duy nhất của bạn.
RichieHH

12

Mặc dù câu trả lời của scottfrazer là chính xác những gì bạn yêu cầu, tôi sẽ đề cập cho hậu thế một giải pháp khác.

Từ Hướng dẫn sử dụng Emacs :

"Không định nghĩa chữ cái Cc là một khóa trong các chương trình Lisp. Các chuỗi bao gồm Cc và một chữ cái (viết hoa hoặc viết thường) được dành riêng cho người dùng; chúng là các chuỗi duy nhất dành riêng cho người dùng, vì vậy đừng chặn chúng."

Nếu bạn ràng buộc các ràng buộc toàn cầu cá nhân của mình với Cc cộng với một chữ cái, thì bạn "nên" được an toàn. Tuy nhiên, đây chỉ là một quy ước và bất kỳ chế độ nào vẫn có thể ghi đè các ràng buộc của bạn.


3
Tôi không mong đợi chế độ tổ chức, trong tất cả các chế độ, sẽ phá vỡ quy tắc này. `` Cc Ch 'cho tôi biết rằng Cc a, b, c và l tương ứng với org-agenda, org-iswitchb, org-capture và org-store-link.
Nate Parsons

7
Afaik, ràng buộc đây là bước đầu tiên mà chế độ tổ chức đề xuất để sử dụng nó, nhưng người dùng phải tự xác định chúng (tức là nó không được thực hiện theo mặc định) và có thể chọn bất kỳ chế độ nào khác trong khi làm như vậy. (cũng có, đó là bởi vì những cam kết ràng buộc có nghĩa vụ phải có tính toàn cầu, không bị ràng buộc để chế độ chính org)
Nikana Reklawyks

3

Nếu bạn muốn "luôn sử dụng keybinds trong bản đồ, trừ khi tôi ghi đè rõ ràng chúng cho một bản đồ chế độ cụ thể" và giả sử bạn đang sử dụng phương pháp của scottfrazier , bạn muốn:

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

Vì thế

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

chỉ nên xóa ràng buộc "\ Ci" khỏi chế độ nhỏ trong bộ đệm hiện tại. Cảnh báo: điều này hoàn toàn chưa được kiểm tra, nhưng có vẻ là cách tiếp cận đúng. Quan điểm của việc đặt giá trị gốc thay vì chỉ đối phó với giá trị toàn cục của my-key-small-mode-map là vì vậy bất kỳ thay đổi nào sau này đối với giá trị toàn cục đều được tự động phản ánh trong giá trị cục bộ.


2

Tôi không nghĩ bạn có thể. Điều đó gần tương đương với việc bạn muốn xác định một biến toàn cục không thể bị ẩn bởi các khai báo biến cục bộ trong các hàm. Phạm vi không hoạt động theo cách đó.

Tuy nhiên, có thể có một cách để viết một hàm elisp để xem qua danh sách chế độ và gán lại nó trong từng chế độ cho bạn.


Ý tưởng về phạm vi này đúng về mặt kỹ thuật, nhưng overriding-local-mapđược thiết kế đặc biệt để ghi đè lên tất cả các bản đồ khác. Tuy nhiên, thật nguy hiểm khi sử dụng nó.
event_jr

2

Trừ khi bạn thực sự muốn tự mình làm điều này, bạn nên kiểm tra xung quanh và xem có ai khác đã làm điều đó hay không.

Có một gói cho Emacs cung cấp các liên kết bàn phím giống như cửa sổ của bạn. Bạn sẽ có thể tìm thấy nó thông qua google.


4
Gói bạn đang nghĩ đến có lẽ là cua-mode.
Drew

1
Vâng, đó là gói.
JesperE
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.