เมื่อฉันเรียกดู Emacs ช่วยฟังก์ชั่นผ่านC-h fฉันมักจะมองเข้าไปในการใช้งาน Elisp / C ฉันต้องการป้อนview-modeอัตโนมัติเมื่อฉันเข้าถึงซอร์สโค้ดด้วยวิธีนี้เพื่อหลีกเลี่ยงการแก้ไขที่ไม่จำเป็น มีตะขอหรือฟังก์ชั่นที่ฉันสามารถแนะนำให้ทำสิ่งนี้ได้หรือไม่?
เมื่อฉันเรียกดู Emacs ช่วยฟังก์ชั่นผ่านC-h fฉันมักจะมองเข้าไปในการใช้งาน Elisp / C ฉันต้องการป้อนview-modeอัตโนมัติเมื่อฉันเข้าถึงซอร์สโค้ดด้วยวิธีนี้เพื่อหลีกเลี่ยงการแก้ไขที่ไม่จำเป็น มีตะขอหรือฟังก์ชั่นที่ฉันสามารถแนะนำให้ทำสิ่งนี้ได้หรือไม่?
คำตอบ:
อัปเดต (หลังจากนอนหลับตอนกลางคืน):คำตอบนี้มีข้อบกพร่องที่สำคัญ: ช่วยให้view-modeเมื่อนำทางไปยังฟังก์ชั่นใด ๆไม่เพียง แต่แหล่ง Emacs นี้สามารถแก้ไขได้ แต่คุณดีกว่าการใช้คำตอบโดย @phils
โดยการทำC-h f describe-function RETแล้วการอ่านรหัสที่มาของdescribe-functionผมค้นพบว่ามันจะสร้าง "ปุ่ม" help-function-defชนิดพิเศษสำหรับการเชื่อมโยงไปยังคำจำกัดความของฟังก์ชั่น:
เล่นzrgrepกับสตริงนี้ (" help-function-def") help-mode.el.gzชี้ให้ฉันไป
หลังจากขุดทั้งหมดนี้ไปรอบ ๆ เราสามารถแทนที่ปุ่มประเภทนี้ด้วยของเราเอง (หมายเหตุความคิดเห็นในรหัส):
(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"))
เท่าที่ฉันสามารถบอกได้ว่าไม่มีฟังก์ชั่นในการเพิ่มคำแนะนำ: Emacs ใช้lambdaที่นี่ ในทางกลับกัน (ตามที่ระบุโดย@rationalrevolt ) เราสามารถแทนที่help-functionคุณสมบัติของhelp-function-defประเภทปุ่มได้:
(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))))
button-type-getและbutton-type-putแทนที่แลมบ์ดาด้วยตัวเองซึ่งส่งต่อไปเป็นแลมบ์ดาที่มีอยู่
คุณสามารถใช้ตัวแปรไดเรกทอรีท้องถิ่นเพื่อทำให้ไฟล์ต้นฉบับของ Emacs เป็นแบบอ่านอย่างเดียวโดยค่าเริ่มต้น (ดูเพิ่มเติมที่C-hig (emacs) Directory Variables RET)
สร้างไฟล์ชื่อ.dir-locals.elที่รูทของทรีไดเรกทอรีที่คุณต้องการป้องกันโดยมีเนื้อหาดังต่อไปนี้:
((nil . ((eval . (view-mode 1)))))
แก้ไข: Michał Politowski ชี้ให้เห็นในความคิดเห็นที่การเปิดใช้งานview-modeในลักษณะนี้เป็นปัญหาเพราะเมื่อคุณปิดบัฟเฟอร์ด้วยqมันจะปิดใช้งานโหมดซึ่งหมายความว่าในครั้งต่อไปที่คุณเยี่ยมชมบัฟเฟอร์view-modeนั้นจะไม่เปิดใช้งาน
แก้ไข 2: Constantine ได้มอบวิธีแก้ไขปัญหาดังกล่าวในความคิดเห็นด้านล่าง:
((nil . ((eval . (when buffer-file-name (view-mode-enter nil #'kill-buffer))))))
สิ่งนี้มีประโยชน์เพิ่มการทดสอบเพื่อให้แน่ใจว่าบัฟเฟอร์กำลังเยี่ยมชมไฟล์อยู่แล้ว แต่การเปลี่ยนแปลงที่สำคัญคือการใช้view-mode-enterแทนที่จะview-modeเป็นเพราะก่อนหน้านี้จะมีการEXIT-ACTIONโต้แย้งซึ่งกำหนดว่าจะทำอย่างไรเมื่อqมีการพิมพ์ view-modeในกรณีนี้การกระทำทางออกคือการฆ่าบัฟเฟอร์เพื่อให้มั่นใจว่าครั้งต่อไปที่ไฟล์จะเข้าเยี่ยมชมอีกครั้งจะสิ้นสุดใน
แก้ไข 3:ตามเส้นทางนั้นเราจะเห็นได้ว่าในEXIT-ACTIONที่สุดการส่งผ่านที่ระบุไปยังview-mode-exitฟังก์ชันและ docstring ของมันทำให้เรามีทางเลือกอื่น:
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.
ดังนั้นเราสามารถใช้สิ่งต่อไปนี้:
((nil . ((eval . (when buffer-file-name
(setq-local view-no-disable-on-exit t)
(view-mode-enter))))))
ผมใช้วิธีทางเลือกที่คุณสามารถระบุทั้งหมดในแฟ้มของคุณ init (เมื่อเทียบกับการสร้าง.dir-locals.elไฟล์) view-modeและฉันก็ทำให้ไฟล์อ่านอย่างเดียวมากกว่าการใช้ การกำหนดค่าของฉันมีลักษณะเช่นนี้:
;; 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)
เห็นได้ชัดว่าคุณสามารถทำสิ่งเดียวกันสำหรับไดเรกทอรี elpa ของคุณและไดเรกทอรีอื่น ๆ ที่มีซอร์สโค้ดของบุคคลที่สาม
.dir-locals.elตัวเอง ... )
find-file-hookและread-only-dirsรายการ แต่ฉันชอบวิธีนี้
((nil . ((eval . (view-mode 1)))))วิธีที่ง่ายที่สุดที่จะทำให้View-quitฆ่าบัฟเฟอร์เข้าถึงได้ผ่านทางความช่วยเหลือคืออะไร? มิฉะนั้นหลังจากออกจากมุมมองต้นฉบับโดยการกดqบัฟเฟอร์จะอยู่ด้านหลังและเมื่อเข้าถึงภายหลังจากไฟล์เดียวกันจากความช่วยเหลืออีกครั้งโหมดดูจะไม่เริ่มขึ้น
view-modeคำตอบอาจจะเป็นทางออกที่ดีที่สุดสำหรับการใช้
((nil . ((eval . (when buffer-file-name (view-mode-enter nil #'kill-buffer))))))(หมายเหตุ(view-mode-enter ...)แทน(view-mode 1)) วิธีนี้กดqฆ่าบัฟเฟอร์และview-mode มีการเปิดใช้งานครั้งต่อไปที่เราจะไปเยี่ยมไฟล์เดียวกัน
ฉันคิดว่าสิ่งที่คุณต้องการคือการเพิ่มเบ็ด :
(add-hook 'find-function-after-hook 'view-mode)
view-modeเมื่อนำทางไปยังฟังก์ชั่นใด ๆ ที่ใช้C-h fไม่ใช่แค่แหล่ง Emacs
find-THINGคำสั่งเชิงโต้ตอบเท่านั้นที่ใช้เบ็ดนี้และปุ่มวิธีใช้จะข้ามไป
นี่ไม่ได้ระบุกรณีและปัญหาของคุณโดยเฉพาะ แต่กรณีทั่วไปมากขึ้นของการสลับไปที่view-modeเมื่อใดก็ตามที่คุณเยี่ยมชมไฟล์ต้นฉบับจากบัฟเฟอร์ความช่วยเหลือ ฉันเสนอเป็นทางเลือกสำหรับคำตอบของ @ Constantine เนื่องจากไม่สามารถอ่านเป็นความคิดเห็นได้
ฉันดูเหมือนว่าฉันเดิมได้นี้จาก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)))
ต่อไปนี้เป็นโซลูชันที่ใช้งานได้กับเอกสารในตัวและตัวอย่างที่แสดงวิธีการขยายไปยัง ELPA มันทำงานได้โดยการจับคู่พา ธ ไปยังไฟล์ปัจจุบันกับบาง regexes และนำไปใช้read-only-modeถ้ามันตรงกับ
โปรดทราบว่าบัฟเฟอร์นั้นเป็น read-only-ified หากคุณเยี่ยมชมผ่านdiredเช่นกันไม่ใช่แค่ผ่านความช่วยเหลือ
ฉันเพิ่มตะขอที่รันหลังจากป้อนemacs-lisp-modeแล้วตรวจสอบว่าเส้นทางไปยังไฟล์ตรงกัน/\.el\.gz$/หรือไม่และใช้โหมดอ่านอย่างเดียวหากทำได้
(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)
นี่คือตัวอย่างที่ตรวจสอบ ELPA ด้วยโดยใช้ฮิวริสติกว่าเส้นทางใด ๆ ที่มี.emacs.d/elpaอยู่นั้นเป็นรหัสของ 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)
emacs-lisp-modeและฉันจะทำC-x C-qถ้าฉันต้องการแก้ไขซอร์สโค้ด(defun set-buffer-read-only () (setq buffer-read-only t)) (add-hook 'emacs-lisp-mode-hook 'set-buffer-read-only)