Overhaul REPL input: token completion and whole-form reading - #1
Merged
Merged
Conversation
The old examples leaned on utop's nREPL server mode, which lives on an experimental branch that will probably never ship. The new sessions were captured against real servers - the Clojure reference implementation and dialtone.
nREPL servers complete bare symbol prefixes ("ma", "lists:re"), not
whole lines, so Tab only ever worked when the line held nothing but
the prefix. Split the line at the last delimiter, ask the server
about the trailing token and splice the candidates back into the
line for linenoise. The splitting lives in a small private
repl_input library so the tests can reach it.
The CLI banner parsed the versions dict inline into a display string, which left no way for other code to ask what is on the other end of the connection. Extract the (name, version-string) pairs in Client.versions and keep only the formatting in the CLI; multi-line input support is about to need the names to pick an input dialect. Names without a version-string now show up bare in the banner instead of being dropped.
Multi-line definitions used to be --load-only. The REPL now keeps prompting for continuation lines (with a ...> prompt) until the input reads as a complete form: balanced brackets and closed strings for Lisp-family servers, a terminating dot for Erlang. The dialect is picked from the server names in describe's version table; Elixir deliberately falls back to the generic bracket rule since do/end blocks can't be bracket-counted. When the heuristic sends too eagerly the server reports the syntax error it would have reported anyway. History is now saved once per form instead of once per line, since linenoise rewrites the whole file on every save.
The linenoise fork we link ships most of the emacs-flavored readline set, including Ctrl-R incremental history search, but none of it is discoverable from the prompt. Spell it out.
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.
Tab completion used to send the whole line as the completion prefix, which real servers answer with nothing - they complete bare symbol prefixes, so completion only worked when the line held nothing but the prefix. And multi-line definitions could only arrive via --load.
The REPL now completes the trailing token and splices the candidates back into the line, and it reads whole forms: continuation lines until brackets and strings balance for Lisp-family servers, or until the terminating dot for Erlang, with the dialect picked from the server names in describe's version table. Elixir stays on the generic bracket rule since do/end blocks can't be bracket-counted. Tested against the Clojure reference server, dialtone and repartee.
While at it, the README drops the utop-based examples (utop's nREPL server mode lives on an experimental branch that will probably never ship) in favor of Clojure and Erlang ones, and documents the key bindings.