Timpa pengikatan kunci secara global di Emacs

100

Bagaimana cara menyetel pengikatan kunci yang secara global menimpa dan didahulukan dari semua pengikatan lain untuk kunci itu? Saya ingin menimpa semua peta mode mayor / minor dan memastikan pengikatan saya selalu berlaku.

Ini tentu saja tidak berhasil:

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

Ini bekerja text-mode, tetapi ketika saya menggunakan lisp-mode, C-irebound ke lisp-indent-line.

Saya dapat melewati dan mengesampingkan pengikatan ini dalam lisp-modedan dalam setiap mode lainnya secara individual, tetapi harus ada cara yang lebih mudah. Setiap kali saya menginstal mode baru untuk jenis file baru, saya harus kembali dan memeriksa untuk memastikan bahwa semua binding kunci saya tidak diganti oleh mode baru.

Saya ingin melakukan ini karena saya ingin meniru binding yang telah saya pelajari dan tertanam dari editor lain.

Brian Carper
sumber

Jawaban:

149

Saya menggunakan mode minor untuk semua binding kunci "timpa" saya:

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

Ini memiliki manfaat tambahan untuk dapat mematikan semua modifikasi saya dalam satu gerakan (cukup nonaktifkan mode minor) jika ada orang lain yang mengendarai keyboard atau jika saya perlu melihat apa yang dilakukan pengikatan tombol default.

Perhatikan bahwa Anda mungkin perlu mematikannya di minibuffer:

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

(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)
scottfrazer.dll
sumber
1
Sepertinya ini ide yang bagus. Adakah cara untuk memastikan mode minor Anda tidak bertarung dengan mode minor lainnya?
Brian Carper
3
Pastikan mode minor Anda pertama di daftar mode-minor-map-alist.
Trey Jackson
2
Trey benar. Biasanya meletakkan ini di dekat akhir .emacs Anda sudah cukup. Selain itu, sebagian besar binding yang akan Anda timpa adalah yang diatur oleh mode utama ... mode minor biasanya tidak menghalangi.
scottfrazer
Saya mengikuti pendekatan ini, tetapi kemudian saya menyadari bahwa apa pun yang saya ikat ke Ci juga terikat ke kunci TAB. Ada saran?
Steve
3
Brian Carper: Berikut peningkatan untuk menangani mode minor yang dimuat selanjutnya: stackoverflow.com/questions/683425/…
phils
30

Sebagai tambahan untuk jawaban scottfrazer , saya telah menulis yang berikut ini sehingga keybindings saya tetap diutamakan, bahkan jika perpustakaan yang dimuat selanjutnya membawa peta kunci baru mereka sendiri.

Karena peta kunci dapat dibuat pada waktu kompilasi, loadsepertinya tempat terbaik untuk melakukannya.

(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))))
phils
sumber
Saya menempelkan skrip Anda tetapi tidak berpengaruh apa pun :(
alper
@alper Saya menyarankan agar Anda memposting pertanyaan dengan semua detail yang relevan, termasuk kode yang sebenarnya Anda gunakan, dan contoh / resep khusus untuk mereproduksi masalah.
phils
21

Instal use-package, evaluasi, dan Anda selesai:

(require 'bind-key)
(bind-key* "C-i" 'some-function)
Mirzhan Irkegulov
sumber
5
Instal hanya bind-key sudah cukup untuk kasus penggunaan, meskipun paket penggunaan bergantung pada kunci-bind.
xuchunyang
2
Ini (paket 'bind-key') tampaknya merupakan solusi yang paling nyaman; Terima kasih telah berbagi.
oligilo
Saya tidak dapat menemukan yang cocok untuk use-package:Install package: use-package [No Match]
alper
14

Saya menemukan pertanyaan ini saat mencari "emacs undefine org mode keybindings", karena saya ingin melepaskan perilaku Cc Cb yang ada agar peta global saya dapat mengubur buffer untuk bekerja di buffer org.

Ini akhirnya menjadi solusi paling sederhana bagi saya:

(add-hook 'org-mode-hook
      (lambda ()
        (local-unset-key (kbd "C-c C-b"))))
Jay Doane
sumber
1
Ini adalah mode khusus dan tidak membahas gambaran yang lebih besar meskipun itu berfungsi untuk kasus penggunaan tunggal Anda.
RichieHH
12

Meskipun jawaban scottfrazer persis seperti yang Anda minta, saya akan menyebutkan solusi lain untuk anak cucu.

Dari The Emacs Manual :

"Jangan mendefinisikan huruf Cc sebagai kunci dalam program Lisp. Urutan yang terdiri dari Cc dan huruf (baik huruf besar atau kecil) disediakan untuk pengguna; mereka adalah satu-satunya urutan yang disediakan untuk pengguna, jadi jangan blokir mereka."

Jika Anda mengikat ikatan global pribadi Anda ke Cc plus surat, maka Anda "harus" aman. Namun, ini hanyalah konvensi, dan mode apa pun masih dapat menggantikan binding Anda.

Kirkland
sumber
3
Saya tidak mengharapkan mode org, dari semua mode, untuk melanggar aturan ini. `Cc Ch 'memberi tahu saya bahwa Cc a, b, c, dan l masing-masing terikat ke org-agenda, org-iswitchb, org-capture, dan org-store-link.
Nate Parsons
7
Afaik, mengikat ini adalah langkah pertama yang disarankan org-mode untuk menggunakannya, tetapi pengguna harus menentukannya sendiri (yaitu tidak dilakukan secara default), dan dapat memilih yang lain saat melakukannya. (juga, itu karena binding ini seharusnya global, tidak terikat ke mode mayor org)
Nikana Reklawyks
3

Jika Anda ingin "selalu menggunakan keybinds di peta, kecuali saya secara eksplisit menimpanya untuk peta mode tertentu", dan dengan asumsi Anda menggunakan pendekatan scottfrazier , Anda ingin:

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

Begitu

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

harus menghapus pengikatan "\ Ci" dari mode minor di buffer saat ini saja. Peringatan: ini sama sekali belum teruji, tetapi sepertinya pendekatan yang tepat. Inti dari menyetel induk daripada hanya mengatasi nilai global my-keys-minor-mode-map adalah agar setiap perubahan selanjutnya pada nilai global secara otomatis tercermin dalam nilai lokal.

gbrunick.dll
sumber
2

Saya tidak berpikir Anda bisa. Itu kira-kira sama dengan mengatakan bahwa Anda ingin mendefinisikan variabel global yang tidak dapat disembunyikan oleh deklarasi variabel lokal dalam fungsi. Cakupan tidak berfungsi seperti itu.

Namun, mungkin ada cara untuk menulis fungsi elisp melalui daftar mode dan menetapkannya kembali di setiap satu untuk Anda.

TED
sumber
Ide pelingkupan ini secara teknis benar, tetapi overriding-local-mapsecara khusus dirancang untuk menimpa semua peta lainnya. Namun berbahaya untuk menggunakannya.
event_jr
2

Kecuali jika Anda benar-benar ingin melakukannya sendiri, Anda harus memeriksa dan melihat apakah ada orang lain yang telah melakukannya.

Ada paket untuk Emacs yang memberikan keybindings mirip windows Anda. Anda harus dapat menemukannya melalui google.

JesperE
sumber
4
Paket yang Anda pikirkan mungkin adalah cua-mode.
Mundur
1
Ya, itulah paketnya.
JesperE