Bagaimana Anda memperbarui definisi mode minor saat Anda mengembangkannya?

13

Saya mulai mengkode mode minor untuk memberikan beberapa keybindings. Upaya awal saya salah ketik:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(([b] . 'previous-line)))

Saya berniat untuk menggunakan bkunci, dan segera menyadari bahwa saya harus menggunakan "b"bukan [b]. Jadi saya mendefinisikan kembali mode minor:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(("b" . 'previous-line)))

Namun, ini tidak berhasil. Ini membuat saya mengejar angsa liar melalui semua berbagai cara mengikat kunci (yaitu, (kbd ...), [...], dll). Akhirnya saya menyadari bahwa hanya mengevaluasi ulang (define-minor-mode ...)formulir itu tidak mengubah apa pun, saya terjebak dengan peta kunci yang asli dan rusak. Saya kemudian mencoba mengubah keymap secara langsung melalui (define-key borked-mode-map ...)dan masih tidak bisa mendapatkan keymap yang diperbaiki. Akhirnya saya me-restart Emacs, dan mode minor saya dimuat dengan benar.

Pertanyaan saya adalah: bagaimana Anda memperbarui definisi mode minor saat Anda mengembangkannya? Apakah ada cara untuk menghapus definisi yang rusak, atau Anda harus me-restart emacs untuk membersihkan bit yang rusak?

Tyler
sumber

Jawaban:

11

Pertama kali Anda mengevaluasi, define-minor-modeia menentukan variabel borked-mode-mapdengan ikatan utama yang Anda tentukan. Namun, setelah simbol itu ditetapkan, mengevaluasi kembali simbol Anda define-minor-modetidak akan mengubahnya.

Anda dapat menghapus berbagai borked-mode-xxxsimbol menggunakan uninterndan kemudian mengevaluasi kembali kode Anda. Mencoba:

(unintern 'borked-mode-map)

Anda mungkin tertarik memperluas define-minor-modemakro untuk melihat apa yang sebenarnya dilakukannya. Masukkan titik di akhir dan panggilan M-x pp-macroexpand-last-sexp. Ini akan membuka buffer baru yang memperlihatkan makro yang diperluas. Di sana Anda akan melihat defvarpanggilan yang digunakan untuk mengatur variabel mode Anda. Jika Anda membaca bantuan untuk defvarAnda akan melihat bahwa nilai awal hanya digunakan jika simbol yang didefinisikan batal - begitu ada, defvarpanggilan selanjutnya tidak akan mengubah nilainya.

glukas
sumber
13

Saya pikir jawaban terbaik yang bisa saya berikan kepada Anda adalah untuk menjauh dari "fitur inline keybindings" dari define-minor-mode. Menggunakan

(defvar borked-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map [b] 'previous-line)
    ...
    map))

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  :global nil
  ...)

Sebagai gantinya. Kemudian Anda dapat menggunakan C-M-xuntuk mengevaluasi kembali definisi tersebut.

Stefan
sumber
1
defvartidak akan mengevaluasi nilainya lagi setelah C-M-x:) Anda perlu defparameteratau terpisah setf.
wvxvw
Sebagaimana ditunjukkan @wvxvw, ini tidak benar-benar mengatasi masalah. Contoh kode Anda melakukan hal yang sama seperti yang dilakukan oleh define-minor-modemakro: memanggil defvaruntuk menentukan peta. Mengevaluasi defvar itu untuk kedua kalinya tidak berpengaruh.
glucas
7
@wvxvw Jika Anda menggunakan C-M-x( eval-defun) untuk mengevaluasi kembali defvarvariabelnya diperbarui. Ini adalah kasus khusus di eval-defun; jika Anda menelepon eval-bufferatau eval-regionkemudian nilai yang ada tidak berubah.
Gilles 'SANGAT berhenti menjadi jahat'
Ah - sepertinya itu poin kuncinya.
glucas
1
Perhatikan bahwa C-M-xpada defvarformulir hanya memperbarui variabel peta mode itu sendiri. Anda juga harus C-M-xpada define-minor-modeformulir untuk mengubah peta yang 'terpasang' ke mode minor. Saya mencoba mencari tahu mengapa dengan memperluas makro, tetapi itu di luar kemampuan saya.
Tyler