Perbedaan antara pengaturan tombol mode utama dengan hook versus menambahkannya ke peta mode

13

Anggaplah saya telah mengunduh mode utama yang disebut magical-mode, dan ia memiliki keymap ajaib yang disebut magical-mode-map. Mode ini juga menyediakan hook magical-mode-hookyang dijalankan setiap kali magical-modemenjadi mode utama buffer. Sekarang saya ingin memodifikasi file init saya untuk menambahkan beberapa binding kunci kustom untuk digunakan dalam mode itu.

Tampaknya ada (setidaknya) dua cara untuk mengatur ikatan kunci khusus magical-mode. Yang paling sering saya lihat adalah ini:

(defun my-magical-keys ()
  (local-set-key (kbd "C-i") 'previous-line)
  (local-set-key (kbd "C-k") 'next-line)
  (local-set-key (kbd "C-j") 'backward-char)
  (local-set-key (kbd "C-l") 'forward-char))
(add-hook 'magical-mode-hook 'my-magical-keys)

Tetapi juga mungkin untuk melakukannya dengan cara ini:

(define-key magical-mode-map (kbd "C-i") 'previous-line)
(define-key magical-mode-map (kbd "C-k") 'next-line)
(define-key magical-mode-map (kbd "C-j") 'backward-char)
(define-key magical-mode-map (kbd "C-l") 'forward-char)

Metode kedua sebenarnya tampak lebih bersih bagi saya. Apakah ada keuntungan untuk melakukannya satu arah dari yang lain?

nispio
sumber
Saya menggunakan tombol yang sama untuk perintah gerakan dasar. Diperingatkan: ini adalah perjuangan berat dan Anda mungkin ingin belajar sedikit lebih banyak tentang ikatan utama sebelum Anda mulai melakukan ini.
tarsius
@tarsius Memang benar-benar perjuangan yang berat. Saya sudah turun bahwa jalan sebelumnya, tapi sekarang saya kembali ke baik ol' C-ndan C-p. Contohnya hanyalah kode dummy. Saya ingin membuat beberapa contoh mode yang sangat sederhana dan contoh binding, tepatnya agar binding itu sendiri tidak mengalihkan perhatian dari tujuan sebenarnya dari pertanyaan itu.
nispio

Jawaban:

15

Pendekatan kedua lebih disukai karena memodifikasi keymap mode hanya sekali.

Jika Anda melakukannya menggunakan pengait mode maka itu akan dipanggil setiap kali mode tersebut diaktifkan di beberapa buffer. Melakukannya lagi biasanya tidak akan benar-benar berpengaruh karena kunci hanya terikat pada apa yang sudah terikat. Kunci mode utama adalah "lokal" ke mode utama, bukan buffer individual yang menggunakan mode itu, jadi jika Anda mengubah pengikatan di salah satu buffer ini menggunakan local-set-keymaka yang mempengaruhi semua buffer dengan mode utama yang sama.

local-set-keyterutama dimaksudkan untuk digunakan sebagai perintah. Setelah Anda menentukan bahwa Anda ingin membuat beberapa perubahan tetap, gunakan define-keydengan mode keymap sebagai argumen pertama.

Jika Anda menggunakan pengait untuk memodifikasi keymap berulang kali maka itu dapat bertentangan dengan tujuan penggunaan local-set-key. Katakanlah Anda menggunakan M-x local-set-key RET C-i fancy-previous-line RETkarena Anda ingin mencoba varian itu previous-line. Jika sekarang Anda membuka buffer baru yang menggunakan mode mayor yang sama, maka hook akan berjalan lagi dan mengesampingkan binding sementara Anda, di semua buffer menggunakan mode mayor itu, termasuk buffer yang sebelumnya Anda gunakan local-set-key.

tarsius
sumber
Saya suka jawaban ini tetapi bagaimana jika mode ini dimuat secara otomatis?
remvee
2
Anda dapat menunda memuat kode apapun sampai setelah beberapa perpustakaan telah dimuat: (eval-after-load 'magical '(progn (define-key magical-mode-map ...) ...)).
tarsius
4

Penggunaan (define-key my-magical-mode-map …)adalah cara biasa.

Saat Anda menggunakan kait dan local-set-key, tombol ditambahkan setiap kali Anda memasuki mode Magis Saya di beberapa buffer. Ini aneh karena local-set-keymempengaruhi semua buffer yang berada dalam mode yang sama (lebih umum, semua buffer menggunakan keymap yang sama). Jadi, jika Anda telah membuat perubahan pada peta tombol, mereka akan diganti setiap kali Anda memasuki mode Magical Saya di buffer.

Metode kedua juga dapat membingungkan jika Anda menyesuaikan keymap di tempat yang berbeda. Kait dieksekusi dalam urutan terbalik dari urutan ditambahkan, dan sampai pertama kali dieksekusi, Anda tidak akan melihat jejak kustomisasi Anda.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2

Anda tampaknya tidak bertanya tentang mendefinisikan keymap mode-utama tetapi tentang kode pengguna untuk menambah atau mengubah beberapa keybindings dalam keymap mode-utama yang ada . Anda mengatakan "kebiasaan", yang menyarankan ini, tetapi kami mungkin juga menjelaskannya.

Yang pasti, apa yang Anda katakan paling sering Anda lihat untuk ini bukanlah apa yang digunakan secara umum untuk menentukan keymap mode-utama. Hal ini tidak apa yang Anda temukan dalam kode sumber Emacs, misalnya. Dan bukan itu yang direkomendasikan dalam manual Elisp (node Major Mode Conventions).

Hanya ingin menyingkirkan hal itu, menjadi jelas bagi orang lain: Anda biasanya tidak ingin menggunakan pengait mode untuk menentukan peta mode-utama.


Untuk pertanyaan Anda tentang penyesuaian kunci pengguna -

Dalam hal apapun itu bukan local-set-keyyang harus Anda gunakan dalam mode hook. Gunakan saja define-keykeymap mode-utama, persis seperti pada contoh pertama Anda. @tarsius sudah menjelaskan ini dengan baik.

Selain itu, jawabannya adalah: itu membuat sedikit perbedaan, secara umum , apakah Anda mengikat kunci (menggunakan define-keydengan mode peta) sekali dan untuk semua atau Anda menggunakan kait untuk mengikatnya setiap kali Anda memasuki mode.

Tapi itu bisa membuat perbedaan jika binding di peta berubah - misalnya, dengan memuat beberapa kode lain yang mengubahnya. Dalam hal ini, menempatkan binding pada hook mode-utama memastikan bahwa ketika mode dimasukkan binding akan terbentuk. Yaitu, memastikan bahwa mereka akan dibuat, tetapi tidak memastikan bahwa tidak ada lagi yang mengubahnya sesudahnya (misalnya fungsi lain pada kait yang sama, dipanggil setelah itu). Ingatlah bahwa Anda memiliki sedikit kendali atas apa yang dijalankan pada hook dan kapan - kecuali, tentu saja Anda yakin bahwa hanya kode Anda sendiri yang mengacaukannya.

Itulah satu-satunya perbedaan efek, yang dapat saya pikirkan. Bagi Anda untuk memutuskan kapan Anda menganggap perbedaan itu sebagai keuntungan dari satu atau lain pendekatan. FWIW, melihat kode saya sendiri, saya rasa saya tidak pernah mengikat kunci pada mode hook.

Drew
sumber
Terima kasih. Saya telah memodifikasi pertanyaan untuk mudah-mudahan memperjelas fakta bahwa saya tidak membuat mode utama, cukup menambahkan ikatan kunci saya sendiri ke mode utama yang ada .
nispio
0

Penamaan Anda sedikit membingungkan (saya pikir Anda harus menghapus mybagian kedua dari pertanyaan Anda).

Lagi pula dengan asumsi my-magical-keysadalah fungsi kustomisasi pengguna magical-mode, saya melihat satu keuntungan yang jelas. Sangat mudah untuk menghapus (dengan remove-hook) kait dalam sekali jalan.

Keuntungan kedua adalah untuk apa fungsi dimaksudkan. Maksud saya mereka dapat digunakan kembali. Anda dapat mengaitkannya ke mode lain.

Edit:

Seperti yang ditunjukkan oleh @tarsius, melepas kait tidak akan mengembalikan perilaku asli dan mengubah fungsi menjadi mode minor mungkin lebih baik.

kindahero
sumber
Saya menyesuaikan mode utama hipotetis yang disebut my-magical-mode. Namun, jika penggunaan my-awalan membingungkan saya tentu dapat mengedit pertanyaan.
nispio
Ya, itu akan lebih baik, biasanya (setidaknya seperti yang saya lihat di alam liar) my-ditambahkan untuk fungsi pengguna.
kindahero
1
Sepakat. Saya baru saja menerapkan my-sehingga tidak ada yang akan berpikir bahwa saya bertanya bagaimana mengkonfigurasi mode nyata yang disebut magical-mode(jika ada).
nispio
1
Tidak, melepas pengait tidak akan mengembalikan ikatan lama. Setidaknya tidak sampai Emacs dimulai kembali, dan kemudian saya tidak melihat harus mengomentari hanya satu baris, bukan empat sebagai perbaikan besar.
tarsius
2
Adapun keuntungan kedua yang Anda sebutkan: di sini akan lebih disukai untuk membuat mode minor yang kemudian dapat diaktifkan untuk berbagai mode utama dan / atau hanya beberapa buffer menggunakan mode utama tertentu.
tarsius