GitHub - Wilfred/elisp-refs: semantic code search for emacs lisp

 4 years ago
source link: https://github.com/Wilfred/elisp-refs
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.



Build Status Coverage Status MELPA

elisp-refs is an intelligent code search for Emacs lisp.

It can find references to functions, macros or variables. Unlike a dumb text search, elisp-refs actually parses the code, so it's never confused by comments or variables with the same name as functions.


This is particularly useful for finding all the places a function is used, or finding examples of usage.

Interested readers may enjoy my blog post: Searching A Million Lines Of Lisp.


Install from MELPA (recommended) or just add elisp-refs to your load-path.

Commands available

  • elisp-refs-function (find function calls)
  • elisp-refs-macro (find macro calls)
  • elisp-refs-variable (find variable references)
  • elisp-refs-special (find special form calls)
  • elisp-refs-symbol (find all references to a symbol)

These command search all the files currently loaded in your Emacs instance.

If called with a prefix, you can limit search results to specific directories. For example:

C-u M-x elisp-refs-macro RET pcase RET ~/.emacs.d/elpa/magit-20160927.510 RET

will search for uses of pcase in magit:

filtering screenshot

Semantic analysis

elisp-refs has street smarts: given (defun foo (bar) (baz)), it understands that bar is a variable and baz is a function.

elisp-refs understands the following forms:

  • defun defsubst defmacro cl-defun
  • lambda
  • let let*
  • funcall apply
  • sharp quoted expressions (e.g. #'some-func)


elisp-refs understands elisp special forms, and a few common macros. However, it cannot understand arbitrary macros.

Therefore elisp-refs will assume that (other-macro (foo bar)) is a function call to foo. If this is incorrect, you may wish to use the command elisp-refs-symbol to find all references to the foo symbol.

If other-macro is a common macro, please consider submitting a patch to elisp-refs--function-p to make elisp-refs smarter.

elisp-refs also does not support indirect calls.

;; Since we do a simple syntax tree walk, this isn't treated as a
;; call to foo.
(let ((x (symbol-function 'foo)))
  (funcall x))

;; Similarly, indirect function calls are not treated as
;; function calls.
(defun call-func (x)
  (funcall x))
(call-func 'foo)

;; However, if you use sharp quoting, elisp-refs knows it's a function
(call-func #'foo)

Running tests

You can run the tests with:

$ cask install
$ cask exec ert-runner


elisp-refs is CPU-intensive elisp and has been carefully optimised. You can run the benchmark script with:

$ cask install
$ ./bench.sh

New features are carefully measured to ensure performance does not get worse.

See elisp-refs-bench.el for more details.

Alternative Projects

xref-find-references: This command is included in Emacs 25.1, but it's based on a text search. It is confused by comments and strings, and cannot distinguish between functions and variables.

xrefs-find-references is also line oriented, so it does not show the whole sexp that matched your search. Since it requires text files, it doesn't search built-in .el.gz files.

TAGS: It is possible to record function references in TAGS files. Whilst universal-ctags (formerly known as exuberant-ctags) does provide the ability to find references, it is not supported in its lisp parser.

etags, the TAGS implementation shipped with Emacs, cannot find references (to my knowledge).

el-search allows you to search for arbitrary forms in elisp files. It's slower, but a much more general tool. Its design greatly influenced elisp-refs.

elisp-slime-nav finds definitions, not references. It's a great complementary tool.

About Joyk

Aggregate valuable and interesting links.
Joyk means Joy of geeK