<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://metaredux.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://metaredux.com/" rel="alternate" type="text/html" /><updated>2026-03-04T08:10:18+00:00</updated><id>https://metaredux.com/feed.xml</id><title type="html">Meta Redux</title><subtitle>Writings on programming and open-source by Bozhidar Batsov, creator of RuboCop, CIDER, and Prelude.</subtitle><author><name>Bozhidar Batsov</name></author><entry><title type="html">What’s Next for clojure-mode?</title><link href="https://metaredux.com/posts/2026/03/03/whats-next-for-clojure-mode.html" rel="alternate" type="text/html" title="What’s Next for clojure-mode?" /><published>2026-03-03T21:30:00+00:00</published><updated>2026-03-03T21:30:00+00:00</updated><id>https://metaredux.com/posts/2026/03/03/whats-next-for-clojure-mode</id><content type="html" xml:base="https://metaredux.com/posts/2026/03/03/whats-next-for-clojure-mode.html"><![CDATA[<p>Good news, everyone! <a href="https://github.com/clojure-emacs/clojure-mode/releases/tag/v5.22.0">clojure-mode
5.22</a> is
out with many small improvements and bug fixes!</p>

<!--more-->

<p>While TreeSitter is the future of Emacs major modes, the present remains a bit
more murky – not everyone is running a modern Emacs or an Emacs built with
TreeSitter support, and many people have asked that “classic” major modes
continue to be improved and supported alongside the newer TS-powered modes (in
our case – <a href="https://github.com/clojure-emacs/clojure-ts-mode">clojure-ts-mode</a>).
Your voices have been heard! On Bulgaria’s biggest national holiday (Liberation
Day), you can feel liberated from any worries about the future of
<code class="language-plaintext highlighter-rouge">clojure-mode</code>, as it keeps getting the love and attention that it deserves!
Looking at the changelog – 5.22 is one of the biggest releases in the last few
years and I hope you’ll enjoy it!<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>Now let me walk you through some of the highlights.</p>

<h2 id="edn-mode-gets-some-love">edn-mode Gets Some Love</h2>

<p><code class="language-plaintext highlighter-rouge">edn-mode</code> has always been the quiet sibling of <code class="language-plaintext highlighter-rouge">clojure-mode</code> – a mode for
editing EDN files that was more of an afterthought than a first-class citizen.
That changed with 5.21 and the trend continues in 5.22. The mode now has its own
dedicated keymap with data-appropriate bindings, meaning it no longer inherits
code refactoring commands that make no sense outside of Clojure source
files. Indentation has also been corrected – paren lists in EDN are now treated
as data (which they are), not as function calls.</p>

<p>Small things, sure, but they add up to a noticeably better experience when
you’re editing config files, test fixtures, or any other EDN data.</p>

<h2 id="font-locking-updated-for-clojure-112">Font-locking Updated for Clojure 1.12</h2>

<p>Font-locking has been updated to reflect Clojure 1.12’s additions – new
built-in dynamic variables and core functions are now properly highlighted.  The
optional <code class="language-plaintext highlighter-rouge">clojure-mode-extra-font-locking</code> package covers everything from 1.10
through 1.12, including bundled namespaces and <code class="language-plaintext highlighter-rouge">clojure.repl</code> forms.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> Some
obsolete entries (like <code class="language-plaintext highlighter-rouge">specify</code> and <code class="language-plaintext highlighter-rouge">specify!</code>) have been cleaned up as well.</p>

<p>On a related note, protocol method docstrings now correctly receive
<code class="language-plaintext highlighter-rouge">font-lock-doc-face</code> styling, and <code class="language-plaintext highlighter-rouge">letfn</code> binding function names get proper
<code class="language-plaintext highlighter-rouge">font-lock-function-name-face</code> treatment. These are the kind of small
inconsistencies that you barely notice until they’re fixed, and then you wonder
how you ever lived without them.</p>

<h2 id="discard-form-styling">Discard Form Styling</h2>

<p>A new <code class="language-plaintext highlighter-rouge">clojure-discard-face</code> has been added for <code class="language-plaintext highlighter-rouge">#_</code> reader discard forms. By
default it inherits from the comment face, so discarded forms visually fade into
the background – exactly what you’d expect from code that won’t be read. Of
course, you can customize the face to your liking.</p>

<h2 id="notable-bug-fixes">Notable Bug Fixes</h2>

<p>A few fixes that deserve a special mention:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">clojure-sort-ns</code> no longer corrupts non-sortable forms</strong> – previously,
sorting a namespace that contained <code class="language-plaintext highlighter-rouge">:gen-class</code> could mangle it. That’s fixed
now.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">clojure-thread-last-all</code> and line comments</strong> – the threading refactoring
command was absorbing closing parentheses into line comments. Not anymore.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">clojure-update-ns</code> works again</strong> – this one had been quietly broken and is
now restored to full functionality.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">clojure-add-arity</code> preserves arglist metadata</strong> – when converting from
single-arity to multi-arity, metadata on the argument vector is no longer
lost.</li>
</ul>

<h2 id="the-road-ahead">The Road Ahead</h2>

<p>So, what’s actually next for <code class="language-plaintext highlighter-rouge">clojure-mode</code>? The short answer is: <strong>more of the
same</strong>. <code class="language-plaintext highlighter-rouge">clojure-mode</code> will continue to receive updates, bug fixes, and
improvements for the foreseeable future. There is no rush for anyone to switch
to <code class="language-plaintext highlighter-rouge">clojure-ts-mode</code>, and no plans to deprecate the classic mode anytime soon.</p>

<p>That said, if you’re curious about <code class="language-plaintext highlighter-rouge">clojure-ts-mode</code>, its main advantage right
now is <strong>performance</strong>. TreeSitter-based font-locking and indentation are
significantly faster than the regex-based approach in <code class="language-plaintext highlighter-rouge">clojure-mode</code>. If you’re
working with very large Clojure files and noticing sluggishness, it’s worth
giving <code class="language-plaintext highlighter-rouge">clojure-ts-mode</code> a try. My guess is that most people won’t notice a
meaningful difference in everyday editing, but your mileage may vary.</p>

<p>The two modes will coexist for as long as it makes sense. Use whichever one
works best for you – they’re both maintained by the same team (yours truly and
co) and they both have a bright future ahead of them. At least I hope so!</p>

<p>As usual - big thanks to everyone supporting my Clojure OSS work, especially the
members of <a href="https://www.clojuriststogether.org/">Clojurists Together</a>! You rock!</p>

<p>That’s all I have for you today. Keep hacking!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>I also hope I didn’t break anything. :-) <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>I wonder if anyone’s using this package, though. For me CIDER’s font-locking made it irrelevant a long time ago. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Clojure" /><category term="Emacs" /><summary type="html"><![CDATA[Good news, everyone! clojure-mode 5.22 is out with many small improvements and bug fixes!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">copilot.el 0.4</title><link href="https://metaredux.com/posts/2026/02/26/copilot-el-0-4.html" rel="alternate" type="text/html" title="copilot.el 0.4" /><published>2026-02-26T10:00:00+00:00</published><updated>2026-02-26T10:00:00+00:00</updated><id>https://metaredux.com/posts/2026/02/26/copilot-el-0-4</id><content type="html" xml:base="https://metaredux.com/posts/2026/02/26/copilot-el-0-4.html"><![CDATA[<p>Good news, everyone – <a href="https://github.com/copilot-emacs/copilot.el/releases/tag/v0.4.0">copilot.el
0.4</a> is out!</p>

<p>But that’s just the start of it. This is the most important release
for me since I assumed the project’s leadership and I hope this
article will manage to make you agree with my reasoning.</p>

<p>Enough empty words – let me now walk you through the highlights.</p>

<h2 id="a-proper-copilot-client">A Proper Copilot Client</h2>

<p>The single biggest change in this release is the migration from the legacy
<code class="language-plaintext highlighter-rouge">getCompletions</code> API (reverse-engineered from
<a href="https://github.com/github/copilot.vim">copilot.vim</a>) to the standard
<code class="language-plaintext highlighter-rouge">textDocument/inlineCompletion</code> LSP method provided by the official
<a href="https://www.npmjs.com/package/@github/copilot-language-server">@github/copilot-language-server</a>.</p>

<p>This might sound like a dry and boring internal change, but it’s actually a big
deal.  copilot.el started its life as a port of copilot.vim – we were
essentially reverse-engineering how that plugin talked to the Copilot server and
replicating it in Elisp. That worked, but it was fragile and meant we were
always playing catch-up with undocumented protocol changes.</p>

<p>Now we speak the official LSP protocol. We send proper <code class="language-plaintext highlighter-rouge">textDocument/didOpen</code>,
<code class="language-plaintext highlighter-rouge">textDocument/didChange</code>, and <code class="language-plaintext highlighter-rouge">textDocument/didFocus</code> notifications. We manage
workspace folders. We handle server-to-client requests like
<code class="language-plaintext highlighter-rouge">window/showMessageRequest</code> and <code class="language-plaintext highlighter-rouge">window/showDocument</code>. We perform a clean
<code class="language-plaintext highlighter-rouge">shutdown</code>/<code class="language-plaintext highlighter-rouge">exit</code> sequence instead of just killing the process. In short,
copilot.el is now a proper Copilot LSP client, not a reverse-engineered hack.</p>

<p>This release, in a way, completes the cycle – from a package born out of
reverse engineering copilot.vim to a legitimate Copilot client built on the
official API.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>But wait, there’s (a lot) more!</p>

<h2 id="ai-model-selection">AI Model Selection</h2>

<p>You can now choose which AI model powers your completions via <code class="language-plaintext highlighter-rouge">M-x
copilot-select-completion-model</code>. The command queries the server for available
models on your subscription and lets you pick one interactively. The selection
is persisted in <code class="language-plaintext highlighter-rouge">copilot-completion-model</code>.</p>

<h2 id="parentheses-balancer-20">Parentheses Balancer 2.0</h2>

<p>The parentheses balancer – the component that post-processes completions in
Lisp modes to fix unbalanced delimiters – got a complete rewrite. The old
implementation counted parentheses as raw characters, which meant it would
“balance” parens inside comments and strings where they shouldn’t be touched.
The new implementation uses <code class="language-plaintext highlighter-rouge">parse-partial-sexp</code> to understand the actual
syntactic structure, so it only fixes genuinely unbalanced delimiters.</p>

<p>Whether the balancer will remain necessary in the long run is an open question
– as Copilot’s models get smarter, they produce fewer unbalanced completions.
But for now it still catches enough edge cases to earn its keep. You can
disable it with <code class="language-plaintext highlighter-rouge">(setopt copilot-enable-parentheses-balancer nil)</code> if you want
to see how well the raw completions work for you.</p>

<h2 id="improved-server-communication">Improved Server Communication</h2>

<p>Beyond the core API migration, we’ve improved the server communication in
several ways:</p>

<ul>
  <li><strong>Status reporting</strong>: <code class="language-plaintext highlighter-rouge">didChangeStatus</code> notifications show Copilot’s state
(Normal, Warning, Error, Inactive) in the mode-line.</li>
  <li><strong>Progress tracking</strong>: <code class="language-plaintext highlighter-rouge">$/progress</code> notifications display progress for
long-running operations like indexing.</li>
  <li><strong>Request cancellation</strong>: stale completion requests are cancelled with
<code class="language-plaintext highlighter-rouge">$/cancelRequest</code> so the server doesn’t waste cycles on abandoned work.</li>
  <li><strong>User-defined handlers</strong>: <code class="language-plaintext highlighter-rouge">copilot-on-request</code> and <code class="language-plaintext highlighter-rouge">copilot-on-notification</code>
let you hook into any server message.</li>
  <li><strong>UTF-16 positions</strong>: position offsets now correctly use UTF-16 code units, so
emoji and other supplementary-plane characters no longer confuse the server.</li>
</ul>

<h2 id="tests-and-documentation">Tests and Documentation</h2>

<p>This release adds a proper test suite using
<a href="https://github.com/jorgenschaefer/emacs-buttercup">buttercup</a>. We went from
zero tests to over 120, covering everything from URI generation and position
calculation to the balancer, overlay management, and server lifecycle. CI now
runs across multiple Emacs versions (27.2 through snapshot) and on macOS and
Windows in addition to Linux.</p>

<p>The README got a (almost) complete rewrite – it now covers installation for
every popular package manager, documents all commands and customization options,
includes a protocol coverage table, and has a new FAQ section addressing the
most common issues people run into. Plenty of good stuff in it!</p>

<p>This might sound like a lot of effort for not much user-visible payoff, but when
I started hacking on the project:</p>

<ul>
  <li>I really struggled to understand how to make the best use of the package</li>
  <li>The lack of tests made it hard to make significant changes, as every change
felt quite risky</li>
</ul>

<p>Anyways, I hope you’ll enjoy the improved documentation and you’ll have easier
time setting up copilot.el.</p>

<h2 id="bug-fixes">Bug Fixes</h2>

<p>Too many to list individually, but here are some highlights:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">copilot-complete</code> now works without <code class="language-plaintext highlighter-rouge">copilot-mode</code> enabled (<a href="https://github.com/copilot-emacs/copilot.el/issues/450">#450</a>)</li>
  <li>Partial accept-by-word no longer loses trailing text when the server uses a replacement range (<a href="https://github.com/copilot-emacs/copilot.el/issues/448">#448</a>)</li>
  <li>JSON-RPC requests send an empty object instead of omitting <code class="language-plaintext highlighter-rouge">params</code>, fixing authentication on newer server versions (<a href="https://github.com/copilot-emacs/copilot.el/issues/445">#445</a>)</li>
  <li>The <code class="language-plaintext highlighter-rouge">company-mode</code> dependency is gone – no more <code class="language-plaintext highlighter-rouge">void-function company--active-p</code> errors (<a href="https://github.com/copilot-emacs/copilot.el/issues/243">#243</a>)</li>
  <li>The completion overlay plays nice with Emacs 30’s <code class="language-plaintext highlighter-rouge">completion-preview-mode</code> (<a href="https://github.com/copilot-emacs/copilot.el/issues/377">#377</a>)</li>
</ul>

<p>See the full <a href="https://github.com/copilot-emacs/copilot.el/blob/main/CHANGELOG.md">changelog</a> for the complete list.</p>

<h2 id="whats-next">What’s Next</h2>

<p>There’s still plenty of work ahead. We have three big feature branches in the
pipeline, all open as PRs and ready for adventurous testers:</p>

<ul>
  <li><a href="https://github.com/copilot-emacs/copilot.el/pull/447"><strong>Next Edit Suggestions (NES)</strong></a> –
proactive edit suggestions that appear at your cursor based on your recent
editing patterns, similar to the NES feature in VS Code.</li>
  <li><a href="https://github.com/copilot-emacs/copilot.el/pull/446"><strong>Copilot Chat</strong></a> –
interactive chat with Copilot, right inside Emacs.</li>
  <li><a href="https://github.com/copilot-emacs/copilot.el/pull/444"><strong>Native installation without Node.js</strong></a> –
use the pre-built Copilot language server binary instead of requiring a
Node.js installation.</li>
</ul>

<p>If any of these sound interesting to you, please give them a spin and report
back. Your feedback is what shapes the next release.</p>

<h2 id="thanks">Thanks</h2>

<p>A big thanks to <a href="https://github.com/ultronozm">Paul Nelson</a> for contributing
several partial acceptance commands and the overlay clearing improvements –
those are some of the most user-visible quality-of-life changes in this
release. Thanks also to everyone who filed detailed bug reports and tested
fixes – you know who you are, and this release wouldn’t be the same without
you.</p>

<p>That’s all I have for you today. Keep hacking!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>That’s why I dropped the word “unofficial” from the package’s description. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Emacs" /><category term="Copilot" /><summary type="html"><![CDATA[Good news, everyone – copilot.el 0.4 is out! But that’s just the start of it. This is the most important release for me since I assumed the project’s leadership and I hope this article will manage to make you agree with my reasoning. Enough empty words – let me now walk you through the highlights. A Proper Copilot Client The single biggest change in this release is the migration from the legacy getCompletions API (reverse-engineered from copilot.vim) to the standard textDocument/inlineCompletion LSP method provided by the official @github/copilot-language-server. This might sound like a dry and boring internal change, but it’s actually a big deal. copilot.el started its life as a port of copilot.vim – we were essentially reverse-engineering how that plugin talked to the Copilot server and replicating it in Elisp. That worked, but it was fragile and meant we were always playing catch-up with undocumented protocol changes. Now we speak the official LSP protocol. We send proper textDocument/didOpen, textDocument/didChange, and textDocument/didFocus notifications. We manage workspace folders. We handle server-to-client requests like window/showMessageRequest and window/showDocument. We perform a clean shutdown/exit sequence instead of just killing the process. In short, copilot.el is now a proper Copilot LSP client, not a reverse-engineered hack. This release, in a way, completes the cycle – from a package born out of reverse engineering copilot.vim to a legitimate Copilot client built on the official API.1 But wait, there’s (a lot) more! AI Model Selection You can now choose which AI model powers your completions via M-x copilot-select-completion-model. The command queries the server for available models on your subscription and lets you pick one interactively. The selection is persisted in copilot-completion-model. Parentheses Balancer 2.0 The parentheses balancer – the component that post-processes completions in Lisp modes to fix unbalanced delimiters – got a complete rewrite. The old implementation counted parentheses as raw characters, which meant it would “balance” parens inside comments and strings where they shouldn’t be touched. The new implementation uses parse-partial-sexp to understand the actual syntactic structure, so it only fixes genuinely unbalanced delimiters. Whether the balancer will remain necessary in the long run is an open question – as Copilot’s models get smarter, they produce fewer unbalanced completions. But for now it still catches enough edge cases to earn its keep. You can disable it with (setopt copilot-enable-parentheses-balancer nil) if you want to see how well the raw completions work for you. Improved Server Communication Beyond the core API migration, we’ve improved the server communication in several ways: Status reporting: didChangeStatus notifications show Copilot’s state (Normal, Warning, Error, Inactive) in the mode-line. Progress tracking: $/progress notifications display progress for long-running operations like indexing. Request cancellation: stale completion requests are cancelled with $/cancelRequest so the server doesn’t waste cycles on abandoned work. User-defined handlers: copilot-on-request and copilot-on-notification let you hook into any server message. UTF-16 positions: position offsets now correctly use UTF-16 code units, so emoji and other supplementary-plane characters no longer confuse the server. Tests and Documentation This release adds a proper test suite using buttercup. We went from zero tests to over 120, covering everything from URI generation and position calculation to the balancer, overlay management, and server lifecycle. CI now runs across multiple Emacs versions (27.2 through snapshot) and on macOS and Windows in addition to Linux. The README got a (almost) complete rewrite – it now covers installation for every popular package manager, documents all commands and customization options, includes a protocol coverage table, and has a new FAQ section addressing the most common issues people run into. Plenty of good stuff in it! This might sound like a lot of effort for not much user-visible payoff, but when I started hacking on the project: I really struggled to understand how to make the best use of the package The lack of tests made it hard to make significant changes, as every change felt quite risky Anyways, I hope you’ll enjoy the improved documentation and you’ll have easier time setting up copilot.el. Bug Fixes Too many to list individually, but here are some highlights: copilot-complete now works without copilot-mode enabled (#450) Partial accept-by-word no longer loses trailing text when the server uses a replacement range (#448) JSON-RPC requests send an empty object instead of omitting params, fixing authentication on newer server versions (#445) The company-mode dependency is gone – no more void-function company--active-p errors (#243) The completion overlay plays nice with Emacs 30’s completion-preview-mode (#377) See the full changelog for the complete list. What’s Next There’s still plenty of work ahead. We have three big feature branches in the pipeline, all open as PRs and ready for adventurous testers: Next Edit Suggestions (NES) – proactive edit suggestions that appear at your cursor based on your recent editing patterns, similar to the NES feature in VS Code. Copilot Chat – interactive chat with Copilot, right inside Emacs. Native installation without Node.js – use the pre-built Copilot language server binary instead of requiring a Node.js installation. If any of these sound interesting to you, please give them a spin and report back. Your feedback is what shapes the next release. Thanks A big thanks to Paul Nelson for contributing several partial acceptance commands and the overlay clearing improvements – those are some of the most user-visible quality-of-life changes in this release. Thanks also to everyone who filed detailed bug reports and tested fixes – you know who you are, and this release wouldn’t be the same without you. That’s all I have for you today. Keep hacking! That’s why I dropped the word “unofficial” from the package’s description. &#8617;]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Flycheck 36</title><link href="https://metaredux.com/posts/2026/02/21/flycheck-36.html" rel="alternate" type="text/html" title="Flycheck 36" /><published>2026-02-21T13:20:00+00:00</published><updated>2026-02-21T13:20:00+00:00</updated><id>https://metaredux.com/posts/2026/02/21/flycheck-36</id><content type="html" xml:base="https://metaredux.com/posts/2026/02/21/flycheck-36.html"><![CDATA[<p>It’s been a while since Flycheck 35, but <a href="https://github.com/flycheck/flycheck/releases/tag/v36.0">Flycheck
36</a> is finally here!
This is a pretty big release with a lot of new features, bug fixes, and some
much-needed cleanup of legacy checkers.</p>

<p>In fact, I’d say it’s the biggest and most important Flycheck release since I
became the project’s primary maintainer a couple of years ago. For a while I had
mostly gone with the flow (adding/improving linters and fixing bugs), but by now
I feel more confident to make bigger and bolder changes.</p>

<p>Anyways, you’re probably interested to learn more about Flycheck 36, so let me
walk you through the highlights.</p>

<h2 id="new-checkers">New Checkers</h2>

<p>We’ve added a couple of new checkers:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">javascript-oxlint</code> – a checker using <a href="https://oxc.rs/">oxlint</a>, the
blazing-fast JavaScript/TypeScript linter written in Rust. If you haven’t
tried oxlint yet, you really should – it’s impressively fast.</li>
  <li><code class="language-plaintext highlighter-rouge">org-lint</code> – an Org mode checker using Emacs’ built-in
<a href="https://orgmode.org/manual/Org-Syntax.html"><code class="language-plaintext highlighter-rouge">org-lint</code></a>. It detects issues
like invalid links, dead links, and duplicate IDs. This one went through a
rewrite mid-cycle to run in the current Emacs process instead of a <code class="language-plaintext highlighter-rouge">--batch</code>
subprocess, which eliminates false warnings for source block languages
provided by external packages.</li>
</ul>

<h2 id="security">Security</h2>

<p>We’ve mitigated
<a href="https://nvd.nist.gov/vuln/detail/CVE-2024-53920">CVE-2024-53920</a> in the
<code class="language-plaintext highlighter-rouge">emacs-lisp</code> checker by disabling local eval directives and restricting local
variables to safe values during byte-compilation. This was an important fix –
byte-compilation involves macro expansion, which means untrusted Elisp files
could potentially execute arbitrary code during syntax checking. A follow-up fix
for Emacs 30+ using <code class="language-plaintext highlighter-rouge">trusted-content</code> is in the works.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<h2 id="shellcheck-improvements">ShellCheck Improvements</h2>

<p>The <a href="https://www.shellcheck.net/"><code class="language-plaintext highlighter-rouge">sh-shellcheck</code></a> checker got some love in this release:</p>

<ul>
  <li>New <code class="language-plaintext highlighter-rouge">flycheck-shellcheck-infer-shell</code> option to let ShellCheck auto-detect the shell dialect</li>
  <li><code class="language-plaintext highlighter-rouge">flycheck-shellcheck-args</code> for passing extra command-line arguments</li>
  <li><code class="language-plaintext highlighter-rouge">flycheck-shellcheck-enabled-checks</code> to enable optional checks via <code class="language-plaintext highlighter-rouge">--enable</code></li>
</ul>

<h2 id="quality-of-life-improvements">Quality-of-Life Improvements</h2>

<p>A bunch of small but welcome improvements:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">flycheck-command-map</code> now works as a prefix command with <code class="language-plaintext highlighter-rouge">keymap-set</code> and friends – no more need for the <code class="language-plaintext highlighter-rouge">define-key</code> workaround</li>
  <li>Buffers are automatically re-checked after <code class="language-plaintext highlighter-rouge">revert-buffer</code>, so <code class="language-plaintext highlighter-rouge">global-auto-revert-mode</code> users get up-to-date diagnostics without manual intervention</li>
  <li>The mode-line indicator now includes info-level errors (format: <code class="language-plaintext highlighter-rouge">errors|warnings|infos</code>)</li>
  <li>The <a href="https://docs.astral.sh/ruff/"><code class="language-plaintext highlighter-rouge">python-ruff</code></a> checker got an error explainer, so you can quickly look up what a rule means</li>
  <li><a href="https://github.com/microsoft/pyright">Pyright</a> rule names (like <code class="language-plaintext highlighter-rouge">reportGeneralTypeIssues</code>) now show up as error IDs</li>
</ul>

<h2 id="bug-fixes">Bug Fixes</h2>

<p>This release includes a massive number of bug fixes – over 25 of them. Some highlights:</p>

<ul>
  <li>Fixed error pattern matching in non-English locales by forcing <code class="language-plaintext highlighter-rouge">LC_ALL=C</code> for checker processes</li>
  <li>Fixed the <code class="language-plaintext highlighter-rouge">rust</code> checker on Windows (no more <code class="language-plaintext highlighter-rouge">/dev/null</code> errors)</li>
  <li>Fixed <code class="language-plaintext highlighter-rouge">flycheck-navigation-minimum-level</code> being ignored in some cases</li>
  <li>Fixed compilation warnings on Emacs 30</li>
  <li>Fixed several issues with the <code class="language-plaintext highlighter-rouge">python-ruff</code>, <a href="https://www.nongnu.org/chktex/"><code class="language-plaintext highlighter-rouge">tex-chktex</code></a>, <code class="language-plaintext highlighter-rouge">emacs-lisp</code>, and <code class="language-plaintext highlighter-rouge">awk-gawk</code> checkers</li>
</ul>

<p>Check the <a href="https://github.com/flycheck/flycheck/releases/tag/v36.0">release notes</a> for the full list.</p>

<h2 id="spring-cleaning">Spring Cleaning</h2>

<p>We’ve removed a number of checkers for tools that have been dead or deprecated for years:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">typescript-tslint</code> (deprecated since 2019, use <a href="https://typescript-eslint.io/">ESLint with typescript-eslint</a>)</li>
  <li><code class="language-plaintext highlighter-rouge">sass</code>, <code class="language-plaintext highlighter-rouge">scss</code>, <code class="language-plaintext highlighter-rouge">sass/scss-sass-lint</code>, <code class="language-plaintext highlighter-rouge">scss-lint</code> (Ruby Sass is dead, use <a href="https://stylelint.io/">Stylelint</a>)</li>
  <li><code class="language-plaintext highlighter-rouge">eruby-erubis</code>, <code class="language-plaintext highlighter-rouge">eruby-ruumba</code> (<a href="https://github.com/kwatch/erubis">Erubis</a> abandoned since 2011)</li>
  <li><code class="language-plaintext highlighter-rouge">css-csslint</code> (abandoned since ~2017, use Stylelint)</li>
  <li><code class="language-plaintext highlighter-rouge">coffee-coffeelint</code>, <code class="language-plaintext highlighter-rouge">protobuf-prototool</code>, <code class="language-plaintext highlighter-rouge">nix-linter</code></li>
</ul>

<p>If you’re still using any of these tools… well, it’s probably time to upgrade!</p>

<h2 id="documentation-site">Documentation Site</h2>

<p><a href="https://www.flycheck.org">flycheck.org</a> got a visual refresh – we’ve switched
from the old Alabaster Sphinx theme to <a href="https://pradyunsg.me/furo/">Furo</a>, which
gives the site a clean, modern look with proper dark mode support and better
mobile responsiveness. We’ve also added prominent GitHub links at the top of
every page, making it easier to jump to the source or file issues.</p>

<p>I hate the old theme, so this one is a major win in my book! I’ve also took some
effort to make sure the documentation accurately reflects the current state of project,
as here and there things were out-of-sync.</p>

<h2 id="flycheck-is-alive-and-well">Flycheck is Alive and Well</h2>

<p>I know that many people wrote Flycheck off when Flymake got tight integration
with Eglot (they share a maintainer, after all), and I understand why – it’s
hard to compete with something that’s built into Emacs and “just works” out of
the box. But Flycheck continues to advance and evolve. We have excellent Eglot
support via <a href="https://github.com/flycheck/flycheck-eglot">flycheck-eglot</a>, a
massive library of built-in checkers,<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> and a feature set that Flymake still
can’t match in many areas.</p>

<p>More importantly, Flycheck’s biggest strength has always been that it’s
community-driven and easy to contribute to. Adding a new checker is
straightforward, PRs get reviewed quickly, and you don’t have to go through the
FSF copyright assignment process. That matters, and it’s why the project keeps
growing.</p>

<h2 id="epilogue">Epilogue</h2>

<p>I’m pretty happy with this release. The combination of new features, security
hardening, and cleanup of dead checkers puts Flycheck in a much healthier
state. Looking ahead to Flycheck 37, I’m thinking about tree-sitter integration,
more new checkers (OCaml and Swift are already in the pipeline), and potentially
dropping support for Emacs 27 so we can take advantage of newer APIs.
The plan is still hazy, but it’s starting to take some shape…</p>

<p>As always, contributions are very welcome! If there’s a lint tool you use that
Flycheck doesn’t support yet, PRs are the fastest way to make it happen.
As mentioned above, Flycheck’s biggest strength remains its community, and are
the community.</p>

<p>That’s all I have for you today. Keep hacking!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>See <a href="https://github.com/flycheck/flycheck/pull/2160">https://github.com/flycheck/flycheck/pull/2160</a>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>See <a href="https://www.flycheck.org/en/latest/languages.html">https://www.flycheck.org/en/latest/languages.html</a> for the full list. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Emacs" /><category term="Flycheck" /><summary type="html"><![CDATA[It’s been a while since Flycheck 35, but Flycheck 36 is finally here! This is a pretty big release with a lot of new features, bug fixes, and some much-needed cleanup of legacy checkers. In fact, I’d say it’s the biggest and most important Flycheck release since I became the project’s primary maintainer a couple of years ago. For a while I had mostly gone with the flow (adding/improving linters and fixing bugs), but by now I feel more confident to make bigger and bolder changes. Anyways, you’re probably interested to learn more about Flycheck 36, so let me walk you through the highlights. New Checkers We’ve added a couple of new checkers: javascript-oxlint – a checker using oxlint, the blazing-fast JavaScript/TypeScript linter written in Rust. If you haven’t tried oxlint yet, you really should – it’s impressively fast. org-lint – an Org mode checker using Emacs’ built-in org-lint. It detects issues like invalid links, dead links, and duplicate IDs. This one went through a rewrite mid-cycle to run in the current Emacs process instead of a --batch subprocess, which eliminates false warnings for source block languages provided by external packages. Security We’ve mitigated CVE-2024-53920 in the emacs-lisp checker by disabling local eval directives and restricting local variables to safe values during byte-compilation. This was an important fix – byte-compilation involves macro expansion, which means untrusted Elisp files could potentially execute arbitrary code during syntax checking. A follow-up fix for Emacs 30+ using trusted-content is in the works.1 ShellCheck Improvements The sh-shellcheck checker got some love in this release: New flycheck-shellcheck-infer-shell option to let ShellCheck auto-detect the shell dialect flycheck-shellcheck-args for passing extra command-line arguments flycheck-shellcheck-enabled-checks to enable optional checks via --enable Quality-of-Life Improvements A bunch of small but welcome improvements: flycheck-command-map now works as a prefix command with keymap-set and friends – no more need for the define-key workaround Buffers are automatically re-checked after revert-buffer, so global-auto-revert-mode users get up-to-date diagnostics without manual intervention The mode-line indicator now includes info-level errors (format: errors|warnings|infos) The python-ruff checker got an error explainer, so you can quickly look up what a rule means Pyright rule names (like reportGeneralTypeIssues) now show up as error IDs Bug Fixes This release includes a massive number of bug fixes – over 25 of them. Some highlights: Fixed error pattern matching in non-English locales by forcing LC_ALL=C for checker processes Fixed the rust checker on Windows (no more /dev/null errors) Fixed flycheck-navigation-minimum-level being ignored in some cases Fixed compilation warnings on Emacs 30 Fixed several issues with the python-ruff, tex-chktex, emacs-lisp, and awk-gawk checkers Check the release notes for the full list. Spring Cleaning We’ve removed a number of checkers for tools that have been dead or deprecated for years: typescript-tslint (deprecated since 2019, use ESLint with typescript-eslint) sass, scss, sass/scss-sass-lint, scss-lint (Ruby Sass is dead, use Stylelint) eruby-erubis, eruby-ruumba (Erubis abandoned since 2011) css-csslint (abandoned since ~2017, use Stylelint) coffee-coffeelint, protobuf-prototool, nix-linter If you’re still using any of these tools… well, it’s probably time to upgrade! Documentation Site flycheck.org got a visual refresh – we’ve switched from the old Alabaster Sphinx theme to Furo, which gives the site a clean, modern look with proper dark mode support and better mobile responsiveness. We’ve also added prominent GitHub links at the top of every page, making it easier to jump to the source or file issues. I hate the old theme, so this one is a major win in my book! I’ve also took some effort to make sure the documentation accurately reflects the current state of project, as here and there things were out-of-sync. Flycheck is Alive and Well I know that many people wrote Flycheck off when Flymake got tight integration with Eglot (they share a maintainer, after all), and I understand why – it’s hard to compete with something that’s built into Emacs and “just works” out of the box. But Flycheck continues to advance and evolve. We have excellent Eglot support via flycheck-eglot, a massive library of built-in checkers,2 and a feature set that Flymake still can’t match in many areas. More importantly, Flycheck’s biggest strength has always been that it’s community-driven and easy to contribute to. Adding a new checker is straightforward, PRs get reviewed quickly, and you don’t have to go through the FSF copyright assignment process. That matters, and it’s why the project keeps growing. Epilogue I’m pretty happy with this release. The combination of new features, security hardening, and cleanup of dead checkers puts Flycheck in a much healthier state. Looking ahead to Flycheck 37, I’m thinking about tree-sitter integration, more new checkers (OCaml and Swift are already in the pipeline), and potentially dropping support for Emacs 27 so we can take advantage of newer APIs. The plan is still hazy, but it’s starting to take some shape… As always, contributions are very welcome! If there’s a lint tool you use that Flycheck doesn’t support yet, PRs are the fastest way to make it happen. As mentioned above, Flycheck’s biggest strength remains its community, and are the community. That’s all I have for you today. Keep hacking! See https://github.com/flycheck/flycheck/pull/2160. &#8617; See https://www.flycheck.org/en/latest/languages.html for the full list. &#8617;]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">adoc-mode 0.8</title><link href="https://metaredux.com/posts/2026/02/21/adoc-mode-0-8.html" rel="alternate" type="text/html" title="adoc-mode 0.8" /><published>2026-02-21T10:15:00+00:00</published><updated>2026-02-21T10:15:00+00:00</updated><id>https://metaredux.com/posts/2026/02/21/adoc-mode-0-8</id><content type="html" xml:base="https://metaredux.com/posts/2026/02/21/adoc-mode-0-8.html"><![CDATA[<p>Almost 3 years after the <a href="/posts/2023/03/12/adoc-mode-reborn.html">rebirth of adoc-mode</a> I’m happy to announce
that <a href="https://github.com/bbatsov/adoc-mode/releases/tag/v0.8.0">adoc-mode 0.8</a> is finally out! This is a massive release
that has been cooking for way too long, but I think it was worth the wait.</p>

<p>Let me walk you through the highlights.</p>

<h2 id="native-code-block-highlighting">Native Code Block Highlighting</h2>

<p>This was the flagship feature I teased at the end of my 0.7 announcement, and
it’s easily the most impactful change in this release. Source code blocks now get
fontified using the appropriate language major mode – Ruby code looks like it
does in <code class="language-plaintext highlighter-rouge">ruby-mode</code>, Python code looks like <code class="language-plaintext highlighter-rouge">python-mode</code>, and so on.</p>

<p>The feature is enabled out-of-the-box with a sensible default – only code blocks
of 5000 characters or fewer are fontified natively, to avoid performance
issues with very large blocks. You can set <code class="language-plaintext highlighter-rouge">adoc-fontify-code-blocks-natively</code>
to <code class="language-plaintext highlighter-rouge">t</code> if you want unlimited fontification, or to <code class="language-plaintext highlighter-rouge">nil</code> to disable it entirely.</p>

<h2 id="inline-image-preview">Inline Image Preview</h2>

<p>You can now see images directly in your buffer instead of just staring at
<code class="language-plaintext highlighter-rouge">image::path/to/screenshot.png[]</code>. Image previews are displayed automatically
when you open a file (controlled by <code class="language-plaintext highlighter-rouge">adoc-display-images</code>), and you can toggle
them on and off with <code class="language-plaintext highlighter-rouge">adoc-toggle-images</code>.</p>

<p>Right-clicking on an image link gives you a context menu to generate or remove
the preview for that specific image. Remote images are supported too – set
<code class="language-plaintext highlighter-rouge">adoc-display-remote-images</code> to <code class="language-plaintext highlighter-rouge">t</code> if you want to fetch and display images from
URLs.</p>

<h2 id="navigation">Navigation</h2>

<p>A couple of welcome additions here:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">adoc-follow-thing-at-point</code> (bound to <code class="language-plaintext highlighter-rouge">C-c C-o</code> and <code class="language-plaintext highlighter-rouge">M-.</code>) lets you follow
URLs (opens in browser), <code class="language-plaintext highlighter-rouge">include::</code> macros (opens the referenced file), and
cross-references (jumps to the anchor). It’s one of those features that once
you have it, you can’t imagine living without.</li>
  <li><code class="language-plaintext highlighter-rouge">adoc-goto-ref-label</code> (<code class="language-plaintext highlighter-rouge">C-c C-a</code>) jumps to an anchor by ID, with a smart
default pulled from the xref at point.</li>
  <li>The <code class="language-plaintext highlighter-rouge">imenu</code> index is now hierarchical – headings are nested under their parent
sections, which makes navigating large documents much more pleasant.</li>
</ul>

<h2 id="asciidoctor-inline-macros">Asciidoctor Inline Macros</h2>

<p><code class="language-plaintext highlighter-rouge">adoc-mode</code> now highlights Asciidoctor-specific inline macros like <code class="language-plaintext highlighter-rouge">kbd:[]</code>,
<code class="language-plaintext highlighter-rouge">btn:[]</code>, <code class="language-plaintext highlighter-rouge">menu:[]</code>, <code class="language-plaintext highlighter-rouge">pass:[]</code>, <code class="language-plaintext highlighter-rouge">stem:[]</code>, <code class="language-plaintext highlighter-rouge">latexmath:[]</code>, and <code class="language-plaintext highlighter-rouge">asciimath:[]</code>.
These were previously ignored by font-lock and would just blend in with regular
text.</p>

<p>I’m a heavy user of Antora, and I really appreciate this one.</p>

<h2 id="bug-fixes-galore">Bug Fixes Galore</h2>

<p>This release squashes a lot of long-standing bugs:</p>

<ul>
  <li>Fixed a noticeable lag when typing in code blocks (this one was particularly annoying).</li>
  <li>Fixed an Emacs hang caused by escaped curly braces in attribute references.</li>
  <li>Fixed multiline font-lock for inline formatting (bold, italic, etc. spanning multiple lines).</li>
  <li>Prevented <code class="language-plaintext highlighter-rouge">auto-fill-mode</code> from breaking section title lines.</li>
  <li>Prevented Flyspell from generating overlays for links and other non-prose regions.</li>
  <li>Fixed table delimiter highlighting (was limited to 4 columns).</li>
  <li>Fixed unconstrained monospace delimiters.</li>
  <li>And quite a few more – check the <a href="https://github.com/bbatsov/adoc-mode/releases/tag/v0.8.0">release notes</a> for the full list.</li>
</ul>

<h2 id="internal-improvements">Internal Improvements</h2>

<p>I’ve also spent some time cleaning up the internals:</p>

<ul>
  <li>The minimum Emacs version is now 28.1 (up from 26).</li>
  <li>Deprecated AsciiDoc backtick-apostrophe quote styles (not supported by
Asciidoctor) have been removed.</li>
  <li>Two-line (Setext) titles are now disabled by default, since Asciidoctor has
deprecated them.</li>
  <li>Image display and tempo templates have been extracted into separate files
(<code class="language-plaintext highlighter-rouge">adoc-mode-image.el</code> and <code class="language-plaintext highlighter-rouge">adoc-mode-tempo.el</code>), making the main file more
manageable.</li>
</ul>

<p>The codebase is in much better shape than it was 3 years ago, but there’s still
some room for improvement.</p>

<h2 id="one-more-thing-asciidoc-mode">One More Thing: asciidoc-mode</h2>

<p>I did eventually act on that idea I mentioned in my 0.7 post – I created
<a href="https://github.com/bbatsov/asciidoc-mode">asciidoc-mode</a>, a tree-sitter-based
AsciiDoc major mode for Emacs 30.1+. It’s a very different beast from <code class="language-plaintext highlighter-rouge">adoc-mode</code>
– focused on the essentials (highlighting, navigation, folding) and leveraging
tree-sitter for accurate and performant parsing.</p>

<p>If you’re on Emacs 30+ and prefer a lighter-weight editing experience,
<code class="language-plaintext highlighter-rouge">asciidoc-mode</code> might be a good fit. If you want the full kitchen sink –
image previews, tempo templates, native code block highlighting – <code class="language-plaintext highlighter-rouge">adoc-mode</code> is
still the way to go. Both packages are maintained by me and they complement each
other nicely.</p>

<h2 id="epilogue">Epilogue</h2>

<p><code class="language-plaintext highlighter-rouge">adoc-mode</code> 0.8 is available on <a href="https://elpa.nongnu.org/nongnu/adoc-mode.html">NonGNU ELPA</a>, <a href="http://stable.melpa.org/#/adoc-mode">MELPA Stable</a>,
and <a href="http://melpa.org/#/adoc-mode">MELPA</a>. Upgrading is just a <code class="language-plaintext highlighter-rouge">M-x package-install</code> away.</p>

<p>I’d like to thank everyone who contributed bug reports, pull requests, and
feedback over the past 3 years. Open-source is a team sport and this release
wouldn’t have happened without you. You rock!</p>

<p>That’s all I have for you today. Keep hacking! And keep writing… in AsciiDoc, of course!</p>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Emacs" /><category term="AsciiDoc" /><summary type="html"><![CDATA[Almost 3 years after the rebirth of adoc-mode I’m happy to announce that adoc-mode 0.8 is finally out! This is a massive release that has been cooking for way too long, but I think it was worth the wait. Let me walk you through the highlights. Native Code Block Highlighting This was the flagship feature I teased at the end of my 0.7 announcement, and it’s easily the most impactful change in this release. Source code blocks now get fontified using the appropriate language major mode – Ruby code looks like it does in ruby-mode, Python code looks like python-mode, and so on. The feature is enabled out-of-the-box with a sensible default – only code blocks of 5000 characters or fewer are fontified natively, to avoid performance issues with very large blocks. You can set adoc-fontify-code-blocks-natively to t if you want unlimited fontification, or to nil to disable it entirely. Inline Image Preview You can now see images directly in your buffer instead of just staring at image::path/to/screenshot.png[]. Image previews are displayed automatically when you open a file (controlled by adoc-display-images), and you can toggle them on and off with adoc-toggle-images. Right-clicking on an image link gives you a context menu to generate or remove the preview for that specific image. Remote images are supported too – set adoc-display-remote-images to t if you want to fetch and display images from URLs. Navigation A couple of welcome additions here: adoc-follow-thing-at-point (bound to C-c C-o and M-.) lets you follow URLs (opens in browser), include:: macros (opens the referenced file), and cross-references (jumps to the anchor). It’s one of those features that once you have it, you can’t imagine living without. adoc-goto-ref-label (C-c C-a) jumps to an anchor by ID, with a smart default pulled from the xref at point. The imenu index is now hierarchical – headings are nested under their parent sections, which makes navigating large documents much more pleasant. Asciidoctor Inline Macros adoc-mode now highlights Asciidoctor-specific inline macros like kbd:[], btn:[], menu:[], pass:[], stem:[], latexmath:[], and asciimath:[]. These were previously ignored by font-lock and would just blend in with regular text. I’m a heavy user of Antora, and I really appreciate this one. Bug Fixes Galore This release squashes a lot of long-standing bugs: Fixed a noticeable lag when typing in code blocks (this one was particularly annoying). Fixed an Emacs hang caused by escaped curly braces in attribute references. Fixed multiline font-lock for inline formatting (bold, italic, etc. spanning multiple lines). Prevented auto-fill-mode from breaking section title lines. Prevented Flyspell from generating overlays for links and other non-prose regions. Fixed table delimiter highlighting (was limited to 4 columns). Fixed unconstrained monospace delimiters. And quite a few more – check the release notes for the full list. Internal Improvements I’ve also spent some time cleaning up the internals: The minimum Emacs version is now 28.1 (up from 26). Deprecated AsciiDoc backtick-apostrophe quote styles (not supported by Asciidoctor) have been removed. Two-line (Setext) titles are now disabled by default, since Asciidoctor has deprecated them. Image display and tempo templates have been extracted into separate files (adoc-mode-image.el and adoc-mode-tempo.el), making the main file more manageable. The codebase is in much better shape than it was 3 years ago, but there’s still some room for improvement. One More Thing: asciidoc-mode I did eventually act on that idea I mentioned in my 0.7 post – I created asciidoc-mode, a tree-sitter-based AsciiDoc major mode for Emacs 30.1+. It’s a very different beast from adoc-mode – focused on the essentials (highlighting, navigation, folding) and leveraging tree-sitter for accurate and performant parsing. If you’re on Emacs 30+ and prefer a lighter-weight editing experience, asciidoc-mode might be a good fit. If you want the full kitchen sink – image previews, tempo templates, native code block highlighting – adoc-mode is still the way to go. Both packages are maintained by me and they complement each other nicely. Epilogue adoc-mode 0.8 is available on NonGNU ELPA, MELPA Stable, and MELPA. Upgrading is just a M-x package-install away. I’d like to thank everyone who contributed bug reports, pull requests, and feedback over the past 3 years. Open-source is a team sport and this release wouldn’t have happened without you. You rock! That’s all I have for you today. Keep hacking! And keep writing… in AsciiDoc, of course!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">nREPL 1.4</title><link href="https://metaredux.com/posts/2025/09/03/nrepl-1-4.html" rel="alternate" type="text/html" title="nREPL 1.4" /><published>2025-09-03T06:36:00+00:00</published><updated>2025-09-03T06:36:00+00:00</updated><id>https://metaredux.com/posts/2025/09/03/nrepl-1-4</id><content type="html" xml:base="https://metaredux.com/posts/2025/09/03/nrepl-1-4.html"><![CDATA[<p>nREPL 1.4.0 is out! This month we celebrate 15 years since nREPL’s development started,
so you can consider this release part of the upcoming birthday celebrations.</p>

<p>So, what’s new?</p>

<p>Probably the highlight is the ability to pre-configure default values for dynamic
variables in all nREPL servers that are launched locally (either per project or
system-wide). The most useful application for this would be to enable
<code class="language-plaintext highlighter-rouge">*warn-on-reflection*</code> in all REPLs. To achieve this, create <code class="language-plaintext highlighter-rouge">~/.nrepl/nrepl.edn</code>
with this content:</p>

<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="no">:dynamic-vars</span><span class="w"> </span><span class="p">{</span><span class="n">clojure.core/*warn-on-reflection*</span><span class="w"> </span><span class="n">true</span><span class="p">}}</span><span class="w">
</span></code></pre></div></div>

<p>Now, any nREPL server started from any IDE will have <code class="language-plaintext highlighter-rouge">*warn-on-reflection*</code> enabled.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ clojure -Sdeps "{:deps {nrepl/nrepl {:mvn/version \"1.4.0\"}}}" -m nrepl.cmdline -i
user=&gt; #(.a %)
Reflection warning, NO_SOURCE_PATH:1:2 - reference to field a can't be resolved.
</code></pre></div></div>

<p><strong>Note:</strong> nREPL doesn’t support directly <code class="language-plaintext highlighter-rouge">XDG_CONFIG_HOME</code> yet, but you can easily
override the default global config directory (<code class="language-plaintext highlighter-rouge">~/.nrepl</code>) with <code class="language-plaintext highlighter-rouge">NREPL_CONFIG_DIR</code>.</p>

<p>Another new feature is the ability to specify <code class="language-plaintext highlighter-rouge">:client-name</code> and <code class="language-plaintext highlighter-rouge">:client-version</code> when
creating a new nREPL session with the <code class="language-plaintext highlighter-rouge">clone</code> operator. This allows collecting information
about the clients used, which some organizations might find useful. (I know Nubank are
making use of this already)</p>

<p>One notable change in nREPL 1.4 is the removal of support for Clojure 1.7. Clojure 1.7 was released
way back in 2015 and I doubt anyone is using it these days, but we try to be extra conservative with the
supported Clojure versions and this is only the second time nREPL’s runtime requirements were bumped
in the 7 and a half years I’ve been the maintainer of the project. (early on I bumped the required Clojure from 1.2 to 1.7)</p>

<p>As usual the release features also small bug-fixes and internal improvements. One such improvement was 
the introduction of <code class="language-plaintext highlighter-rouge">matcher-combinators</code> in our test suite. (which was the main motivation to bid farewell to Clojure 1.7)
You can check out the <a href="https://github.com/nrepl/nrepl/releases/tag/v1.4.0">release note</a> for a complete list of changes.</p>

<p>That’s all I have for you today. I hope we’ll have more exciting nREPL news to share by nREPL’s “official” birthday, October 8th.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>
Big thanks to everyone who has contributed to this release and to all the people supporting my Clojure OSS work!
In the REPL we trust! Keep hacking!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>nREPL 0.1 was released on Oct 11, 2015. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Clojure" /><category term="nREPL" /><summary type="html"><![CDATA[nREPL 1.4.0 is out! This month we celebrate 15 years since nREPL’s development started, so you can consider this release part of the upcoming birthday celebrations. So, what’s new? Probably the highlight is the ability to pre-configure default values for dynamic variables in all nREPL servers that are launched locally (either per project or system-wide). The most useful application for this would be to enable *warn-on-reflection* in all REPLs. To achieve this, create ~/.nrepl/nrepl.edn with this content: {:dynamic-vars {clojure.core/*warn-on-reflection* true}} Now, any nREPL server started from any IDE will have *warn-on-reflection* enabled. $ clojure -Sdeps "{:deps {nrepl/nrepl {:mvn/version \"1.4.0\"}}}" -m nrepl.cmdline -i user=&gt; #(.a %) Reflection warning, NO_SOURCE_PATH:1:2 - reference to field a can't be resolved. Note: nREPL doesn’t support directly XDG_CONFIG_HOME yet, but you can easily override the default global config directory (~/.nrepl) with NREPL_CONFIG_DIR. Another new feature is the ability to specify :client-name and :client-version when creating a new nREPL session with the clone operator. This allows collecting information about the clients used, which some organizations might find useful. (I know Nubank are making use of this already) One notable change in nREPL 1.4 is the removal of support for Clojure 1.7. Clojure 1.7 was released way back in 2015 and I doubt anyone is using it these days, but we try to be extra conservative with the supported Clojure versions and this is only the second time nREPL’s runtime requirements were bumped in the 7 and a half years I’ve been the maintainer of the project. (early on I bumped the required Clojure from 1.2 to 1.7) As usual the release features also small bug-fixes and internal improvements. One such improvement was the introduction of matcher-combinators in our test suite. (which was the main motivation to bid farewell to Clojure 1.7) You can check out the release note for a complete list of changes. That’s all I have for you today. I hope we’ll have more exciting nREPL news to share by nREPL’s “official” birthday, October 8th.1 Big thanks to everyone who has contributed to this release and to all the people supporting my Clojure OSS work! In the REPL we trust! Keep hacking! nREPL 0.1 was released on Oct 11, 2015. &#8617;]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Weird Ruby: Anonymous Heredocs</title><link href="https://metaredux.com/posts/2025/06/02/weird-ruby-anonymous-heredocs.html" rel="alternate" type="text/html" title="Weird Ruby: Anonymous Heredocs" /><published>2025-06-02T04:55:00+00:00</published><updated>2025-06-02T04:55:00+00:00</updated><id>https://metaredux.com/posts/2025/06/02/weird-ruby-anonymous-heredocs</id><content type="html" xml:base="https://metaredux.com/posts/2025/06/02/weird-ruby-anonymous-heredocs.html"><![CDATA[<p>Heredocs in Ruby are quite common, quite flexible, and… somewhat weird. Still,
this doesn’t stop people from suggesting more features for them, like this
(rejected) <a href="https://bugs.ruby-lang.org/issues/20852">proposal</a> for an anonymous
heredocs syntax:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># regular Ruby code</span>
<span class="no">Markdown</span><span class="p">.</span><span class="nf">render</span> <span class="o">&lt;&lt;~</span><span class="no">MARKDOWN</span><span class="sh">
  # Hello there

  This is a Markdown file. See?

  1. This is a list
  2. With items
  3. And more items
</span><span class="no">MARKDOWN</span>

<span class="c1"># proposed syntax</span>
<span class="no">Markdown</span><span class="p">.</span><span class="nf">render</span> <span class="o">&lt;&lt;~</span>
  <span class="c1"># Hello there</span>

  <span class="no">This</span> <span class="n">is</span> <span class="n">a</span> <span class="no">Markdown</span> <span class="n">file</span><span class="o">.</span> <span class="no">See</span><span class="p">?</span>

  <span class="mi">1</span><span class="o">.</span> <span class="no">This</span> <span class="n">is</span> <span class="n">a</span> <span class="n">list</span>
  <span class="mi">2</span><span class="o">.</span> <span class="no">With</span> <span class="n">items</span>
  <span class="mi">3</span><span class="o">.</span> <span class="no">And</span> <span class="n">more</span> <span class="n">items</span>
<span class="o">~&gt;&gt;</span>
</code></pre></div></div>

<p>Even though this proposal didn’t make it, you can get pretty close by just using <code class="language-plaintext highlighter-rouge">_</code>
as your heredoc delimiter:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Markdown</span><span class="p">.</span><span class="nf">render</span> <span class="o">&lt;&lt;~</span><span class="no">_</span><span class="sh">
  # Hello there

  This is a Markdown file. See?

  1. This is a list
  2. With items
  3. And more items
</span><span class="no">_</span>
</code></pre></div></div>

<p>Looks a bit weird, but it gets the job done.</p>

<p>That’s all I have for you today. Keep Ruby weird!</p>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Ruby" /><category term="Weird Ruby" /><category term="Series" /><summary type="html"><![CDATA[Heredocs in Ruby are quite common, quite flexible, and… somewhat weird. Still, this doesn’t stop people from suggesting more features for them, like this (rejected) proposal for an anonymous heredocs syntax: # regular Ruby code Markdown.render &lt;&lt;~MARKDOWN # Hello there This is a Markdown file. See? 1. This is a list 2. With items 3. And more items MARKDOWN # proposed syntax Markdown.render &lt;&lt;~ # Hello there This is a Markdown file. See? 1. This is a list 2. With items 3. And more items ~&gt;&gt; Even though this proposal didn’t make it, you can get pretty close by just using _ as your heredoc delimiter: Markdown.render &lt;&lt;~_ # Hello there This is a Markdown file. See? 1. This is a list 2. With items 3. And more items _ Looks a bit weird, but it gets the job done. That’s all I have for you today. Keep Ruby weird!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">CIDER 1.18 (“Athens”)</title><link href="https://metaredux.com/posts/2025/04/30/cider-1-18.html" rel="alternate" type="text/html" title="CIDER 1.18 (“Athens”)" /><published>2025-04-30T08:25:00+00:00</published><updated>2025-04-30T08:25:00+00:00</updated><id>https://metaredux.com/posts/2025/04/30/cider-1-18</id><content type="html" xml:base="https://metaredux.com/posts/2025/04/30/cider-1-18.html"><![CDATA[<p>Great news, everyone - <a href="https://github.com/clojure-emacs/cider/releases/tag/v1.18.0">CIDER 1.18</a> (“Athens”) is out!</p>

<p>This is a huge release that has an equal amount of new features, improvements to
the existing ones, and also trimming down some capabilities in the name of
improved efficiency and maintainability.</p>

<p>I’m too lazy to write a long release announcement today, so I’ll just highlight
the most important aspects of CIDER 1.18 and how they fit our broader vision
for the future of CIDER.</p>

<p>Let’s go!</p>

<h2 id="reduced-surface-area">Reduced surface area</h2>

<ul>
  <li>CIDER 1.18 dropped support for Boot and Emacs 26. Boot development has been frozen for many years, and it’s now a long past due to migrate to other build tools.</li>
  <li>CIDER no longer bundles Puget dependency. Puget is still supported as a pretty-printer for all CIDER output, but you need to add it to dependencies explicitly.</li>
  <li>Haystack is no longer included. With it, we removed some largely unknown facilities for parsing printed stacktraces and presenting them inside <code class="language-plaintext highlighter-rouge">*cider-error*</code> buffer.</li>
  <li>Replaced the outdated <code class="language-plaintext highlighter-rouge">thunknyc/profile</code> dependency with a homegrown implementation in Orchard.</li>
</ul>

<p>I’m happy that we continue on the path of reducing the 3rd-party dependencies in
<code class="language-plaintext highlighter-rouge">cider-nrepl</code> and rely more and more on functionality optimized for our
use-cases, living in Orchard. Looking back, at some of the decisions I’ve taken
in the past - I sometimes regret going overboard with the feature set (we have
so many features today, that even I occasionally forget about some of them) and
the dependencies needed to provide certain features. Going forward I hope to
gradually reduce the feature set and the dependencies by:</p>

<ul>
  <li>removing features that are rarely used</li>
  <li>making certain dependencies optional (instead of bundling everything with <code class="language-plaintext highlighter-rouge">cider-nrepl</code>)</li>
</ul>

<h2 id="inspector">Inspector</h2>

<p>Our beloved inspector got a lot better!</p>

<ul>
  <li>New analytics module (<a href="https://github.com/clojure-emacs/orchard/pull/329">orchard#329</a>) (shows you some useful info about the data you’re inspecting)</li>
  <li>Table view mode (<a href="https://github.com/clojure-emacs/orchard/pull/331">orchard#331</a>) (I think you’ll totally love this!)</li>
  <li>Pretty-printing mode (<a href="https://github.com/clojure-emacs/cider/pull/3813">#3813</a>) and a command to separately pretty-print the currently inspected value (<a href="https://github.com/clojure-emacs/cider/pull/3810">#3810</a>)</li>
</ul>

<p>That’s how the analytics and the table view look:</p>

<p><img src="/assets/images/cider-inspector-analytics.png" alt="inspector-analytics" /></p>

<p><img src="/assets/images/cider-inspector-table-view.png" alt="table-view-mode" /></p>

<p>Cool stuff!</p>

<h2 id="error-handling">Error handling</h2>

<ul>
  <li>In exchange for removing Haystack, CIDER now allows jumping to munged Clojure functions and Java methods anywhere from the source buffers or the REPL. This means that you can press <code class="language-plaintext highlighter-rouge">M-.</code> on printed frames like <code class="language-plaintext highlighter-rouge">clojure.core$with_bindings_STAR_.doInvoke</code> or <code class="language-plaintext highlighter-rouge">clojure.lang.Compiler$InvokeExpr.eval</code> within the exception, and CIDER will take you there.</li>
  <li>Stacktrace processing has been greatly simplified and optimized. You may notice that the delay between an exception occuring and <code class="language-plaintext highlighter-rouge">*cider-error*</code> buffer popping up disappeared, especially in big projects.</li>
  <li>Ex-data is now always displayed for each exception cause which has it, albeit in an abbreviated form. You can click or press <code class="language-plaintext highlighter-rouge">RET</code> (a.k.a. <code class="language-plaintext highlighter-rouge">Enter</code>) on to open it in the inspector (<a href="https://github.com/clojure-emacs/cider/issues/3807">#3807</a>).</li>
</ul>

<p>I’m guessing some of those changes might be considered slightly controversial
(especially the last item), but I think they are a bit step towards simplicity
and more internal consistency.</p>

<h2 id="misc-features">Misc features</h2>

<ul>
  <li>Completions got better with priority-based sorting and fuzzy-matching enabled by default (so you can complete unimported short classnames, and things like <code class="language-plaintext highlighter-rouge">cji</code>, <code class="language-plaintext highlighter-rouge">rkv</code>, etc.)</li>
  <li>The middleware that powers dynamic font-locking was made tremendously faster and more memory efficient on both Clojure and Emacs sides of CIDER. Again, this effect would be more pronounced in large codebases.
This optimization is well overdue, and perhaps it will encourage more editors to embrace the <code class="language-plaintext highlighter-rouge">track-state</code> middleware, as I think it’s one of the coolest aspects of CIDER.</li>
  <li>Added support for dynamic indentation in clojure-ts-mode (<a href="https://github.com/clojure-emacs/cider/pull/3803">#3803</a>)</li>
</ul>

<p>Side note - I’ve been spending a lot of time on <code class="language-plaintext highlighter-rouge">clojure-ts-mode</code> lately and it’s shaping up pretty nicely. If you’re happy with <code class="language-plaintext highlighter-rouge">clojure-mode</code> there’s no real reason to switch yet, but if you’ve
experienced performance issues with font-locking on indentation you may want to check out <code class="language-plaintext highlighter-rouge">clojure-ts-mode</code>.</p>

<p>I’m happy to report that I’ve also finally started to clean up the numerous compilation warnings introduced in Emacs 29. Most of the meaningful problems are now addressed and the bulk
of the remaining work is related to a new rule for quoting <code class="language-plaintext highlighter-rouge">'</code> in docstrings, which is annoying but not particularly important.</p>

<h2 id="epilogue">Epilogue</h2>

<p>This release is named “Athens” for a reason - Athens is one of the greatest cities
in the world<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> and I think that’s one of the greatest CIDER releases!</p>

<p>For me that’s one of the most important CIDER releases in the past couple of
years, if not the most important. We’ve tackled a lot of long-standing problems
and we’ve started to simplify the internals of CIDER.  The feedback we got from
the “State of CIDER” survey really helped us with some of the decisions - stay
tuned for a detailed analysis of all the feedback we’ve collected there.</p>

<p>As usual - a huge shoutout to all the contributors and “Clojurists Together” for
their support! A special thanks to Sashko Yakushev, who has been firing on all
cylinders lately, and was once again the driving force behind most of the work
in this release. You’re a legend, buddy!</p>

<p>Sadly, the amount of financial support CIDER is receiving has dropped a lot in
the past 3 years (by about 50%). I hope the situation will change, as solid and
predictable financial backing is the only way to ensure the long-term future of
CIDER and friends.</p>

<p>This is all I have for you today. I hope you’ll have as much fun using it, as we
had developing it! Keep hacking!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>And one of my favorite cities. I’ve got a lot of fond memories of working on CIDER there. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Emacs" /><category term="Clojure" /><category term="CIDER" /><summary type="html"><![CDATA[Great news, everyone - CIDER 1.18 (“Athens”) is out! This is a huge release that has an equal amount of new features, improvements to the existing ones, and also trimming down some capabilities in the name of improved efficiency and maintainability. I’m too lazy to write a long release announcement today, so I’ll just highlight the most important aspects of CIDER 1.18 and how they fit our broader vision for the future of CIDER. Let’s go! Reduced surface area CIDER 1.18 dropped support for Boot and Emacs 26. Boot development has been frozen for many years, and it’s now a long past due to migrate to other build tools. CIDER no longer bundles Puget dependency. Puget is still supported as a pretty-printer for all CIDER output, but you need to add it to dependencies explicitly. Haystack is no longer included. With it, we removed some largely unknown facilities for parsing printed stacktraces and presenting them inside *cider-error* buffer. Replaced the outdated thunknyc/profile dependency with a homegrown implementation in Orchard. I’m happy that we continue on the path of reducing the 3rd-party dependencies in cider-nrepl and rely more and more on functionality optimized for our use-cases, living in Orchard. Looking back, at some of the decisions I’ve taken in the past - I sometimes regret going overboard with the feature set (we have so many features today, that even I occasionally forget about some of them) and the dependencies needed to provide certain features. Going forward I hope to gradually reduce the feature set and the dependencies by: removing features that are rarely used making certain dependencies optional (instead of bundling everything with cider-nrepl) Inspector Our beloved inspector got a lot better! New analytics module (orchard#329) (shows you some useful info about the data you’re inspecting) Table view mode (orchard#331) (I think you’ll totally love this!) Pretty-printing mode (#3813) and a command to separately pretty-print the currently inspected value (#3810) That’s how the analytics and the table view look: Cool stuff! Error handling In exchange for removing Haystack, CIDER now allows jumping to munged Clojure functions and Java methods anywhere from the source buffers or the REPL. This means that you can press M-. on printed frames like clojure.core$with_bindings_STAR_.doInvoke or clojure.lang.Compiler$InvokeExpr.eval within the exception, and CIDER will take you there. Stacktrace processing has been greatly simplified and optimized. You may notice that the delay between an exception occuring and *cider-error* buffer popping up disappeared, especially in big projects. Ex-data is now always displayed for each exception cause which has it, albeit in an abbreviated form. You can click or press RET (a.k.a. Enter) on to open it in the inspector (#3807). I’m guessing some of those changes might be considered slightly controversial (especially the last item), but I think they are a bit step towards simplicity and more internal consistency. Misc features Completions got better with priority-based sorting and fuzzy-matching enabled by default (so you can complete unimported short classnames, and things like cji, rkv, etc.) The middleware that powers dynamic font-locking was made tremendously faster and more memory efficient on both Clojure and Emacs sides of CIDER. Again, this effect would be more pronounced in large codebases. This optimization is well overdue, and perhaps it will encourage more editors to embrace the track-state middleware, as I think it’s one of the coolest aspects of CIDER. Added support for dynamic indentation in clojure-ts-mode (#3803) Side note - I’ve been spending a lot of time on clojure-ts-mode lately and it’s shaping up pretty nicely. If you’re happy with clojure-mode there’s no real reason to switch yet, but if you’ve experienced performance issues with font-locking on indentation you may want to check out clojure-ts-mode. I’m happy to report that I’ve also finally started to clean up the numerous compilation warnings introduced in Emacs 29. Most of the meaningful problems are now addressed and the bulk of the remaining work is related to a new rule for quoting ' in docstrings, which is annoying but not particularly important. Epilogue This release is named “Athens” for a reason - Athens is one of the greatest cities in the world1 and I think that’s one of the greatest CIDER releases! For me that’s one of the most important CIDER releases in the past couple of years, if not the most important. We’ve tackled a lot of long-standing problems and we’ve started to simplify the internals of CIDER. The feedback we got from the “State of CIDER” survey really helped us with some of the decisions - stay tuned for a detailed analysis of all the feedback we’ve collected there. As usual - a huge shoutout to all the contributors and “Clojurists Together” for their support! A special thanks to Sashko Yakushev, who has been firing on all cylinders lately, and was once again the driving force behind most of the work in this release. You’re a legend, buddy! Sadly, the amount of financial support CIDER is receiving has dropped a lot in the past 3 years (by about 50%). I hope the situation will change, as solid and predictable financial backing is the only way to ensure the long-term future of CIDER and friends. This is all I have for you today. I hope you’ll have as much fun using it, as we had developing it! Keep hacking! And one of my favorite cities. I’ve got a lot of fond memories of working on CIDER there. &#8617;]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Projectile Introduces Significant Caching Improvements</title><link href="https://metaredux.com/posts/2025/02/03/projectile-introduces-significant-caching-improvements.html" rel="alternate" type="text/html" title="Projectile Introduces Significant Caching Improvements" /><published>2025-02-03T09:23:00+00:00</published><updated>2025-02-03T09:23:00+00:00</updated><id>https://metaredux.com/posts/2025/02/03/projectile-introduces-significant-caching-improvements</id><content type="html" xml:base="https://metaredux.com/posts/2025/02/03/projectile-introduces-significant-caching-improvements.html"><![CDATA[<p>One of Projectile’s key features has always been the ability to cache the files in a project,
so next time you need to do something with them you’d skip the potentially expensive project file
indexing step. The feature has always worked reasonably well, but it suffered from a couple of design
flaws that I’ve been meaning to address for a while:</p>

<ul>
  <li>The cache for all projects is stored in the same file, which means that often you need to
load information that you don’t really need. Also - storing all the cache data in the same file
means that there’s a higher chance that the cache would get corrupted for one reason or another.</li>
  <li>When caching is enabled, Projectile loads the data from the cache file when <code class="language-plaintext highlighter-rouge">projectile-mode</code>
is enabled. That causes two problems:
    <ul>
      <li>The mode’s init is slower than it could be</li>
      <li>The cache is not loaded unless you enable <code class="language-plaintext highlighter-rouge">projectile-mode</code></li>
    </ul>
  </li>
</ul>

<p>I’m happy to report that I finally got to doing something about the problems listed above!<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> In a nutshell:</p>

<ul>
  <li>Now each project gets its own cache file in the root of the project’s
directory. (named <code class="language-plaintext highlighter-rouge">.projectile-cache.eld</code> by default)<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> I’ve opted for this
approach over something like <code class="language-plaintext highlighter-rouge">.emacs.d/cache</code>, as it avoids the need to hash
the project paths. (so cache files could be mapped to project root paths) I
might change this behavior in the future, depending on the user feedback I
receive.</li>
  <li>The cache is read from disk only when you trigger <code class="language-plaintext highlighter-rouge">projectile-find-file</code> for the first time.</li>
  <li>Both reading and writing the cache file is much faster, as you’re only
reading/writing the cache file for the currently visited project.</li>
</ul>

<p>This means that Projectile’s loading time is much snappier if you’re a heavy cache user.</p>

<p>I’ve also addressed a common problem for people using Projectile over TRAMP - that writing to the
cache file can be quite slow there if you’re working on huge project. The writing of the cache
when individual files are added to it is now deferred using <code class="language-plaintext highlighter-rouge">run-with-idle-timer</code><sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>, which means
that you’ll never experience a lock-up right after creating a new file within a project.
Perhaps even more importantly - I’ve introduced the concept of “transient” cache. Basically
it lives only in memory and is not persisted to a file.<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> Going forward this is going to be
the default caching behavior in Projectile, as I think it offers a better blend of performance and
convenience. To enable the traditional “persistent” cache you’ll have to add this to your config:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">projectile-enable-caching</span> <span class="ss">'persistent</span><span class="p">)</span>
</code></pre></div></div>

<p>To make things better I’ve also reorganized how known projects are initialized, so now no IO operations
happen during Projectile’s initialization and it’s lightning fast! To illustrate this with a bit
of code:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; projectile-mode init before</span>
<span class="c1">;;</span>
<span class="c1">;; initialize the projects cache if needed</span>
<span class="p">(</span><span class="nb">unless</span> <span class="nv">projectile-projects-cache</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">projectile-projects-cache</span>
        <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nv">projectile-unserialize</span> <span class="nv">projectile-cache-file</span><span class="p">)</span>
            <span class="p">(</span><span class="nb">make-hash-table</span> <span class="ss">:test</span> <span class="ss">'equal</span><span class="p">))))</span>
<span class="p">(</span><span class="nb">unless</span> <span class="nv">projectile-projects-cache-time</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">projectile-projects-cache-time</span>
        <span class="p">(</span><span class="nb">make-hash-table</span> <span class="ss">:test</span> <span class="ss">'equal</span><span class="p">)))</span>
<span class="c1">;; load the known projects</span>
<span class="p">(</span><span class="nv">projectile-load-known-projects</span><span class="p">)</span>
<span class="c1">;; update the list of known projects</span>
<span class="p">(</span><span class="nv">projectile--cleanup-known-projects</span><span class="p">)</span>
<span class="p">(</span><span class="nb">when</span> <span class="nv">projectile-auto-discover</span>
  <span class="p">(</span><span class="nv">projectile-discover-projects-in-search-path</span><span class="p">))</span>

<span class="c1">;; projectile-mode init now</span>
<span class="c1">;;</span>
<span class="c1">;; nothing IO-related to show here</span>
</code></pre></div></div>

<p>Last week I’ve started to prepare for the release of Projectile 2.9, which will bring a lot of
bug fixes and improvements. I know that a lot of people have probably written off Projectile by
now, but I still believe that it has a place in the broader Emacs ecosystem (as a community-driven and more
feature-rich alternative of <code class="language-plaintext highlighter-rouge">project.el</code>) and the best is yet to come!</p>

<p>That’s all I have for you today. Keep hacking!</p>

<p><strong>P.S.</strong> I’d appreciate it if more Projectile users experimented with the current snapshot package, before
Projectile 2.9 gets officially released.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>See <a href="https://github.com/bbatsov/projectile/commit/5061bd8dcd9f4d0e874884272f88b10892d15da3">https://github.com/bbatsov/projectile/commit/5061bd8dcd9f4d0e874884272f88b10892d15da3</a>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>You’ll probably want to add this file to your <code class="language-plaintext highlighter-rouge">.gitignore</code>. Or not, as the paths stored in it are relative to the project’s root, so they can actually be reused across different machines. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>See <a href="https://github.com/bbatsov/projectile/commit/0efac68c82d8ebdb3fd83ea5e530c4b816c87f8f">https://github.com/bbatsov/projectile/commit/0efac68c82d8ebdb3fd83ea5e530c4b816c87f8f</a>. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>See <a href="https://github.com/bbatsov/projectile/commit/a4a6cacd908bc614d60c6233a7f224baebfe1178">https://github.com/bbatsov/projectile/commit/a4a6cacd908bc614d60c6233a7f224baebfe1178</a>. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="Emacs" /><category term="Projectile" /><summary type="html"><![CDATA[One of Projectile’s key features has always been the ability to cache the files in a project, so next time you need to do something with them you’d skip the potentially expensive project file indexing step. The feature has always worked reasonably well, but it suffered from a couple of design flaws that I’ve been meaning to address for a while: The cache for all projects is stored in the same file, which means that often you need to load information that you don’t really need. Also - storing all the cache data in the same file means that there’s a higher chance that the cache would get corrupted for one reason or another. When caching is enabled, Projectile loads the data from the cache file when projectile-mode is enabled. That causes two problems: The mode’s init is slower than it could be The cache is not loaded unless you enable projectile-mode I’m happy to report that I finally got to doing something about the problems listed above!1 In a nutshell: Now each project gets its own cache file in the root of the project’s directory. (named .projectile-cache.eld by default)2 I’ve opted for this approach over something like .emacs.d/cache, as it avoids the need to hash the project paths. (so cache files could be mapped to project root paths) I might change this behavior in the future, depending on the user feedback I receive. The cache is read from disk only when you trigger projectile-find-file for the first time. Both reading and writing the cache file is much faster, as you’re only reading/writing the cache file for the currently visited project. This means that Projectile’s loading time is much snappier if you’re a heavy cache user. I’ve also addressed a common problem for people using Projectile over TRAMP - that writing to the cache file can be quite slow there if you’re working on huge project. The writing of the cache when individual files are added to it is now deferred using run-with-idle-timer3, which means that you’ll never experience a lock-up right after creating a new file within a project. Perhaps even more importantly - I’ve introduced the concept of “transient” cache. Basically it lives only in memory and is not persisted to a file.4 Going forward this is going to be the default caching behavior in Projectile, as I think it offers a better blend of performance and convenience. To enable the traditional “persistent” cache you’ll have to add this to your config: (setq projectile-enable-caching 'persistent) To make things better I’ve also reorganized how known projects are initialized, so now no IO operations happen during Projectile’s initialization and it’s lightning fast! To illustrate this with a bit of code: ;; projectile-mode init before ;; ;; initialize the projects cache if needed (unless projectile-projects-cache (setq projectile-projects-cache (or (projectile-unserialize projectile-cache-file) (make-hash-table :test 'equal)))) (unless projectile-projects-cache-time (setq projectile-projects-cache-time (make-hash-table :test 'equal))) ;; load the known projects (projectile-load-known-projects) ;; update the list of known projects (projectile--cleanup-known-projects) (when projectile-auto-discover (projectile-discover-projects-in-search-path)) ;; projectile-mode init now ;; ;; nothing IO-related to show here Last week I’ve started to prepare for the release of Projectile 2.9, which will bring a lot of bug fixes and improvements. I know that a lot of people have probably written off Projectile by now, but I still believe that it has a place in the broader Emacs ecosystem (as a community-driven and more feature-rich alternative of project.el) and the best is yet to come! That’s all I have for you today. Keep hacking! P.S. I’d appreciate it if more Projectile users experimented with the current snapshot package, before Projectile 2.9 gets officially released. See https://github.com/bbatsov/projectile/commit/5061bd8dcd9f4d0e874884272f88b10892d15da3. &#8617; You’ll probably want to add this file to your .gitignore. Or not, as the paths stored in it are relative to the project’s root, so they can actually be reused across different machines. &#8617; See https://github.com/bbatsov/projectile/commit/0efac68c82d8ebdb3fd83ea5e530c4b816c87f8f. &#8617; See https://github.com/bbatsov/projectile/commit/a4a6cacd908bc614d60c6233a7f224baebfe1178. &#8617;]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">A Simpler Way to Deal with Java Sources in CIDER</title><link href="https://metaredux.com/posts/2025/01/17/a-simpler-way-to-deal-with-java-sources-in-cider.html" rel="alternate" type="text/html" title="A Simpler Way to Deal with Java Sources in CIDER" /><published>2025-01-17T11:02:00+00:00</published><updated>2025-01-17T11:02:00+00:00</updated><id>https://metaredux.com/posts/2025/01/17/a-simpler-way-to-deal-with-java-sources-in-cider</id><content type="html" xml:base="https://metaredux.com/posts/2025/01/17/a-simpler-way-to-deal-with-java-sources-in-cider.html"><![CDATA[<p>For ages dealing with Java sources in CIDER has been quite painful.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> Admittedly,
much of the problems were related to an early design decision I made to look for
the Java sources only in the classpath, as I assumed that would be easiest way
to implement this. Boy, was I wrong! Countless of iterations and refinements to
the original solution later, working with Java sources is still not easy.
<a href="https://github.com/clojure-emacs/enrich-classpath">enrich-classpath</a> made
things better, but it required changes to the way CIDER (nREPL) was being started
and slowed down the first CIDER run in each project quite a bit, as it fetches
all missing sources at startup. It’s also a bit trickier to use it with
<code class="language-plaintext highlighter-rouge">cider-connect</code>, as you need to start nREPL together with <code class="language-plaintext highlighter-rouge">enrich-classpath</code>.
Fortunately, my good friend and legendary Clojure hacker <a href="https://github.com/alexander-yakushev">Oleksandr
Yakushev</a> recently proposed a <a href="https://github.com/clojure-emacs/cider/pull/3769">different
way</a> of doing things and today
I’m happy to announce that this new approach is a reality!</p>

<p>There’s an exciting new feature waiting for you in the latest CIDER MELPA build. After
updating, try turning on the new variable <code class="language-plaintext highlighter-rouge">cider-download-java-sources</code>
(<code class="language-plaintext highlighter-rouge">M-x customize-variable cider-download-java-sources</code> and then toggle to enable
it). Now CIDER will download the Java sources of third-party libraries for Java
classes when:</p>

<ul>
  <li>you request documentation for a class or a method (<code class="language-plaintext highlighter-rouge">C-c C-d C-d</code>)</li>
  <li>you jump to some definition (<code class="language-plaintext highlighter-rouge">M-.</code>) within a Java class</li>
</ul>

<p>Note that <code class="language-plaintext highlighter-rouge">eldoc</code> won’t trigger the auto-download of Java sources, as we felt this might
be harmful to the user experience.</p>

<p>This feature works without <code class="language-plaintext highlighter-rouge">enrich-classpath</code>.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>  The
auto-downloading works for both tools.deps and Leiningen-based projects. In both
cases, it starts a subprocess of either <code class="language-plaintext highlighter-rouge">clojure</code> or <code class="language-plaintext highlighter-rouge">lein</code> binary (this is the same
approach that Clojure’s 1.12 <code class="language-plaintext highlighter-rouge">add-lib</code> utilizes).</p>

<p>And that’s it! The new approach is so seamless that it feels a bit like magic.</p>

<p>This approach should work well for most cases, but it’s not perfect. You
might have problems downloading the sources of dependencies that are not public
(i.e. they live in a private repo), and the credentials are non-global but under
some specific alias/profile that you start REPL with. If this happens to you,
please report it; but we suspect such cases would be rare.  The download usually
takes up to a few seconds, and then the downloaded artifact will be reused by
all projects. If a download failed (most often, because the library didn’t publish
the <code class="language-plaintext highlighter-rouge">-sources.jar</code> artifact to Maven), CIDER will not attempt to download it again
until the REPL restarts.  Try it out in any project by jumping to
<code class="language-plaintext highlighter-rouge">clojure.lang.RT/toArray</code> or bringing up the docs for
<code class="language-plaintext highlighter-rouge">clojure.lang.PersistentArrayMap</code>.</p>

<p>Our plan right now is to have this new feature be disabled by default in CIDER
1.17 (the next stable release), so we can gather some user feedback before
enabling it by default in CIDER 1.18.  We’d really appreciate your help in
testing and polishing the new functionality and we’re looking forward to hear if
it’s working well for you!</p>

<p>We also hope that other Clojure editors that use <code class="language-plaintext highlighter-rouge">cider-nrepl</code> internally (think Calva,
<code class="language-plaintext highlighter-rouge">iced-vim</code>, etc) will enable the new functionality soon as well.</p>

<p>That’s all I have for you today! Keep hacking!</p>

<p><strong>P.S.</strong> The <a href="https://forms.gle/H24Z1Yk79mGAnAHn8">State of CIDER 2024 survey</a> is still open and it’d be great if you took a moment to fill it in!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>You need to have them around to be able to navigate to (definitions in) them and improved Java completion. More details <a href="https://github.com/clojure-emacs/orchard?tab=readme-ov-file#dealing-with-java-sources">here</a>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>If you liked using <code class="language-plaintext highlighter-rouge">enrich-classpath</code> you can still continue using it going forward. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="CIDER" /><category term="Clojure" /><category term="Emacs" /><category term="Java" /><summary type="html"><![CDATA[For ages dealing with Java sources in CIDER has been quite painful.1 Admittedly, much of the problems were related to an early design decision I made to look for the Java sources only in the classpath, as I assumed that would be easiest way to implement this. Boy, was I wrong! Countless of iterations and refinements to the original solution later, working with Java sources is still not easy. enrich-classpath made things better, but it required changes to the way CIDER (nREPL) was being started and slowed down the first CIDER run in each project quite a bit, as it fetches all missing sources at startup. It’s also a bit trickier to use it with cider-connect, as you need to start nREPL together with enrich-classpath. Fortunately, my good friend and legendary Clojure hacker Oleksandr Yakushev recently proposed a different way of doing things and today I’m happy to announce that this new approach is a reality! There’s an exciting new feature waiting for you in the latest CIDER MELPA build. After updating, try turning on the new variable cider-download-java-sources (M-x customize-variable cider-download-java-sources and then toggle to enable it). Now CIDER will download the Java sources of third-party libraries for Java classes when: you request documentation for a class or a method (C-c C-d C-d) you jump to some definition (M-.) within a Java class Note that eldoc won’t trigger the auto-download of Java sources, as we felt this might be harmful to the user experience. This feature works without enrich-classpath.2 The auto-downloading works for both tools.deps and Leiningen-based projects. In both cases, it starts a subprocess of either clojure or lein binary (this is the same approach that Clojure’s 1.12 add-lib utilizes). And that’s it! The new approach is so seamless that it feels a bit like magic. This approach should work well for most cases, but it’s not perfect. You might have problems downloading the sources of dependencies that are not public (i.e. they live in a private repo), and the credentials are non-global but under some specific alias/profile that you start REPL with. If this happens to you, please report it; but we suspect such cases would be rare. The download usually takes up to a few seconds, and then the downloaded artifact will be reused by all projects. If a download failed (most often, because the library didn’t publish the -sources.jar artifact to Maven), CIDER will not attempt to download it again until the REPL restarts. Try it out in any project by jumping to clojure.lang.RT/toArray or bringing up the docs for clojure.lang.PersistentArrayMap. Our plan right now is to have this new feature be disabled by default in CIDER 1.17 (the next stable release), so we can gather some user feedback before enabling it by default in CIDER 1.18. We’d really appreciate your help in testing and polishing the new functionality and we’re looking forward to hear if it’s working well for you! We also hope that other Clojure editors that use cider-nrepl internally (think Calva, iced-vim, etc) will enable the new functionality soon as well. That’s all I have for you today! Keep hacking! P.S. The State of CIDER 2024 survey is still open and it’d be great if you took a moment to fill it in! You need to have them around to be able to navigate to (definitions in) them and improved Java completion. More details here. &#8617; If you liked using enrich-classpath you can still continue using it going forward. &#8617;]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">State of CIDER Survey (2024)</title><link href="https://metaredux.com/posts/2024/12/23/state-of-cider-2024.html" rel="alternate" type="text/html" title="State of CIDER Survey (2024)" /><published>2024-12-23T12:48:00+00:00</published><updated>2024-12-23T12:48:00+00:00</updated><id>https://metaredux.com/posts/2024/12/23/state-of-cider-2024</id><content type="html" xml:base="https://metaredux.com/posts/2024/12/23/state-of-cider-2024.html"><![CDATA[<p><strong>TL;DR</strong> You’ll find the survey <a href="https://forms.gle/H24Z1Yk79mGAnAHn8">here</a>.</p>

<p>It’s been a while since the first and only “State of CIDER” survey.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> Right
after it happened in the end of 2019, the world went to shit and I kind of
forgot about my intent to do the survey annually.  5 years later, it’s high
time we get back on track!</p>

<p>CIDER has changed a lot in the past 5 years. nREPL has changed a lot. The development tooling Clojure
ecosystem has changed a lot. Even Emacs has changed a lot. I’m guessing your usage of CIDER has changed a lot as well. If you’re still
using Clojure and CIDER today, that is…</p>

<p>You can find the new survey <a href="https://forms.gle/H24Z1Yk79mGAnAHn8">here</a>.
We’ve made several updates to the questions - most notably there’s now a question about how frequently are you using certain CIDER features.</p>

<p>I’ve been thinking a lot lately that perhaps we went overboard with the feature-set in CIDER and that it might be prudent to trim the fat
in CIDER 2.0, but we need data, so we can accurately know what’s being used and what’s not. I’ve also been thinking that mentioning many of
the less known features in the survey might provoke some people to try them out. We’ll see.</p>

<p>There are other important questions that I like to get answers for, e.g.:</p>

<ul>
  <li>Can we drop support for Emacs 26 (and maybe even Emacs 27)?</li>
  <li>Can we drop support for Java 8?<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></li>
  <li>Do people think that CIDER improved in the last year?</li>
  <li>How often are people upgrading their CIDER installation?</li>
  <li>What problems are users encountering? What would they like to see added/changed/improved?</li>
  <li>Are people willing to support the project in one way or another?<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup></li>
  <li>Is Figwheel still a thing in ClojureScript?</li>
</ul>

<p>Your responses will also be instrumental in shaping up the roadmap for CIDER 2.0.</p>

<p>Last time around we got 545 responses and I hope this time around we’ll do a bit
better, as more responses mean that the data we got is more accurate. The new
survey is off to a pretty slow start - less than 200 responses in the first
week. It will likely stay open till the end of January, so I hope we are going
to get 500+ responses in total this around time as well.</p>

<p>Thanks for taking the time to fill in the survey! This means a lot to me and our
team! I’d really appreciate it if you shared the survey on your social media
profiles, so more people see it and take part in it. Let’s make CIDER better together!</p>

<p>That’s all I have for you today. Keep hacking!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="https://metaredux.com/posts/2019/11/02/state-of-cider.html">https://metaredux.com/posts/2019/11/02/state-of-cider.html</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Who am I kidding here… I’m well aware we’ll be stuck supporting it for all eternity… <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>The financial support the project has received eroded quite a lot in the last couple of years, which was somewhat disappointing given all the work that went into CIDER and its ecosystem. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bozhidar Batsov</name></author><category term="posts" /><category term="CIDER" /><category term="Emacs" /><category term="Clojure" /><category term="Survey" /><summary type="html"><![CDATA[TL;DR You’ll find the survey here. It’s been a while since the first and only “State of CIDER” survey.1 Right after it happened in the end of 2019, the world went to shit and I kind of forgot about my intent to do the survey annually. 5 years later, it’s high time we get back on track! CIDER has changed a lot in the past 5 years. nREPL has changed a lot. The development tooling Clojure ecosystem has changed a lot. Even Emacs has changed a lot. I’m guessing your usage of CIDER has changed a lot as well. If you’re still using Clojure and CIDER today, that is… You can find the new survey here. We’ve made several updates to the questions - most notably there’s now a question about how frequently are you using certain CIDER features. I’ve been thinking a lot lately that perhaps we went overboard with the feature-set in CIDER and that it might be prudent to trim the fat in CIDER 2.0, but we need data, so we can accurately know what’s being used and what’s not. I’ve also been thinking that mentioning many of the less known features in the survey might provoke some people to try them out. We’ll see. There are other important questions that I like to get answers for, e.g.: Can we drop support for Emacs 26 (and maybe even Emacs 27)? Can we drop support for Java 8?2 Do people think that CIDER improved in the last year? How often are people upgrading their CIDER installation? What problems are users encountering? What would they like to see added/changed/improved? Are people willing to support the project in one way or another?3 Is Figwheel still a thing in ClojureScript? Your responses will also be instrumental in shaping up the roadmap for CIDER 2.0. Last time around we got 545 responses and I hope this time around we’ll do a bit better, as more responses mean that the data we got is more accurate. The new survey is off to a pretty slow start - less than 200 responses in the first week. It will likely stay open till the end of January, so I hope we are going to get 500+ responses in total this around time as well. Thanks for taking the time to fill in the survey! This means a lot to me and our team! I’d really appreciate it if you shared the survey on your social media profiles, so more people see it and take part in it. Let’s make CIDER better together! That’s all I have for you today. Keep hacking! https://metaredux.com/posts/2019/11/02/state-of-cider.html &#8617; Who am I kidding here… I’m well aware we’ll be stuck supporting it for all eternity… &#8617; The financial support the project has received eroded quite a lot in the last couple of years, which was somewhat disappointing given all the work that went into CIDER and its ecosystem. &#8617;]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://metaredux.com/assets/og-image.png" /><media:content medium="image" url="https://metaredux.com/assets/og-image.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>