The SLIME Emacs package for Common Lisp supports cross-referencing: one can list all references pointing to a symbol, move through this list and jump to the source code of each reference.
Removing automatic reference jumps
While cross-referencing is very useful, the default configuration is frustrating: moving through the list in the Emacs buffer triggers the jump to the reference under the cursor. If you are interested in a reference in the middle of the list, you will have to move to it, opening multiple buffers you do not care about as a side effect. I finally took the time to fix it.
Key bindings for slime-ref-mode
mode are stored in the slime-xref-mode-map
keymap. After a quick look in slime.el
, it is easy to remove bindings for
slime-xref-prev-line
and slime-xref-next-line
:
(define-key slime-xref-mode-map (kbd "n") nil)
(define-key slime-xref-mode-map [remap next-line] nil)
(define-key slime-xref-mode-map (kbd "p") nil)
(define-key slime-xref-mode-map [remap previous-line] nil)
If you are using use-package
, it is even simpler:
(use-package slime
(:map slime-xref-mode-map
(("n")
([remap next-line])
("p")
([remap previous-line]))))
Changing the way references are used
SLIME supports two ways to jump to a reference:
- With
return
orspace
, it spawns a buffer containing the source file and close the cross-referencing buffer. - With
v
, it spawns the source file buffer but keeps the cross-referencing buffer open and keeps it current.
This is not practical to me, so I made a change. The default action, triggered
by return
, now keeps the cross-referencing buffer open and switches to the
source file in the same window. This way, I can switch back to the
cross-referencing buffer with C-x b
to select another reference without
spawning buffers in other windows (I do not like having my windows hijacked by
commands).
To do that, I need a new function:
(defun g-slime-show-xref ()
"Display the source file of the cross-reference under the point
in the same window."
(interactive)
(let ((location (slime-xref-location-at-point)))
(slime-goto-source-location location)
(with-selected-window (display-buffer-same-window (current-buffer) nil)
(goto-char (point))
(g-recenter-window))))
Note the use of g-recenter-window
, a custom function to move the current
point at eye level. Feel free to use
the builtin recenter
function instead.
I then bind the function to return
and remove other bindings:
(define-key slime-xref-mode-map (kbd "RET") 'g-slime-show-xref)
(define-key slime-xref-mode-map (kbd "SPC") nil)
(define-key slime-xref-mode-map (kbd "v") nil)
Much better now!