Bagaimana cara masuk ke mode hanya melihat saat menelusuri kode sumber Emacs dari bantuan?

10

Ketika saya menelusuri Emacs help for functions via C-h f, saya sering ingin mengintip implementasi Elisp / C. Saya ingin memasukkan view-modesecara otomatis ketika saya mengakses kode sumber dengan cara ini untuk menghindari modifikasi yang tidak perlu. Apakah ada kaitan atau fungsi yang bisa saya sarankan untuk menyelesaikan ini?

rasional revolt
sumber
2
Inilah yang saya gunakan untuk mencegah modifikasi yang tidak disengaja dari semua file saya yang terbuka emacs-lisp-modedan saya hanya melakukan C-x C-qjika saya ingin mengedit kode sumber. (defun set-buffer-read-only () (setq buffer-read-only t)) (add-hook 'emacs-lisp-mode-hook 'set-buffer-read-only)
hukum

Jawaban:

2

Pembaruan (setelah tidur malam): Jawaban ini memiliki kelemahan besar: ini memungkinkan view-modeketika menavigasi ke fungsi apa pun , bukan hanya sumber Emacs. Ini bisa diperbaiki, tetapi Anda lebih baik menggunakan jawaban oleh @phils .

Dengan melakukan C-h f describe-function RETdan kemudian membaca kode sumber describe-functionsaya menemukan bahwa itu menciptakan "tombol" dari jenis khusus untuk link ke definisi fungsi: help-function-def.

Berjalan zrgrepdengan string ini (" help-function-def") mengarahkan saya ke help-mode.el.gz.

Setelah semua penggalian ini, kita dapat mengganti jenis tombol ini dengan milik kita sendiri (perhatikan komentar dalam kode):

(define-button-type 'help-function-def
  :supertype 'help-xref
  'help-function (lambda (fun file)
               (require 'find-func)
               (when (eq file 'C-source)
                 (setq file
                       (help-C-file-name (indirect-function fun) 'fun)))
               ;; Don't use find-function-noselect because it follows
               ;; aliases (which fails for built-in functions).
               (let ((location
                      (find-function-search-for-symbol fun nil file)))
                 (pop-to-buffer (car location))
                 (if (cdr location)
                     (goto-char (cdr location))
                   (message "Unable to find location in file")))
                   (view-mode t)) ; <= new line: enable view-mode
  'help-echo (purecopy "mouse-2, RET: find function's definition"))

Sejauh yang saya tahu tidak ada fungsi untuk menambahkan saran: Emacs menggunakan di lambdasini. Di sisi lain (seperti yang ditunjukkan oleh @rationalrevolt ) seseorang dapat mengganti help-functionproperti dari help-function-defjenis tombol:

(require 'help-mode)
(let ((help-func (button-type-get 'help-function-def 'help-function)))
  (button-type-put 'help-function-def 'help-function
                   `(lambda (func file)
                      (funcall ,help-func func file) (view-mode t))))
Constantine
sumber
1
Saya pikir saya bisa mencoba menggunakan button-type-getdan button-type-putmengganti lambda dengan milik saya sendiri yang meneruskan ke lambda yang ada.
rasional
@rationalrevolt: Ide bagus! (Tampaknya agak rapuh, tetapi saya kira ini juga rapuh.)
Constantine
@rationalrevolt: Silakan lihat jawaban yang diperbarui. (Sepertinya tidak ada baris baru dalam komentar, ...)
Constantine
Terima kasih! Saya mencoba sesuatu yang serupa tetapi menjadi seorang pemula untuk elisp saya digigit oleh ikatan dinamis dan tidak bisa mendapatkan penutupan saya untuk bekerja :)
rationalrevolt
16

Anda dapat menggunakan variabel direktori-lokal untuk membuat file sumber Emacs hanya-baca secara default. (Lihat juga C-hig (emacs) Directory Variables RET).

Buat file yang disebut .dir-locals.eldi root pohon direktori yang ingin Anda lindungi, dengan konten berikut:

((nil . ((eval . (view-mode 1)))))

Sunting: Michał Politowski menunjukkan dalam komentar bahwa mengaktifkan view-modedengan cara ini bermasalah, karena ketika Anda mengabaikan buffer dengan qitu juga menonaktifkan mode, yang berarti bahwa lain kali Anda mengunjungi buffer view-modeitu tidak akan diaktifkan.

Sunting 2: Constantine telah memberikan solusi untuk masalah itu di komentar di bawah:

((nil . ((eval . (when buffer-file-name (view-mode-enter nil #'kill-buffer))))))

Ini berguna menambahkan tes untuk memastikan bahwa buffer sudah mengunjungi file, tetapi perubahan kuncinya adalah penggunaan view-mode-enteralih-alih view-mode, karena yang pertama mengambil EXIT-ACTIONargumen yang menentukan apa yang harus dilakukan ketika qdiketik. Dalam hal ini tindakan keluar adalah untuk membunuh buffer, memastikan bahwa waktu berikutnya file dikunjungi lagi akan berakhir view-mode.

Sunting 3: Mengikuti jalur itu, kita juga dapat melihat bahwa yang ditentukan EXIT-ACTIONakhirnya diteruskan ke view-mode-exitfungsi, dan docstringnya memberi kita solusi alternatif:

view-no-disable-on-exit is a variable defined in `view.el'.
Its value is nil

Documentation:
If non-nil, View mode "exit" commands don't actually disable View mode.
Instead, these commands just switch buffers or windows.
This is set in certain buffers by specialized features such as help commands
that use View mode automatically.

Maka kita dapat menggunakan yang berikut ini:

((nil . ((eval . (when buffer-file-name
                   (setq-local view-no-disable-on-exit t)
                   (view-mode-enter))))))

Saya menggunakan pendekatan alternatif yang dapat Anda tentukan seluruhnya dalam file init Anda (sebagai lawan membuat .dir-locals.elfile), dan saya hanya membuat file read-only daripada menggunakan view-mode. Konfigurasi saya terlihat seperti ini:

;; Emacs
(dir-locals-set-class-variables
 'emacs
 '((nil . ((buffer-read-only . t)
           (show-trailing-whitespace . nil)
           (tab-width . 8)
           (eval . (whitespace-mode -1))))))

(dir-locals-set-directory-class "/usr/local/src/emacs" 'emacs)
(dir-locals-set-directory-class "/usr/local/share/emacs" 'emacs)
(dir-locals-set-directory-class "/usr/share/emacs" 'emacs)

Jelas Anda dapat melakukan hal yang sama untuk direktori elpa Anda, dan direktori lain yang berisi kode sumber pihak ketiga.

phils
sumber
Bagus! Ini jelas lebih baik dari apa yang saya pikirkan. (Apa yang saya pikirkan? Saya tahu dan menggunakan .dir-locals.eldiri saya sendiri ...)
Constantine
Saya telah melakukan sesuatu yang sama berdasarkan daftar find-file-hookdan read-only-dirsdaftar, tapi saya suka pendekatan ini.
glukas
Ini terlihat seperti pendekatan yang sangat bersih. Saya punya satu masalah kecil. Dengan cara ((nil . ((eval . (view-mode 1)))))apa yang paling sederhana untuk membuat View-quitkill buffer diakses melalui bantuan? Jika tidak setelah keluar dari tampilan sumber dengan menekan q, buffer tetap berada di belakang dan ketika nanti mengakses sumber dari file yang sama dari bantuan lagi mode tampilan tidak dimulai.
Michał Politowski
Michał Politowski: Benar sekali. Saya telah memperbarui jawaban untuk memasukkan fakta itu, tetapi saya tidak punya solusinya. Jawaban Constantine (yang diedit) mungkin merupakan solusi terbaik untuk digunakan view-mode.
phils
1
Hari ini saya menemukan bahwa saya perlu solusi untuk masalah yang ditunjukkan oleh @ MichałPolitowski --- dan saya menemukan satu: gunakan ((nil . ((eval . (when buffer-file-name (view-mode-enter nil #'kill-buffer))))))(perhatikan (view-mode-enter ...)bukan (view-mode 1)). Dengan cara ini menekan qmembunuh buffer dan view-mode ini memungkinkan kali saya kunjungi file yang sama.
Constantine
0

Saya pikir yang Anda butuhkan hanyalah menambahkan sebuah kait :

(add-hook 'find-function-after-hook 'view-mode)
sds
sumber
Ini lebih baik daripada keburukan saya, tetapi masih tidak benar-benar cocok dengan pertanyaan: itu menyala view-modeketika menavigasi ke fungsi apa pun menggunakan C-h f, bukan hanya sumber Emacs.
Constantine
Secara eksperimental, tautan bantuan tidak benar-benar menjalankan hook ini. Sepertinya hanya find-THINGperintah interaktif yang menggunakan kait ini, dan tombol bantuan memintasnya.
phils
0

Ini tidak membahas kasus spesifik Anda, tetapi kasus yang lebih umum beralih ke view-modesetiap kali Anda mengunjungi file sumber dari buffer bantuan. Saya menawarkannya sebagai alternatif untuk jawaban @ Constantine, karena itu tidak dapat dibaca sebagai komentar.

Sepertinya saya mendapat ini dari EmacsWiki .

(defadvice find-function-search-for-symbol (after view-function-source last (symbol type library) activate)
  "When visiting function source via Help, switch to view-mode"
  (with-current-buffer (car ad-return-value)
    (view-mode 1)))

(defadvice find-variable-noselect (after view-var-source last (variable &optional file) activate)
  "When visiting variable source via Help, switch to view-mode"
  (with-current-buffer (car ad-return-value)
    (view-mode 1)))
glukas
sumber
0

Berikut adalah solusi yang berfungsi untuk dokumentasi internal dan contoh yang menunjukkan cara memperluasnya ke ELPA. Ini bekerja dengan mencocokkan jalur ke file saat ini terhadap beberapa regex dan menerapkan read-only-modejika ada yang cocok.

Perhatikan bahwa buffer tersebut hanya dapat dibaca jika Anda mengunjunginya diredjuga, tidak hanya melalui bantuan.

Saya menambahkan hook yang berjalan setelah memasukkan emacs-lisp-modeyang memeriksa apakah path ke file cocok /\.el\.gz$/, dan menerapkan mode read-only jika ya.

(defun readonly-if-el-gz ()
  (cond
   ((string-match "\\.el\\.gz\\'" (or (buffer-file-name) ""))
    (read-only-mode +1))))

(add-hook 'emacs-lisp-mode-hook 'readonly-if-el-gz)

Berikut adalah contoh yang memeriksa ELPA juga, menggunakan heuristik bahwa setiap jalur yang mengandung .emacs.d/elpasebenarnya adalah kode ELPA.

(defun readonly-if-internal ()
  (let
      ((name (or (buffer-file-name) "")))
    (cond
     ((string-match "\\.el\\.gz\\'" name) (read-only-mode +1))
     ((string-match "\\.emacs\\.d/elpa" name) (read-only-mode +1)))))

(add-hook 'emacs-lisp-mode-hook 'readonly-if-internal)
Gregory Nisbet
sumber