rlwrap
rlwrap provides a nicer repl outside of SLIME for implementations that don't have a user-friendly REPL on the terminal, such as SBCL (but unlike CLISP).

The usability issue is that, when you run a barebones SBCL REPL on the terminal:

$ sbcl

you'll want to use the arrow keys, for example the up arrow to get the previous prompt, right? Except you'll get "^[[D" instead. You don't have history either. In short, all the readline keys that you are used to in a terminal (C-a, C-e, arrows, M-p, M-n, C-r, the basic Emacs keybindings we find in Bash and in many Unix programs) do not work.

Call SBCL with rlwrap and get a nice readline wrapper:

$ rlwrap sbcl

and the keybindings work.

However, rlwrap is independent of Common Lisp. It won't complete Lisp keywords and functions out of the box, but it is possible to give home-made lists of strings to complete. This script configures rlwrap for Lisp code and enables custom completion:

#!/bin/sh
BREAK_CHARS="(){}[],^%$#@\"\";''|\\"
RLWRAP=
if [ $TERM == "dumb" ]; then  # slime
  RLWRAP=
else
  RLWRAP="rlwrap --remember --history-filename=$HOME/.sbcl_history --histsize=1000000 -c -b $BREAK_CHARS -f $HOME/.sbcl_completions"
fi
if [ $# -eq 0 ]; then
  exec $RLWRAP /opt/local/bin/sbcl
else # permits #!/usr/bin/env sbcl , but breaks sbcl --help, etc.
  exec /opt/local/bin/sbcl --script $*
fi

And here's an SBCL script to generate the completions:

#! /usr/bin/env sbcl
(let (symbols)
  (do-all-symbols (sym)
    (let ((package (symbol-package sym)))
      (cond
        ((not (fboundp sym)))
        ((or (eql #.(find-package :cl) package)
             (eql #.(find-package :cl-user) package))
         (pushnew (symbol-name sym) symbols))
        ((eql #.(find-package :keyword) package)
         (pushnew (concatenate 'string ":" (symbol-name sym)) symbols))
        (package
          (pushnew (concatenate 'string (package-name package)
                               ":"
                               (symbol-name sym))
                  symbols)))))
  (with-open-file (output #.(concatenate 'string (posix-getenv "HOME")
                                         "/.sbcl_completions")
                          :direction :output :if-exists :overwrite
                          :if-does-not-exist :create)
    (format output "~{~(~A~)~%~}" (sort symbols #'string<))))


This also this list on GitHub to get a list with added packages: Alexandria, uiop, asdf, quicklisp.


Development