Projectile 3.0
Projectile 3.0 is finally out, and it’s a big one - easily the biggest
release in years. There’s a nice reason for that: this year Projectile turns 15.1 It
all started back in the summer of 2011, simply because I was frustrated that
find-file-in-project didn’t work on Windows, and somehow that little
anniversary made me want to shake things up and finally tackle a whole pile of
changes I’d been putting off for ages. Some new features, some long-overdue
spring cleaning, and a few things I’d wanted to remove for the better part of a
decade.
What’s dead can’t die
There’s a running joke that Projectile is obsolete now that Emacs ships
project.el out of the box. I’ve heard it many times, and I even wrote about it
when Projectile turned 10 - it’s
obviously hard to compete with a built-in package, as it has a home-field
advantage you can never match.
But here’s the thing. If it’s really true that Projectile is dead and everyone
has moved on to project.el, then that’s oddly liberating. What’s dead can’t
die, right? If there are no users left to upset, I can finally go wild with my
wildest ideas and stop worrying about breaking the workflows of Projectile’s
(non-existent) users. And that’s more or less the spirit in which I approached
3.0 - I stopped being quite so precious about backwards compatibility and just
did what I felt was right for the project.
(Turns out there might still be a user or two out there after all, so do skim the migration notes below. Sorry in advance!)
The highlights
There’s a lot in this release - well over a hundred entries in the changelog - but here are the highlights I’m most excited about:
projectile-dispatch(bound tos-p m) is a newtransientmenu that mirrors the command map, so you no longer have to remember every keybinding. It also exposes command modifiers as switches, so you can toggle a regexp search, start a fresh shell, invalidate the cache, or open a result in another window/frame right from the menu.- Projectile can now index a project asynchronously, in a background process, so
a cold
projectile-find-fileno longer freezes Emacs while it walks a huge tree. The building blocks are public, so external tools can drive Projectile’s indexing asynchronously as well. - There’s a new (optional)
projectile-consultintegration built on those async data sources. Its finder streams candidates into the minibuffer as the project gets indexed, instead of blocking until indexing is done, while still honouring your VCS and indexing configuration. - The various search commands got folded into a single
projectile-search, backed by a small, extensible backend registry. It ships grep, ripgrep and ag backends out of the box, and you can register your own (deadgrep, consult-ripgrep, whatever you fancy) in a few lines. - The shell, REPL and terminal commands got the same treatment - one
projectile-runwith shell, eshell, ielm, term, vterm, eat and ghostel backends, plus a seam to plug in your own. - The indexers got a thorough going-over - batched
statcalls, single directory listings instead of dozens offile-exists-pprobes, smarter caching. It all adds up, and it really shows over TRAMP, where every needless round-trip used to hurt. I think that 15 years later I’ve finally solved Projectile’s infamous performance issues over TRAMP![^2] - I finally removed a pile of features that had outlived their usefulness - the
single-key Commander (superseded by the dispatch menu), the idle timer,
projectile-browse-dirty-projects, and all of the built-in tags support (xrefand LSP do this far better nowadays). - The minimum supported Emacs is now 28.1. That let me drop a heap of
compatibility shims and finally make
transienta proper dependency instead of an optional extra. - Projectile is a better
project.elcitizen now - it implements more of the protocol (project name, buffers, ignores), so tools built on top ofproject.elbehave correctly in Projectile-managed projects. - I also dropped the legacy
ido/ivy/helmcompletion systems - these days everything rides on the standardcompleting-read, so Vertico, Consult and friends just work.idofans are the one group that has to lift a finger: installido-completing-read+(the package formerly known asido-ubiquitous) and turn onido-ubiquitous-mode, andidowill drive Projectile’s prompts just like before. - And there’s a pile of smaller quality-of-life additions - subproject
compile/test for multi-module projects (
c m c/c m t), a%pplaceholder for the project name in command strings,projectile-add-and-switch-project, jumping back to the most recent project, and more.
Upgrading
3.0 is a major release for a reason - there are breaking changes. The minimum Emacs version is now 28.1, several long-deprecated commands and options are gone, and a couple of keybindings moved around. I’ve written a dedicated Migrating to Projectile 3.0 guide that walks through everything and how to adapt your config. Most setups will keep working untouched, but please give it a read before you upgrade.
Fifteen years later
As I said back when Projectile turned 10 - it’s always hard to compete with built-in packages. Still, I’m genuinely proud that 15 years in, Projectile is still here and, hopefully, still relevant to at least some of you. It remains one of my favourite projects and the one I reach for every single day.
Huge thanks to everyone who has contributed code, reported bugs, written extensions, or simply used Projectile over the years - none of this would exist without you. I really hope 3.0 isn’t the end of the innovation for Projectile, and that it’ll keep surprising and delighting its users for years to come.
Keep hacking!
-
Give or take - I started Emacs Prelude the same year, so it’s always been a little hard to say which of my open-source projects was truly first. In my mind it’s always been Projectile. [^2]: Famous last words… I know… ↩