Treadmill: Gerbil-Emacs Networked REPL Environment
Branch: master
Clone or download
Latest commit 271d117 Jan 7, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
doc update screenshot and caption Jan 2, 2019
.gitignore ignore compilation files Jan 1, 2019
LICENSE Initial commit Dec 27, 2018 add init-forms hook for new feature, post start-up sent forms Jan 4, 2019 initial notes on style Jan 6, 2019
gerbil.pkg rename to match package name Dec 31, 2018
treadmill-history.el address melpa issues Jan 7, 2019
treadmill.el address melpa issues Jan 7, 2019

Treadmill: Gerbil-Emacs Networked REPL Environment

Gerbil Screenshot


Gerbil is a great Scheme and it deserves a great programming environment. While you're waiting for someone to create it, feel free to use Treadmill.

Treadmill is shamelessly modelled on CIDER, the Clojure Emacs-based IDE. I wrote a profiler for CIDER -- which later became the profiler for it -- and while doing so I came to appreciate its design, as well as the leadership of the team.

Treadmill supports plugins via its treadmill-plugin-functions abnormal hook. Currently, any feature that requires modification of the interpreter command line or evaluation of expressions after connection can be accomodated without changes to Treadmill proper. This allows front end features to have the in-process code they need to function without requiring users to painstakingly configure the Emacs and Gerbil sides of the connection separately.

Non-core bundled features -- i.e. history and completion -- are implemented as plugins. It is my goal that Treadmill allow members of the Gerbil community to introduce features without having to modify Treadmill's source. Implementing bundled features as plugins instills discipline and cultivates empathy for plugin writers.


I'm currently going through the process of getting Treadmill available through MELPA; until that's done you won't be able to do the regular package-list-packages routine; you'll need to grab treadmill.el and put it in your Emacs load path. After you do that, stick this in your .emacs.d/init.el, .emacs, or whatever:

(require 'treadmill) ; will not be required with MELPA package
(add-hook 'gerbil-mode-hook #'treadmill-gerbil-mode)

Additionally, you will need to install Gerbil and the Treadmill server package:

gxpkg install

Treadmill finds gxi, the Gerbil interpreter, using the GERBIL_HOME environment variable. You can override this behavior by setting treadmill-interpreter-name.

Currently, Treadmill requires a feature in Gerbil v0.15, which is unnreleased as of this writing (2019-01-02). Building Gerbil from the head of the master branch of the GitHub repository is generally safe.


M-x treadmill-spawn

Run a local Gerbil interpreter and start up a network REPL. Then, connect to the REPL.

M-x treadmill-connect

Prompt you for a host and a port and will then connect to a network REPL. Presumes that you've somehow gotten a network REPL running inside your program without Treadmill's help.

M-x treadmill-quit

Destroy the current Treadmill interaction buffer, which by the way needs to be the current buffer.

Once you're in the *treadmill* buffer, you can type expressions and evaluate them in the current module.

Default Key bindings

Interaction buffers

Binding Description
RET Evaluate expression entered at prompt.
C-c q Close interactive session and associated processes and buffers.
C-c m Prompt for a module name in which to evaluate entered expressions.
C-c C-z Switch back to the most recent switched-from Gerbil buffer.

Gerbil buffers

Binding Description
C-x C-e Evaluate last sexp in current Treadmill interaction buffer session using this buffer's current module.
C-c C-e Evaluate the current region.
C-c C-c, C-M-x Evaluate the current toplevel.
C-c m Change the buffer's current module, overriding the module discerned from the nearest gerbil.pkg file.
C-c C-r Reload the module corresponding to the current buffer.
C-c TAB Import the module corresponding to the current buffer.
C-c C-z Switch to the current Treadmill interaction buffer.

In addition to Treadmill bindings in Gerbil buffers, some Gerbil mode commands remain relevant:

Binding Description
C-c C-b Build.
C-c C-f Compile current buffer.


Plugins are supported through the treadmill-plugin-functions abnormal hook. A plugin adds a function the the hook using add-hook and then is informed of various events or given the opportunity to modify values. The function receives two arguments and EVENT and an ARG. Hook functions should execute (treadmill-plugin-null-hook EVENT ARG) if they do not specifically handle an event.

Event Type Description
command Filter gxi command line arguments (ARG).
init-forms Filter gxi spawn process initial form string (ARG).
keymap Filter Interaction buffer keymap (ARG).
expression Filter Expression (ARG) entered in interaction buffer to be evaluated.
gerbil-keymap Filter Gerbil Treadmill buffer keymap (ARG).
connected Notify Interaction buffer (ARG) connected to network REPL.
quitting Notify Interaction buffer (ARG) about to quit.

A note on grammar

  • Filters events are nouns (e.g. command) -- what the filter is operating on.

  • Notify events that indicate something has happened (e.g. connected) are named in the simple past tense.

  • Notify events that indicate something is happening (e.g. quitting) are named in the present continuous tense.


There are potentially three buffers associated with a Treadmill session:

  1. A *treadmill-spawn* buffer, in which gxi is run and a the net REPL is launched. If you set up a net REPL inside your app by hand using thunknyc/treadmill, you can connect to it via treadmill-connect, and this buffer won't exist. No user serviceable parts inside.

  2. A *treadmill-repl* buffer, the buffer for the connection to the network REPL, in which Treadmill evaluates code. Again, no user serviceable parts inside.

  3. A *treadmill* buffer, the buffer in which human interaction takes place.