Treadmill: Gerbil-Emacs Networked REPL Environment
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
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
and put it in your Emacs load path. After you do that, stick this in
.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 github.com/thunknyc/gerbil-treadmill
gxi, the Gerbil interpreter, using the
environment variable. You can override this behavior by setting
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.
Run a local Gerbil interpreter and start up a network REPL. Then, connect to the REPL.
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.
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
||Evaluate expression entered at prompt.|
||Close interactive session and associated processes and buffers.|
||Prompt for a module name in which to evaluate entered expressions.|
||Switch back to the most recent switched-from Gerbil buffer.|
||Evaluate last sexp in current Treadmill interaction buffer session using this buffer's current module.|
||Evaluate the current region.|
||Evaluate the current toplevel.|
||Change the buffer's current module, overriding the module discerned from the nearest
||Reload the module corresponding to the current buffer.|
||Import the module corresponding to the current buffer.|
||Switch to the current Treadmill interaction buffer.|
In addition to Treadmill bindings in Gerbil buffers, some Gerbil mode commands remain relevant:
||Compile current buffer.|
Plugins are supported through the
abnormal hook. A plugin adds a function the the hook using
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.
||Filter||gxi command line arguments (ARG).|
||Filter||gxi spawn process initial form string (ARG).|
||Filter||Interaction buffer keymap (ARG).|
||Filter||Expression (ARG) entered in interaction buffer to be evaluated.|
||Filter||Gerbil Treadmill buffer keymap (ARG).|
||Notify||Interaction buffer (ARG) connected to network REPL.|
||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:
*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.
*treadmill-repl*buffer, the buffer for the connection to the network REPL, in which Treadmill evaluates code. Again, no user serviceable parts inside.
*treadmill*buffer, the buffer in which human interaction takes place.