counsel-describe-function 查询不到函数的问题?

刚开始使用emacs,经常使用C-h f查询函数,配置了ivy后,发现counsel-describe-function不能查询一些没有require文件中的函数(除了autoload的函数),而emacs -Qdescribe-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 文件有没有被加载,以及在何时被加载了。

你用batch调用一个interactive

你确定他能像平常一样吗?

能。其实 Emacs -Q 会得到同样的结果,但是这样我得要文字说明或者截个图,没有「Show me the code」来得方便。

Emacs -Q 直接调用 describe-function 确实查不到 find-lisp-find-files,不过通过交互式调用 describe-function是可以查询到 find-lisp-find-files的,感觉有点神奇

emacs 25.1查不到

emacs 26 可以查的到

三个人都说查的到 你还坚持自己的想法吗?

有什么问题么?

我忘记提我用的是 Emacs 25.3。

根据上面的一些回复,估计你观察到的是 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-"))

跟 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,然后再查找函数,就能得到返回结果了。

表面上看是这样的,但是实际的原因是开始的时候 find-lisp 并没有加载,然后你调用 ivy-modecounsel-mode 命令的时候加载了。你可以用 (featurep 'find-lisp) 验证这一点。开始的时候结果是 nil,关闭 ivy 后结果是 t

我是实验的结果是关闭ivy和counsel后,(featurep 'find-lisp)的结果还是nil, 然后我试着查询find-lisp-然后按下tab补全(这时候 ivy-modecounsel-mode是关闭的),出现了*Completions* buffer后再C-x o切换窗口执行 (featurep 'find-lisp),结果为t(这时候查询操作还没完成)

是的,我没仔细看是那个函数加载了 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 个赞