Unfortunately, no one can be told what CIDER is, you have to see it for yourself.

– Clorpheus, The REPLix

Today is the day. 22.12.21. 12/22/21. No matter how you cut it, it’s one auspicious date and if it’s good enough for a new Matrix movie, it’s certainly good enough for a new CIDER release as well! So, it is with great pleasure that I announce the immediate release of CIDER 1.2 (“Nice”). We have been brewing it for 7 months, but I can assure you that the long wait was worth it.

First, an explanation of the name. I’ve spent the final weeks of my sabbatical from work in Nice and Antibes and I totally loved my time there. Admittedly I didn’t do any programming at all in France (I didn’t even take my computer with me), but it’s there that the real work towards CIDER 1.2 began. I spent a lot of time today wondering whether to name this release “Nice”, “Antibes” or “Côte d’Azur”, before settling on “Nice”. Naming is hard!

CIDER 1.2 is not just Nice! It’s f*cking Great! It’s easily the most ambitious release in the past 3 years!1 Here’s why…

Highlights

Dynamic nREPL Connection Upgrade

Ever since in 2014 (CIDER 0.7) I made the decision to make some of CIDER’s functionality depending on cider-nrepl, some people have been frustrated that CIDER effectively needed a special nREPL server to unleash its full potential. In practice that meant additional setup that sometimes wasn’t even possible (e.g. you usually can’t add development dependencies to production apps).

CIDER 0.11 (released in 2016) addressed part of the problem, by coming up with the notion of jack-in dependencies that were automatically injected. Down the road the problem with remote REPLs was alleviated somewhat by extending the nREPL protocol with ops like lookup and completions. Still, there was no easy way to just connect to a regular nREPL server and teach it all the tricks that CIDER needs it to know.

Today this changes. Just run M-x cider-upgrade-nrepl-connection after cider-connect and magic will happen! This (experimental) feature is the culmination of a lot of work that was happening in nREPL, over the past couple of years, to allow clients to dynamically load code in nREPL (a feature known as sideloading).

Huge thanks to Arne Brasseur for working on this and for all of his contributions to the Clojure community over the years! Arne wrote a couple of nice articles on the subject that I can heartily recommend:

The current connection upgrade approach is not without its flaws, but I’m confident we’ll be able to improve it a lot down the line. As Arne mentions we might be able to find simpler alternative approaches as well and that’s totally fine.

By the way, did I mention that now nREPL’s sideloader is fully supported in CIDER, so you can load random Clojure libraries (not just nREPL middleware) on demand? Here’s how it works:

  • Place some resources on cider-sideloader-path (e.g. a cider/rocks.clj file)
  • M-x cider-sideloader-start
  • require cider/rocks somewhere and it will be loaded on demand

I just realized I should write documentation on the subject. Oh well, at least we have the official nREPL docs and the blog post I wrote about sideloading a while ago.

Auto-fetch Java Sources and Javadocs (Lein-only)

I don’t know how many of you have used Maven, but one thing I loved about it that it could just fetch all the Java sources and Javadocs for the packages I used in my projects and then I could easily navigate to definitions, read Javadocs locally, etc.

CIDER has had support for parsing and navigating to Java sources and Javadocs for ages, but it required users to manually ensure the necessary resources are on the classpath. In CIDER 1.2 we finally catch up to the Maven experience, thanks to enrich-classpath - a library (and Leiningen plugin) that, as its main feature, automatically downloads all available .jars with Java sources and javadocs for a given project, so that various tooling (e.g. CIDER) can access it.

This was supposed to be enabled by default, but we hit a mysterious last-minute Lein issue, so you’ll have to enable it yourself if you want to try it out:

(setq cider-enrich-classpath t)

When this is enabled (and working), the experience is magical - you can navigate to any Java source with M-. without any additional setup!

Note: Our debugging of the mysterious issue leads us to believe it’s a simple case of not accounting for the JDK sources and docs being installed. On Debian-like Linux distros that is as simple as:

$ sudo apt install openjdk-11-source openjdk-11-doc

On Fedora/Red Hat you’ll need to do something like:

$ sudo dnf install java-11-openjdk-src java-11-openjdk-javadoc

I encourage all Leiningen users to enable the enrich-classpath integration and share their feedback about it with us!

Another round of huge thanks for vemv, who was the driving force behind enrich-classpath!

cider-jack-in support for babashka

The title here says it all. Basically, CIDER now knows about bb.edn (same way it knows about project.clj and deps.edn) and will launch a babashka REPL if it detects one.

This simple feature took a while to brew, but it was also a proof that hammock-time really works, as the final version is much simpler than anything else that was original considered/proposed.

Up next - nbb support!

Unix Socket Support

nREPL 0.9 supports listening to Unix domain sockets, and now CIDER supports connecting to those. When using cider-connect just pick local-unix-domain-socket as the hostname (it’s kind of magical) and then type the path to the local socket file. Don’t forget that you’ll need to start nREPL a bit differently:

$ clj -M:nREPL -m nrepl.cmdline --socket path/to/nrepl.sock

The support for this in CIDER is experimental and subject to changes. Down the road it will be able to jack-in using an Unix socket and we might have some auto-detection for their presence in cider-connect. As usual - sky is the limit and your help is most welcome!

xref

xref is an Emacs framework for looking up identifiers, that was introduced in Emacs 25. CIDER provides pretty much all of its features (e.f. find definition, apropos, find references, etc), but because it didn’t have an xref backend it was overriding a lot of its keybindings (e.g. M-.) and that frustrated users of xref.

Beginning with version 1.2.0, CIDER supports Emacs’s built-in xref functionality, which means M-. will invoke xref-find-definitions instead of CIDER’s own command cider-find-var. You can disable the use of CIDER’s xref backend like this:

(setq cider-use-xref nil)

Note: You’ll have to disable and enable cider-mode for this setting to have effect.

If you use other packages that also integrate with xref (e.g. lsp-mode), you may wish to customize the precedence of CIDER’s xref backend. The precedence is controlled by the order in which backend functions appear in the xref-backend-functions hook. By default, the CIDER xref function will be added with a depth of -90, so it will (should?) come first. If you would prefer for it to have a lower precedence, you can change cider-xref-fn-depth:

(setq cider-xref-fn-depth 90)

See Setting Hooks for more information about depth.

Everything Else

As usual there are plenty of small improvements and plenty of bug-fixes. I love the richer completion annotations in company-mode and the usability improvements for ClojureDocs.

Some bug-fixes, like handling of empty stackframes, have been long overdue. Better late than never!

cider-nrepl and orchard got a lot of love as well, and I’m happy to report that in Orchard 0.8 we’ve removed our last runtime dependency (dynapath), and now Orchard is completely self-contained. What’s even better - it does no classpath manipulations at all, for the sake of putting tools.jar and your JDK’s sources on the classpath. enrich-classpath is the way to go.

Next

Our work is never done. Our roadmap is never empty. Our open issues keep growing. As usual this releases ended up taking more time than I expected it to take and the final scope is a bit smaller than what I had in mind. I’m not concerned about this, as there’s always the next release.

I plan to start distributing CIDER over NonGNU ELPA soon, so it’s available for installation out-of-the-box for everyone using Emacs 28+. clojure-mode and inf-clojure are already available there.

I guess improving the sideloading experience/connection upgrade will be one of the focal points of the next CIDER release as well. ClojureScript support continues to be an area that needs a lot of love, as does connection management with sesman.

We’ll need to figure out how to bring the awesomeness of enrich-classpath to tools.deps users. Your help is most welcome!

Epilogue

And that’s a wrap! I can’t remember when was the last time I wrote a release announcement that long.

As usual, here I’ll thank all the people who contributed to the release in one way or another. You rock and you show why the Clojure community is so awesome! Another round of special thanks goes to Clojurists Together and Cognitect, the main patrons of my open-source Clojure work!

2021 was another interesting and pretty tough year. Conference-driven development is dead, but at least Matrix-driven development is making a comeback. Clojurists together STRONG!

Happy holidays, everyone! CIDER 1.2 is my small Christmas gift to the Clojure community! I miss you all and I hope that next year will bring us back to together! I’m running out of sanity, but I’m never running out of Emacs. M-x forever!

  1. Don’t panic! Upgrades should be painless!