เมื่อฉันเรียกดู 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)