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…
Dynamic nREPL Connection Upgrade
Ever since in 2014 (CIDER 0.7) I made the decision to make some of CIDER’s functionality
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
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/rockssomewhere 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,
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
cider-jack-in support for babashka
The title here says it all. Basically, CIDER now knows about
bb.edn (same way it knows about
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
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!
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
Beginning with version 1.2.0, CIDER supports Emacs’s built-in
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
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
(setq cider-xref-fn-depth 90)
See Setting Hooks for more information about depth.
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!
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
your JDK’s sources on the classpath.
enrich-classpath is the way to go.
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+.
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
We’ll need to figure out how to bring the awesomeness of
tools.deps users. Your help is most welcome!
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!
Don’t panic! Upgrades should be painless! ↩