Repository navigation
Conversation
let-go's run-tests now defaults to *ns* like Clojure's, so the bare (run-tests) in test.run ran 0 tests and reported success. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
C-c M-c connects (pre-filled from the nearest .nrepl-port that lg -n writes), C-c C-q disconnects. While connected, C-x C-e, C-j, C-c C-v and C-c C-e send their source to the server; the let-go-mode lighter reads nrepl. - letgo: all eval commands now build one backend request (:op :eval/:load). In-process stays synchronous; any other backend runs the command through spawn-task. Remote results are printed-result (server's printed text plus captured output). C-j and C-c C-v verify the form is still in the same buffer before writing. - nrepl: blocking bencode round trips over net, serialized by a channel-token lock inside the job future, so no persistent reader goroutine for the main loop to poll. Errors are cleaned to the message plus caused-by chain; an eval in a namespace the server hasn't loaded (let-go falls back to user silently) gets a note. - tests against a fake bencode server on a loopback socket. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
C-c M-j starts the project's nREPL server, waits for it, connects, and stops it on C-c C-q or editor exit. Launch configs are data (register-launch-config!) for lgx (lgx.edn), Clojure CLI with cider-nrepl (deps.edn), Babashka (bb.edn) and plain lg (deps.edn or no project); the buffer's extension and :priority settle deps.edn/bb.edn ambiguity, a real tie prompts. nrepl-jack-in-command edits the command first; nrepl-server-log shows the server output. Processes: let-go interop can't reach cmd.Process, so servers run under sh -c writing a pid file and logging to a file, exec'ing the command, with stdin held open (lg -n exits on EOF). Stop = SIGTERM + close stdin; liveness via ps stat since kill -0 counts zombies. The editor picks the port (bb doesn't write .nrepl-port for port 0). New bufs exit hooks run after the terminal is restored. Connections are now per project root: buffers visiting files under a connected root evaluate there, via a backend resolver in letgo (eval-backend-for); fileless buffers like *scratch* stay in-process. Completion (legmacs.modes.letgo-complete): TAB completes when indenting changes nothing and point ends a symbol, M-TAB always. In-process from the VM (buffer ns, aliases incl. the ns form's requires, alias/ publics, special forms); on nREPL via cider's complete or completions. One candidate inserts, a longer common prefix extends, else the minibuffer picker with type/ns/arglists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
legmacs.modes.letgo-lookup, routed per buffer like eval and completion through a lookups registry: - eldoc: an after-command hook shows the enclosing call's arglists in the echo area when nothing else claimed it. It scans back only to the top-level form and reads the ns form from the buffer's head, so it's cheap per key; remote answers come from a short-TTL cache filled by a quiet spawn-task. - C-c C-d d / C-c C-d C-d: arglists, doc and source location in *Help*. - M-.: jump to the definition -- the current buffer, an open one, a file opened fresh, or for Clojure libraries the source read out of the jar into a read-only buffer. M-, pops back across buffers. In-process answers come from var metadata, resolving relative :file paths from the buffer's directory upward, LG_SOURCE_PATHS and the cwd. nREPL answers use cider-nrepl's eldoc/info, or nREPL's built-in lookup. Plumbing: letgo after-command-hooks (run after paren-matching, each in a try); a :visit buffer-command (show a buffer by id/filename/name or open :state, at row/col, clamped); a shared :xref-stack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…PATH The nREPL client needs let-go's net and bencode namespaces, which the old pin (a665761) predates. build/go.mod/go.sum are go mod tidy against the new pin. The suite now runs for real (it ran 0 tests before), and the jack-in tests start an actual lg -n server, so CI's test step puts the freshly built lg on PATH. Tests clean up with rm -rf rather than os/delete-tree for the same reason: not every lg has it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CIDER-style Clojure/let-go tooling for let-go-mode: an nREPL client, one-command jack-in, completion, eldoc, doc lookup and goto-definition. Each buffer routes all of it to either the editor's own VM or its project's nREPL server.
What you get
C-c M-jC-c C-qor editor exitC-c M-c/C-c C-q.nrepl-port) / disconnectC-x C-eC-jC-c C-vC-c C-eC-c C-e=load-file)TAB/M-TABTABcompletes only when indenting would change nothing and point ends a symbolns/name: [args]in the echo area while typing a callC-c C-d d*Help*M-./M-,Jack-in launch configs are data (
register-launch-config!):lgx.ednlgx nrepl --port Ndeps.ednclojure -Sdeps '{nrepl + cider-nrepl}' -M -m nrepl.cmdline …bb.ednbb nrepl-server Ndeps.edn, or nonelg -n -p NWhen the markers are ambiguous (
deps.ednfor both CLI and lg,bb.ednnext todeps.edn), the buffer's extension and a priority decide, and a real tie prompts.M-x nrepl-jack-in-commandedits the command first, andM-x nrepl-server-logshows the server output.Connections are per project root. File buffers under a connected root use that server. Fileless buffers (
*scratch*,*repl*) always stay in-process, so editor scripting keeps working next to two projects on two servers. The lighter showsnrepl:clj/:bb/:lg/:lgx.How it's built
legmacs.modes.letgo: every eval command builds one backend request.eval-backend-forpicks the backend per buffer through registered resolvers. With:in-process,C-x C-e/C-j/C-c C-estay synchronous, exactly as before; any other backend runs them throughspawn-task. Remote results come back asprinted-result.C-jandC-c C-vcheck that the form is still in the same buffer before writing. Newafter-command-hookslet eldoc run after paren-matching.legmacs.nrepl: bencode overnet, one blocking round trip per request, serialized by a channel-token lock inside the job's future. There's no long-lived reader goroutine forloop-waitto keep polling. Connections are keyed by project root; ops are discovered withdescribe, preferring cider-nrepl'scomplete/info/eldocwhen present. Server errors are cleaned to one line (message pluscaused by:chain), and an eval in a namespace the server hasn't loaded gets a note, because let-go silently falls back touser.legmacs.jack-in: let-go interop can't reachcmd.Process, so servers run undersh -c. The script writes a pidfile, logs to a file (an unread pipe would block the server) andexecs the command. The editor holds its stdin open (lg -nexits on EOF), and stopping it is SIGTERM plus closing stdin. Liveness usesps -o stat=, becausekill -0reports a zombie as alive. The editor picks the port, since bb doesn't write.nrepl-portfor port 0. Newbufs/add-exit-hook!stops everything after the terminal is restored.legmacs.modes.letgo-complete/letgo-lookup:completersandlookupsregistries per backend. In-process answers come fromns-map/ns-publics/aliases (including thensform's:requires) and var metadata. eldoc scans only back to the top-level form and caches remote answers for 15s. A new:visitbuffer-command and a shared:xref-stackimplementM-./M-,.Also in here
test/run.lgran 0 tests. let-go'srun-testsnow defaults to*ns*, so the suite had been reporting success without running anything, in CI too. It now usesrun-all-testsand runs 401 tests.CLAUDE.md's single-namespace command is fixed the same way.main(36d57e3), because the old pin predates thenet/bencodenamespaces.build/go.mod/go.sumare tidied against it. CI's test step putslgonPATH, since the jack-in tests start a reallg -nserver.What was tested
36d57e3(the new pin). The new tests use a fake bencode server on a loopback socket, a reallg -njack-in, and a server that dies at startup.M-.intoclojure/core.cljinside the Clojure jar.M-TAB,M-./M-,, doc, and no server left running afterC-x C-c.build.shplus the plan9/amd64 and plan9/arm cross-builds against the new pin. The generated Go has no closure-hoisting pattern (gogen: a capturing closure inside a conditional is emitted as the function's return value, discarding the branch let-go#766).Known gaps, from let-go
Filed together as nooga/let-go#961:
defmetadata (plus an option to elide it on purpose), so the native binary's in-process eldoc/doc/M-.know names only.inforeturns name/ns only, and it has noeldoc, streamed output, headless mode, plain-text errors, ornsin completions.Not done yet from CIDER: test runner, stacktrace view, interrupt (nooga/let-go#589), macroexpand, and a REPL buffer tied to the connection.
🤖 Generated with Claude Code