First tagged release of neat, a small, language-agnostic nREPL client for Emacs.
The codec, async dispatch, comint REPL, and source-buffer minor mode are all in place; eldoc, completion-at-point, xref find-definition, doc-lookup, namespace-aware eval, and stdin/need-input handling work against any conformant server. Tested against Clojure (nrepl/nrepl), Babashka, and Basilisp via the parameterised integration suite.
Expect rough edges — this is the start of the road, not the end.
Highlights
- Pure-elisp bencode codec with a stack-based decoder.
- Async dispatch via a single callback per request.
- comint-based REPL with multi-line input, persistent history, namespace-aware prompt, and styled output.
neat-modesource-buffer minor mode wiring up eval, load-file, find-definition (xref), doc lookup, eldoc with arg highlighting, completion-at-point with type annotations, and namespace-aware evaluation.- Multi-connection registry with default-connection routing and a
*neat-connections*tabulated-list inspector. - Mode-line indicator showing the active connection.
- Graceful handling of dead connections, malformed bencode, and
need-inputreads.
Added
neat-load-filelibrary op andneat-load-buffer-fileinteractive command (bound toC-c C-l).neat-evalaccepts optionalfile,line, andcolumnarguments; the source-buffer eval commands compute these so error messages can point at the actual source location.- xref backend in
neat-modeandneat-repl-modebuffers —M-.jumps to definitions via thelookupop,M-,pops back. Customize timeout vianeat-lookup-timeout. neat-list-connections—*neat-connections*tabulated-list buffer with RET = set default,d= disconnect,g= reload.neat-disconnect-connectioninteractive picker; library-level primitive isneat-disconnect.neat-show-doc-at-point(C-c C-d C-din bothneat-modeandneat-repl-mode) pops a*neat-doc*help buffer with full docstring, arglists, and source location.- Completion candidates carry the server-reported
typevia:annotation-function. stdinop +need-inputhandling — prompts in the minibuffer when evaluated code reads from stdin.- Mode-line shows the active connection (
[host:port]or[closed]). neat-disconnect-functionsabnormal hook fires when a connection's process dies; the REPL marks itself closed.- Process filter survives malformed bencode (catches, logs, recovers).
neat-repl-clear-buffer(C-c M-o).- Buffer-local namespace:
neat-nsdefvar-local,neat-set-nsinteractive command (C-c M-n), andneat-buffer-ns-functionswappable seam for language-specific parsers. - Initial project skeleton with Eldev and Buttercup.
- Core nREPL ops in
neat-client:describe,clone,eval,load-file,stdin,interrupt,close,completions,lookup. - Integration test suite parameterised over nREPL implementations (Clojure, Babashka, Basilisp).
.nrepl-portauto-discovery —M-x neat RET RETis enough in a project with a running server.- Multi-connection support with auto-demotion on disconnect.
- REPL multi-line input via
parse-partial-sexp, persistent history, namespace-aware prompt. - Completion-at-point and eldoc active in both source buffers and the REPL.
- Eldoc highlights the current argument in the displayed arglist (works for any Lisp-family mode; swappable seams for other languages).
Changed
neat-active-connectionfalls back toneat-default-connectionwhen the buffer-local override is dead.neat-evalandneat-load-filetake a property list of options after the required positional args (instead of stacking positional&optionals).- Connection routing primitives moved from
neat.eltoneat-client.elwhere they belong as a library-level concern.
Removed
neat-repl-promptdefcustom (replaced byneat-repl-prompt-format+neat-repl-default-nsduring the unreleased churn window).
See CHANGELOG.md for the unabridged list.