Emacs Complete: Feedback Loops in Emacs, Feedback Loops in Computing
Completion within Emacs is not just about “intellisense” auto-completion as you type, or tab-completion in command prompts. When I think of “completion” within Emacs, I think about all operations within Emacs being (closed over) textual representations.
Text buffers form a complete representation of process interaction in Emacs.
Maybe it’s even accurate to say: Emacs is complete over textual processes. I’m not sure, it sounds almost correct, but I may be missing important nuances. (You tell me in the comments or via email!)
If it’s text, it’s Emacs-able, that’s what I’m getting at. And oh boy can you emacs a lot of textual things in weird ways.
In this post, I’ll share a particular insight that you can not only extend how many processes you can move into Emacs, but also use the textual representation itself again as input to then inform processes to change Emacs further in a feedback loop of textuality.
This is my February Emacs Carnival entry, hosted by Sacha.
At a recent Software Craftsmanship Open Space, I’ve squeezed in as much Emacs weirdness into the description of one workflow as possible. The day was full of excitement about large language models for coding in various flavors, sadly and oddly enough (there’s not much Craftsmanship in that!). Being a good sport, I wanted to show the extent of how Emacs is, in a way, a general purpose text-based abstraction over anything that you pump through its Lispy veins, and how well this composes, and then feeds into anybody’s favorite coding agent of choice if needed.
The example is this:
- File management: Use
diredas a wrapper around a mere directory listing withlson the command line to get both the directory listing and interactivity for each of the file entries (open, preview, mark, copy, …) - Window management: Create a new split pane
- Server management: Connect to your webserver via SSH with a path prefix,
/ssh:user@example.com/, but otherwise using the normal file opening facilities. - Server file management: Have a directory listing on the server, already combining two pieces!, that looks just like your local directory listing. Copy. With the appropriate settings, you can copy between the split windows, local to remote, remote to local. Just like that.
- View and edit remotely by interacting with the server’s files, and you just get a (slower) file editing and image viewer for the remote contents.
- Save anything to a file for later because the UI is all text anyway, you can just save it as a file, and when you open it next time pick the appropriate mode to interpret this file in. (Caveats apply as some additional state may be lost, but it works beautifully for ‘persisted’ directory listings.) Including process lists, email inboxes, calendars; doesn’t matter if it’s text.
- With all that set-up, now for the Software Craftsmanship Open Space twist: Use Emacs packages for LLMs (agentic-shell, gpt.el, …) on the remote machine transparently since the buffers in your local editor visit files on the remote machine, you can let the bots do changes to your buffer contents and transparently perform changes on the remote.
Veteran Emacs users will nod along and now see anything particularly exciting. That’s just normal, everyday Emacs.
This particular integration of remote/local file management and connecting to machines at all got me so excited that I became sad that I cannot use this to sync files with my Supernote e-ink tablet, convert the notes to PDF, and sync projects.
So I did the sensible thing: set out and generated mtp.el to make Emacs TRAMP connect to the Supernote via /mtp:...:/... for me. Aafter a couple of hours of research and planning using the mtp CLI behind the scenes (eventually interfacing with libmtp for potentially better performance):
https://codeberg.org/ctietze/mtp.el
In this post, my point is not that this remote connection to a Supernote tablet is possible in this awkwardly niche way by using Emacs directory listings – my point is how I got there.
Everything is in text buffers. That’s the primary abstraction that Emacs offers.
Run emacs -nw and you get a text-only terminal application, a TUI if you will, that presents in a text-only terminal emulator text-only representations of much more complex, much more interactive things. Like files you can ‘click’ on to open them from a directory listing. (In TUI mode, you can’t click and press Return instead, but the idea is the same.) The terminal emulator only sees text. The interpretation, the charade, is all in Emacs.
While the terminal emulator only sees text, well, it sees text at least and not just an image of colorful pixels that require OCR to read and other algorithms I have no clue about to interpret.
Consequently, the directory listing within Emacs showing contents of the Supernote tabled has predicable textual output that you can save to a file for later – as we have established in the beginning.
Hey, did you know that tmux can be remote-controlled with commands to move the cursor to positions and to create snapshots?
I didn’t, but I knew asciinema.org exists and people record their terminal contents to produce replays as ‘videos’ there, so the problem of screen-shotting terminal windows was solved already. (asciinema has a custom frame-by-frame JSON format, it turns out, but still a great start for the research.)
With tmux, you can remote control Emacs in TUI mode and capture the whole ‘screen’ as a text file to then check whether Emacs output is what it is supposed to be from a user’s perspective. (You could also save the buffer contents directly, but that won’t capture minibuffer messages and modeline.)
More detail is in mtp.el’s doc on TUI snapshot testing; the gist for end-to-end testing Emacs via tmux sessions (this one called “test”) is the following:
# Create 'test' tmux session 80x24, launch emacs TUI
tmux new-session -d -s test -x 80 -y 24 "emacs -nw --init-directory=dev ..."
# Send shortcuts and type to execute a command:
tmux send-keys -t test M-x
tmux send-keys -t test 'mtp-list-devices' Enter
sleep 3
# Capture a snapshot as plain text
tmux capture-pane -t test -p
# Cleanup
tmux kill-session -t test
With this, you can do snapshot-based UI tests – as long as the UI you create is in Emacs, and it fits into the text-only TUI mode. Or you just grep as a way to assert that the output contains something specific.
Interfacing with any device or hardware is a fiddly procedure I don’t enjoy much. That’s just not the kind of computing I particularly like.
I do not mind it as much when I have a suite of regression tests that make manual QA testing easier the more edge cases I discover and save as test scenarios to automate-away.
So by closing the feedback loop from tmux to launch emacs -nw to invoking work-in-progress implementations for interactive Supernote directory and file listings o saving snapshots of the results to test automation with “golden files” that in turn can be opened and viewed in Emacs again as text, I found that the true power of Emacs lies in being complete over any process that can be represented in text. Any and all. There can be no gaps, and there are none, and thus the world is in order.
Emacs does not just “complete me” in a cheesy Valentines Day way, it “completes computing” for me by creating a textual (mostly) bottleneck to do tasks, inspect them, copy/store/restore/automate away. Now I also found that Emacs is “complete computing”, can be used for input and output, throughput, make the computer inspect the computer (by virtue of tmux snapshots for example).
Emacs complete.