Projectile 3.2 is out!1 That’s the third Projectile release thismonth, and by now you probably see the pattern - a whole lot of nothing for acouple of years, then everything at once. Where 3.0 was the big cleanupand 3.1 the pile of long-standing feature requests, 3.2 is a focusedrelease with one clear theme: search and replace. Plus one bonus feature I’vewanted for ages, but more on that below.Replace, but with a previewprojectile-replace has always been one of those commands that technicallyworked, but that I never quite trusted. It walks the project file by file withquery-replace, asking you about every match with no way to see the bigpicture, and once you start there’s no graceful way out. I’ve been promisingmyself a better story there for years (that’s #1924, if you’re keepingscore at home).3.2 finally delivers it. projectile-replace-review (s-p R) prompts for asearch string and a replacement, gathers every match across the project into a*projectile-replace* buffer, and shows you a per-match preview of exactlywhat’s about to change. Every match can be toggled on or off, and ! appliesjust the enabled ones - in any order, whenever you’re ready. Here’s the wholeflow, start to finish:The matches are gathered in Emacs Lisp rather than by shelling out to grep, soprojectile-replace-regexp-review honours full Emacs regexp syntax (yes,including \_ and capture groups in the replacement), and the previewreflects the exact text that will be edited - including unsaved changes inbuffers you already have open. The apply step is equally paranoid: files areedited bottom-up so earlier edits can’t shift later matches, open buffers get asingle undo step, and buffers modified since the scan are skipped rather thanclobbered.The results buffer is a little workbench of its own - you can toggle casesensitivity (c), flip between literal and regexp matching (x), keep orflush matches by line or by file (k/d/K/D), and export everything to agrep-mode buffer (e) if you’d rather finish the job with wgrep. And bothreviewers scan the project asynchronously, so a big search no longer freezesEmacs - matches stream in as they’re found and you can bail out at any point.Search gets the same treatmentOnce the replace reviewer existed, the obvious next question was “can I havethis without the replacing part?”. You can. projectile-search-review(s-p s R) collects every match for a term into a read-only*projectile-search* buffer, grouped by file, with the matched spanshighlighted:It shares the replace reviewer’s navigation and filtering, and pressing rhands the current search over to the replace reviewer, carrying along the termand settings and prompting only for the replacement. So “look first, replacelater” is now a single keystroke, not a re-do.My favourite touch: when rg is installed, a literal search rides ripgrep andstreams matches in near-instantly even on huge projects (customizable viaprojectile-search-use-ripgrep). The regexp variant and the replace revieweralways use the portable Emacs Lisp scan, so the preview you act on is alwaysthe real thing.A tab per projectThe bonus feature: projectile-session-mode, a global minor mode that giveseach project its own tab-bar tab. Switch to a project and Projectile eitherselects its existing tab (with the window layout you left there) or opens afresh one named after the project. Sessions can also persist across restarts -s-p w s saves a project’s layout and buffers, switching to the project canrestore it automatically, and projectile-session-restore-all brings yourwhole working set back after a restart, each project in its own tab.I’ve long envied the “workspace per project” workflows people build withtab-bar and a handful of hooks, and now Projectile just does it out of thebox. It’s opt-in, so nothing changes unless you enable the mode.Odds and endsA few smaller things that shipped alongside the headliners: The reviewable search/replace learned whole-word matching - toggle it withw in the results buffer, or default it with projectile-search-whole-word. projectile-dispatch picked up matching switches - --word and--case-sensitive seed the reviewable search/replace, the same way--regexp already did for the other search commands. All the search prompts now share one consistent format that shows the toolthat will actually run and the symbol-at-point default up front. No moreguessing whether you’re about to invoke grep or ripgrep. Projectile’s prompts now advertise the right completion metadata category percommand, so marginalia annotates candidates properly (buffers get bufferannotations, projects get file ones) and embark can act on them. Withvertico and marginalia the built-in commands look downright fancy now: Function-valued lifecycle commands (say, a CMake preset picker) arere-invoked on every run instead of having their first result frozen in thecommand cache - an old gotcha that bit CMake users in particular.Wrapping upNo breaking changes this time, and nothing to migrate - the full list ofchanges is in the changelog, as always.More importantly, 3.2 completes - for now - the arc I embarked on with 3.0.Looking back at the whole 3.x series, the mission boils down to three things: make Projectile’s internals faster, simpler and more robust modernize the UX (async everything, the dispatch menu, and now reviewablesearch and replace) and give people more reasons to prefer Projectile replace hardcoded behavior with mechanisms - backend registries, file kinds,named tasks, session serializers - that you can bend to your own workflow ina few lines of configAll three boxes feel properly ticked at this point, so the summer release burstis probably winding down.2 Projectile is in the best shape it’s been inyears, and I’m having more fun working on it than I’ve had in a long time. Hugethanks to everyone who reported issues and tested the new reviewers while theywere taking shape!Keep hacking! Technically it’s been out since July 12th, and there’s already a 3.2.1patch release, because 3.2.0 shipped with a crash in projectile-search.You polish a release for a week and then break the one command everyoneuses. Classic. ↩ Famous last words, again. I said something similar after 3.1. ↩