Answers:
更新(经过一夜的睡眠):这个答案有一个主要缺陷: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
其替换为我自己的lambda。
您可以使用目录本地变量将Emacs的源文件默认设置为只读。(另请参见C-hig (emacs) Directory Variables
RET)。
.dir-locals.el
在要保护的目录树的根目录中创建一个名为的文件,其内容如下:
((nil . ((eval . (view-mode 1)))))
编辑: MichałPolitowski在注释中指出,view-mode
以这种方式启用是有问题的,因为当您使用q它关闭缓冲区时,也会禁用该模式,这意味着下次访问该缓冲区时view-mode
将不会启用。
编辑2:君士坦丁在以下评论中提供了该问题的解决方案:
((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
函数,它的文档字符串为我们提供了另一种解决方案:
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))))))
我使用另一种方法,您可以在初始化文件中完全指定它(而不是创建.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
list,我一直走得很近,但是我喜欢这种方法。
((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
是使下一次我访问同一个文件。
这不会解决您的特定情况,而是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的示例。它通过将某些正则表达式匹配到当前文件的路径并在read-only-mode
它们中的任何一个匹配时应用而起作用。
请注意,如果您也通过缓冲区访问缓冲区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)
这也是一个使用启发式检查任何路径.emacs.d/elpa
实际上都是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)