Dan's Musings

Developing Common Lisp using GNU Screen, Rlwrap, and Vim

Some folks have asked me about my Common Lisp set-up. Since it uses Vim, it's pretty unique off-the-bat. I wanted to describe it in more detail.

My set-up is geared around GNU Screen. In one window, I have a REPL running, and in another vim is running. Using Jpalardy's vim-slime I send stuff to the REPL.

Like much of the community, I use CL tools like roswell and CLPM, but I will focus in this post on the editing and REPL tools, considering these the most unique part of my workflow.


I use Edi Weitz's rlwrap completions. Rlwrap is actually a pretty feature-rich tool. One of my favorite things about rlwrap is that you can use an external editor (Ctrl+^), which fits in really nicely with vim. It calls vim, and I can copy and paste from registers or what have you. This is useful when I want to edit my commands, but not "save" them. They are experiments I run as part of exploring the code space that I don't want to put in my final copy.

Thus, I put this script in my PATH and call it when I need the REPL:

# Filename: /home/<your-user>/.local/bin/clrepl

# Completion file taken from here:
# https://web.archive.org/web/20031207221537/http://weitz.de/files/cmucl_completions
# Pointed out from here: https://stackoverflow.com/a/60281483
# Thanks to Dr. Edi Weitz, who first created the completion file.
# His home page is at https://weitz.de/
# His CL projects are here: https://edicl.github.io/
export RLWRAP_HOME=${PWD}/.repl
export C_INCLUDE_PATH=/usr/include
export LIBRARY_PATH=/usr/lib64:/usr/lib
rlwrap \
    --break-chars "(){}[],'#\";|\\" \
    --case-insensitive \
    --file ~/.config/common-lisp/edi-weitz \
    --history-filename ~/.cl-history \
    --forget-matching '^[^(]' \
    -M '.lisp' \
    --multi-line='  ' \
    --only-cook '^[^[:blank:]]*>>* *' \
    --prompt-colour=red \
    --quote-characters "\"" \
    --remember \
    ros run -- "${@}"
    #ros run --load tools/load-clpm.lisp
#clpm bundle exec -- ros run

The C_INCLUDE_PATH and LIBRARAY_PATH are important to me because I use Embedded Common Lisp. You may not need those lines if you are using SBCL.

Then, I use vim-sexp and vim-slime from the Vim side.

Start Up

Here is how I start up my environment. In one of my projects, I have automated this.

Here is a list of use cases, and how I do them with my set-up:

Explanation Key Presses
Start up GNU Screen screen -dRR -S ergo -t djha-skin
Name the window repl C-a A repl
Start the REPL clrepl
Start new window C-a c
Start up the editor nvim <file>.lisp

My editor is configured to automatically send information using vim-slime to the window named repl, so naming it is important for me.

Use Cases

Here is a short list of common use cases and how I address them with my set-up.

Key Presses Explanation
g g V G C-c C-c Evaluate whole file in REPL
C-a C-a Switch to REPL or back to editor
C-^ Open editor in REPL
v a F C-c C-c Evaluate top-level form in REPL
v a f C-c C-c Evaluate current form in REPL
g g V G = Indent file
C-a C-a :doc <thing> View docs of thing (ECL)
C-a C-a (apropos <thing>) Search for things

Many other interesting combinations of key presses can be made up by consulting vim-slime and vim-sexp documentation. See :help slime and :help sexp.