Hi everyone,
Cursive 1.12.2 is out! This one took much longer than I expected due to non-work stuff, my apologies for that. This release is also a bit messy, since I was waiting for the release of a bug-fix for IDEA-290436, which the issue stated would be in 2022.1. So I was taken by surprise by the final release of 2022.1 today without that fix, but it seems that the fix is actually in and the fixed-in build on the issue must be incorrect. So this release contains a couple of fixes that haven’t been in an EAP release, but if there are problems with them I’ll get a new build out ASAP.
This release contains a feature many have been waiting far too long for, the Optimize Imports feature for namespace sorting. This feature involved some unexpectedly large changes to some of the code formatting configuration code. The short version is that when I was young and foolish, I thought it would be a good idea to store config as EDN inside IntelliJ’s XML config files. It turns out that it wasn’t a good idea, and I haven’t been able to take advantage of a lot of improvements in IntelliJ around config file management because of this. So when you upgrade to this release you may see some code style config files switch from EDN to XML. It’s an upgrade, I promise.
There is a caveat to this change - I couldn’t make it work with IntelliJ’s config migration mechanism, so if you have to downgrade from this release for whatever reason, you’ll lose your indentation configuration. I’m sorry about this, but I couldn’t make it work.
In this release, the Optimize Imports function in IntelliJ will now update your ns form according to how you have it configured. The configuration is in the new config pane, Preferences | Editor | Code Style | Clojure | Namespaces. By default, it will make your namespaces look like Stuart Sierra’s How to ns document, but it’s possible to change this to a certain extent.
The main limitation to this at the moment is that it doesn’t handle reader conditionals well. It will work on cljc files as long as the ns declaration doesn’t contain reader conditionals, but if it does contain them then Cursive won’t touch it. I’m planning to work on this, and have it handle common cases as sensibly as it can - that will be in future releases.
Cursive will now mark requires from ns forms as unused if they’re not used anywhere in the code. Unused referred symbols will also be marked, as well as aliases which were marked previously. All of this will also be automatically cleaned up by the Optimize Imports operation.
Since require is also side-effecting, sometimes namespaces are required for their side effects even if they’re not used explicitly in the code (e.g. for loading multimethod implementations, specs and so on). clj-kondo has a convention that namespaces which have no modifiers (i.e. no :as or :refer) are treated as side-effecting requires and are not marked as unused. I’m a little uncomfortable with that much magic convention, but users seem to like it in practice so Cursive supports this by default. If you hate it you can disable it in the configuration for the “Unused require” inspection.
There are still some outstanding items to fix for the Optimize Imports functionality:
Another new feature is the ability to invoke Cursive’s visual diff from the REPL, which is something that has been requested for a while now. In REPLs where Cursive controls the startup (most Clojure & Babashka REPLs, and some CLJS ones), you can do it like this:
(cursive/diff <left> <right>)
You can also optionally provide a title for the diff:
(cursive/diff <left> <right> :title <title>)
For example:
(cursive/diff (meta #'defn) (meta #'let) :title "Metadata")
This function is really just a thin wrapper which returns a tagged literal which Cursive interprets, so if for some reason Cursive can’t inject it into your REPL automatically (e.g. when you have a Clojure REPL which gets upgraded to a CLJS one), you can do the following (and create your own function if desired, of course):
(tagged-literal 'cursive/diff {:left <left> :right <right> :title <title>})
Again, for example:
(tagged-literal 'cursive/diff {:left (meta #'defn) :right (meta #'let) :title "Metadata"})
Here the :title entry is optional. Let me know how this works, and if there are other features that would be helpful.
Apart from these features and the 2022.1 support, there are also a lot of bugfixes in this release. There are also 3 fixes that never made it into an EAP release because of the confusion described above - one bugfix where Optimise Imports would remove goog requires in CLJS, and another in completion for referred vars. The last fix adds support for multiline TODO matchers.
Here are the issues:
AddedCheers,
Colin