# Changelog

<!-- Entries are one line per item and section headings repeat for every release,
     so the line-length and duplicate-heading rules don't fit this file. -->
<!-- markdownlint-disable MD013 MD024 -->

## master (unreleased)

### New features

- [#2160](https://github.com/bbatsov/projectile/pull/2160): Add `projectile-find-file-in-sibling-projects` (`s-p n f`) and `projectile-search-in-sibling-projects` (`s-p n s`), which work across the family of related projects rather than just the one you're in.
  - Both are built on `projectile-find-file-in-projects` and `projectile-search-in-projects`, which take any list of projects, so a command for a group of your own is a two-line wrapper.
  - A group search puts every match in one `*projectile-search*` buffer, named relative to the directory containing the group, so each one is labelled with the project it came from.
- [#2165](https://github.com/bbatsov/projectile/pull/2165): A subproject now has its own project type, so the `s-p c m` lifecycle commands build a monorepo member with the member's own toolchain - a Rust crate or Go module under a JavaScript repository runs `cargo test` or `go test` rather than the repository's `npm test`. New `projectile-subproject-type`.
  - A member identified by the same manifest as the repository keeps the repository's type: a pnpm or yarn workspace member holds only a `package.json` and would otherwise fall back to plain `npm`.
- [#2166](https://github.com/bbatsov/projectile/pull/2166): Subprojects now come from the workspace's own member list when the repository declares one - pnpm, npm/yarn/bun, Cargo and `go.work` - instead of from scanning for manifests, so test fixtures and excluded crates stop showing up as subprojects. Babel's repository goes from 205 to its declared 162. New `projectile-subproject-functions`.
  - Build tools that compute their members rather than declaring them (Gradle, Bazel) keep using the scan, which is why it remains the fallback.
- [#2163](https://github.com/bbatsov/projectile/pull/2163): Add `projectile-switch-to-buffer-in-sibling-projects` (`s-p n b`), `projectile-multi-occur-in-sibling-projects` (`s-p n o`) and `projectile-todos-in-sibling-projects` (`s-p n t`), so buffers and annotations follow the same family as files and searches.
  - `projectile-switch-to-buffer-in-projects` joins the two existing generic commands, and `projectile-todos` now shares one implementation with its group form.

### Changes

- [#2179](https://github.com/bbatsov/projectile/pull/2179): `projectile-session-autosave` now defaults to `t`. `projectile-session-restore-on-switch` reads what autosave writes, so with the save off by default `projectile-session-mode` restored layouts it had never recorded and did nothing until you saved one by hand.
- [#2160](https://github.com/bbatsov/projectile/pull/2160): `projectile-switch-sibling-project` moved from `s-p n` to `s-p n p`. `s-p n` is now the prefix for every command that works across related projects, with each key mirroring the project-wide one a level down, the way `c m` does for subprojects.
- [#2168](https://github.com/bbatsov/projectile/pull/2168): Search results are redrawn at most every `projectile-search-render-interval` while streaming, instead of on every chunk. The buffer is redrawn from scratch, so drawing per chunk cost roughly chunks times matches - two thirds of a sibling-group search went on redrawing. A search across 18 projects drops from 0.32s to 0.18s, and across 122 from 4.8s to 2.8s.
- [#2164](https://github.com/bbatsov/projectile/pull/2164): A search across several projects now uses ripgrep, one run per project, instead of falling back to the Emacs Lisp scanner. The candidate file list is also only computed when something is going to scan it, so the ripgrep path no longer pays for a directory walk it never reads.

### Bugs fixed

- [#2178](https://github.com/bbatsov/projectile/pull/2178): The file-extension filter of `projectile-replace` and friends is now shell-quoted. ag received it unquoted, so a `*.el` filter reached it as the regexp `.el$` and also matched files ending in `model` or `panel`; on the other tools an extension containing a quote broke the command outright.
...
...
