Bagaimana cara mengikat kunci Anda ke kartu kunci yang belum dimuat?

9

Saya menggunakan use-packageuntuk mengelola paket yang diinstal dan bind-keyuntuk menetapkan tindakan ke tombol kustom yang saya suka.

Saya menimpa sebagian besar penjilidan kunci Emacs default (misalnya C-nmenjadi M-k, C-pmenjadi M-i), tapi saya OK dengan mode lain mengabaikan skema penjilidan kunci saya. Kadang-kadang, saya ingin pengikat kunci saya bertahan. Saya ingin M-kberarti sesuatu yang lain, daripada di default Gnus atau Helm.

Namun mereka semua bertentangan satu sama lain pada startup Emacs, karena saya tidak dapat menambahkan ikatan ke keymap, jika itu tidak ada (karena use-packagekadang-kadang menolak pemuatan paket). Misalnya, perintah berikut melempar kesalahan (misalnya (void-variable helm-map)), karena Helm dan Gnus belum dimuat sepenuhnya.

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

Saya memiliki semua use-packagedoa saya di satu file dan bind-keyuntuk keybindings kustom di file lain. Saya tidak ingin memasukkan binding ke dalam use-packagepanggilan, karena mungkin saya ingin mempublikasikan skema pengikat kunci khusus saya sebagai paket mandiri. Bagaimana jika saya ingin seseorang menginstal skema saya dan Helm dan Gnus keybindings lokal saya juga diganti?

Bagaimana cara saya mengelola ikatan kunci mode-lokal menggunakan bind-key, sehingga semua kunci diatur bahkan jika paket dimuat akhir-akhir ini, dan semua pengaturan kunci berada di dalam satu file?

Mirzhan Irkegulov
sumber

Jawaban:

20

Anda dapat menggunakan with-eval-after-loaduntuk menunda pengikatan kunci sampai setelah modul tertentu dimuat (dan dengan demikian mendefinisikan keymap):

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

Gunakan C-h v helm-mapuntuk menemukan modul mana keymap didefinisikan, dan dengan demikian apa yang akan dimasukkan ke dalam string pada baris pertama.


with-eval-after-loaddiperkenalkan di Emacs 24.4. Jika Anda memiliki versi Emacs sebelumnya, Anda harus menggunakannya eval-after-load, dan letakkan satu kutipan di depan bind-keypanggilan:

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

Jika Anda ingin melakukan beberapa bind-keypanggilan dalam formulir ini, with-eval-after-loadcukup masukkan satu per satu, tetapi eval-after-loadAnda harus membungkusnya semua dalam 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)))
legoscia
sumber
9

Larutan

Dalam melaksanakan hal-hal setelah paket yang diberikan dimuat, Anda harus menempatkan bahwa setelah :configdi use-package.

Berikut ini contoh menggunakan cuplikan dalam pertanyaan Anda:

Cuplikan # 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))

Penjelasan

Tidak apa-apa untuk memiliki 2 snippet di bawah ini di berbagai tempat di emacs Anda init.elatau di salah satu file yang di-load / diperlukan.

Cuplikan # 2

(use-package gnus)

Cuplikan # 3

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

Alasannya adalah bahwa tidak masalah yang mana dari 2 cuplikan di atas yang dieksekusi terlebih dahulu.

Inilah alasannya .. di bawah ini adalah tujuan Snippet # 3.

Anda mendapatkan di bawah ini dengan melakukan M-x pp-macroexpand-last-sexpketika titik (kursor) adalah setelah kurung tutup terakhir dari potongan itu.

Cuplikan # 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)

Cuplikan di atas pada dasarnya berarti demikian

  • gnusdiperlukan pertama dan kemudian bind-keyformulir dieksekusi.
  • Jika gnustidak ditemukan maka Anda akan melihat pesan di buffer * Pesan * yang mengatakan bahwa paket itu tidak dapat dimuat.
  • Itu akan melempar kesalahan jika ada masalah dalam mengeksekusi (bind-key "M-s" #'other-window gnus-summary-mode-map)

Juga jika gnussudah diminta oleh Cuplikan # 2 di atas dan diminta kembali oleh Cuplikan # 3 , itu tidak masalah karena requiretidak memuat paket lagi jika sudah dimuat.


Referensi

Dari use-packagedasar - dasar pada github-nya,

:configdapat digunakan untuk mengeksekusi kode setelah paket dimuat. Dalam kasus di mana pemuatan dilakukan dengan malas (lihat lebih lanjut tentang autoloading di bawah), eksekusi ini ditangguhkan hingga setelah terjadi pengisian otomatis:

Cuplikan # 5

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

Di atas menjalankan :initbagian ( (setq foo-variable t)) sebelum foo paket dimuat. Tetapi (foo-mode 1)di :configbagian ini dijalankan setelah foo dimuat.

Kaushal Modi
sumber
3

Berlawanan dengan jawaban lain, saya selalu menggunakan pengait untuk ini:

(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)
Jesse
sumber
Saya juga, saya pikir ini adalah cara yang disukai untuk melakukannya.
Nama pengguna yang berarti
2

Karena Anda sudah menggunakan bind-key, langsung dari dokumentasi bind-key.el:

Jika Anda ingin pengikat tombol menimpa semua mode minor yang juga dapat mengikat kunci yang sama, gunakan formulir `bind-key * ':

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

Untuk melepaskan ikatan sebuah kunci dalam keymap (misalnya, untuk menghentikan mode utama favorit Anda dari mengubah ikatan yang tidak ingin Anda timpa di mana-mana), gunakan unbind-key:

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

Formulir terakhir rusak jika keymap saat ini tidak terdefinisi karena file mendefinisikan some-other-mode-mapbelum dimuat. Jadi Anda bisa meletakkan ini dalam use-packagefor some-other-mode(paket mendefinisikan some-other-mode-map), atau menggunakan with-eval-after-load:

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

Alternatif lain akan mendefinisikan mode minor Anda sendiri yang berisi semua binding yang tidak boleh diganti oleh mode utama:

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