What happens when you start a CLJS REPL?
Hey, just saw this in my Twitter feed.
I recently spent some time with REPL related ideas myself and one of the key requirements for me is that I want to be able to launch a CLJS REPL seamlessly. I like your approach but what happens if you start another REPL that is not aware of this protocol?
Take the default CLJS REPL as an example. It will takeover the *in* and only write to *out*. While that should produce proper [:out ...] EDN forms (assuming you provide a custom *out* binding) that will be the only thing it sends. No :eval or :prompt. The UI I imagine you'd build out of this would seem "stuck"?
You nested them in the wrong order: (CLJ -> )CLJS -> EDN
However the real question to address is how to ensure that CLJ -> EDN -> CLJS -> EDN works.
Right now I'm thinking of having the server sending [:upgrade nil] before yielding control to the inner repl. Then the client can attempt upgrading plain cljs repl to an unrepl cljs repl.
The CLJS REPL has some other hidden "problems" in that print and eval happen in the JS runtime. This makes a custom eval and print tricky without having the code already present in CLJS.
Maybe the REPL should support arbitrary output streams (not just :out) as well. Since in the CLJS world you'll have the CLJS compiler producing output (eg. compile warnings) as well as the connected JS process.
As far as the output streams go, it would probably be useful to make them thread aware to avoid garbled output like
user=> (dotimes [x 10] (future (Thread/sleep 1) (prn :foooo)))
nil
user=> :foooo
:foooo
:foooo
:foooo:foooo
:foooo:foooo
:foooo:foooo
:foooo
So the tool can re-assemble the streams easily.
That's what the third optional component ("group id") is for in the tuples.
@thheller https://github.com/cgrand/unrepl/commit/1da6ef75160c9466e865963a7a6f13562ee22115 enables the use of "group id" in the prototype impl.