You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
The client starts a REPL process as usual
Client then sends the protocol as input to the REPL with an editor-specific formatting function
After that, REPL responds with a message that the initialization was either a success or a failure
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.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
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