title |
---|
Using Emacs as an IDE |
This page is meant to provide an introduction to using Emacs as a Lisp IDE. The key bindings used in the example code snippets assume an Emacs configuration similar to that provided by the .emacs file that is included as part of the Setting up an IDE with Emacs on Windows or Mac OS X page.
Note: Portacle is a portable and multiplatform CL development environment, a straightforward way to get going.
- Emacs has fantastic support for working with Lisp code
- Not tying yourself into a single CL vendor's editor
- Runs on virtually every OS and CL implementation
- Extensible: awesome-emacs.
- Can be customized to do many common tasks
- Built-in support for different source code version control systems
- Vast number of add-on packages
- Emacs will probably always be around
- Emacs works well either with a mouse or without a mouse
- Emacs has a large user base with multiple newsgroups
- Benefits of using Emacs far outweigh the effort spent in learning it
- org-mode
- Because Emacs Rocks !
-
Learning Emacs Lisp is useful and similar (but different from CL):
- Dynamic scope is everywhere
- There are no reader (or reader-related) functions
- Does not support all the types that are supported in CL
- Incomplete implementation of CLOS (with the add-on EIEIO package)
- Not all of CL is supported
- No numerical tower support
-
Some good Emacs Lisp learning resources:
SLIME is the goto major mode for CL programming.
-
Pros:
- Provides REPL which is hooked to implementation directly in Emacs
- Has integrated Common Lisp debugger with Emacs interface
- Interactive object-inspector in Emacs buffer
- Has its own minor mode which enhances lisp-mode in many ways
- Supports every common Common Lisp implementation
- Readily available from MELPA
- Actively maintained
- Symbol completion
- Cross-referencing
- Can perform macroexpansions
-
Cons:
- Installing SLIME without MELPA can be tricky
-
Setup:
- Installing it from MELPA is straightforward. Search package-list-packages for 'slime' and click to install. If MELPA is configured correctly, it will install itself and all dependencies.
- Enable the desired contribs (SLIME does very little by defaults), e.g.
(slime-setup '(slime-fancy slime-quicklisp slime-asdf))
. - Run SLIME with
M-x slime
.
Check out this video tutorial ! (and the author's channel, full of great stuff)
SLIME also has some nice extensions like Helm-SLIME which features, among others
- Fuzzy completion,
- REPL and connection listing,
- Fuzzy-search of the REPL history,
- Fuzzy-search of the apropos documentation.
From the SLIME REPL, press ,
to prompt for commands. There is completion
over the available systems and packages. Examples:
,load-system
,reload-system
,in-package
,restart-inferior-lisp
and many more.
With the slime-quicklisp
contrib, you can also ,ql
to list all systems
available for installation.
SLY is a SLIME fork that contains the following improvements:
- Completely redesigned REPL based on Emacs's own full-featured comint.el
- Live code annotations via a new sly-stickers contrib
- Consistent interactive button interface. Everything can be copied to the REPL.
- Multiple inspectors with independent history
- Regexp-capable M-x sly-apropos
- Contribs are first class SLY citizens, enabled by default, loaded with ASDF on demand.
- Support for NAMED-READTABLES, macrostep.el and quicklisp.
In this short tutorial we'll see how to:
- edit Lisp code
- evaluate and compile Lisp code
- search Lisp code
- Note: Example code assumes you are using a setup similar to what is defined in the .emacs file from the CL Cookbook site.
In addition to the built-in Emacs commands, you have several packages at your disposal that will help to keep the parens and/or the indentation balanced. The list below is somewhat sorted by age of the extension, according to the history of Lisp editing:
- Paredit - Paredit is a classic. It defines the must-have commands (move, kill, split, join a sexp,…). (visual tutorial)
- Smartparens - Smartparens not only deals with parens but with everything that comes in pairs (html tags,…) and thus has features for non-lispy languages.
- Lispy - Lispy reimagines Paredit with the goal to have the shortest bindings (mostly one key) that only act depending on the point position.
- Paxedit - Paxedit adds commands based on the context (in a symbol, a sexp,… ) and puts efforts on whitespace cleanup and context refactoring.
- Parinfer - Parinfer automatically fixes the parens depending on the indentation, or the other way round (or both !).
We personnaly advice to try Parinfer and the famous Paredit, then to go up the list. See explanations and even more on Wikemacs.
{% include code/s1.lisp %}
With C-M-k
and C-M-backspace
(which may restart the system on gnu/linux):
{% include code/s2.lisp %}
With C-M-q
:
{% include code/s3.lisp %}
M-(
insets a pair, M-x check-parens
to spot malformed sexps, C-u <n> M-(
to enclose sexps with parens:
{% include code/s4.lisp %}
{% include code/s5.lisp %}
Use the built-in C-c TAB
to complete symbols in SLIME. You can get tooltips
with company-mode.
{% include code/s7.lisp %}
With C-x n n
(narrow) and C-x n w
to widen back.
See also code folding.
{% include code/s8.lisp %}
Insert a comment, comment a region with M-;
, adjust text with M-q
.
{% include code/s9.lisp %}
Compile the entire buffer by pressing C-c C-k
.
Compile a region by selecting the first 2 forms in test-all and
running M-x slime-compile-region
.
Compile a defun by putting the cursor inside the "test-format"
defun and pressing C-c C-e
.
Compile the sexp before the point by putting the cursor after the
closing paren of (test-format)
and pressing C-c C-e
.
To evaluate rather than compile:
- evaluate a region with
C-c C-r
, - evaluate a defun with
C-M-x
, - evaluate the sexp before the point with
C-x C-e
. See also other commands in the menu.
C-s
does an incremental search forward (e.g. - as each key is
the search string is entered, the source file is searched for the
first match. This can make finding specific text much quicker as
you only need to type in the unique characters. Repeat searches
(using the same search characters) can be done by repeatedly
pressing C-s
C-r
does an incremental search backward
C-s RET
and C-r RET
both do conventional string searches
(forward and backward respectively)
C-M-s
and C-M-r
both do regular expression searches (forward
and backward respectively)
M-%
does a search/replace while C-M-%
does a regular
expression search/replace
With M-x grep
, rgrep
, occur
,…
{% include code/s13.lisp %}
See also interactive versions with helm-swoop, helm-occur, ag.el.
{% include code/s14.lisp %}
See also helm-imenu and imenu-anywhere.
Put the cursor on any symbol and press M-.
to go to its
definition. Press M-,
to come back.
Slime has a nice cross referencing facility, for example, you can see what calls a particular function or expands a macro. It presents a list of places which reference a particular entity, from there you can recompile the thing which references by pressing C-c C-c on that line. C-c C-k will recompile all the references. This is useful when modifying macros, inline functions, or constants.
The following bindings are also shown in Slime's menu:
- C-c C-w c slime-who-calls callers of a function
- C-c C-w m slime-who-macroexpands places where a macro is expanded
- C-c C-w r slime-who-references global variable references
- C-c C-w b slime-who-bind global variable bindings
- C-c C-w s slime-who-sets global variable setters
- C-c C-w a slime-who-specializes methods specialized on a symbol
And when the slime-asdf
contrib is enabled,
C-c C-w d slime-who-depends-on lists dependent ASDF systems
And a general binding: M-? or M-_ slime-edit-uses* combines all of the above, it lists every kind of references.
(thanks to Slime tips)
{% include code/s16.lisp %}
{% include code/s17.lisp %}
When you put the cursor on a function, SLIME will show its signature in the minibuffer.
- C-c C-d h looks up documentation in CLHS. But it works only on symbols, so there are two more bindings:
- C-c C-d # for reader macros
- **C-c C-d ~** for format directives
Other bindings which may be useful:
- C-c C-d d describes a symbol using
describe
- C-c C-d f describes a function using
describe
{% include code/s19.lisp %}
{% include code/s21.lisp %}
{% include code/s22.lisp %}
- CL HyperSpec (online)
- CL HyperSpec (tarball)
- CLtL2
- ACL Documenation
- Example code ( s23.lisp )
{% include code/s23.lisp %}
(ql:quickload "clhs")
Then add this to your Emacs configuration:
(load "~/.quicklisp/clhs-use-local.el" 'noerror)
**C-c ~** (slime-sync-package-and-default-directory): When run in a buffer with a lisp file it will change the current package of the REPL to the package of that file and also set the current directory of the REPL to the parent directory of the file.
C-c C-y (slime-call-defun): When the point is inside a defun and C-c C-y is pressed,
(I’ll use [] as an indication where the cursor is)
(defun foo ()
nil[])
then (foo [])
will be inserted into the REPL, so that you can write
additional arguments and run it.
If foo
was in a different package than the package of the REPL,
(package:foo )
or (package::foo )
will be inserted.
This feature is very useful for testing a function you just wrote.
That works not only for defun, but also for defgeneric, defmethod, defmacro, and define-compiler-macro in the same fashion as for defun.
For defvar, defparameter, defconstant: [] *foo*
will be inserted
(the cursor is positioned before the symbol so that you can easily
wrap it into a function call).
For defclass: (make-instance ‘class-name )
.
Inserting calls to frames in the debugger
C-y in SLDB on a frame will insert a call to that frame into the REPL, e.g.,
(/ 0) =>
…
1: (CCL::INTEGER-/-INTEGER 1 0)
…
C-y will insert (CCL::INTEGER-/-INTEGER 1 0)
.
(thanks to Slime tips)
{% include code/s24.lisp %}
See also eval-in-repl to send any form to the repl.
C-c x (slime-export-symbol-at-point) from the slime-package-fu
contrib: takes the symbol at point and modifies the :export
clause of
the corresponding defpackage form. It also exports the symbol. When
called with a negative argument (C-u C-c x) it will remove the symbol
from :export
and unexport it.
M-x slime-export-class does the same but with symbols defined by a structure or a class, like accesors, constructors, and so on. It works on structures only on SBCL and Clozure CL so far. Classes should work everywhere with MOP.
Customization
There are different styles of how symbols are presented in
defpackage
, the default is to use uninterned symbols (#:foo
).
This can be changed:
to use keywords:
(setq slime-export-symbol-representation-function
(lambda (n) (format ":%s" n)))
or strings:
(setq slime-export-symbol-representation-function
(lambda (n) (format "\"%s\"" (upcase n))))
ASDF is the de-facto build facility. It is shipped in most Common Lisp implementations.
Start the ediff utility by entering M-x ediff
. Enter two file names, press
the space bar to step through the changes, and q
to exit.
Of course, see also magit for a wonderful git integration into Emacs.
You might want to set this to your init file:
(set-language-environment "UTF-8")
(setenv "LC_CTYPE" "en_US.UTF-8")
and for Sly:
(setq sly-lisp-implementations
'((sbcl ("/usr/local/bin/sbcl") :coding-system utf-8-unix)
))
This will avoid getting ascii stream decoding error
s when you have
non-ascii characters in files you evaluate with SLIME.
I switch between UNIX® and Windows environments and, although Emacs makes this switch a lot easier, I find it inconvenient having to use different Shell environments on different operating systems.
On Windows, the Cygwin tools provide a lot of the same tools that are available under UNIX® as well as a BASH shell. Alternatively, you might want to consider using eshell, a shell written in Emacs Lisp that comes as a standard feature in Emacs. If you use the given Emacs configuration, you can access eshell by pressing "F12".
I would like to use Emacs with Franz's ACL but find that I use the Franz tools so much that I can't afford to not load their IDE.
It doesn't have to be an either/or decision. On Windows, Franz allows you to specify (under Options) that Emacs is to be the default editor in place of their built-in editor. On UNIX®, Emacs also works very well together with the Franz tools.*
I want to use Emacs on a Windows machine. Unfortunately, I have the Windows cut/copy/paste key bindings burned into my fingertips and would find it very difficult to switch back and forth between the Windows standard for these shortcut keys and the Emacs standard.
Luckily, you don't have to! Download cua.el and you can continue to use the Windows defaults. In fact, you may find that the following commands in your .emacs file will make Emacs more Windows-like:
;; Windows-like mouse/arrow movement & selection (pc-selection-mode)
(delete-selection-mode t)
;; C-z=Undo, C-c=Copy, C-x=Cut, C-v=Paste (needs cua.el)
(require 'cua) (CUA-mode t)
There was a lot of Emacs Lisp code presented in this paper. Do I really have to type in all this stuff to get started with Emacs and Lisp?
No, you can add yourself just what's needed to get SLIME working.
You can try Portacle which has everything ready.
There is also a sample .emacs file that can be used to get started. It contains all of the configurations that have been described in this page and (hopefully) should work with some minor tweaking. See the CL-Cookbook page on "Setting up an IDE with Emacs on Windows or Mac OS X".
The original material on this page was originally presented at the ILC 2003 conference. A paper with more in-depth coverage of some of the material on this page can be found on Bill Clementson's ILC2003 page, which is now archived.
It was edited in 2017.