Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Calva to work with Fennel? #2664

Open
noncom opened this issue Nov 5, 2024 · 2 comments
Open

Using Calva to work with Fennel? #2664

noncom opened this issue Nov 5, 2024 · 2 comments

Comments

@noncom
Copy link

noncom commented Nov 5, 2024

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

But:

  • Calva's handshake is very Clojure-centric. Which is of course not very surprising.
  • Fennel is Clojure-like, but not 100%-like. For example, it doesn't have the concept of *ns*.

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.

  • Does this sound possible, or are there other known possible difficulties that I might be missing?
  • Is there maybe a documentation of the protocol that Calva works with? I can't seem to find anything specific in the nREPL docs or Calva manuals.
  • Is there some kind of debug mode in Calva to fully log all the nREPL communication?
@PEZ
Copy link
Collaborator

PEZ commented Nov 5, 2024

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
Copy link
Author

noncom commented Nov 9, 2024

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.

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.

  • Sending the top form to REPL doesn't work. Simply nothing happens. I haven't managed to get any error or message or anything at all.
  • Sending the selection to REPL works, but it looks like it doesn't submit the input. An additional press of the enter button is needed in the REPL window.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants