BetterThanTomorrow / calva

Clojure & ClojureScript Interactive Programming for VS Code
https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.calva
Other
1.71k stars 218 forks source link

Using Calva to work with Fennel? #2664

Open noncom opened 3 weeks ago

noncom commented 3 weeks ago

I'm currently trying to see if I can make the Fennel nREPL server JeeJah work with Calva Connect to REPL.

But:

So there are some problems in communication right from the start, the server gets confused by the handshake requests from Calva.

What I think is that if the connection is made, and all such specifics is emulated on the Fennel/nREPL-server side, further work should go pretty well. The source code format of Fennel is very similar to Clojure, so there would likely be not much problem further on?

So my hope is to emulate on the Fennel side what Calva expects, and make them work together.

PEZ commented 3 weeks ago

Hello! Super fun that you are experimenting with this. Less fun that it doesn't work, but let's make it work!

I'm thinking one source of problems could be the code in the calva.autoEvaluateCode.onConnect setting. It defaults to:

(when-let [requires (resolve 'clojure.main/repl-requires)] (clojure.core/apply clojure.core/require @requires))

Which maybe trips Fennel up?

I don't think Calva fiddles with *ns* directly, but I could remember that wrong.

Your strategy is sound, I think. However, maybe we could start in the Calva end of things and see how much Fennel support we can reach that way? Calva has a few adaptions like that for some different runtimes. Though, these are more Clojure runtimes, than Clojure-like runtimes, so who knows.

There is not much in the way of documentation on the protocol from the Calva side. The nREPL project is where this is described. The ultimate sources of truth will be Fennel's nREPL server and Calva's nREPL client.

There is a command in Calva for enabling logging of the messages that Calva sends and receives. Search the command palette for Calva Diagnostics and you should find it. If Fennel's nREPL server has any similar logging, that would be powerful in combo.

Please let me know if there is anything I can answer or help with. I can make myself available for a screen-sharing session, if you think that would speed things up.

noncom commented 3 weeks ago

Hey, thanks so much for the support! 😄 Much appreciated! I tried a bit more, and managed to get it to some kind of a working state. Calva Diagnostics together with debug printing on the JeeJah's side helped a lot! But there are some more details to be figured out.

Mostly I'm loaded with various stuff these days, and only get occasional pockets of time to work on experiments, so my overall progress might be naturally slow. But also I'm good to try to make it work WELL in the end, so if a co-op would be needed, I'm also available, that's no problem. My hope is that it would be really great to have an alternative to Emacs, it's fine in its own right, but some of it feels very outdated.

So I created a fork of JeeJah with the changes. A bit messy, but it's in the WIP status.

The beginning of the readme has the details on how it currently works, but I would additionally highlight the following points of varying levels of problematic:

1. Handshake

As for what Calva sends, it's first this:

{:code "*ns*" :id "1" :op "eval"}

and then yeah, this:

{:code "(when-let [requires (resolve 'clojure.main/repl-requires)] (clojure.core/apply clojure.core/require @requires))"
 :column 1
 :file "d:\\work\\_fennel\\jeejah\\.calva\\output-window\\output.calva-repl"
 :id "4"
 :line 52
 :nrepl.middleware.print/options {:length 50 :right-margin 120}
 :nrepl.middleware.print/print "cider.nrepl.pprint/pprint"
 :ns ">"
 :op "eval"
 :pprint 1
 :session "318942278"}

both of which cause errors in Fennel, but they don't break anything. After the handshake passes, the REPL works, and can be used to talk to Fennel. I'm not sure if the overall mission of Calva includes supporting any Clojurelikes in addition to Clojure itself, but if that's something in sight, then maybe a more in-depth customization of handshake would be good to have to make it all cleaner. Otherwise this can be ignored.

2. The Jack-In doesn't work

But Connect to REPL works. See in the readme.

3. The capabilities format

JeeJah sends nREPL ops as a ["op1", "op2", ...], while Calva expects {"op1": {}, "op2": {}, ...}. I'm not sure about this one, this might be some nREPL version thing or something, I have little experience with the protocol. Currently I added an option to JeeJah to emit the {...} version, which solves the problem.

4. The info op

I get this popup in Calva:

The nREPL server does not support cider-nrepl `info` op, which indicates troubles ahead. You need to start the REPL with cider-nrepl dependencies met.

I found this example of a similar issue, referring to the CIDER implementation as the example, and finally the Babashka implementation.

Currently I haven't looked much into it yet, but as far as I understood, this is Clojure-specific, and idk if it's possible to support this in Fennel.

5. Sending to REPL

There are some issues. Not sure if they are somehow related to the absense of the info op or not.

All in all it seems like it should be possible to address all or most of these issues. The most mysterious one for me is the point about info, I'll take a deeper look at the examples next time.