Emacs中Lisp的位置

3

我在哪里可以找到所有 Emacs 的 elisp 脚本?我不是指用户开发或安装的脚本,而是已经存在的常见 elisp 脚本。

例如,

如果我有一个像 describe-charinsert-file 这样的函数,我该如何找到包含这些函数的文件?


2
M-x find-function-other-windowM-x find-variable-other-window。我已经设置了 (global-set-key (kbd "C-h F") 'find-function-other-window)(global-set-key (kbd "C-h V") 'find-variable-other-window)。我的模式行设置为显示打开缓冲区中显示的文件路径。一旦文件打开,您还可以使用 M-x describe-variable RET buffer-file-name,这将为您提供完整的路径。 - lawlist
当然,C-h F有一个相当有用的默认绑定,所以我建议选择一个未使用的绑定。我的选择是C-h C-f;虽然它仍不是保留绑定,但目前没有被默认使用。 - phils
5
请注意,.el文件可以被卸载。例如在debian系统中,您需要安装emacs23-el或emacs24-el软件包。如果您没有安装这些软件包,则只有elc(已编译的lisp文件)可用。 - Rémi
5个回答

3

Ctrl-h f 可以告诉你一个函数的解释以及它所在的位置。

如果你想要一个函数自动执行这个操作,可以参考以下草稿代码:

(defun my-find-lisp-object-file-name (function)
  "Display the lisp file name of FUNCTION (a symbol)."
  (interactive
   (let ((fn (function-called-at-point))
     (enable-recursive-minibuffers t)
     val)
     (setq val (completing-read (if fn
                    (format "Describe function (default %s): " fn)
                  "Describe function: ")
                obarray 'fboundp t nil nil
                (and fn (symbol-name fn))))
     (list (if (equal val "")
           fn (intern val)))))
  (if (null function)
      (message "You didn't specify a function")
    (setq object-file-name (find-lisp-object-file-name function (symbol-function function)))
    (if (eq object-file-name 'C-source)
        (message "%s is in %s" function "C source code")
      (setq buff (find-function-search-for-symbol function nil object-file-name))
      (setq buf-name (buffer-name(car buff)))
      (setq buf-pos (cdr buff))
      (switch-to-buffer (car buff))
      (message "%s is in %s(%s, %d)" function object-file-name buf-name buf-pos))))

是的,它描述了函数的作用,但没有说明它在哪里。我想知道包含该函数的*.el文件在哪里。 - Pierre B
1
@PierreB 我不确定你想知道什么,但是当你获取一个函数的文档,比如 describe-char,你可以在 *Help* 缓冲区中获取 .el 文件的链接,并获取 .el 文件的位置。例如 /usr/local/share/emacs/24.3/lisp/descr-text.el.gz 中的 descr-text.el。是这样吗? - songyuanyao
1
也就是说,在“Help”缓冲区中显示的库名称与定义所描述函数的源文件相关联;因此,您可以只需跟随链接(而不是调用“find-function”)即可。 - phils
1
好的,这个方法可行,但只有在安装了emacs23-el包之后才有效,正如Remi上面指出的那样。 - Pierre B

2
我猜测M-x locate-library RET RET可能是一个答案,虽然需要库名而不是函数名。否则,M-x find-function-other-window不仅会告诉您文件在哪里,而且还会打开文件,之后您可以使用M-x pwd了解您的所在位置。
还有一件事:您可以执行C-h v load-path RET以查看Emacs用于查找其库的目录,因此这应该能让您很好地了解所有捆绑的Elisp文件所在的位置。

1

初稿(2014年3月25日):第一份草稿。

编辑(2014年3月26日):添加了一个global-set-key。在最终消息中添加了一个额外的car,以完全从按钮文本属性列表中提取文件名路径。对初始和最终消息进行了一些着色。在函数末尾添加了返回光标到缓冲区开头的选项。添加了find-variable-other-windowfind-function-other-window的选项。添加了条件,以便在没有文件名时不生成任何消息。


这是一个我编写的有趣小函数,如果在*Help*缓冲区中显示了*.el文件,它会显示一个带文件路径的消息。
(global-set-key (kbd "C-h z") 'lawlist-describe-find-function-variable)

(defun lawlist-describe-find-function-variable ()
"Describe or find a function / variable.  Displays the path of filename."
(interactive)
  (message (concat
    (propertize "Describe" 'face 'font-lock-keyword-face)
    " ["
    (propertize "f" 'face 'font-lock-warning-face)
    "]unction / ["
    (propertize "v" 'face 'font-lock-warning-face)
    "]ariable | "
    (propertize "Find" 'face 'font-lock-keyword-face)
    " ["
    (propertize "F" 'face 'font-lock-warning-face)
    "]unction / ["
    (propertize "V" 'face 'font-lock-warning-face)
    "]ariable"))
  (let* (
      (select-f-or-v (read-char-exclusive))
      function
      variable)
    (cond
      ((eq select-f-or-v ?f)
        (setq function (read (read-string "Please enter a function name:  ")))
        (describe-function function)
        (select-window (get-buffer-window "*Help*")))
      ((eq select-f-or-v ?v)
        (setq variable (read (read-string "Please enter a variable name:  ")))
        (describe-variable variable)
        (select-window (get-buffer-window "*Help*")))
      ((eq select-f-or-v ?F)
        (setq function (read (read-string "Please enter a function name:  ")))
        (find-function-other-window function)
        (when buffer-file-name
          (message (propertize buffer-file-name 'face 'font-lock-warning-face))))
      ((eq select-f-or-v ?V)
        (setq variable (read (read-string "Please enter a variable name:  ")))
        (find-variable-other-window variable)
        (when buffer-file-name
          (message (propertize buffer-file-name 'face 'font-lock-warning-face))))
      (t
        (message "Thanks and come again!")))
    (when (and
        (equal (buffer-name) "*Help*")
        (save-excursion
          (goto-char (point-max))
          (re-search-backward "\\(`*[.]el'\\)" nil t)))
      (goto-char (point-max))
      (re-search-backward "\\(`*[.]el'\\)" nil t)
      (message 
        (propertize
          (car (cdr (car (nthcdr 1 (text-properties-at (point))))))
            'face 'font-lock-warning-face) )
      (goto-char (point-min))) ))

0

如果您使用lispy小模式:

  1. 你可以将光标定位在函数的左括号上,然后按下 F 键来打开当前函数的定义。
  2. 你可以选中变量并按下 F 键来打开当前变量的定义。
  3. 你可以使用 g 键在当前目录中查找所有定义。 你会得到一个 helm 完成界面,其中包含所有 Elisp 文件中的所有标签。 每行的第一列是标签,第二列是文件名。 我的安装基础 Elisp 目录有 19838 个标签,并且完成速度足够快。

  4. 你可以使用 lispy-goto-recursive 在当前目录及其子目录中查找所有定义。 它需要几分钟来解析,但只需要几秒钟就能带出完成界面。 但它允许交互式地搜索 Emacs 源中的所有文件 - 共有 89675 个标签。 一个示例搜索:有 55 个顶级标签包含 insert-file,分布在大约 20 个文件中。 其中大多数是函数,但顶级标签 (define-key ctl-x-map "i" 'insert-file) 也被匹配并可以在不打开文件的情况下查看。


0
您可以获取Emacs的源代码(如果您已经安装了Emacs,则可能有.elc文件-这些是编译的elisp文件),并搜索该函数,如果您使用类Unix系统,则可以使用ackfind/grep查找所有Lisp文件都在lisp目录中。
cd Emacs-24.4/lisp
ack 'defun some-function'
find . -name '*.el' | xargs grep 'defun some-function'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接