Recently on reddit there was a reminder about lisptips.com and slime-tips. I already knew the two, but this time I fully enjoyed the Slime tips. I copy my favourites.
As usual, I enhanced the Cookbook/emacs-ide.html at the same time.
The Slime documentation is here: https://common-lisp.net/project/slime/doc/html/
Documentation lookup
- 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
Synchronizing packages
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.
Calling code
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)
Exporting symbols
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))))
Crossreferencing: find who’s calling, referencing, setting a symbol
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.
Monitoring and controlling threads with Slime
M-x slime-list-threads (you can also access it through the slime-selector, shortcut t) will list running threads by their names, and their statuses.
The thread on the current line can be killed with k, or if there’s a lot of threads to kill, several lines can be selected and k will kill all the threads in the selected region.
g will update the thread list, but when you have a lot of threads
starting and stopping it may be too cumbersome to always press g, so
there’s a variable slime-threads-update-interval
, when set to a number
X the thread list will be automatically updated each X seconds, a
reasonable value would be 0.5.