Evaluating Elisp in Emacs
There are several ways of evaluating elisp code in Emacs, and picking the right approach will help you get your job done faster and more efficiently. If you’re new to elisp you will quickly realize that Emacs has many shortcuts and features that makes writing, inspecting or debugging elisp code very easy.
Evaluating Chunks of Code
If you have a body of code that you want to evaluate, this approach is by far the simplest. To quickly evaluate any amount of code – from one to many forms, where a form is essentially something that Emacs can evaluate – simply yank the code into an empty buffer and run
If you want something less hamfisted you can tell Emacs to only evaluate the region by marking what you want to run and executing
It goes without saying that I assume
transient-mark-mode is active, which is it in newer Emacsen by default; but chances are it is enabled in your
.emacs anyway, as transient makes the region visible on your screen, and not surprisingly that is what most people want.
If you are a disbeliever and prefer a simpler life without transient then you’re familiar with narrowing and exchanging the point and the mark to get what you want anyway. I should mention, by the way, that the vanguard of Emacs conversatism, Richard Stallman himself, does use
This is where Emacs starts to shine, for it has special tools available to it to evaluate single s-expressions. The facilities that are in place in Emacs to do this depend on the major mode you are using (and, rarely, your mode’s syntax table) but most modes still expose
C-x C-e, which is bound to
eval-last-sexp command is very interesting, because it is one of few commands that are globally available to most modes, and it only works if you have the point at the end of an s-expression (“sexp”), which is anything enclosed by a pair of parentheses, like this:
(message "Hello, World!")| where
| is your point.
There are a couple of limitations that make
C-x C-e a poor tool to use if you are writing and testing elisp code, because it cannot update variables declared with
defcustom, and it goes with saying that having to move point to the end of the expression every time you want to eval the sexp is annoying as well.
Emacs 28+: In Emacs 28 or later, this inconsistency is gone. Either method now works with
defcustom & friends.
Arguably the best way to evaluate a form is
eval-defun, bound to
C-M-x. This command does not suffer from the problems I mentioned before, as it is designed for a typical hacker’s write-eval-test cycle. You can type
C-M-x anywhere in a form, and it will evaluate the outer-most form, ensuring that you won’t accidentally evaluate only a part of a larger form.
What makes it even better is its built-in support for edebug, Emacs’ elisp debugger. Using the universal argument
C-u Emacs will evaluate the form as normal, but enable debug instrumentation. The next time it is run it kicks off the debugger and lets you step through the code, with every evaluation showing its value (if any) in the echo area.
You can also use this functionality for exploratory purposes by enabling debugging on Emacs’ own routines.
This is by far the best way of quickly re-evaluating code you’ve updated, and it should be muscle memory for any serious elisp hacker.
Another quick way of evaluating an expression is to use
eval-expression, bound to
M-:. Evaluated expressions are printed to the echo area and the value prepended to the list variable
values. It is important to note that as it takes expressions and not sexps or forms you can also print the value of any variable in Emacs – just be sure not to wrap the variable in parenthesis.
This command is particularly handy if you quickly want to change a setting or invoke an elisp function directly, as it evaluates code in the context of the buffer it was invoked from. If you use the universal argument
C-u, the output of the expression will be inserted into the buffer. In a similar vein, you can tell Emacs to redo the previous command it did and let you edit the command beforehand by invoking
C-x M-:. Another useful way of exploring Emacs.
One thing you cannot do is invoke multiple expressions; to get around this, you can wrap the expressions in the
progn form, like so:
(progn (foo) (bar) (baz)).
The Scratch Buffer
*scratch* buffer comes with a few useful additions over the regular Emacs-Lisp mode that makes it useful for throw-away scripts and quick code evaluation. If you put point at the end of an sexp and type
C-j Emacs will evaluate the expression and print the result straight into the buffer. Note: If you use paredit, be aware that it rebinds the key!
The scratch buffer is a poor substitute for a proper REPL, but thankfully Emacs does come with one of those too.
The Interactive Emacs-Lisp Mode
This is a fantastic, and hidden, gem in Emacs: a proper REPL. Type
M-x ielm to run the elisp REPL. It comes with all the useful features you would expect from an interactive shell, like
*** to get the last three outputs from the shell. Multi-line commands are fully supported as well, of course.
ielm inherits from comint you get all the advantages that provides, like a command history and so on. You also get limited completion support with
TAB, which is very nice.
Another useful feature is the concept of a working buffer - a buffer through which your changes are evaluated. If you type
C-c C-b you can change ielm’s working buffer to one of your choosing and then all the code you evaluate thereafter will be treated as if you executed it in the context of that buffer. This functionality comes in handy if you are dealing with buffer-local variables or changes that’re specific to one buffer only. Very, very powerful.
Honorable Mention: Eshell
You can evaluate elisp in Eshell directly from the prompt, with some limitations. I have covered this in greater detail in my article on Mastering Eshell.
That just about covers evaluating code in Emacs, from one-liners to entire buffers of code. If you’re hacking elisp you want
C-M-x for your everyday editing and quick debugging; if you’re inspecting state or want to change something in Emacs real quick, use
M-:; if you want to evaluate a buffer or region, use
eval-region; if you’re exploring elisp and want an interactive environment, use
ielm. The rest serve more specialized roles, but you cannot go wrong if you stick to these recommendations.