Piggieback, middleware for running ClojureScript REPLs over an nREPL session

505 views
Skip to first unread message

Chas Emerick

unread,
Aug 10, 2012, 11:26:27 PM8/10/12
to clojur...@googlegroups.com
I've released Piggieback tonight:

https://github.com/cemerick/piggieback

"Piggieback provides an alternative ClojureScript REPL entry point (cemerick.piggieback/cljs-repl) that lifts a ClojureScript REPL on top of any nREPL session, while accepting all the same options as cljs.repl/repl."

This helps a sore spot of mine, as well others that have tried to use ClojureScript via Leiningen, nrepl.el, CounterClockwise, etc.:

http://code.google.com/p/counterclockwise/issues/detail?id=357

Feedback most welcome, as well as contributions to make it easier to use with other ClojureScript REPL environments and such.

I'll likely make an announcement on the main Clojure mailing list once Piggieback (and nREPL middleware in general) is easier to use.

Cheers,

- Chas

Laurent PETIT

unread,
Aug 11, 2012, 7:09:02 PM8/11/12
to clojur...@googlegroups.com
Hello, can't wait trying it from CCW!

Some remarks/questions:


Le 11 août 2012 à 05:26, Chas Emerick <ch...@cemerick.com> a écrit :

> I've released Piggieback tonight:
>
> https://github.com/cemerick/piggieback
>
> "Piggieback provides an alternative ClojureScript REPL entry point (cemerick.piggieback/cljs-repl) that lifts a ClojureScript REPL on top of any nREPL session, while accepting all the same options as cljs.repl/repl.":

Does that mean that as with the out of the box clojurescript repl, the
user has to type some incantation to enter in "clojurescript repl"
mode, or should we start, on the server side, two nrepl servers, one
serving regular clojure, and one serving as a proxy for clojurescript
repl?

>
> This helps a sore spot of mine, as well others that have tried to use ClojureScript via Leiningen, nrepl.el, CounterClockwise, etc.:
>
> http://code.google.com/p/counterclockwise/issues/detail?id=357
>
> Feedback most welcome, as well as contributions to make it easier to use with other ClojureScript REPL environments and such.

Is it possible for the middleware to be parameterized so that e.g. the
kind of back-end can be passed as a middleware configuration
parameter? (maybe this question makes no sense and shows how few I
know about clojurescript :-/ )

Regards,

Laurent

Chas Emerick

unread,
Aug 11, 2012, 8:25:00 PM8/11/12
to clojur...@googlegroups.com
> Le 11 août 2012 à 05:26, Chas Emerick <ch...@cemerick.com> a écrit :
>
>> I've released Piggieback tonight:
>>
>> https://github.com/cemerick/piggieback
>>
>> "Piggieback provides an alternative ClojureScript REPL entry point (cemerick.piggieback/cljs-repl) that lifts a ClojureScript REPL on top of any nREPL session, while accepting all the same options as cljs.repl/repl.":
>
> Does that mean that as with the out of the box clojurescript repl, the
> user has to type some incantation to enter in "clojurescript repl"
> mode, or should we start, on the server side, two nrepl servers, one
> serving regular clojure, and one serving as a proxy for clojurescript
> repl?

The default ClojureScript REPL "takes over" control of *in* and *out* of a Clojure REPL in a terminal session; it's built up just like you might write your own read-eval-print-loop for Clojure code (or any other evaluated expressions) on top of a Clojure REPL.

Piggieback does the same, but on top of an nREPL session (thus the name). Invoking cemerick.piggieback/cljs-repl will set! a couple of vars to contain a provided or default ClojureScript REPL environment, and a function which has the responsibility of actually evaluating ClojureScript expressions. All the middleware does is listen for and intercept :op "eval" nREPL messages, and, if those ClojureScript REPL vars are bound, modifies the "eval" message to evaluate provided expressions using the function and environment set up by cljs-repl instead of doing so directly.

This makes it so that existing nREPL clients don't have to change anything about how they send code to be evaluated, and the semantics of sessions, returned values vs. streamed *out*/*err*, etc., all remain intact.

To answer your question directly: yes, the incantation required is (cemerick.piggieback/cljs-repl) (with some optional configuration if desired), and no, only one nREPL server is required.

>> This helps a sore spot of mine, as well others that have tried to use ClojureScript via Leiningen, nrepl.el, CounterClockwise, etc.:
>>
>> http://code.google.com/p/counterclockwise/issues/detail?id=357
>>
>> Feedback most welcome, as well as contributions to make it easier to use with other ClojureScript REPL environments and such.
>
> Is it possible for the middleware to be parameterized so that e.g. the
> kind of back-end can be passed as a middleware configuration
> parameter? (maybe this question makes no sense and shows how few I
> know about clojurescript :-/ )

There's really no need to parameterize the middleware. What type of ClojureScript REPL you want to run is a decision easily made on the Clojure REPL when invoking cemerick.piggieback/cljs-repl, e.g. Rhino vs. V8 vs. browser-repl. (The latter, BTW, has been confirmed to work with piggieback quite transparently: https://www.refheap.com/paste/4239).

If you really want to, you could set up a ccw REPL configuration to immediately load a file or expression with a cemerick.piggieback/cljs-repl invocation to start whatever sort of ClojureScript REPL you want. I have a variety of more general ideas about how all of this can be made as smooth as possible in ccw, but that should probably go onto the ccw-specific list. ;-)

- Chas

Shane Daniel

unread,
Feb 7, 2013, 5:32:33 AM2/7/13
to clojur...@googlegroups.com
Chas,

Thanks for the awesome libraries! I am trying to put Drawbridge & Piggieback together, allowing me to connect to browser REPL running on Heroku. However, Heroku doesn't allow multiple ports as far as I can tell, so the browser REPL has to run alongside everything else somehow.

Currently Piggieback makes for an excellent local dev tool, but I'd like to see it applied beyond localhost. Any pointers would be appreciated.

Thanks again for your contributions,

Shane Daniel

Chas Emerick

unread,
Feb 7, 2013, 6:41:33 AM2/7/13
to clojur...@googlegroups.com
Shane,

I'm not clear on what you're trying to do; AFAIK, the browser REPL is decidedly not intended to be used from a deployed app not in a development environment.  Even if you were able to start and run the browser-REPL server alongside your primary application, the REPL would still be effectively running locally (in the JS runtime of the browser you connect to the browser-REPL server, which really is only needed as conduit to the ClojureScript compiler).

Of course, you can drop drawbridge into a deployed heroku app without difficulty (though securing access to the REPL's handler is imperative, and is up to you).

Cheers,

- Chas

--
You received this message because you are subscribed to the Google Groups "clojure-tools" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-tool...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Shane Daniel

unread,
Feb 10, 2013, 4:44:13 PM2/10/13
to clojur...@googlegroups.com
Chas,

It was a breeze to set up Drawbridge with auth on Heroku following technomancy's example, Chortles.

https://github.com/technomancy/chortles

My intention was to use the browser REPL in a fashion similar to http://jsconsole.com for remote debugging. It wouldn't be used in a production build, but in a distributed, deployed dev environment (where Heroku shines).

Piggieback locally is cool because it gives the developer access to all parts of the system. If the browser REPL could also be set up like Drawbridge with specific routes dedicated to it, we'd have ClojureScript remote debugging. A party time zones away could test and reproduce a tricky bug, and the developer could connect directly into their session. JS Console already allows these interactions, with the proper set up (and trust in jsconsole.com). What if we could have it in Clojure, over our own servers?

Thanks,

Shane

zoka

unread,
Feb 11, 2013, 6:44:12 PM2/11/13
to clojur...@googlegroups.com
Hi Shane,

Have look at http://webrepl.herokuapp.com/ringmon/monview.html

It provides web based REPL with multiple remote users sharing the same Clojure app instance in the cloud. Rudimentary IRC-alike chat facility is provided as well.

Regards
Zoka

Chas Emerick

unread,
Feb 13, 2013, 7:53:37 PM2/13/13
to clojur...@googlegroups.com
I'm not familiar with jsconsole, but browser-REPL doesn't quite work the way you're describing. The ClojureScript runtime is *in* the browser, the server-side portion of it simply hosts the ClojureScript compiler (which is implemented in Clojure, thus requiring the dueling runtimes). So, if two people connect to a browser-REPL endpoint, two completely separate ClojureScript runtimes would be humming, in each person's respective browser. (This wouldn't actually work due to browser-REPL implementation details that prevent running two concurrent sessions, but the principle holds.)

Now, it's certainly plausible for multiple people to join in on a single Clojure REPL session, or a single ClojureScript REPL session running in a commonly-accessible runtime (e.g. Rhino, Nashorn, etc. on the server). That'll just require some nREPL hacking. :-)

- Chas

Shane Daniel

unread,
Feb 15, 2013, 12:45:59 AM2/15/13
to clojur...@googlegroups.com
The problem I'm trying to solve is not multiple browsers connected to one REPL (though that could be interesting if cljs was simultaneously evaluated in different contexts producing results somehow organized presentably to the REPL, eg testing polyfills for functionality in different browsers).

Nor am I trying to allow multiple users of a Cljscript REPL, though that could make for some interesting pair programming.

Often in web development, someone will find an obscure bug that only occurs when you have xyz user settings on zyx browser on wvu OS with a network restricted in miscellaneous ways. Sometimes, these bugs are showstoppers, potentially causing a lot of customer support issues and/or angry Internet nerds. General debug recreates the bug by recreating the environment, but as devices proliferate (hello mobile web) and standards evolve, it can be hard to cover all the bases.

A web service that offers remote debugging could avoid attempting to recreate the bug's environment by inspecting the original host.

Jsconsole has a similar one-connection only restriction to Clojure's browser REPL server. If multiple browsers are listening, things can get wonky. That's why I start JSconsole with pseudo-random :listen ids and dynamically load the required javascript (remote.js) with a simple <input> (to match the :listen id) and script injection. I can tell someone to navigate to the debug form in their browser, input the :listen id, and hit submit. This gives me access to their browser environment with all its glory. If I exposed tests in my code, I could see what failed and try it again for myself.

Anyway, I have settled with restricting my browser-environment nREPL goodness to localhost. With a few leiningen profiles with different REPL-init commands (and some aliases to keep them memorable), I can get whatever REPL I need.

Thanks again for the great tools. The more I use them the more uses I find for them.

Reply all
Reply to author
Forward
0 new messages