anmonteiro / lumo

Fast, cross-platform, standalone ClojureScript environment
Eclipse Public License 1.0
1.88k stars 84 forks source link

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

Open bhurlow opened 7 years ago

bhurlow commented 7 years ago

@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 commented 7 years ago

https://github.com/cgrand/cljs-js-repl

anmonteiro commented 7 years ago

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 commented 7 years ago

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

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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

@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: https://github.com/binaryage/dirac/issues/53#issuecomment-276828904

mfikes commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

I second unrepl :)

johanatan commented 6 years ago

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

arichiardi commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

Nothing there yet, but contributions are welcome!

bhurlow commented 6 years ago

@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 commented 5 years ago

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 commented 5 years ago

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

djblue commented 5 years ago

@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 commented 5 years ago

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

djblue commented 5 years ago

@anmonteiro Sorry, I meant ns-map.

djblue commented 5 years ago

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 commented 5 years ago

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

vigilancetech-com commented 5 years ago

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

djblue commented 5 years ago

@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 :+1:

arichiardi commented 5 years ago

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 😃