刚开始使用emacs,经常使用C-h f
查询函数,配置了ivy
后,发现counsel-describe-function
不能查询一些没有require
文件中的函数(除了autoload
的函数),而emacs -Q
后describe-function
却能够查到。不知道这该怎么解决。
比如,在没有执行(require 'find-lisp)
的情况下:
counsel-describe-function
无法查找到函数find-lisp-find-files
,而describe-function
却可以。
恐怕是 vanilla emacs 没有 lazy load 该包,而是直接加载了,所以你能查到吧。一个验证方法是在 vanilla emacs 中加载 ivy 然后看下 counsel 能否查询同一函数。
1 个赞
ivy查找函数的方式比较简单 核心的代码是
(let (cands)
(mapatoms
(lambda (x)
(when (fboundp x)
(push (symbol-name x) cands))))
(length cands))
而emacs查找的方式比较复杂(我没有完全理解)
应该是通过文件的前缀找到相应的函数
C-h v help-definition-prefixes
应该感谢emacs的编码规范 让函数可以通过前缀而找到
不可以:
~ $ emacs -Q --batch --eval "(describe-function 'find-lisp-find-files)"
Symbol’s function definition is void: find-lisp-find-files
~ $ emacs -Q --batch --eval "(describe-function 'describe-function)"
Type C-x 1 to delete the help window, C-M-v to scroll help.
~ $
如果一个函数没加载(或者想象一个不存在的函数),任何版本的 describe-function
都不会有结果。此外,像 @et2010 所提到的,一个用户常常并不能确定一个 Elisp 文件有没有被加载,以及在何时被加载了。
能。其实 Emacs -Q 会得到同样的结果,但是这样我得要文字说明或者截个图,没有「Show me the code」来得方便。
Emacs -Q 直接调用 describe-function
确实查不到 find-lisp-find-files
,不过通过交互式调用 describe-function
是可以查询到 find-lisp-find-files
的,感觉有点神奇
根据上面的一些回复,估计你观察到的是 Emacs 26 的新特性,类似于,describe-function
在补全期间,如果输入 foo-bar
,它会自动加载 foo.el
,即便 foo-bar
并没有被 autoload。这是 counsel-describe-function
所没有的功能,因为它有自己的补全方法,类似的 Helm-mode 下的 describe-function
也没这功能。
2 个赞
相关实现的代码在 ldefs-boot.el
下的:
(register-definition-prefixes "find-lisp" '("find-lisp-"))
et2010
12
跟 counsel 没关系,我在 Vanilla Emacs 中使用 counsel 一样可以找到函数:
关键问题是 spacemacs,doom 等都大量使用 lazy load。
注意 counsel-describe-function 的说明,已经说了是 forward 到 describe-function 的,也就是说两者完全一样的:
所以楼主的问题准确来说,应该是为什么 Vanilla Emacs 可以找到函数,而楼主的配置不能找到函数? 答案也很简单,因为楼主的配置使用了 lazy load。
1 个赞
还有一种情况不我能理解,当我使用spacemacs (emacs version 26.1.50, develop branch, ivy layer)的时候。
启动spacemacs,SPC h d f 查找find-lisp-find-files (其他相似的函数也可以),没有查询结果。
当我关闭了ivy-mode和counsel-mode,然后再查找函数,就能得到返回结果了。
et2010
15
表面上看是这样的,但是实际的原因是开始的时候 find-lisp
并没有加载,然后你调用 ivy-mode
或 counsel-mode
命令的时候加载了。你可以用 (featurep 'find-lisp)
验证这一点。开始的时候结果是 nil,关闭 ivy 后结果是 t
我是实验的结果是关闭ivy和counsel后,(featurep 'find-lisp)
的结果还是nil, 然后我试着查询find-lisp-
然后按下tab
补全(这时候 ivy-mode
和counsel-mode
是关闭的),出现了*Completions* buffer
后再C-x o
切换窗口执行 (featurep 'find-lisp)
,结果为t
(这时候查询操作还没完成)
et2010
17
是的,我没仔细看是那个函数加载了 find-lisp,但是大意就是那样。
Vanilla Emacs 中使用 describe-function
会触发文件加载,而启用ivy-mode
或使用counsel-describe-function
不会。
还有能够找到没有require文件中函数好像是因为loaddefs
,
find-library loaddefs
可以查到一行
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "find-lisp" '("find-lisp-")))
2 个赞