Protocol-based Fennel REPL #478
andreyorst
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi! First of all, I'm not a Neovim or Conjure user, so this is an idea coming from someone outside of both communities. I'm however part of the Fennel community, and as far as I know, Conjure is one of the most popular plugins to interface with Fennel outside of Neovim. I'm one of the maintainers of the fennel-mode package, and recently I've spent a lot of time thinking about how we can improve Fennel integration in fennel-mode.
As far as I can see, Conjure uses a similar approach to fennel-mode as it also parses the output of the
fennel --repl
process. This can lead to many problems, because the process output may contain things that look like the prompt. Implementing such features as completion, documentation, and goto definition is then quite hard to do, and I'm not sure that Conjure provides completion support for Fennel (correct me if I'm wrong). In fennel-mode, we had support for completions, and other interactive commands, but the implementation was error-prone.So I've created a protocol for Fennel, which is also
stdio
based, as a normal REPL. It doesn't require any dependencies, and it can upgrade an existing REPL (requires Fennel 1.3.1+), thus it can be embedded in the client.The way it works is as follows:
Then the client can send messages as Fennel tables and read back messages as the data structure specified by the format function. For example, in Emacs we send messages like
{:id 1 :eval "(+ 1 2)"}
and read back property-lists(:id 1 :op "eval" :values ("3"))
. If the editor has native support for JSON or even Lua tables, a format function can be provided to properly serialize outgoing REPL messages, so the editor would read them natively. So the protocol is editor-agnostic.I've implemented a new client for Emacs around this protocol, and at the core of it are just two functions, one that sends message asynchronously, and the other one that does the same in a synchronous way, the rest is basically wrappers around them and Fennel REPL features. These functions can override default callback for
stdout
and error handling for a given message, and as a result can be used in a variety of ways. I suppose the same can be done in Neovim.The protocol is similar to nREPL, as it is ID-based, with a small difference that it is Fennel REPL-centric, and is much smaller because it relies on built-in REPL comma-commands. All messages are single line, so it's easy to parse based on literal newlines, and everything is serialized in a way that the editor can just read back data. So if the client has a way of registering a callback for a specific ID, and then once the message for that ID comes back from the REPL process, the client can execute the callback. As I can see, the Clojure support in Conjure is based on callbacks, so this should be possible to do with such a protocol.
Let me know what you think!
Beta Was this translation helpful? Give feedback.
All reactions