Meta Redux: Projectile 3.0

Wait 5 sec.

Projectile 3.0 is finally out, and it’s a big one - easily the biggestrelease in years. There’s a nice reason for that: this year Projectile turns 15.1 Itall started back in the summer of 2011, simply because I was frustrated thatfind-file-in-project didn’t work on Windows, and somehow that littleanniversary made me want to shake things up and finally tackle a whole pile ofchanges I’d been putting off for ages. Some new features, some long-overduespring cleaning, and a few things I’d wanted to remove for the better part of adecade.What’s dead can’t dieThere’s a running joke that Projectile is obsolete now that Emacs shipsproject.el out of the box. I’ve heard it many times, and I even wrote about itwhen Projectile turned 10 - it’sobviously hard to compete with a built-in package, as it has a home-fieldadvantage you can never match.But here’s the thing. If it’s really true that Projectile is dead and everyonehas moved on to project.el, then that’s oddly liberating. What’s dead can’tdie, right? If there are no users left to upset, I can finally go wild with mywildest 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 approached3.0 - I stopped being quite so precious about backwards compatibility and justdid 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 themigration notes below. Sorry in advance!)The highlightsThere’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 to s-p m) is a new transient menu that mirrorsthe command map, so you no longer have to remember every keybinding. It alsoexposes command modifiers as switches, so you can toggle a regexp search, starta fresh shell, invalidate the cache, or open a result in another window/frameright from the menu. Projectile can now index a project asynchronously, in a background process, soa cold projectile-find-file no longer freezes Emacs while it walks a hugetree. The building blocks are public, so external tools can drive Projectile’sindexing asynchronously as well. There’s a new (optional) projectile-consult integration built on those asyncdata sources. Its finder streams candidates into the minibuffer as the projectgets indexed, instead of blocking until indexing is done, while still honouringyour 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 agbackends 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 - oneprojectile-run with shell, eshell, ielm, term, vterm, eat and ghostelbackends, plus a seam to plug in your own. The indexers got a thorough going-over - batched stat calls, singledirectory listings instead of dozens of file-exists-p probes, smartercaching. It all adds up, and it really shows over TRAMP, where every needlessround-trip used to hurt. I think that 15 years later I’ve finally solvedProjectile’s infamous performance issues over TRAMP![^2] I finally removed a pile of features that had outlived their usefulness - thesingle-key Commander (superseded by the dispatch menu), the idle timer,projectile-browse-dirty-projects, and all of the built-in tags support(xref and LSP do this far better nowadays). The minimum supported Emacs is now 28.1. That let me drop a heap ofcompatibility shims and finally make transient a proper dependency instead ofan optional extra. Projectile is a better project.el citizen now - it implements more of theprotocol (project name, buffers, ignores), so tools built on top ofproject.el behave correctly in Projectile-managed projects. I also dropped the legacy ido/ivy/helm completion systems - these dayseverything rides on the standard completing-read, so Vertico, Consult andfriends just work. And there’s a pile of smaller quality-of-life additions - subprojectcompile/test for multi-module projects (c m c / c m t), a %p placeholderfor the project name in command strings, projectile-add-and-switch-project,jumping back to the most recent project, and more.Upgrading3.0 is a major release for a reason - there are breaking changes. The minimumEmacs version is now 28.1, several long-deprecated commands and options are gone,and a couple of keybindings moved around. I’ve written a dedicatedMigrating to Projectile 3.0 guide that walks through everything andhow to adapt your config. Most setups will keep working untouched, but pleasegive it a read before you upgrade.Fifteen years laterAs I said back when Projectile turned 10 - it’s always hard to compete withbuilt-in packages. Still, I’m genuinely proud that 15 years in, Projectile isstill here and, hopefully, still relevant to at least some of you. It remains oneof my favourite projects and the one I reach for every single day.Huge thanks to everyone who has contributed code, reported bugs, writtenextensions, or simply used Projectile over the years - none of this would existwithout 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 alittle hard to say which of my open-source projects was truly first. In mymind it’s always been Projectile.[^2]: Famous last words… I know… ↩