piggieback nrepl counterclockwise cider-nrepl

171 views
Skip to first unread message

Laurent PETIT

unread,
Mar 26, 2015, 6:17:59 PM3/26/15
to clojur...@googlegroups.com
Hello,

I've been toying with cider-nrepl on the nrepl server side, managing to get counterclockwise use "complete" and "info" ops from its own private connection (not the one used by the user repl client).

This works well, and opens interesting perspectives.

Next, I'm trying to leverage this to get "for free" completion / information for clojurescript projects.

I'm able to start a clojurescript repl from the repl client.

But I don't know how to do this from the counterclockwise private connection.
I was hoping it would have been transparent, but it's probably not possible. Counterclockwise will somehow have to decide that it wants to reach a clojurescript env.

But how?



--
Laurent Petit

Michael Griffiths

unread,
Mar 29, 2015, 2:13:51 PM3/29/15
to clojur...@googlegroups.com
Hi Laurent,

cider-nrepl works by checking the current session map for vars bound by piggieback. If you pass the user REPL's session id in the `session` slot of your messages, it should transparently do the right thing Clojure/ClojureScript-wise depending on if a piggieback REPL is active in that session.

Thanks,

Michael

Laurent PETIT

unread,
Mar 29, 2015, 2:41:05 PM3/29/15
to clojur...@googlegroups.com
Hey,


Le dimanche 29 mars 2015, Michael Griffiths <mikeygr...@gmail.com> a écrit :
Hi Laurent,

cider-nrepl works by checking the current session map for vars bound by piggieback. If you pass the user REPL's session id in the `session` slot of your messages, it should transparently do the right thing Clojure/ClojureScript-wise depending on if a piggieback REPL is active in that session.

I see, that's cool ! So I just steal the user's repl session id and use it through my tool connection. 

I will soon have to distinguish between several open repls (one for the clojure server code, one for the cljs repl, quite a classic pattern I guess). Do you know if there's a reliable way to know which repl can be qualified as "clojure repl" and which one as "clojurescript repl", either indirectly by checking return maps of some ops, or directly via some specific op call, or jus by trying to read either clojure-version or clojurescript-version ?
 

Thanks,

Michael

On Thursday, 26 March 2015 22:17:59 UTC, Laurent Petit wrote:
Hello,

I've been toying with cider-nrepl on the nrepl server side, managing to get counterclockwise use "complete" and "info" ops from its own private connection (not the one used by the user repl client).

This works well, and opens interesting perspectives.

Next, I'm trying to leverage this to get "for free" completion / information for clojurescript projects.

I'm able to start a clojurescript repl from the repl client.

But I don't know how to do this from the counterclockwise private connection.
I was hoping it would have been transparent, but it's probably not possible. Counterclockwise will somehow have to decide that it wants to reach a clojurescript env.

But how?



--
Laurent Petit

--
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/d/optout.


--
Laurent Petit

Michael Griffiths

unread,
Mar 29, 2015, 3:24:17 PM3/29/15
to clojur...@googlegroups.com
In CIDER we don't currently distinguish between Clojure and ClojureScript sessions on the client-side at all, but I'm sure we can add an op to cider-nrepl to let clients do this.

CIDER doesn't yet have first-class support for multiple sessions/REPLs for the same connection, but I've been thinking about how to add it recently. Do you plan on just routing requests for any *.cljs file to any available ClojureScript session, or something more advanced?
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-tools+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--
Laurent Petit

Laurent PETIT

unread,
Mar 29, 2015, 3:38:23 PM3/29/15
to clojur...@googlegroups.com
2015-03-29 21:24 GMT+02:00 Michael Griffiths <mikeygr...@gmail.com>:
In CIDER we don't currently distinguish between Clojure and ClojureScript sessions on the client-side at all, but I'm sure we can add an op to cider-nrepl to let clients do this.

CIDER doesn't yet have first-class support for multiple sessions/REPLs for the same connection, but I've been thinking about how to add it recently. Do you plan on just routing requests for any *.cljs file to any available ClojureScript session, or something more advanced?

Since it's quite hard to know what the user assumes (for instance they may be working with 2 REPLs on 2 projects, one being a dependency of the other, but sometimes wants code to go to the dependency REPL, some other time go to the other REPL), I don't try to do anything advanced.

I just use the REPL that was last active. The open question being: should I try to segregate REPLs by their clojure/clojurescript type, thus effectively maintaining a "last active clojure repl" and a "last active clojurescript repl", and sending to one or the other depending on the file extension ...

I guess I'll do that, but I can already see a time where a user will say "hey, I use crossovers, why is it my code always goes there ... and not there ..." :-)
 
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/d/optout.



--
Laurent Petit

Michael Griffiths

unread,
Mar 29, 2015, 4:04:36 PM3/29/15
to clojur...@googlegroups.com
One idea I have is to have some project-level configuration for the sessions to create on connection. Something like this:

{:clj {:predicate "*.clj"}
 :cljs {:predicate "*.cljs" :init "(start-cljs-repl)"}

This would cause both a :clj and a :cljs session to be created on connection, and eval "(start-cljs-repl)" in :cljs once it's created. :predicate could be a path specification, or something equivalent (e.g. a function of the current buffer in emacs), and the :predicate of each session would be evaluated in declaration order to determine which session to use for each request. This would account for project setups like:

* CLJS client in browser / CLJS server in node.js
* CLJ client / CLJ server

But as you say, this kind of thing is hard to get right in the face multiple projects and tools like CLJX/crossovers/feature expressions.

Michael

Laurent PETIT

unread,
Mar 29, 2015, 4:33:48 PM3/29/15
to clojur...@googlegroups.com
Yep, and as an "IDE" provider, willing to please as many users as possible, and provide as much "no brainer / out of the box" behavior as possible, the fact that there are still so many build tools available for users to place this kind of information does not really help :) (lein, boot, maven, gradle as usual suspects).

The recent move of clojurescript towards exposing the functions as APIs, and also the recent work on leveraging sockets for clojure repls gives me some hope in this area: if things could move from build-tool specific mix of declarative/imperative stuff to simple "starter scripts" as those described e.g. in the recent clojurescript "Quick Start" Guide ( build.clj, release.clj, node.clj, node_repl.clj, etc. https://github.com/clojure/clojurescript/wiki/Quick-Start ), then things may be simpler during development (please, let me dream a little bit ;-).

The scenario would then be really easy: provide the user with a list of "starter files" (one of the many *.clj files at the top of the project) to choose from. Connect the IDE to the input / output, and there you go.

In this ideal world, build tools would downgrade from their "master of the process" pedestal to "library to be used/called from the *.clj starter files".
Things like that ;-)




Michael

--
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/d/optout.



--
Laurent Petit

Colin Fleming

unread,
Mar 30, 2015, 12:07:32 AM3/30/15
to clojur...@googlegroups.com
Interesting discussion! I'm also hopeful that we can break up monolithic build tools into composable libraries - I'm a big fan of shadow-build for this reason and I think boot looks promising too, although I haven't had time to look at it in detail yet.

What I've found in Cursive is that the best solution is for the user to be able to say "this is now a CLJS REPL" (in Cursive this is a combobox in the toolbar), and then Cursive tries to switch automatically by monitoring the output for banner strings. This works pretty well so far - it's not perfect, but when it doesn't work the user can do it manually. There are just too many different ways for a REPL to become a CLJS REPL for Cursive to anticipate them all. That flag affects which files can be loaded into the REPL, how completion etc works in the editor and how forms are executed.

I've also been thinking about the multiple REPL idea. Cursive has a "sync files in REPL" feature similar to tools.namespace. I'd love that to be able to work across multiple REPLs, and knowing which to send the files to is really tricky. My plan is to define scopes within the project ("server code", "client code") and have a scope associated with each REPL. IntelliJ has modules which would work for those scopes, and they're created from lein projects so that would map nicely with the only restriction being that server and client code would have to be separate lein projects. REPLs are already implicitly associated with a module since that's where the classpath is built from. You also need the language of the REPL, but Cursive already has that as detailed above. IntelliJ also has the concept of scopes within the project that I could use, but that would be more fiddly, I think. Then the file sync can find the scope associated with all modified files, and load them into the appropriate REPL. I'm actually going to need the scope idea even with single REPLs since for users with large multi-module projects, Cursive will currently try to load files even if they're not related to the module which the REPL was started from, which is not good.

Laurent PETIT

unread,
Mar 30, 2015, 11:09:56 AM3/30/15
to clojur...@googlegroups.com
A little something I've written as a way to clear my mind of some thoughts:


--
Laurent Petit

Bozhidar Batsov

unread,
Apr 2, 2015, 3:09:48 AM4/2/15
to clojur...@googlegroups.com
Nice list!

Here a few comments from me:

* there's actually fuzzy matching in the completion, but it currently works only for Clojure (compliment has it, cljs-tooling doesn't). You can't see this in CIDER, though, as we didn't make any efforts to support it in the UI.
* on the topic of losing stability - we collaborate with vim-fireplace when we're doing incompatible changes and we're obviously open to collaborate with other projects as well. Lately there haven't been that many serious changes and I'm hopeful that 1.0 is around the corner.
* as you know we're well aware of the deps issue and are looking into using either a tool like https://github.com/benedekfazekas/mranderson or some alternative (e.g. classloader isolation to solve this). We've tried to depend only on projects which are unlikely to be used by applications (or have a stable enough API that would reduce the possibility for conflicts). At any rate, this is something that has to be solved regardless of how many projects depend on cider-nrepl.
* I don't believe nREPL lock-in is a real issue right now, as the alternative doesn't really exist. And even when it arrives there's still the problem of providing tooling support for it - obviously the built-in REPL will provide none of the functionality needed by Clojure dev tools. Much of cider-nrepl's code is not tied to nREPL at all so having something cider-nrepl and cider-whatever is definitely possible, although I'm not sure if it'll be needed in the foreseeable future.

At any rate I believe that collaboration is the key to building better Clojure tooling - most of the projects have pretty limited resources, so it doesn't make much sense to keep reinventing the wheel for every possible project (therefore our decision to leverage off-the-shelf libraries when possible instead of reimplementing everything ourselves).

Laurent PETIT

unread,
Apr 2, 2015, 3:23:15 AM4/2/15
to clojur...@googlegroups.com
I am very happy to read your answer!

On my side, I've been able to port completion and already part of the contextual / additional symbol documentation from ccw-server to cider-nrepl on a local branch. 

So far everything goes well. 

I haven't found yet how fuzzy completion works in cider-nrepl. Can you show me the way?

Cheers,

Laurent


--
Laurent Petit

Bozhidar Batsov

unread,
Apr 2, 2015, 12:29:58 PM4/2/15
to clojur...@googlegroups.com

Laurent PETIT

unread,
Apr 3, 2015, 6:27:09 AM4/3/15
to clojur...@googlegroups.com
They I may be trying something that is out of the scope:

Currently in CCW, if a user types "prtln", they have a match for "println". I didn't have a match with my integration of cider-nrepl. Did I miss an advanced parameter to pass in so that it works?

Laurent PETIT

unread,
Apr 3, 2015, 6:36:57 AM4/3/15
to clojur...@googlegroups.com
But the fuzzy stuff let apart, I'm amazed by what compliment already provides, and more than happy to join cider in using it!
--
Laurent Petit

Laurent PETIT

unread,
Apr 3, 2015, 6:55:48 AM4/3/15
to clojur...@googlegroups.com
By the way, I'm actively working on it! https://github.com/laurentpetit/ccw/issues/734
--
Laurent Petit

Bozhidar Batsov

unread,
Apr 3, 2015, 12:44:32 PM4/3/15
to clojur...@googlegroups.com
Regarding completions of things like "prln" - that's not supported indeed.  See this discussion - https://github.com/alexander-yakushev/compliment/issues/17

Laurent PETIT

unread,
Apr 3, 2015, 1:46:48 PM4/3/15
to clojur...@googlegroups.com
OK, I browsed the issue, thanks for mentioning it.

So far, we have fuzzy completion in CCW, and people don't complain about things being too noisy.
I remember I have implemented a smart sorting algorithm so that even with fuzzy completion enabled, it is always symbols with the lefmost matching parts and with the higher distance density between consecutive character matches which are displayed first. And then of course sorted alphanumerically if considered at the same leftmost/distance density level.

If what I've said above makes you want to consider full fuzzy completion again (or at least as an addition / option), I will gladly dive into ccw.server code again (yeah the kind of code even the original author needs to carefully re-read before fully understand it again :-/ ) and extract the relevant and more accurate algorithmic parts to share here.





Bozhidar Batsov

unread,
Apr 3, 2015, 3:25:22 PM4/3/15
to clojur...@googlegroups.com
Guess you can discuss this further with Alex Yakushev. He might be more inclined to add something if more people would end up using it.

Colin Fleming

unread,
Apr 4, 2015, 12:46:30 AM4/4/15
to clojur...@googlegroups.com
FWIW, Cursive also fuzzy matches on the whole string, mostly ignoring separators and so forth - it's great. No-one has ever complained about it being too noisy, and it's really nice to use.

Laurent PETIT

unread,
Apr 4, 2015, 4:03:33 AM4/4/15
to clojur...@googlegroups.com
2015-04-04 6:46 GMT+02:00 Colin Fleming <colin.ma...@gmail.com>:
FWIW, Cursive also fuzzy matches on the whole string, mostly ignoring separators and so forth - it's great. No-one has ever complained about it being too noisy, and it's really nice to use.

Yeah, really same experience here.

In my opinion, for fuzzy match to work, there are 2 necessary conditions(*):
- highlighting the characters that match via the fuzzy logic (generally colored differently in the list)
- smart sorting of the results


Out of curiosity: is the Cursive fuzzy match a given from the IntelliJ platform, or did you have to implement it yourself?



(*) I didn't say they are sufficient



--
Laurent Petit

Colin Fleming

unread,
Apr 4, 2015, 4:42:49 AM4/4/15
to clojur...@googlegroups.com
I had to customise the matching a little for Clojure, since the default matcher had some Java specific behaviour that didn't make sense. I could tweak it some more since the sorting could still be better, but it's pretty good now. But everything else comes out of the box - it's actually pretty sophisticated. It highlights the matched chars correctly even with my custom matcher. Importantly, I don't filter anything based on the prefix - I always return the complete list of possible completions and the framework filters it.

Laurent PETIT

unread,
Apr 4, 2015, 6:06:48 AM4/4/15
to clojur...@googlegroups.com
Ouuuuuch, this fuzzy completion itch is catching agaiiiin, it's soooo painful, I think I won't resist shhhhhaaaaving this yack again, pleeease don't stop me, it's so interesting sometimes to reinvent the wheel .......  

Stay tuned, I guess a littl' clojure library focused solely on generic fuzzy completion filtering and sorting is gonna make it in a few days ....


--
Laurent Petit

Laurent PETIT

unread,
Apr 6, 2015, 5:35:18 AM4/6/15
to clojur...@googlegroups.com
Hi again Colin,

If the user keeps adding letters to the prefix to be matched, does the IntelliJ framework re-ask your code for a new list? Or once it's got a list from your code after the first letter is pressed (or presumably some higher threshold of 2-3 letters for perf reason?), does the IntelliJ framework filter the list itself as long as the user does not "escape" (eg pressing enter or space, or typing backspace, etc.)?



Colin Fleming

unread,
Apr 6, 2015, 4:41:47 PM4/6/15
to clojur...@googlegroups.com
I actually haven't checked exactly when it asks me for more completions, but it doesn't do it on every keypress, right. Obviously it asks if the element that's being completed changes i.e. if you're completing a symbol and hit /, or if you delete the entire symbol you were working on.

Bozhidar Batsov

unread,
Apr 14, 2015, 2:03:01 AM4/14/15
to clojur...@googlegroups.com
A small update - we're pretty close to inlining all deps https://github.com/clojure-emacs/cider-nrepl/pull/183

Once this is merged dep conflicts will no longer be an issue.

Laurent PETIT

unread,
Apr 14, 2015, 2:50:28 AM4/14/15
to clojur...@googlegroups.com
This is great news!

Counterclockwise support is also in good shape, undergoing user tests / debugat the moment. 

Not all cider-nrepl features are exposed yet, but all pre-existing features of CCW are ported and we're working on stabilizing this first scope. 


--
Laurent Petit

Laurent PETIT

unread,
Apr 14, 2015, 2:58:03 AM4/14/15
to clojur...@googlegroups.com
Out of curiosity, are there any Java class dependencies for cider-nrepl ?

benedek fazekas

unread,
Apr 15, 2015, 3:49:28 AM4/15/15
to clojur...@googlegroups.com
hi,

cider-nrepl, java deps: I don't think so at least at the moment.

Somewhat related: https://github.com/clojure-emacs/refactor-nrepl may be interesting eventually too I suppose.

--
Benedek Fazekas

Reply all
Reply to author
Forward
0 new messages