如何找到哪个文件提供(d)emacs elisp中的功能

Tal*_*Kit 6 emacs elisp

目前我正在使用load-history变量来查找功能来自哪个文件.

假设找到gnus来自的特征文件.

我在暂存缓冲区中执行以下代码,它连续地在单独的行中打印文件名和符号.

(dolist (var load-history)
  (princ (format "%s\n" (car var)))
  (princ (format "\t%s\n" (cdr var))))
Run Code Online (Sandbox Code Playgroud)

然后搜索"(提供.gnus)"然后将该点移动到行的开头(Ctrl + A).上一行中的文件名是该功能来自的文件.

这种方法有什么问题,或者存在更好的方法.

eve*_*_jr 8

我真的不知道你在尝试做什么,但这里有一些注意事项.

  • 你的方法很好.在我的书中,任何破解你自己的问题解决方案的方法都是好的.

  • @Tom是正确的,你不应该真的需要这样做,因为问题已经由帮助系统解决了.即C-h f

但那不是那么有趣.假设你真的想要一个自动,更优雅的解决方案.你想要一个功能 - locate-feature有这个签名:

(defun locate-feature (feature)
  "Return file-name as string where `feature' was provided"
  ...)
Run Code Online (Sandbox Code Playgroud)

方法1的load-history方法

我将描述我为解决这个问题所采取的步骤:

  1. 您已经拥有了最重要的部分 - 使用您需要的信息查找变量.

  2. 我立即注意到这个变量有很多数据.如果我将它作为单行插入缓冲区,Emacs将不会感到高兴,因为它在处理长行时非常糟糕.我知道prett-print软件包可以很好地格式化这些数据.所以我打开我的*scratch*缓冲区并运行

    M-: (insert (pp-to-string load-history))

  3. 我现在可以看到我正在处理的数据结构.它似乎是(伪代码):

    ((file-name
      ((defun|t|provide . symbol)|symbol)*)
     ...)
    
    Run Code Online (Sandbox Code Playgroud)
  4. 现在我只写函数

    (eval-when-compile (require 'cl))
    (defun locate-feature (feature)
      "Return file name as string where `feature' was provided"
      (interactive "Sfeature: ")
      (dolist (file-info load-history)
        (mapc (lambda (element)
                (when (and (consp element)
                           (eq (car element) 'provide)
                           (eq (cdr element) feature))
                  (when (called-interactively-p 'any)
                    (message "%s defined in %s" feature (car file-info)))
                  (return (car file-info))))
              (cdr file-info))))
    
    Run Code Online (Sandbox Code Playgroud)

    这里的代码很简单.向Emacs询问您不理解的功能.

方法2帮助方法

方法一适用于功能.但是如果我想知道定义任何可用函数的位置呢?不只是功能.

C-h f已经告诉我了,但是我想要一个字符串中的文件名,而不是所有详细的帮助文本.我要这个:

(defun locate-function (func)
  "Return file-name as string where `func' was defined or will be autoloaded"
  ...)
Run Code Online (Sandbox Code Playgroud)

开始了.

  1. C-h f是我的出发点,但我真的想阅读定义的代码describe-function.我这样做:

    C-h k C-h f C-x o tab enter

  2. 现在我help-fns.el的定义是describe-function.我想只使用这个函数定义.所以缩小是有序的:

    C-x n d

  3. 我有一种预感,有趣的命令会在其名称中"找到"或"找到",所以我occur用来搜索有趣的行:

    M-s o find\|locate

    无匹配.嗯.在这个defun中没有很多线. describe-function-1似乎在做真正的工作,所以我们试试.

  4. 我可以访问describe-function-1via 的定义C-h f.但我已经打开了文件. imenu现已上市:

    C-x n w M-x imenu desc*1 tab enter

  5. 缩小并再次搜索:

    C-x n d M-s o up enter

    我看哪find-lisp-object-file-name看起来很有希望.

  6. 看完之后C-h f find-lisp-object-file-name我想出来:

    (defun locate-function (func)
      "Return file-name as string where `func' was defined or will be autoloaded"
      (interactive "Ccommand: ")
      (let ((res (find-lisp-object-file-name func (symbol-function func))))
        (when (called-interactively-p 'any)
          (message "%s defined in %s" func res))
        res))
    
    Run Code Online (Sandbox Code Playgroud)

现在去探索Emacs吧.