Lisp Machine ideas, and Emacs

Several of Jonquil's features come from the Lisp Machines, the MIT CADR and Symbolics Genera. This page says what those machines were, how Emacs relates to them, and where Jonquil sits next to both.

What a Lisp Machine was

A Lisp Machine was a whole computer where everything was Lisp: the operating system, the file system, the network, the window system and your own programs, all live objects in one running image. Any of it could be inspected, changed or debugged while it ran, and the environment explained itself. You could ask a key what it does, click a result to open the object, and when an error happened the debugger opened with the stack still there. The Lisp Machine museum documents both systems in depth.

How Emacs relates

The Lisp Machines had their own Emacs-style editor, Zwei (Zmacs), written in Lisp and running inside that live system. GNU Emacs came out of the same MIT culture and keeps the central idea at a smaller size: its core is a Lisp interpreter, so the editor is a running Lisp program you can change from inside itself. It runs as an application on an ordinary operating system, though, so your files, processes and network aren't Lisp objects. You can think of Emacs as the Lisp Machine's live, self-describing environment without the rest of the computer.

Where Jonquil sits

Jonquil heads the same way, and a lot of what it takes from the Lisp Machines Emacs took first:

JonquilEmacs
Describe Key, Key Bindings, Recent KeysC-h k, C-h b, C-h l
The keys for the symbol at the caret, in the status bareldoc shows the signature, not the keys; Genera's mouse documentation line, which named each click's action on the thing under the pointer
The command palette (Cmd/Ctrl+Shift+P)M-x
The locations list and F8 / Shift+F8next-error, xref
Find Usages in Project, by how each place uses the name and which var it namesxref-find-references (M-?); Genera's who-calls, resolved from each file's ns form rather than from a callers database
Save the layout, Use layout: namewindow-configuration-to-register and jump-to-register; Genera's Select key brought up a whole activity
Switch to a recent tab, Go back to the tab used beforeswitch-to-buffer, most recent first
Switch to a recent panel, Cmd/Ctrl+Alt+1 to 8 for each panelnone built in: C-x o cycles windows; Genera's Select key, where Select L brings up the Lisp Listener, is where this comes from
The docs panel: a symbol's doc or a guide page beside the code, with Back, Forward and bookmarksdescribe-function and the *Help* buffer, with l and r to go back and forward; Genera's Document Examiner, whose reading list and cross-references this follows
The Messages panel: agent actions, files changed on disk, connections, with an unread countthe *Messages* buffer, which keeps the echo area's lines; Genera's notifications and Converse are where this comes from
Time the form at the caretbenchmark-run
Count how often each line runs, beside the codeprofiler-start's call tree and elp, which sample or time functions; Genera's metering and gcov-style line counts are closer
Live console results: click to inspect, right-click verbsnone built in: CIDER inspects the last result; Genera's presentations are where this comes from
Trace the function at the caret, the Trace paneltrace-function and the *trace-output* buffer; CIDER's cider-toggle-trace-var
The Processes panel: the fibers your program spawned, Interrupt and Killlist-processes (M-x proced for OS processes); Genera's Peek, which showed every process and let you arrest or kill one
Compare with the file on disk, git HEAD, another tab or the last Run, Take the other version herediff-buffer-with-file, vc-diff and ediff's per-hunk copy; Genera's Compare Files
The changed-form marks, Run the forms changed since they last rannone built in: diff-hl marks lines changed since the last commit, not since the last eval
Change sets: the changed forms as a named, reviewable bundle you can apply to the REPL or revertnone built in: git stash and branches work on whole files and never touch the running Lisp
Show the last error's frames and localsthe *Backtrace* buffer (debug-on-error)
Break on error, Continuedebug-on-error while the error is live: e evaluates in a frame, c continues
Toggle Breakpoint (F9): pause at a line, live at oncedebug-on-entry and Edebug's breakpoints (edebug-defun, then b), which instrument a function the same way
Step Into (F7), Step Over (F10), Step Out (Shift+F7) in forms holding a breakpoint, or every function of a tab instrumented for steppingEdebug stepping (SPC to the next stop point, o to step out), within instrumented definitions
Retry, Edit and retry, Define and retrynone close: the Elisp debugger resumes a live stack, which an unwound one can't
Save World, Restore World: your session's data, one world per projectnone close: desktop-save keeps buffers, not values; Genera's Save World wrote the whole machine, this writes data vars only
Open last session's replay: what the project evaluated last time, as a script in a new tab that runs only when you Run itnone close: desktop-save keeps buffers, not the forms you evaluated
Plugins written in Clojure, in the settings folderEmacs Lisp packages

Three things set it apart:

  • Your code runs in the editor's own runtime. Emacs is extended in Emacs Lisp, a dialect separate from the language you're working in. Jonquil is written in Clojure on Jolt, and your Jolt code runs on that same runtime: inline in Jonquil's process for a loose file, or in a Jolt child process for a project (see Dialects and runtimes). The inspector, its history and Time the form look at your program's real values, not the editor's.
  • The debugger reads that runtime. Jolt's jolt.debug keeps the frames and locals of a throw, and the Frames panel (Show the last error's frames and locals, see Help and the inspector) lists them for your own code: a frame opens at its line, a local opens in the inspector, and a form typed in the panel evaluates with that frame's locals bound. With Break on error the panel opens before the stack unwinds, and a form runs on the thread that threw, inside its bindings. It needs a Jolt release with jolt.debug. Emacs debugs Emacs Lisp well, but debugging Clojure there goes through CIDER and nREPL, a separate layer.
  • It stays a Clojure IDE. Emacs turns everything into a buffer: mail, a shell, a file manager. Jonquil takes Lisp Machine ideas only where they help you write and understand Clojure code, and leaves the rest.

This page is docs/guide/lisp-machine.md in the Jonquil repository.

Enter to open · Esc to close