Slime Tips

Little known features of Slime.

1 note &

Disassembling and inspecting things

While things can be inspected and disassembled by their name with slime-inspect (C-c I) and slime-disassemble-symbol (C-c M-d), it’s often easier to do that through their definitions.

slime-inspect-definition inspects the object defined by the definition at point (e.g. defun or defpackage), works on functions, variables, macros, packages, classes.
slime-disassemble-definition disassemble the object defined by the definition at point, works on functions and macros.

Neither is bound to anything by default, but I bind them to C-c M-i and C-c M-d respectively.

One limitation is that they don’t work properly on DEFMETHOD, instead of finding a particular method they just use a generic function. I plan on fixing that someday.

3 notes &

Cross referencing

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.

Bindings:
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 slime-asdf contrib is enabled
C-c C-w d slime-who-depends-on list dependant ASDF systems

And a general binding:
M-? or M-_ slime-edit-uses combines all of the above, lists every kind of reference

2 notes &

Expanding format strings

M-x slime-format-string-expand: expands the format control string at point.

 ”~a, ~a.” on SBCL yields

#'(LAMBDA
      (STREAM
       &OPTIONAL
       (#:FORMAT-ARG1502
        (ERROR 'SB-FORMAT:FORMAT-ERROR :COMPLAINT "required argument missing"
               :CONTROL-STRING "~a, ~a." :OFFSET 1))
       (#:FORMAT-ARG1503
        (ERROR 'SB-FORMAT:FORMAT-ERROR :COMPLAINT "required argument missing"
               :CONTROL-STRING "~a, ~a." :OFFSET 5))
       &REST SB-FORMAT::ARGS)
    (DECLARE (IGNORABLE STREAM))
    (BLOCK NIL
      (PRINC #:FORMAT-ARG1502 STREAM)
      (WRITE-STRING ", " STREAM)
      (PRINC #:FORMAT-ARG1503 STREAM)
      (WRITE-STRING "." STREAM))
    SB-FORMAT::ARGS)

1 note &

REPL history customization

There are two useful features which are turned off by default
slime-repl-history-remove-duplicates, when set to T removes duplicate entries.
slime-repl-history-trim-whitespaces, when set to T strips whitespace characters from the beginning and the end.

1 note &

Clearing REPL

C-c M-o clears everything, only leaves a new prompt.
C-c C-o clears output of the previous command, for example, after evaluting (make-array 10000) there’ll be a large array printed, and C-c C-o will only remove that array, leaving all previous command outputs untouched.

Update: C-c M-o also clears presentations and *, **, ***, etc. variables (the latter feature was added just today), so that the objects bound by them can be GCed.

6 notes &

Documentation look up

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

3 notes &

slime-selector

Slime has many buffers, and sometimes it’s not easy navigating between them, slime-selector simplifies this task.
It’s not bound to any key by default, I bind it globally to C-z

(global-set-key "\C-z" 'slime-selector)


Then it allows you to select a buffer by a letter.
Some of the most useful shortcuts are listed here, the full list can be seen by pressing “?”.

  • r   Current active REPL
  • l    Most recently visited lisp file
  • d   Debugger 
  • c   List of implementations slime is connected to
  • t   Threads list
  • i   *inferior-lisp* buffer
  • s    *slime-scratch* buffer (for writing one-off code)
  • v   Log of slime events (useful for debugging Slime problems)

0 notes &

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 current directory of the REPL to the parent directory of the file.

On success it will display

package: NEW-PACKAGE-NAME  directory: ~/

 in the minibuffer, or

package: CURRENT-REPL-PACKAGE (package :foo doesn't exist)  directory: ~/

when specified in the file package doesn’t exist yet.

5 notes &

Viewing large arglists

Arglists of some functions are quite long and they may not fit on the screen in one line, there are two ways to display them.

First

(setq slime-autodoc-use-multiline-p t)

that’ll make the minbuffer change its height automatically to accommodate several lines of text.

But I find it annoying when the minibuffer jumps up and down, especially when I don’t really want to read the whole arglist.

For this case there’s a binding C-c C-d A (not an easy one), it will redisplay the current arglist on several lines. And its effect is temporary.

You can try it on WRITE function

1 note &

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 poistioned 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)