原本函数的帮助页面会指向函数定义所在的 el 文件(比如图中的 yas-text
给出了 yasnippet.el
的链接)但是我发现有些函数给出的地址是我的配置文件(比如图中的的 yas-global-mode
给出的链接是 ../emacs-config.el
),导致无法直接跳转到函数定义。请问大家有遇到这种情况没?有没有什么解决方法?
我的配置文件是 org 生成的 el,并通过 init.el
里面的 load
函数进行加载。Emacs 版本是 master 版本前几天编译的,但是这个问题很久之前就出现过。猜测可能和 use-package 有关?
补充一个配置:
;; init.el 文件内容
(setq gc-cons-threshold (* 400 (expt 2 20))
gc-cons-percentage 0.6)
(let* ((file-name-handler-alist nil)
(read-process-output-max (expt 2 22)))
(load "~/.emacs.d/emacs-config.el")
;; load-history 是在这里变化的
)
(setq gc-cons-threshold (expt 2 23)
gc-cons-percentage 0.1)
;; emacs-config.el 文件内容
(setq custom-file "~/.emacs.d/customs.el")
(load custom-file t)
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(setq use-package-compute-statistics t)
(straight-use-package 'use-package)
(setq straight-use-package-by-default t) ; Ensure :straight t
(use-package yasnippet
:init (yas-global-mode 1))
(use-package yasnippet-snippets
:after yasnippet)
没有。只有 emacs-config.el
,没有 elc 和 eln。
檢查下 load-history
变量的內容,用 add-variable-watcher
定位是什么地方改了这个变量
和 use-package
不太可能有关系,更可能是 org tangle 的问题。
本身 “autoloaded” 和 “byte-compiled” 不应该同时出现。
1 个赞
load-history
里面 yas-global-mode
出现了两次,位置靠前的一次是在 emacs-config.el
文件下面,另外一次是在 yasnippet.elc
文件下面。 猜测帮助界面里找到了第一个匹配的位置就直接返回了,所以返回的文件是 emacs-config.el
。
我这边 org=>el 是手动进行的,所以在 Emacs 启动的时候并不会进行 org tangle。
我在加载 emacs-config.el
之前,执行了下面这句,但启动的时候并没有打印出东西来 。
(add-variable-watcher 'load-history #'(lambda (sym new op where) (print "HIHI")))
load 不会改变定义的位置,可能是你在 emacs-config.el
执行了 eval 之类的操作。
最好把配置精简一下,验证是否仍然存在问题,把有问题的 emacs-config.el
贴出来。
补充了一下配置,没有明显的 eval
,依然是显示
yas-global-mode is an autoloaded interactive byte-compiled Lisp
function in ‘…/…/…/emacs-config.el’.
就在那句 load
之后才变的,在 emacs-config.el 的最后一行都还没有。 这个也符合预期,load 之后才会加载 load-history 里。
hilde
2022 年8 月 1 日 11:09
11
我也遇到了类似的情况,感觉可能和 master 版本相关
同样的配置,上面的是 28.1.1,下面的是最近几天装的 master 版本
1 个赞
应该不是 Emacs 版本的问题,至少我没有观察到 29.0 有什么不同。
加载时机/顺序的可能性更大。可以用 -Q
做个测试,常规加载方式可能有些隐含的步骤你没有发现:
$ tree /path/to/scratch/emacs/2022-08/test-load/
/path/to/scratch/emacs/2022-08/test-load/
├── bar.el
├── foo.el
└── init.el
0 directories, 3 files
bar.el
;;; bar.el --- Bar package -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(provide 'bar)
;;; bar.el ends here
foo.el
;;; foo.el --- Foo package -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(defun foo-function-toplevel () nil)
(add-hook 'window-setup-hook
(lambda ()
(defun foo-function-after-init () nil)))
(with-eval-after-load 'bar
(defun foo-function-after-bar () nil))
(provide 'foo)
;;; foo.el ends here
init.el
(add-to-list 'load-path (file-name-directory load-file-name))
(load "foo")
(load "bar")
(require 'help-fns)
(defun find-function-library (function)
"Return filename the FUNCTION defined."
(pcase-let* ((`(,_real-function ,def ,aliased ,real-def)
(help-fns--analyze-function function))
(file-name
(find-lisp-object-file-name function (if aliased 'defun def))))
file-name))
(run-with-timer
0.1 nil
(lambda ()
(switch-to-buffer "*Messages*")
(message "foo-function-toplevel : %S" (find-function-library 'foo-function-toplevel))
(message "foo-function-after-init : %S" (find-function-library 'foo-function-after-init))
(message "foo-function-after-bar : %S" (find-function-library 'foo-function-after-bar))))
测试结果:
$ emacs -Q -l /path/to/scratch/emacs/2022-08/test-load/init.el -nw
For information about GNU Emacs and the GNU system, type C-h C-a.
Loading /path/to/scratch/emacs/2022-08/test-load/foo.el (source)...done
Loading /path/to/scratch/emacs/2022-08/test-load/bar.el (source)...done
foo-function-toplevel : "/path/to/scratch/emacs/2022-08/test-load/foo.el"
foo-function-after-init : nil
foo-function-after-bar : "/path/to/scratch/emacs/2022-08/test-load/init.el"
可以看到三个函数分指向不同的位置。其中 (with-eval-after-load ...)
中定义的函数就指向了 init.el
。
1 个赞
mkvoya
2022 年8 月 12 日 08:48
15
我把 symbol-file
函数里面使用 load-history
的地方加了 reverse
,解决了问题。感觉就是顺序的问题,延迟定义的函数在 load-history
里面出现了两次,原有的逻辑用了第一次出现的位置,恰好就是我的配置文件。
;; (pcase-dolist (`(,file . ,elems) load-history) ; 原来的代码
(pcase-dolist (`(,file . ,elems) (reverse load-history))
Hxppdv
2022 年8 月 16 日 14:32
16
我发现我也有这个问题在 emacs 29 上,emacs 28 上没有问题,但是只有在同时使用 straight
和 use-package
的时候才能复现,如果使用 package.el
和 use-package
则一切正常。
init.el 使用 straight
和 use-package
复现
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'use-package)
(straight-use-package 'sudoku)
(use-package sudoku)
的确用 straight 可以重现这个问题,但是非 autoload 函数 不受影响:
$ emacs -Q -l ~/.scratch/emacs/2022-08/test-load-history.el -nw
==> filename in load-history:
(async-start . "~/.scratch/emacs/2022-08/test-load-history.el")
(async-start . "~/.emacs.d/straight/build/async/async.elc")
(async-get . "~/.emacs.d/straight/build/async/async.elc")
==> filename in describe-function:
(async-start . "~/.scratch/emacs/2022-08/test-load-history.el")
(async-get . "~/.emacs.d/straight/build/async/async.el")
test-load-history.el
;;; Usage: /path/to/emacs -nw -Q -l /path/to/test-load-history.el
;;; Date: 2022-08-17_10.04.02
;; @topic https://emacs-china.org/t/topic/21808
(toggle-debug-on-error)
;; ---------------------------------------------------------------------------
;; straight
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
;; ---------------------------------------------------------------------------
;; config
(straight-use-package 'async)
(require 'async)
(defun print-filename-describe-function (function)
"Print filename of FUNCTION you see in `describe-function'."
(require 'help-fns)
(pcase-let* ((`(,_real-function ,def ,aliased ,real-def)
(help-fns--analyze-function function))
(file-name
(find-lisp-object-file-name function (if aliased 'defun def))))
(print (cons function file-name))))
(defun print-filename-load-history (function)
"Print filename of FUNCTION you see in `load-history'."
(mapc (lambda (it)
(when (member (cons 'defun function) (cdr it))
(print (cons function (car it)))))
load-history))
(add-hook 'window-setup-hook
(lambda ()
(switch-to-buffer "*Messages*")
(message "==> filename in load-history:")
(print-filename-load-history 'async-start)
(print-filename-load-history 'async-get)
(message "==> filename in describe-function:")
(print-filename-describe-function 'async-start)
(print-filename-describe-function 'async-get)))
;;; test-load-history.el ends here
1 个赞
Hxppdv
2022 年8 月 17 日 13:52
19
这么看来问题只是关于 straight
,跟 use-package
没啥关系应该。