You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add reviewable read-only search commands, a search-only sibling of the reviewable replace UI.
projectile-search-review (s R) searches for a literal string; projectile-search-regexp-review (s X) searches for an Emacs regexp, honoring full Emacs regexp syntax.
Matches are gathered into a read-only *projectile-search* buffer, grouped by file, one LINE:COL: CONTEXT line per match with the matched span highlighted; there is no preview, no per-match toggle and no apply.
The buffer reuses the replace reviewer's navigation, case/regexp toggles (c/x), line and file filters (k/d/K/D), re-search (g) and grep-mode export (e).
r bridges the current search to the replace reviewer, carrying over the term, literal-ness and case setting and prompting only for the replacement.
A literal projectile-search-review accelerates its scan with ripgrep when rg is installed, streaming matches in near-instantly on large projects.
Controlled by projectile-search-use-ripgrep (default on); set it to nil to always use the pure-elisp scan.
The ripgrep fast-path follows ripgrep's ignore rules plus Projectile's ignore globs, which can differ slightly from the elisp path's file set (e.g. hidden files, symlinks); regexp search and the whole replace reviewer always use the portable elisp scan.
The commands are available from projectile-dispatch and the Projectile menu.
#1924: Add reviewable project-wide replace commands that let you preview matches and choose which to apply, instead of the blocking, file-by-file query-replace walk of projectile-replace.
projectile-replace-review (R) does a literal replace; projectile-replace-regexp-review does an Emacs-regexp replace whose replacement can reference capture groups.
Matches are gathered in Emacs Lisp, so the regexp command honors full Emacs regexp syntax and the preview reflects exactly what will be edited, including unsaved changes in open buffers.
The *projectile-replace* results buffer shows a per-file, per-match preview where each match can be toggled on or off; ! (or C-c C-c) applies just the enabled ones, in any order.
Applying edits each file from the bottom up, edits open buffers in place under a single undo step, writes closed files back preserving their coding system, and skips buffers modified since the search rather than corrupting them.
The results buffer can reshape the search in place, each action re-scanning and re-rendering the previews:
c toggles case sensitivity (seeded from case-fold-search).
x toggles between literal and Emacs-regexp matching, refusing an invalid regexp rather than erroring.
k/d keep or flush the matches whose line matches a regexp; K/D do the same by file name; re-searching with g restores anything filtered away.
A status line at the top shows the term, replacement, match and file counts, the mode flags, and a note when the list has been filtered.
e exports the shown matches to a grep-mode buffer so wgrep or Emacs 31's grep-edit-mode can turn them editable and write back; wgrep stays an optional integration and ! remains the no-dependency apply path.
Both reviewers scan the project asynchronously, so a large search no longer freezes Emacs.
The results buffer opens right away, matches stream in as they're found (the header shows a "Searching..." progress note), and the scan is cancelable with q, C-g, or by killing the buffer.
While a scan is still running, ! (apply), e (export) and the filter keys (k/d/K/D) refuse until it finishes, so the write-back never runs against a partial match set and a filter can't be outrun by a later chunk; starting a new scan (g/c/x) cancels any in-flight one.
Set projectile-replace-async to nil to force the old synchronous single-pass scan; batch runs always scan synchronously.
The commands are available from projectile-dispatch and the Projectile menu, and the match cap is customizable via projectile-replace-max-matches.
Add projectile-session-mode, a global minor mode that gives each project its own tab-bar tab.
Switching to a project selects its existing tab (restoring that project's window layout) when one is open, or otherwise opens a fresh tab named after the project and populated via projectile-session-default-action.
Same-named checkouts get distinct tab names (e.g. work/foo and home/foo); customize the scheme with projectile-session-tab-name-function.
projectile-session-switch-to-buffer completes over just the current tab's project buffers.
Sessions persist across Emacs restarts: projectile-session-save, projectile-session-restore and projectile-session-forget write a project's window layout and buffers to a file under projectile-session-directory and read it back; projectile-session-save-all saves every open project at once.
Switching to a project with a saved session restores it (gated by projectile-session-restore-on-switch); projectile-session-autosave saves sessions on switch-away and on exit.
projectile-session-restore-all reopens every saved project's session, each into its own tab (skipping projects already open and dropping stale sessions whose files are gone); set projectile-session-restore-on-startup to run it automatically at Emacs startup.
Which buffers are recorded, and how, is extensible via projectile-session-buffer-serializers; file-visiting and dired-mode buffers work out of the box.
The session commands are bound under the w sub-prefix of the command map (s-p w s, s-p w S, s-p w r, s-p w R, s-p w f, s-p w b), and are also available from projectile-dispatch and the Projectile menu.
Changes
Add projectile-frecency-max-projects (default 100), which caps how many projects' frecency history is kept so the store can't grow without bound.
projectile-replace-scan-chunk-size is now a user-facing defcustom (was an internal variable).
Advertise the right completion metadata category per command so marginalia and embark annotate and act on candidates correctly: buffer switching now uses the buffer category (so marginalia shows its rich buffer annotations), project switching uses file, and file commands keep project-file - previously every completion was hardcoded to project-file. projectile-completing-read gained a :category keyword for this.
Add whole-word matching to the reviewable search/replace: toggle it with w in the results buffer, default it with projectile-search-whole-word, or seed it for one run with the projectile-dispatch--word switch. The elisp scan fences the pattern with word boundaries and the ripgrep fast-path passes --word-regexp, so both engines agree.
Wire the reviewable search/replace into the projectile-dispatch Modifiers: the two literal/regexp search entries are folded into one sR driven by --regexp (matching how --regexp already drives the ag/ripgrep search), and a new --case-sensitive switch seeds the reviewable search/replace case-sensitive. Both can still be flipped with x/c in the results buffer.
Highlight the search tool and the default value in the search prompts, and give them one consistent Search [tool] for (default: X) format across projectile-search, projectile-grep/-ag/-ripgrep and the reviewable search. The tool that will run (grep/ag/ripgrep, or ripgrep/elisp for the reviewable search's literal fast-path) is faced with projectile-search-prompt-tool and the symbol-at-point default with projectile-search-prompt-default. The reviewable search now also shows its default up front and which engine it will use.
Bugs fixed
#1549, #1676: Re-invoke a function-valued lifecycle command (e.g. a CMake preset picker or a project type's :run/:test function) on every run instead of freezing its first result in the command cache, so it can prompt again.