196 lines
15 KiB
Plaintext
196 lines
15 KiB
Plaintext
<blockquote>
|
||
<p>Unfortunately, no one can be told what CIDER is, you have to see it for yourself.</p>
|
||
|
||
<p>– Clorpheus, The REPLix</p>
|
||
</blockquote>
|
||
|
||
<p>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 <a href="https://github.com/clojure-emacs/cider/releases/tag/v1.2.0">CIDER 1.2 (“Nice”)</a>. We have been brewing it for 7 months, but I can assure you that the long wait was worth it.</p>
|
||
|
||
<p>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!</p>
|
||
|
||
<p>CIDER 1.2 is not just Nice! It’s f*cking Great! It’s easily the most ambitious release in the past 3 years!<sup id="fnref:1"><a class="footnote" href="https://metaredux.com/posts/2021/12/22/cider-1-2-nice.html#fn:1" rel="footnote">1</a></sup> Here’s why…</p>
|
||
|
||
<h2 id="highlights">Highlights</h2>
|
||
|
||
<h3 id="dynamic-nrepl-connection-upgrade">Dynamic nREPL Connection Upgrade</h3>
|
||
|
||
<p>Ever since in 2014 (CIDER 0.7) I made the decision to make some of CIDER’s functionality
|
||
depending on <code class="language-plaintext highlighter-rouge">cider-nrepl</code>, 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).</p>
|
||
|
||
<p>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 <a href="https://metaredux.com/posts/2020/06/15/nrepl-0-8-evolving-the-protocol.html">extending the
|
||
nREPL protocol</a> with
|
||
ops like <code class="language-plaintext highlighter-rouge">lookup</code> and <code class="language-plaintext highlighter-rouge">completions</code>. 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.</p>
|
||
|
||
<p>Today this changes. Just run <code class="language-plaintext highlighter-rouge">M-x cider-upgrade-nrepl-connection</code> after
|
||
<code class="language-plaintext highlighter-rouge">cider-connect</code> 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).</p>
|
||
|
||
<p>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:</p>
|
||
|
||
<ul>
|
||
<li><a href="https://lambdaisland.com/blog/2021-11-03-making-nrepl-cider-more-dynamic-1">https://lambdaisland.com/blog/2021-11-03-making-nrepl-cider-more-dynamic-1</a></li>
|
||
<li><a href="https://lambdaisland.com/blog/2021-11-24-making-nrepl-cider-more-dynamic-2">https://lambdaisland.com/blog/2021-11-24-making-nrepl-cider-more-dynamic-2</a></li>
|
||
</ul>
|
||
|
||
<p>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.</p>
|
||
|
||
<p>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:</p>
|
||
|
||
<ul>
|
||
<li>Place some resources on <code class="language-plaintext highlighter-rouge">cider-sideloader-path</code> (e.g. a <code class="language-plaintext highlighter-rouge">cider/rocks.clj</code> file)</li>
|
||
<li><code class="language-plaintext highlighter-rouge">M-x cider-sideloader-start</code></li>
|
||
<li><code class="language-plaintext highlighter-rouge">require</code> <code class="language-plaintext highlighter-rouge">cider/rocks</code> somewhere and it will be loaded on demand</li>
|
||
</ul>
|
||
|
||
<p>I just realized I should write documentation on the subject. Oh well, at least we have
|
||
the official nREPL docs and the <a href="https://metaredux.com/posts/2020/03/28/nrepl-0-7.html">blog post</a> I wrote about sideloading a while ago.</p>
|
||
|
||
<h3 id="auto-fetch-java-sources-and-javadocs-lein-only">Auto-fetch Java Sources and Javadocs (Lein-only)</h3>
|
||
|
||
<p>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.</p>
|
||
|
||
<p>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
|
||
<a href="https://github.com/clojure-emacs/enrich-classpath">enrich-classpath</a> - a
|
||
library (and Leiningen plugin) that, as its main feature, automatically
|
||
downloads all available <code class="language-plaintext highlighter-rouge">.jar</code>s with Java sources and javadocs for a given
|
||
project, so that various tooling (e.g. CIDER) can access it.</p>
|
||
|
||
<p>This was supposed to be enabled by default, but we hit a <a href="https://github.com/technomancy/leiningen/issues/2777">mysterious last-minute
|
||
Lein issue</a>, so you’ll
|
||
have to enable it yourself if you want to try it out:</p>
|
||
|
||
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">cider-enrich-classpath</span> <span class="no">t</span><span class="p">)</span>
|
||
</code></pre></div></div>
|
||
|
||
<p>When this is enabled (and working), the experience is magical - you can navigate
|
||
to any Java source with <code class="language-plaintext highlighter-rouge">M-.</code> without any additional setup!</p>
|
||
|
||
<p><strong>Note:</strong> 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:</p>
|
||
|
||
<pre><code class="language-shellsession">$ sudo apt install openjdk-11-source openjdk-11-doc
|
||
</code></pre>
|
||
|
||
<p>On Fedora/Red Hat you’ll need to do something like:</p>
|
||
|
||
<pre><code class="language-shellsession">$ sudo dnf install java-11-openjdk-src java-11-openjdk-javadoc
|
||
</code></pre>
|
||
|
||
<p>I encourage all Leiningen users to enable the <code class="language-plaintext highlighter-rouge">enrich-classpath</code> integration and share their feedback about it with us!</p>
|
||
|
||
<p>Another round of huge thanks for <code class="language-plaintext highlighter-rouge">vemv</code>, who was the driving force behind <code class="language-plaintext highlighter-rouge">enrich-classpath</code>!</p>
|
||
|
||
<h3 id="cider-jack-in-support-for-babashka">cider-jack-in support for babashka</h3>
|
||
|
||
<p>The title here says it all. Basically, CIDER now knows about <code class="language-plaintext highlighter-rouge">bb.edn</code> (same way it knows about <code class="language-plaintext highlighter-rouge">project.clj</code> and <code class="language-plaintext highlighter-rouge">deps.edn</code>)
|
||
and will launch a babashka REPL if it detects one.</p>
|
||
|
||
<p>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.</p>
|
||
|
||
<p>Up next - <a href="https://github.com/clojure-emacs/cider/issues/3061">nbb support</a>!</p>
|
||
|
||
<h3 id="unix-socket-support">Unix Socket Support</h3>
|
||
|
||
<p><a href="https://metaredux.com/posts/2021/12/12/nrepl-0-9.html">nREPL 0.9</a> supports listening to Unix domain sockets, and now CIDER supports connecting to those. When using <code class="language-plaintext highlighter-rouge">cider-connect</code> just
|
||
pick <code class="language-plaintext highlighter-rouge">local-unix-domain-socket</code> 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:</p>
|
||
|
||
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>clj <span class="nt">-M</span>:nREPL <span class="nt">-m</span> nrepl.cmdline <span class="nt">--socket</span> path/to/nrepl.sock
|
||
</code></pre></div></div>
|
||
|
||
<p>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 <code class="language-plaintext highlighter-rouge">cider-connect</code>. As usual - sky is the limit and your help is most welcome!</p>
|
||
|
||
<h3 id="xref">xref</h3>
|
||
|
||
<p><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html">xref</a> 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 <code class="language-plaintext highlighter-rouge">xref</code> backend it was overriding a
|
||
lot of its keybindings (e.g. <code class="language-plaintext highlighter-rouge">M-.</code>) and that frustrated users of <code class="language-plaintext highlighter-rouge">xref</code>.</p>
|
||
|
||
<p>Beginning with version 1.2.0, CIDER supports Emacs’s built-in <code class="language-plaintext highlighter-rouge">xref</code>
|
||
functionality, which means <code class="language-plaintext highlighter-rouge">M-.</code> will invoke <code class="language-plaintext highlighter-rouge">xref-find-definitions</code> instead of
|
||
CIDER’s own command <code class="language-plaintext highlighter-rouge">cider-find-var</code>. You can disable the use of CIDER’s <code class="language-plaintext highlighter-rouge">xref</code> backend like this:</p>
|
||
|
||
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">cider-use-xref</span> <span class="no">nil</span><span class="p">)</span>
|
||
</code></pre></div></div>
|
||
|
||
<p><strong>Note</strong>: You’ll have to disable and enable <code class="language-plaintext highlighter-rouge">cider-mode</code> for this setting to have effect.</p>
|
||
|
||
<p>If you use other packages that also integrate with <code class="language-plaintext highlighter-rouge">xref</code> (e.g. <code class="language-plaintext highlighter-rouge">lsp-mode</code>), you may wish to customize the precedence of CIDER’s <code class="language-plaintext highlighter-rouge">xref</code> backend. The precedence is controlled by the
|
||
order in which backend functions appear in the <code class="language-plaintext highlighter-rouge">xref-backend-functions</code> hook. By default, the CIDER <code class="language-plaintext highlighter-rouge">xref</code> 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 <code class="language-plaintext highlighter-rouge">cider-xref-fn-depth</code>:</p>
|
||
|
||
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">cider-xref-fn-depth</span> <span class="mi">90</span><span class="p">)</span>
|
||
</code></pre></div></div>
|
||
|
||
<p>See <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Setting-Hooks.html">Setting Hooks</a> for more information about depth.</p>
|
||
|
||
<h2 id="everything-else">Everything Else</h2>
|
||
|
||
<p>As usual there are plenty of small improvements and plenty of bug-fixes.
|
||
I love the richer completion annotations in <code class="language-plaintext highlighter-rouge">company-mode</code> and the usability
|
||
improvements for ClojureDocs.</p>
|
||
|
||
<p>Some bug-fixes, like handling of empty stackframes, have been long overdue.
|
||
Better late than never!</p>
|
||
|
||
<p><code class="language-plaintext highlighter-rouge">cider-nrepl</code> and <code class="language-plaintext highlighter-rouge">orchard</code> 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 (<code class="language-plaintext highlighter-rouge">dynapath</code>), and now
|
||
Orchard is completely self-contained. What’s even better - it does no
|
||
classpath manipulations at all, for the sake of putting <code class="language-plaintext highlighter-rouge">tools.jar</code> and
|
||
your JDK’s sources on the classpath. <code class="language-plaintext highlighter-rouge">enrich-classpath</code> is the way to go.</p>
|
||
|
||
<h2 id="next">Next</h2>
|
||
|
||
<p>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.</p>
|
||
|
||
<p>I plan to start distributing CIDER over <a href="https://elpa.nongnu.org/nongnu/">NonGNU ELPA</a> soon, so it’s available for
|
||
installation out-of-the-box for everyone using Emacs 28+. <code class="language-plaintext highlighter-rouge">clojure-mode</code> and <code class="language-plaintext highlighter-rouge">inf-clojure</code> are already available there.</p>
|
||
|
||
<p>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 <code class="language-plaintext highlighter-rouge">sesman</code>.</p>
|
||
|
||
<p>We’ll need to figure out how to bring the awesomeness of <code class="language-plaintext highlighter-rouge">enrich-classpath</code> to <code class="language-plaintext highlighter-rouge">tools.deps</code> users. Your help is most welcome!</p>
|
||
|
||
<h2 id="epilogue">Epilogue</h2>
|
||
|
||
<p>And that’s a wrap! I can’t remember when was the last time I wrote a release announcement that long.</p>
|
||
|
||
<p>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!</p>
|
||
|
||
<p>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!</p>
|
||
|
||
<p>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!</p>
|
||
|
||
<div class="footnotes">
|
||
<ol>
|
||
<li id="fn:1">
|
||
<p>Don’t panic! Upgrades <em>should</em> be painless! <a class="reversefootnote" href="https://metaredux.com/posts/2021/12/22/cider-1-2-nice.html#fnref:1">↩</a></p>
|
||
</li>
|
||
</ol>
|
||
</div> |