Skip to content
This repository has been archived by the owner on Jun 4, 2022. It is now read-only.

question: best way to integrate nrepl style tooling? #171

Open
bhurlow opened this issue May 27, 2017 · 25 comments
Open

question: best way to integrate nrepl style tooling? #171

bhurlow opened this issue May 27, 2017 · 25 comments
Labels

Comments

@bhurlow
Copy link

bhurlow commented May 27, 2017

@anmonteiro apologies if this question has been asked elsewhere. I'd like to start sending forms to a running lumo repl for remote evaluation ala "regular" clj nrepl tooling. It appears the socket repl is implemented but whats the preferred way to do this? would it make sense to implement the nrepl protocol inside lumo, or is this preferred as an external cljs lib?

Thanks!

@bhurlow
Copy link
Author

bhurlow commented May 27, 2017

@anmonteiro
Copy link
Owner

There's currently no nREPL implementation in CLJS and no plans to do it as part of Lumo. That said, there is inf-clojure support for Lumo and #105 aims to be a more general implementation of the socket REPL with support for extensible socket handling (a la clojure.core.server).

@pesterhazy
Copy link

@bhurlow I'd be curious what you mean by "nREPL style tooling", i.e. what pieces of functionality would you need? Specifically,

  • evaluating a form
  • evaluating a buffer
  • show-doc
  • auto-completion for function names, namespaces

I'm asking because of possible implications for unrepl. With the unrepl project we're trying to come up with a simple but universal tooling protocol for Clojure dialects. It's WIP, but ClojureScript support is being actively worked on.

@darwin
Copy link

darwin commented Jun 1, 2017

In theory Dirac machinery should be able to do that, but nobody has ever tried that before I guess.

The idea is to:

  1. install Dirac Runtime into your lumo script (which has to sit in event looping)
  2. setup your nREPL server with Dirac middleware and Dirac Agent
  3. run lumo's node with debugger port opened (--inspect)
  4. connect with Dirac DevTools
  5. join Dirac session from your favourite IDE via Clojure nREPL session

https://github.com/binaryage/dirac/blob/master/docs/about-repls.md#dirac
https://github.com/binaryage/dirac/blob/master/docs/node.md
https://github.com/binaryage/dirac/blob/master/docs/integration.md
https://github.com/binaryage/dirac/blob/master/docs/installation.md

@arichiardi
Copy link
Collaborator

@darwin I'd like to try that!

I have also seen the latest Google Chrome additions and they automatically detect node processes started with --inspect and can debug. Of course no cool Dirac pretty printing is shown in their plugin, but source maps are working fine.

@darwin
Copy link

darwin commented Jun 1, 2017

@arichiardi Cool! Don't forget to let me know how it went. If you hit a road block, you could share a demo project and I would try to fix it. And btw. stock DevTools still might have confused "locals" and other names: binaryage/dirac#53 (comment)

@mfikes
Copy link
Collaborator

mfikes commented Jun 2, 2017

I thought Socket REPL would be widely supported by tooling, and added support for it to Planck 1.9 back in Jan 2016.

I now think that a (self-host compatible) ClojureScript port of nREPL should be done so that ClojureScript REPLs can support nREPL if desired. I think @futuro had been contemplating such a port.

@futuro
Copy link
Contributor

futuro commented Jun 2, 2017

The Lumo (and possibly Planck) Socket REPL implementation should be easily adaptable to putting an nREPL server on top of it.

I break the nREPL up into four large parts; the Orchestrator, the Transport layer, the Handler, and the Middleware. You can read more about my thoughts on that at this medium post but the relevant point is that the Socket REPL already has the Orchestrator in that it listens on a socket and, when someone connects, passes that connection off to an accept function.

So, if you want to create an nREPL on top of that, your accept function just needs to take in a socket and some optional args, then set up the Transport, Handler, and Middleware.

The Transport is Bencode, so once you've got a library to bencode/debencode the messages over the wire, that's mostly done.

With regards to the middleware, the biggest difference between the CLJ nREPL and some potential future CLJS nREPL is that the CLJ nREPL can rely on JVM threading for async tasks, as well as uniform I/O semantics through clojure.java.io.

If you just want to build the nREPL for a singular platform you could skip a platform agnostic I/O library and use something built just for your host. Personally I'm keen on https://github.com/abiocljs, which is focused on creating a JS platform agnostic I/O library.

Handling async tasks like reading files or executing code will probably rely on either cljs.core.async (perhaps using https://github.com/mfikes/andare/) or leveraging the js platform's semantics for async code and callbacks. Personally I'm currently in favor of using andare so I don't have to also create a platform agnostic, clojurified async js library, but possibly something will come along before I or anyone else gets to this point and core.async won't make sense anymore.

My current plan is to get the Lumo Socket REPL to run user specified accept functions (almost done here), then square away abio's async I/O functionality, and finally write a POC on top of Lumo for the nREPL. Your mileage may vary ;)

@bhurlow
Copy link
Author

bhurlow commented Aug 15, 2017

@anmonteiro tweeted this link, but I figured I'd leave here for those interested in repl related things re: lumo and beyond: https://www.youtube.com/watch?v=2P-UzXksdHs

@arichiardi
Copy link
Collaborator

I second unrepl :)

@johanatan
Copy link

So what's the latest story on integrating Lumo with, e.g. CIDER?

@arichiardi
Copy link
Collaborator

Everything that @futuro said is still valid, he added the socket repl implementation and there is a PR for getting suspension in Lumo for supporting unrepl in the future.
In the meantime, something like inf-clojure works perfectly well if you don't need feature parity with CIDER.

@johanatan
Copy link

johanatan commented Jan 9, 2018

I am asking particularly with respect to CIDER. I have no idea what unrepl is or whether it is related to or integrates with or can cooperate with CIDER. But I am looking for a "one button click/ turnkey" solution for CIDER particularly. Thanks!

@arichiardi
Copy link
Collaborator

Nothing there yet, but contributions are welcome!

@bhurlow
Copy link
Author

bhurlow commented Jan 9, 2018

@johanatan there is no out of the box solution for integrating with lumo repl like you may be used to with clj.

Lumo supports the socket repl spec, which you may use via clj with something like: https://github.com/mfikes/tubular

@djblue
Copy link

djblue commented May 2, 2019

I started on an nrepl implementation in lumo using the node net package. I can pass messages successfully between an existing client(vim-fireplace) and my tcp nrepl server.

However, I am having issues integrating the nrepl eval op with lumo. It looks like fireplace depends on clojure namespace introspection features such as all-ns, ns-maps and ns-aliases. I'm looking through repl.cljs to figure out how to wire everything together.

Basically, the problem is how should I got about implementing nrepl eval for lumo. Does anyone have some pointers on how I should approach this problem?

@anmonteiro
Copy link
Owner

@djblue that's pretty awesome. are those 3 functions all you need?

@djblue
Copy link

djblue commented May 2, 2019

@anmonteiro I might need more stuff later but I think those three should get auto completion working in fireplace. I'm incrementally adding features as I go. The code is pretty bad right now, but simple stuff like (+ 1 2 3) and (range 100) seem to work just fine. I could push up the code if that would help.

@anmonteiro
Copy link
Owner

@djblue I can add ns-aliases, but can you clarify what you expect ns-maps to be?

@djblue
Copy link

djblue commented May 2, 2019

@anmonteiro Sorry, I meant ns-map.

@djblue
Copy link

djblue commented May 2, 2019

Should my nrepl server be accessing those private function in the lumo.repl namespace? Also, fireplace expects those functions to be in clojure.core I think, so I've just been manually def'ing them in cljs.core. What's a good approach for exposing those functions to clients?

@anmonteiro
Copy link
Owner

I think fireplace just expects them to be referred, which is doable in Lumo.

@vigilancetech-com
Copy link

how is this coming? Is there a github repo on it? A blog?

@djblue
Copy link

djblue commented Jun 15, 2019

@vigilancetech-com I have a github repo nrepl-cljs which I've been working in when I have time. It's still in the initial phase but I'd be happy to collaborate with others 👍

@arichiardi
Copy link
Collaborator

arichiardi commented Jun 15, 2019

That's a very nice project! My 2c on this is that the best approach would be to have a server with bencode transport going (I see it there already and actually there is a JS lib for bencode we could reuse) and then port with conditionals the nRepl middlewares that we want to hook in it, either from cider-nrepl or directly from orchard. I have basically ported the info op already to ClojureScript and it should be lumo compatible.

A simple test would be to import orchard so that it is available to the lumo classpath and try to require it. I will see what I can do I might be able to play around with this. It is definitely exciting not just for lumo but for ClojureScript in general - a fast-startup nRepl is very desirable 😃

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

No branches or pull requests

10 participants