Commit Graph
2773 Commits
Author SHA1 Message Date
Kirill Bulatov 77d716d5ce Keep first match selecting during type on search (#63375)
Follow-up to https://github.com/zed-industries/zed/pull/62506

Before:


https://github.com/user-attachments/assets/19f6f0df-c5e3-417e-a351-13a09ccb726b

After:


https://github.com/user-attachments/assets/0b302ed7-a98d-4db4-81bc-d67f5cc7db87


* Fixes type on search not selecting the very first result as the
regular search does.
* Unifies the flicker freezing state better in the editor

Release Notes:

- N/A
2026-08-31 11:41:34 +00:00
Kirill Bulatov 6dc2206180 Reduce LLVM IR bloat in closure funnels (#63426)
Follow-up to https://github.com/zed-industries/zed/pull/63232

Cuts closure monomorphization in settings and editor: settings file
updates now share one boxed write-pipeline instantiation instead of
inlining the `SettingsContent` clone, both `serde_json::to_value` calls,
and the JSON diff at every call site; `Editor::register_action` and the
settings enum dropdown get the same treatment. Behavior and public
signatures are unchanged; thin generic shims remain.

Symbol table of the release binary:
Before: `update_settings_file_inner` 229 instantiations, inlined
`serde_json` `SerializeMap` machinery 6547 copies
After: 3 instantiations, 673 copies (-89.7%); `render_dropdown` is no
longer instantiated at all

With sccache disabled, `cargo clean` and `cargo build --release -p zed`:
Before: zed binary 420677880 bytes
After: zed binary 396999464 bytes (-5.6%, -23.7MB)

Release Notes:

- N/A
2026-08-29 22:51:20 +00:00
Cole Miller 9cdbece495 Normalize ranges returned by language servers in more cases (#63372)
Previously, we'd panic when constructing multibuffer excerpts in
response to "find all references" if a language server returned a
reversed range. This PR makes it so we normalize those ranges using the
existing `range_from_lsp` helper before passing them to
`set_excerpts_for_path`. It also replaces several other places where we
were calling `point_from_lsp` on each endpoint of a range separately
with `range_from_lsp`.

Closes ZED-79W

Co-authored-by: Mikayla <mikayla@zed.dev>

Release Notes:
- Fixed a crash with some languages servers when handling
`editor::FindAllReferences`.
2026-08-28 18:06:41 +00:00
951357a916 editor: Add language detection for untitled buffers (#61412)
# Objective

Closes #4868.

Reintroduce automatic language detection for user-created untitled
buffers without allowing it to override language choices made by users
or owning surfaces.

More details:
+ https://github.com/zed-industries/zed/pull/61201
+ https://github.com/zed-industries/zed/pull/61351

## Solution

VS Code distinguishes between inferred and explicitly selected
languages, and only continues automatic detection in the former state.
This change introduces a buffer-local opt-in flag with the same purpose.
It defaults to disabled and is enabled only for user-created untitled
buffers and restored untitled buffers that did not persist a language.
Choosing a language through the language picker disables detection,
while automatically detected languages remain eligible for later
redetection. Buffers whose language is assigned by their owning surface,
such as Channel Notes, never opt in.

Rather than adding persisted state or changing the database schema,
restoration reuses the existing optional serialized language. An
opted-in buffer that remains Plain Text is serialized without a language
and resumes detection after restoration. Once automatic detection has
selected a language, that language is serialized normally and
restoration leaves detection disabled, effectively treating it as an
explicit selection. This also matches VS Code's effective default after
restoration.

Candidate selection adopts VS Code's confidence-group filtering. Results
below the minimum confidence are discarded, and candidate groups are
accepted only after a clear confidence gap. The detector then selects
the first available Zed language without eagerly loading every
candidate. I then added a separate switching rule: Zed keeps the current
language unless another candidate has a clear confidence advantage,
reducing language changes as model scores fluctuate during editing.
Model inference runs off-thread on a bounded sample, and stale results
are discarded.

I also evaluated penalizing YAML and using stricter global switching
thresholds, but neither reliably resolves the ambiguity between Markdown
and YAML. In the reproduction from #61351, Betlang assigns YAML more
than 80% confidence during editing and peaks around 90%. This is
reasonable from the content alone: `#` denotes a YAML comment, while `-`
denotes a sequence item. Adding ordinary prose or a fenced code block
shifts the model strongly toward Markdown. A fixed penalty would overfit
this example and risk suppressing legitimate YAML detection. Since
known-language buffers do not opt in and manual language selection takes
precedence, I consider this level of ambiguity acceptable and prefer not
to introduce language-specific score tuning.

Model inference itself is fast. As noted in #61201:

> In release builds on Linux with an Intel Core i5-13600KF, the
`betlang::detect` call alone typically completes within 3 ms when
processing the maximum sampled input.

The main concern is the work surrounding inference. Without debouncing,
rapid typing creates a snapshot and launches a background detection task
on every keystroke, while the detected language may change before the
user has finished typing. This change therefore adds a 200 ms debounce
delay, allowing detection to run and update the language only after the
user pauses.

## Testing

Automated coverage verifies that short inputs remain Plain Text,
sufficient Rust content is detected as Rust, replacing it with Go
content triggers redetection, and manually selecting Plain Text prevents
subsequent automatic changes. Restoration coverage verifies that a
stored language keeps detection disabled, while an empty language-less
untitled buffer resumes detection.

Beyond the automated tests, I manually tested automatic language
detection while editing untitled buffers.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase


https://github.com/user-attachments/assets/103fc731-e12e-48d6-ae89-03978f1c9d74




---

Release Notes:

- Added automatic language detection for untitled buffers.

---------

Co-authored-by: Max Stevens <maxstevens2708@gmail.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
2026-08-28 13:19:29 +00:00
Sean WoodandChristopher Biscardi a0608b889d feat: Add reveal buffer if already open (#63306)
# Objective

Fixes #12572

## Solution

- Adds an opt-in `reveal_if_open` setting which enables searching and
revealing an already open buffer
- Ensures this only happens if there is no pane target for the open
intent

## Testing

- Built for and tested on my Mac
- Tests added covering the scope of the feature

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase


https://github.com/user-attachments/assets/cdcc78cd-85fd-4b56-b562-feba375ecd03

---

Release Notes:

- Added configuration to reveal buffers already open in a different pane
instead of the active pane, via `reveal_if_open`

---------

Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
2026-08-28 11:51:00 +00:00
Saber OueslatiandKirill Bulatov bb3b7953fe editor: Auto-refresh Bookmarks tab when bookmarks change (#56363)
[## Context

Fixes a bug where the Bookmarks tab, opened via `editor: view
bookmarks`, showed a stale snapshot and had to be reopened to display
bookmarks added or removed while it was open.

Closes #56268

`view_bookmarks` built a one-time multibuffer and never subscribed to
`BookmarkStore`. The store also calls `cx.notify()` while resolving
serialized bookmarks into anchors, even though that bookkeeping does not
represent a user-visible bookmark change. Observing all notifications
would therefore feed resolution notifications back into the refresh
mechanism and cause redundant cancellation and requeue work. The store
now emits a dedicated `BookmarkStoreEvent::BookmarksChanged` from
bookmark mutation paths, while `resolve_all` deliberately does not emit
it.

Refresh state lives on a `BookmarksView` entity that holds the tab's
multibuffer. Split editors already share that multibuffer, so they share
the view as well. Each store event drives one reconciliation regardless
of how many split editors display it. The view remains alive as long as
any split retains it, so closing the original tab does not stop the
remaining split from refreshing.

Each refresh reconciles excerpts per path instead of rebuilding the
multibuffer: `set_excerpts_for_path` updates files that still contain
bookmarks, while `remove_excerpts` removes files whose final bookmark
was deleted. This follows the per-path reconciliation pattern used by
project diff views.

`view_bookmarks` creates the tab synchronously and populates it
asynchronously, following the existing patterns in
`ProjectDiagnosticsEditor::deploy` and
`ProjectSearchView::existing_or_new_search`. Repeated invocations focus
the existing Bookmarks tab instead of opening duplicates.

Video of the manual test:

[Screencast from 2026-05-11
02-03-38.webm](https://github.com/user-attachments/assets/8ac97245-09ff-4a79-9634-20cb8dfbb7eb)

## How to Review

**`crates/project/src/bookmark_store.rs`**

Adds `BookmarkStoreEvent::BookmarksChanged`, emitted from bookmark
mutation paths such as toggle, label edit, file rename or deletion,
clear, and deserialization, but not from anchor resolution. It also adds
`BookmarkStore::is_empty`.

**`crates/editor/src/bookmarks.rs`**

Adds `BookmarksView`, which holds the multibuffer, store subscription,
and in-flight refresh task. It reconciles excerpts and emits
`BookmarksViewEvent::Populated(ranges)` for per-editor highlights and
cursor placement. It also caches the latest populated ranges and replays
them when an editor attaches, allowing a split created after population
to display bookmark highlights immediately.

**`crates/editor/src/editor.rs`**

Adds the shared `bookmark_view`, a per-editor subscription to its
population events, and `bookmark_initial_selection_pending` for initial
cursor placement. `Editor::clone` attaches the split to the shared view
instead of creating another store subscription and refresh task.

**`crates/editor/src/editor_tests.rs`**

Adds five tests covering automatic addition and removal across multiple
files, removal of a file's path after its final bookmark is deleted,
initial cursor placement, a bookmark change racing initial population,
splitting while population is pending, cached highlights in a
late-attaching split, and continued refreshing after the original tab
releases its view handle.

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed Bookmarks tab not updating when bookmarks are added or removed
while the tab is open](https://github.com/zed-industries/zed/pull/56363)

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-27 23:28:05 +00:00
Kirill Bulatov 28c7f0cd8e Enable project search on type by default (#62506)
Closes https://github.com/zed-industries/zed/issues/9318

Most of the diff is tests.

Notable behavior changes during this mode, compared to current mode:

* unsaved changes in multi buffer won't spawn any "save or not" pop-ups
during typing — submitting the query still does it, as before.
Unsaved files will stay so after being sorted out on typing: we cannot
save them by default as file-less buffers need a save modal; Zed should
already be able to persist and restore such changes on restart.

* gutter may jump during search, if new excerpts with large line numbers
appear during query input — yet it would not shrink back to avoid
excessive flickering and rewraps

Release Notes:

- Enabled project search on type by default (use `{ "search": {
"search_on_type": false } }` to restore the previous behavior)
2026-08-26 14:33:03 +00:00
Austin Cummings 5a4473f92a editor: Repaint gutter immediately when bookmarks change (#62847)
Closes #61005

The bookmark store notified on every change, but nothing was listening.
Editors only repainted their bookmark icons because the toggle actions
happened to notify the editor directly - so workspace::ClearBookmarks,
which never touches an editor, left stale icons in the gutter until
something else caused a repaint.

Now editors observe the bookmark store, so any change repaints them.
This also fixes toggling a bookmark in one split not updating another
split showing the same file.

Release Notes:

- Fixed bookmarks not disappearing from the gutter immediately when
running `workspace::ClearBookmarks`.
2026-08-24 20:01:46 +00:00
Matei OpreaandKirill Bulatov 5d473cc6af editor: Prevent auto save formatting on read only files (#62921)
# Objective

Read-only marked files in zed could still be affected by format on save
feature. This PR fixes that.
FIXES #62899 

## Solution

These changes add an early return on Editor's `Item::save`
implementation so neither formatting nor the write to disk occurs.

## Testing

I've tested by reproducing the issue in the original ticket. 

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed read-only files being formatted and saved when `format_on_save`
is enabled

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-21 13:19:58 +00:00
Anıl Zeybek 1829879ca1 workspace: Persist recent navigation history across sessions (#55034)
Saves the recent navigation history (up to 20 entries) to the workspace
DB so it survives restarts. When reopening a workspace, persisted paths
that resolve to the current project are merged into the file finder's
history, deduplicated against files already opened in the session.


https://github.com/user-attachments/assets/3d8934e1-0da6-4445-8f3d-acc5597d7ac8

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes: https://github.com/zed-industries/zed/issues/56271

Release Notes:

- Improved file finder history to include recently opened files from
previous sessions.
2026-08-20 11:27:03 +00:00
Nikita Demin 459fe185a4 editor: Add in_preview boolean context for keybindings (#61777)
# Objective

- Add an `in_preview` context that is available when the current editor
is in preview mode (opened from project panel or go to definition).
- closes https://github.com/zed-industries/zed/discussions/61765

## Solution

- In `editor.rs`, added a check in `key_context()` that detects if the
editor is the active preview item in its pane, and if so, adds
`"in_preview"` to the key context.
- Uses existing `workspace.pane_for_item_id()` and
`pane.is_active_preview_item()` methods — no new APIs introduced.

## Testing

- Added two tests in `editor_tests.rs`:
- `test_in_preview_context_added_when_in_preview_mode` — verifies
`in_preview` is present when editor is set as preview item.
- `test_in_preview_context_not_added_when_not_in_preview_mode` —
verifies `in_preview` is absent for regular (non-preview) tabs.
- Tested on Linux.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Added `in_preview` keybinding context for when an editor is in preview
mode.
2026-08-19 21:35:38 +00:00
Kirill Bulatov c1dab7a0d3 Support blaming parent revisions (#62614)
Closes https://github.com/zed-industries/zed/discussions/42583

Adds more tooltip entries and `editor::BlameRevision`,
`editor::BlamePreviousRevision` actions to use.
Started to highlight gutter blame entries that belong to currently
annotated commit.


https://github.com/user-attachments/assets/ba754e0b-6431-407c-8d79-2f8b0324fde1


Release Notes:

- Supported blaming parent revisions
2026-08-14 20:24:13 +00:00
Bennet Bo Fenner a5234566b4 editor: Treat blank rename as no-op (#62630)
Confirming an inline rename after deleting the entire symbol name or
entering only whitespace currently submits an invalid rename request to
the language server. This can remove the symbol text instead of leaving
the source unchanged.

Treat empty and whitespace-only replacements as successful no-ops after
dismissing the inline rename UI. Returning a completed task also
consumes the confirmation action, preventing Enter from propagating back
into the editor. Non-blank rename behavior remains unchanged.

The regression test covers both empty and whitespace-only rename fields,
verifying that no LSP rename request is sent and the original buffer
remains intact.

Release Notes:

- editor: Fixed confirming a blank symbol LSP-rename modifying the
source code
2026-08-14 13:53:21 +00:00
Som TripathiandKirill Bulatov dda3143f2c editor: Align selections by display position instead of byte column (#61997)
# Objective

Fixes #60192
Closes https://github.com/zed-industries/zed/issues/62308

`editor: align selection` lines cursors up by their buffer column, and
that column counts bytes. If a multi-byte character sits before the
cursor, the byte column is larger than the position the cursor is
actually drawn at, so the row gets padded with the wrong number of
spaces.

The issue reports it with `←` (3 bytes) and `π` (2 bytes):

```
a ← 1  # one
bc ← π  # two
```

Put a cursor on each `#`, run the action, and the result is still
misaligned:

```
a ← 1    # one
bc ← π  # two
```

This is not the columnar selection bug fixed in #57097. That one was
`select_columns` in `selection.rs`, where the output is a selection
range. This one is `align_selections` in `editor.rs`, where the output
is inserted spaces, so the same byte-column assumption was left behind
in a second place, and fixing it here needs a rounding step that the
first fix did not.

## Solution

Measure each cursor by its x offset in the laid-out display row
(`DisplaySnapshot::x_for_display_point`), take the target for a column
as the furthest x across the rows, then turn the difference into whole
spaces by dividing by the advance width of `' '`. The offset that
carries into later columns becomes an x offset instead of a column
count.

The display map has already expanded tabs by the time the row is laid
out, so a leading tab now counts as its expanded width instead of as a
single byte.

Two things I would look at first in review:

- The division rounds instead of truncating. The x offsets are built by
repeated float addition, so a gap that should be exactly three spaces
can arrive as 2.9999998, and truncating inserts two.
- The function returns early if the space advance is missing or zero.
Dividing by zero gives `inf`, which saturates to a huge `u32` and then
tries to allocate that many spaces.

I did not add any public items and did not touch `selection.rs`.

## Testing

`cargo test -p editor align` on Windows: 6 passed, 0 failed. That is the
new test plus the two existing `align_selections` tests, which I did not
change and which still pass.

`test_align_selections_with_multibyte_chars` covers the repro from the
issue, a second column whose offset has to carry past a multi-byte
character in the first, a leading tab, a non-BMP character, and a case
where multi-byte characters sit after the cursors and nothing should
move.

I also checked that the test catches the bug rather than just passing:
reverting the change in `editor.rs` and keeping the test makes it fail
on the repro, inserting four spaces where three are right. Putting the
change back makes it pass. The two older align tests pass either way,
since they are pure ASCII.

What I have not covered:

- Wide CJK characters, combining marks, and ZWJ clusters. These should
be right by construction, since the code measures advances rather than
counting characters, but I have no tests for them. The headless text
system behind `gpui::test` gives every BMP character the same advance,
so a test there would assert the test double's behavior rather than the
real renderer's.
- Proportional fonts. Aligning with inserted spaces cannot be exact when
glyph widths vary. The code rounds to the nearest whole space.
- Soft-wrapped rows. I measure x from the start of the wrapped row but
still group cursors by buffer row, so two cursors on one buffer row that
sit either side of a wrap boundary get measured from different origins,
and the carried offset crosses that boundary as if they shared one. The
old byte-column code did not have that particular failure. I left it
alone because fixing it is a different change, but I would rather flag
it than have you find it.
- I work on Windows and have no macOS machine. The arithmetic is
platform independent, so I do not expect a difference, but I have not
checked.

To try it: paste the two lines from the issue, put a cursor on each `#`
with `editor: select next`, then run `editor: align selection`. The two
`#` should line up.

## Self-Review Checklist:

- [ ] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed `editor: align selections` misaligning rows and Vim `ctrl-d` /
`ctrl-u` / `ctrl-f` leaving the cursor behind on lines with multi-byte
characters or tabs.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-14 00:20:27 +00:00
Ibrahim KhanandKirill Bulatov 3e19851f8f editor: Keep the cursor before text inserted by on-type formatting (#61823)
## Why

`textDocument/onTypeFormatting` edits that insert or replace text at an
empty cursor use its right bias and move it past the new text. In paired
tags, pressing Enter can therefore leave the cursor on the closing tag
instead of between the tags.

## What

- Capture a left-biased pin for each empty cursor before requesting
on-type formatting.
- Skip cursor tracking unless a matching language server advertises the
trigger.
- Restore only unchanged empty cursors whose displacement is fully
covered by formatting transaction ranges, so intervening user edits are
preserved.
- Reset vertical movement state when restoring a cursor.

## Testing

- `cargo test -p editor test_on_type_formatting` (5 passed)
- `./script/clippy -p editor`

## References

- Fixes https://github.com/zed-industries/zed/issues/61574

Release Notes:

- Fixed the cursor being moved past text inserted or replaced at its
position during on-type formatting.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-12 18:14:00 +00:00
Apoorva VermaandKirill Bulatov 0d952edd5a text_finder: Highlight the query as a regex when the regex filter is on (#61128)
the buffer search and project search bars both already load the `regex`
language and put it on their query buffer when the regex filter is on.
the text finder never got that, so a regex you type in there is just
plain text.

did the same thing here. the only slightly annoying part was that the
picker's head editor is `pub(crate)`, so text_finder couldn't get at it.
added a small `query_editor()` accessor to `Picker` for that.
`adjust_query_regex_language` mirrors the two existing ones.

test asserts the query buffer's language is regex with the filter on,
and gone once it's off.

Closes #59945.

Release Notes:

- Improved the text finder by highlighting the query as a regex when the
regex filter is on

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-08-08 14:03:54 +00:00
William Whittakeranddino b40afd1905 vim: Fix insert above auto-indentation (#52594)
Fixes InsertLineAbove (Shift + O) auto-indent handling by deciding
whether to trim the first character or the last character based on
direction. Previously, inserting a line above would auto format the line
the cursor was originally on and not the new line (instead of the
correct behavior which is to do the opposite).

No tests because I couldn't find any Vim-specific auto-indent tests and
this only affects Vim mode. If I'm missing something there LMK and I'll
take a closer look.

Closes #52588.

Release Notes:

- Vim: Fixed auto-indentation for insert above action.

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-08-04 11:45:33 +00:00
Mikayla MakiandBen Kunkle 0500fd9ee9 git: Add diff_base setting for showing changes since the default branch (#61501)
# Objective

Let git indicators — the editor gutter, file colors, and `git::Diff` —
show all changes on the current branch relative to its merge base with
the default branch, instead of only uncommitted changes.

Supersedes #60398; thanks to @samuelcolvin for the original
implementation and motivation.

Closes FR-135

## Solution

- New `git.diff_base` setting (`"head"` | `"default_branch"`), applied
live and toggleable per session from the editor controls menu ("Diff
Against Default Branch").
- Statuses come from a real merge-base-to-worktree tree diff (`git diff
--merge-base`), so local edits that revert branch changes correctly show
as unchanged.
- `GitStore` shares one `DiffBufferList` per repository with the Branch
Diff view; `repo_snapshots` and `project_path_git_status` keep returning
index/worktree truth, while display surfaces use separate `display_*`
APIs.
- `BufferDiff` now records what its base is (`DiffBaseKind`); hunks
whose base isn't HEAD are read-only in the gutter — stage/restore
buttons and keybindings are inert, so committed work can't be silently
rewritten.
- `git::Diff` follows the setting; new `git::DiffHead` always opens the
HEAD diff; `git::BranchDiff` is renamed `git::DiffBranch` (deprecated
alias kept).

Tradeoffs / known limitations:

- Hunk-level staging is unavailable while in `default_branch` mode
(whole-file staging via the git panel still works). Staging just the
uncommitted sub-ranges of a branch hunk is a follow-up.
- Remote hosts running an older server ignore the new
`GetTreeDiff.includes_worktree` proto field and degrade to
committed-changes-only branch diffs.
- Repositories with no resolvable default branch fall back to
HEAD-relative behavior; a failed first resolution retries on the next
branch-list change.

## Testing

- Real-git-repo tests for the merge-base-to-worktree diff's edge cases:
files recreated after index deletion, committed deletions recreated on
disk, and symlinks.
- GPUI tests for status semantics (a branch change reverted on disk
shows clean), `git::Diff` routing, live setting changes, and read-only
hunk enforcement (restore/stage leave buffer and index untouched).

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Git: Added a `git.diff_base` setting (`"head"` or `"default_branch"`)
that makes the editor gutter, file colors, and diff view show all
changes on the current branch since its merge base with the default
branch, instead of only uncommitted changes.

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2026-07-31 19:57:13 +00:00
AidanVandLukas Wirth f22500a71b editor: Add multiple_selections key context (#60018)
# Objective

- I would like to have the Vim command `z z` do different actions
depending on if I have multiple selections. If I only have one selection
I want `z z` to center my only selection (current behavior); however, if
I have multiple selections I would like `z z` to run
`editor::OpenSelectionsInMultibuffer`. This PR does not add this
specific functionality (happy to be convinced otherwise), but it does
let users add this type of functionality.

## Solution

- Add a new key context field that is active only when there are
multiple selections.

## Testing

- Changes are quite small. A test on this would really be testing other
parts of the code-base more than this change.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase



https://github.com/user-attachments/assets/2559e218-d6fa-492a-949b-f4ab8b880f28


This allows us to add something like the following to the `keymap.json`:

```json
  {
    "context": "VimControl && !menu && multiple_selections",
    "bindings": {
      "z z": "editor::OpenSelectionsInMultibuffer",
    },
  },
```

which lets us change the functionality of a keystroke based on if there
are multiple selections.

This video has the following keystroke sequence:

`z z` (Center the cursor normally)
`5 g l` (Select the 5 next occurrences of the word under the cursor)
`z z` (Open selections in multi-buffer) (Previously `z z` in this
context would just center the last selection)


https://github.com/user-attachments/assets/a0dc1813-5420-4cda-a1ec-99e6681680e7

---

Release Notes:

- Added `multiple_selections` keystroke context

Co-authored-by: Lukas Wirth <lukas@zed.dev>
2026-07-31 06:49:53 +00:00
Finn Eitreim d73ad3de55 gpui: Give divs (the option for) a better scrolling experience (#61797)
# Objective

Closes #56127

Right now there is an issue where in certain contexts, specifically GPUI
div elements, horizontal scrolling w/ a trackpad works very poorly, even
when trying to scroll sideways, vertical scrolling will happen.

This happens with both a trackpad and scrollwheel. The showcase video
also shows the broken behavior.

## Solution

The way that scrolling works in the editor is really nice, scrolls are
locked to the axis they started on but with enough force can change
axis. so by taking the ongoing scroll handler from the editor and moving
it up into GPUI, we can get that same functionality for GPUI.

I somewhat "take over" the functionality of the existing
`restrict_scroll_to_axis` property, because it seems like its purpose
was basically trying to fix this problem already, just unsuccessfully.
The alternative, and would make things overall nicer to look at, would
be to tie this to `allow_concurrent_scroll`, but the effect radius tied
to that option is way bigger, so im holding off on that atleast right
now.

## Testing

Theres a good number of scroll related tests generally, so I don't think
i've perturbed any common existing behaviors. attach the functionality
to `restrict_scroll_to_axis` really limits the surface. There are also
some new tests for the ongoing_scroll behaviors.
Tested on my mac w/ both trackpad and mouse. 

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase

Video show casing all the behaviors:
broken w/ trackpad
working w/ trackpad
broken w/ scroll
working w/ scroll



https://github.com/user-attachments/assets/1935cd2d-a255-4a77-81d5-daa9f72470a6


---

Release Notes:

- markdown_preview: Fix horizontal scrolling inside certain elements
2026-07-30 16:30:13 +00:00
Julien RoncagliaandMrSubidubi b4f0eaf03f theme: Specify color format and pattern in schema (#49136)
## Purpose

While developing a theme for Zed I remarked that the schema available
doesn't mark colors in a way that Zed recognize to display the color
annotations:

```json
{
  "$schema": "https://zed.dev/schema/themes/v0.2.0.json"
}
```
<img width="119" height="190" alt="Screenshot 2026-02-25 at 23 15 10"
src="https://github.com/user-attachments/assets/3f1bb703-cb26-4630-9598-3a7cb8873c20"
/>

But Zed has support for it when colors are marked with `"format":
"color"` in the schema:

<img width="127" height="186" alt="Screenshot 2026-02-25 at 23 14 58"
src="https://github.com/user-attachments/assets/1a9387a4-613a-4cf8-a3af-f6ac201bdf54"
/>

So I searched if the schema file was Open Source somewhere, discovered
it was generated from the codebase and attempted the change.

## Implementation

This is essentially done using a `ThemeColor` wrapper for the color
strings that implements `JsonSchema` with a dedicated regex for
validation and the color format specified. This ends up with a new
`$defs` of `Color` being specified and used:

```json
{
  "$defs": {
    "Color": {
      "type": "string",
      "format": "color",
      "pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
    }
  }
}
```

## Other

- There is a small change I made for testing to the schema_generator
that adds an `--output` / `-o` flag. When provided it writes the
generated schema JSON to the specified file path instead of printing to
stdout. This was done to made testing easier but I can remove it or
split it to a separate PR (It's already a separate commit)
- For this PR to do anything a new schema version will need to be
published at something like `https://zed.dev/schema/themes/v0.3.0.json`
and documentation needs to be updated to point to it.

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing (Manual testing, couldn't find any existing good place to test
it)
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- N/A

---------

Co-authored-by: MrSubidubi <finn@zed.dev>
2026-07-29 20:59:24 +00:00
guopenghuianddino 8d0742b017 Fix adding breakpoint/bookmark via gutter context menu using the wrong row (#59269)
# Objective

Fixes #59265

## Solution

Use `display_point_to_anchor` to properly convert `DisplayRow` to
`Anchor`, instead of manually constructing `Point` directly as done
currently.

## Testing

- Tested manually, see video in issue
- Tested on windows

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase


<details>
  <summary>Click to view showcase</summary>

My super cool demos here

</details>

---

Release Notes:

- Fixed the gutter context menu adding breakpoints/bookmarks to the
wrong row in multibuffers.

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
2026-07-24 12:20:06 +00:00
Kirill BulatovandFinn Evers aa1fd6bff0 Calculate buffer chunks lazily (#61523)
<img width="1728" height="1084" alt="image"
src="https://github.com/user-attachments/assets/a560b10a-6e26-43ff-b830-c528e2dc6798"
/>

Before, each edit in a 50 MB plaintext file would trigger a lot of
anchor calculations (as chunk is 50 lines only) done on main thread +
did extra work when no language grammar or brackets were available.

The PR now moves all anchor calculations into `computed_chunks:
Mutex<HashMap<usize, RowChunk>>,` cache miss.
`TreeSitterData` is wrapped in `Arc` and shared as a part of the
snapshot, hence the need for `Mutex` and internal mutability here.

Trace after the changes:

<img width="1728" height="1084" alt="image"
src="https://github.com/user-attachments/assets/cb258980-8461-4559-b725-aef63c835e60"
/>


Release Notes:

- Improved input performance in large files

---------

Co-authored-by: Finn Evers <finn@zed.dev>
2026-07-23 13:36:40 +00:00
Kirill Bulatov 336679c8e1 Fall back to file names in breadcumbs with LSP symbols (#61511)
Closes https://github.com/zed-industries/zed/issues/60905

Also makes the breadcrumbs to update on settings change — before, one
needed to focus them.

Release Notes:

- Improved breadcrumbs for `"document_symbols": "on"` case when no LSP
data is sent
2026-07-23 11:35:26 +00:00
Tautik AgrahariandKirill Bulatov 756e764b90 project: Track inlay hint / code lens / document symbol registrations by ID (#55340)
extends the precedent set by #43703 (thanks @reflectronic) so that
`textDocument/inlayHint`, `textDocument/codeLens`, and
`textDocument/documentSymbol` correctly track multiple dynamic
registrations by id. previously each register call overwrote the slot on
`ServerCapabilities`, and unregister either silently did nothing
(inlayHint, documentSymbol — no match arm) or wiped the entire
capability (codeLens). now each method keeps its own id-keyed map on
`DynamicRegistrations`; the field on `ServerCapabilities` is cleared
only when the last registration is removed.

textDocument-sync notifications (`didChange`/`didSave`/`willSave`) are
deliberately out of scope — their fan-out semantics are ambiguous in the
spec and were flagged on @smitbarmase's earlier exploration in #36876.

verified with `cargo check -p project -p lsp -p editor`, `cargo test -p
project --test integration -- multi_registration` (3/3 passing), and
`cargo fmt -p project`.

closes part of #37838.

Release Notes:

- Improved support for language servers that dynamically register inlay
hints, code lens, or document symbols multiple times.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-23 07:53:30 +00:00
ᴀᴍᴛᴏᴀᴇʀ 24058c8659 editor: Fix right-click context menus failing to appear at pixel-snapped scroll positions (#61348)
# Objective

Fixes #56136.

The issue was initially reported while an agent was generating code.
Later reports reproduced it during manual editing and with AI disabled,
ruling out the agent as the cause.

At fractional display scales, the editor's right-click context menu
could fail to appear at specific discrete scroll positions. Scrolling
one line at a time could make the menu alternate between hidden and
visible, even when its anchor remained within the viewport.



## Solution

The editor-specific changes in #54728 started pixel-snapping the
vertical scroll position used by `EditorElement` to derive and render
visible rows. However, `Editor::display_to_pixel_point` continued using
the raw scroll position for its visibility check and vertical
projection.

When a downward pixel snap crossed an integer display-row boundary,
`EditorElement` treated the preceding row as the visible range start.
`display_to_pixel_point` then rejected that row as being above the raw
viewport. Mouse context menu layout returned early before inspecting the
actual clicked anchor, leaving the menu state present without rendering
its element.

This change applies the same line-height and display-scale pixel
snapping in `display_to_pixel_point`. Its visibility check and
coordinate projection now use the coordinate space actually rendered by
the editor.

A test-support-only scale-factor setter was also added so GPUI tests can
exercise fractional display scaling without depending on the host
display.

## Testing

Added a GPUI regression test using 100 plain-text lines so the editor
can scroll. The test uses a `1.25` scale factor and a `14px` font with
`1.3` relative line height. The resulting `18.2px` line height is
rounded to `18px`, producing exactly `22.5` device pixels per row.

At a raw scroll position of one row, midpoint-toward-zero snapping maps
`22.5` device pixels to `22`, or approximately `0.978` rows. This
reproduces the old boundary mismatch where the snapped visible range
starts at row zero while the raw visibility check starts at row one.

The test pins these values with precondition assertions. Row five and an
in-bounds click keep the actual source visible, while checking the
rendered bounds of the `Copy` item ensures the test does not pass merely
because menu state was created.

Manually verified that scrolling from the start of a document no longer
makes the context menu alternate between hidden and visible.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase

Before:


https://github.com/user-attachments/assets/e14c030f-1587-4172-aed2-fecfbfcb65ed


After:



https://github.com/user-attachments/assets/3080db1e-46eb-4e20-a619-b1608f233668



---

Release Notes:

- Fixed editor right-click context menus intermittently failing to
appear at certain scroll positions.
2026-07-22 19:17:25 +00:00
Ruslan Semagin 185c6986da Add gutter action to clear run status (#61375)
# Objective

Add a way to manually clear completed run statuses from the gutter.

Folow-up to #61095 

This follows up on feedback from the previous gutter run status PR.
Currently, editing a file clears run statuses automatically, but there
was no direct way to clear a completed status without changing the file.

## Solution

- Added a `Clear Run Status` entry to the gutter context menu.
- Show the entry only when the row has a completed run status.
- Clear the stored run status for that runnable when selected.
- Keep running statuses unchanged, so this does not behave like task
cancellation.

## Testing

- Ran `cargo check -p editor`.
- Manually ran a test from the gutter and waited for a completed status.
- Verified right-clicking the gutter icon shows `Clear Run Status`.
- Verified selecting `Clear Run Status` clears the status icon.
- Verified the action is not shown for rows without a completed run
status.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable


[after.webm](https://github.com/user-attachments/assets/1ae284e1-03b1-4842-a63e-9d66c290b325)

---

Release Notes:

- Improved gutter run statuses by allowing completed statuses to be
cleared from the gutter context menu.
2026-07-22 09:03:13 +00:00
saberoueslati b7e1f5026b editor: Disable gutter breakpoint and bookmark actions in unsaved buf… (#61310)
## Context

Closes #58818

Breakpoints and bookmarks are keyed by a buffer's absolute file path. In
an unsaved (untitled) buffer there is no worktree file, so both
`BreakpointStore::toggle_breakpoint` and
`BookmarkStore::toggle_bookmark` early-return and do nothing. The gutter
still offered the affordances, so clicking (or cmd-clicking) the gutter
hover button, or picking an entry from the gutter right-click menu,
silently did nothing.

Rather than support these actions on unsaved buffers, this hides them:
the gutter hover button and the gutter context menu are both suppressed
for buffers without a worktree file, matching the store-level
eligibility check (`project::File::from_dyn(...).is_some()`). The buffer
is resolved per row via `anchor_to_buffer_anchor`, so multibuffers with
a mix of saved and unsaved excerpts behave correctly.

Manual test after the changes :

[Screencast from 2026-07-19
18-46-26.webm](https://github.com/user-attachments/assets/d1fe6704-3843-49bb-bcd6-d84ecdd4f19d)


## How to Review

**`crates/editor/src/element/mouse.rs`**

In the gutter hover-button computation in `mouse_moved`, the existing
`anchor_to_buffer_anchor(...).is_some()` guard is tightened to also
require the resolved buffer to have a worktree file. When the row
belongs to an unsaved buffer the button state stays `None` and the
debounce task is never armed, so the add-breakpoint/add-bookmark button
no longer appears. This is the single writer of `gutter_hover_button`,
and it recomputes on every mouse move, so a buffer that later gets saved
picks up the button again immediately.

**`crates/editor/src/editor.rs`**

`set_gutter_context_menu` now binds the multibuffer snapshot once,
computes the effective anchor, and returns early when that anchor's
buffer is not file-backed, so no menu is opened. This is the shared
choke point for all three ways the menu can open (gutter background
right-click, breakpoint-marker right-click, bookmark-marker
right-click), so every store-backed entry (Set/Unset Breakpoint,
log/condition/hit-condition, Enable/Disable, Add/Remove Bookmark, Edit
Bookmark, Run to Cursor) and the file-meaningless Git Blame entry are
all suppressed together. `gutter_context_menu` itself is unchanged.

**`crates/editor/src/editor_tests.rs`**

Adds a shared `build_gutter_hover_test_editor(saved)` helper that builds
either a saved-file editor or an untitled-buffer editor (via
`Project::create_buffer`), plus small helpers that draw the window and
simulate a mouse move / right-click over row 0 of the gutter hitbox.
Four tests cover both surfaces on both buffer kinds:
`test_gutter_hover_button_shown_for_saved_buffer` /
`test_gutter_hover_button_hidden_for_unsaved_buffer` (asserting the
hover button state and its activation debounce), and
`test_gutter_context_menu_shown_for_saved_buffer` /
`test_gutter_context_menu_hidden_for_unsaved_buffer` (asserting
`mouse_context_menu` opens only for the saved buffer). The saved-buffer
tests act as positive controls so the negative tests cannot pass
vacuously.

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed the gutter offering breakpoint and bookmark actions in unsaved
buffers, where they could not take effect
2026-07-22 08:28:46 +00:00
Counterfeit IQandKirill Bulatov 8c1364c8ca Fix toggling diagnostics off not allowing to toggle them back (#60963)
# Objective

This change fixes an issue where once a single file has had it
diagnostics disabled, it will permenently make re-enabling diagnostics
in that specific file, no longer possible by either command or keybind.
This fixes issue #60958.

## Solution

This solution is quite simple. The logic used for registering the action
in the editor used a one way flip. The editor read the `cx` and then
checked its `diagnostics_enabled()` and `inline_diagnostics_enabled()`
and if they were disabled they would not register the corrosponding
`Editor::toggle_diagnostics` and `Editor::toggle_inline_diagnostics`
respectively. This meant once toggled off, the editor was no longer able
to register the action as it was already disabled, and thus made the
"toggle" part impossible. The fix simply removes the state checks for
the current editor and will leave the actions registered.

## Testing

This has been both manualy tested as well as had an `editor_tests.rs`
test added. Simply taking in the the `EditorTestContext`, then checks
the starting state, then toggles the diagnostics off and checks that it
correctly shows the state change, and then proceeds to re-enable the
diagnostics state, and check its again to make sure the appropriate
state has been set.
I manually tested this on windows_11_x64/x86(Desktop),
archlinux_7.0.10_x64/x86(Laptop), and it has **not** been tested on my
mac mini **yet**. However, the change 'should' be platform agnostic. If
someone wants to review this, they can simply open their settings file
with the JSONC lsp `on` and then disable their diagnostics and then, the
option to re-enable them, toggle, will now show up and also be able to
be executed by the keybinds too.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase

<details>
  <summary>Click to view showcase</summary>

Original Behaviour:
[Zed Diagnostic Toggle (Original
Behaviour).webm](https://github.com/user-attachments/assets/bca860cd-f7e9-42b9-9456-56b9b1d2604f)

New Behaviour:
[Zed Diagnostic Toggle (New
Behaviour).webm](https://github.com/user-attachments/assets/e3629491-abb5-4e29-95ab-e8f0464db726)

</details>

---

Release Notes:

- Fixed `editor::ToggleDiagnostics` & `editor: toggle diagnostics`
permanently turning off diagnostics for the current file/editor,
addressing issue #60958.

---------

Signed-off-by: Counterfit IQ <logicye@proton.me>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-21 17:28:38 +00:00
Ruslan Semagin 5f865ffd69 Show runnable task results in gutter (#61095)
# Objective

- Make runnable task results visible directly in the editor gutter after
running a test or task.
- This makes it easier to see whether the last run passed or failed
without looking at the terminal output.

## Solution

- Track the completion result for scheduled runnable tasks.
- Show the last runnable result in the gutter:
  - running task: accent play icon
  - successful task: success check icon
  - failed/cancelled task: error icon
- Apply the same status update path when running from the gutter play
button and from inline code lens actions such as `Run Test`.

## Testing

- Ran `cargo check -p editor -p workspace`.
- Ran `cargo test -p workspace
test_schedule_resolved_task_with_completion_reports_success`.
- Manually tested running a GPUI test from the gutter play button.
- Manually tested running a GPUI test from the inline `Run Test` code
lens.
- Verified the gutter icon updates after completion in both cases.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and [icon]

(https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase

Before:
<img width="1897" height="691" alt="before"
src="https://github.com/user-attachments/assets/614c2811-ee0a-43c0-8619-d0301836aa62"
/>

After:
<img width="1897" height="691" alt="after"
src="https://github.com/user-attachments/assets/a3db19f2-71e6-4c9b-824d-43a4f020a6b7"
/>

---

Release Notes:

- Improved runnable tasks by showing the last run result in the editor
gutter.
2026-07-21 05:36:42 +00:00
Sathwik Chirivelli fcd85e1bfb git_ui: Show full files by default in solo diffs (#60989)
# Objective

Make solo diff views show the full file by default while preserving an
easy way to focus on changed hunks. This addresses a recurring request
across issues and pull requests for full-file context in single-file Git
diffs.

## Solution

- Initialize the solo diff with a singleton multibuffer so the entire
file is visible on open.
- Keep the existing toolbar toggle available for switching to
changes-only excerpts.
- Use the singleton path key when replacing excerpts so toggling remains
reliable.
- Preserve Git change indicators in the scrollbar; the editor generates
those markers for singleton buffers.

## Testing

- Ran `cargo fmt -p git_ui`.
- Ran `git diff --check`.
- Ran `cargo check -p git_ui --no-default-features` successfully.
- Manually reviewed the full-file and changes-only state transitions in
`SoloDiffView`.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase

Before, solo diffs opened with only changed hunks and surrounding
context. They now open with the complete file, retain Git change
indicators in the scrollbar, and can still be toggled to changes-only
from the toolbar.

---

Release Notes:

- Improved solo diffs to show the full file by default while retaining
Git change indicators in the scrollbar.
2026-07-20 21:31:42 +00:00
Chris Biscardi 2d06fded9c Revert "editor: Add language detection for untitled buffers (#61201)" (#61351)
This reverts commit a98c7e2fa8.

# Objective

language detection is firing very often in channel notes, often picking
YAML instead of markdown, causing some language-detection flickering.

cc/ @amtoaer (author of the original PR)
2026-07-20 16:43:55 +00:00
ᴀᴍᴛᴏᴀᴇʀandMax Stevens a98c7e2fa8 editor: Add language detection for untitled buffers (#61201)
# Objective

Closes #4868.

Untitled buffers start as Plain Text and require users to select a
language manually before receiving syntax highlighting. Add lightweight
automatic language detection for code entered or pasted into untitled
buffers.

## Solution

This builds on [Max Stevens's earlier language-detection
work](https://github.com/zed-industries/zed/pull/43057), replacing
Magika with [Betlang](https://github.com/DioxusLabs/betlang).

While researching smaller and faster alternatives to Magika, I came
across Betlang, a recently introduced language detection library
developed by DioxusLabs for dioxus-code. The fact that it comes from
DioxusLabs gave me more confidence in evaluating this relatively new
dependency for Zed. Betlang embeds an approximately 50 KB model, is
MIT-licensed, and depends only on `fearless_simd`, making it well suited
to Zed's cross-platform embedding requirements.

Detection runs on the background executor with bounded input sampling.
It is restricted to untitled buffers, skips content shorter than 20
bytes, and requires at least 50% confidence. These limits have worked
well in local testing. In release builds on Linux with an Intel Core
i5-13600KF, the `betlang::detect` call alone typically completes within
3 ms when processing the maximum sampled input.

## Testing

I added a test for language detection in untitled buffers that covers
both manually entered and pasted content. The test passes successfully.
I also manually tested the feature to verify that the overall experience
works well.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase



https://github.com/user-attachments/assets/96e28ad7-2968-4325-9aff-37fe813a2da7



---

Release Notes:

- Added automatic language detection for untitled buffers.

---------

Co-authored-by: Max Stevens <maxstevens2708@gmail.com>
2026-07-20 05:12:49 +00:00
Xin Zhao 67341c7d9e editor: Fix Git blame gutter width with avatars (#61287)
# Objective

When using column Git blame with avatars enabled, blame entries whose
author name is the longest in the buffer can exceed the blame border.

For example, line 10 of `crates/vim/src/visual.rs` is displayed as
follows:

<img width="998" height="121" alt="issue"
src="https://github.com/user-attachments/assets/eff3e1ff-bd1c-42af-ae9b-da8efb0a7c22"
/>

The blame contents exceeds the width.

The root cause is in the blame width calculation:

https://github.com/zed-industries/zed/blob/4feae499a62c4ab971a47dfbbd0667e944322ee1/crates/editor/src/editor.rs#L11583-L11598
The calculation accounts for the commit SHA, author name, and timestamp.
Other elements, including spacing, margins, and the avatar, are
represented by the fixed `SPACING_WIDTH` constant.

For typical fonts, `ch_advance` is approximately `0.5rem` to `0.6rem`,
so `SPACING_WIDTH` provides approximately `2rem` to `2.4rem` for
non-text content. However, the avatar itself occupies `1rem`:

https://github.com/zed-industries/zed/blob/4feae499a62c4ab971a47dfbbd0667e944322ee1/crates/ui/src/components/avatar.rs#L81
When avatars are displayed, the entry also contains three `0.5rem` gaps
and also one `0.5rem` right margin:

https://github.com/zed-industries/zed/blob/4feae499a62c4ab971a47dfbbd0667e944322ee1/crates/git_ui/src/blame_ui.rs#L170-L188

This requires approximately `3.0rem`, which can exceed the space
provided by `SPACING_WIDTH`. When an entry contains both the longest
author name in the buffer and a long timestamp, its content can
therefore exceed the blame border.

## Solution

The simplest fix would be to increase `SPACING_WIDTH`, but that would
still rely on an approximate conversion between editor character widths
and UI dimensions.

Instead, this PR adds a method to the blame renderer for calculating the
non-text width of a blame entry. The editor uses this value together
with the measured text width when calculating the final blame width.

## Testing

Tested locally. A before-and-after comparison is included below.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

## Showcase

| Before | After |
| :--: | :--: | 
| <img width="551" height="94" alt="Before"
src="https://github.com/user-attachments/assets/b6741a41-6531-4fae-adaa-f9ae0b298e0f"
/> |<img width="566" height="93" alt="After"
src="https://github.com/user-attachments/assets/e8d75d2a-6b07-43f6-b2a8-bfb76d118611"
/> |

Release Notes:

- Fixed Git blame entries overflowing the gutter when avatars are
displayed.
2026-07-20 02:50:00 +00:00
Xin Zhao 1625b90fd1 Preserve Markdown emphasis delimiters when joining lines (#61298)
# Objective

When joining lines, Zed checks the next line and strips comment,
documentation-comment, and unordered-list delimiters. The logic trims
whitespace from these delimiters, then checks whether the next line
starts with the trimmed delimiter. If it does, Zed removes the delimiter
before joining the lines.

This works for comment and documentation-comment delimiters, where
trailing whitespace does not affect their meaning. However, it causes
unexpected behavior for unordered-list delimiters, which, as far as I
know, are unique to Markdown.

In Markdown, `* ` is an unordered-list marker, while `*` is also used as
an emphasis delimiter, such as `*italics*` and `**bold**`. The current
logic strips the leading `*` from these emphasis cases, which it should
not.

## Solution

For unordered-list delimiters, Zed should strip the exact delimiter,
such as `* `, rather than the trimmed `*`. It should strip a bare `*`
only when the next line contains only `*`.

## Testing

Tested locally and new GPUI tests were added.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed markdown emphasis delimiters being removed when joining lines.
2026-07-20 02:03:51 +00:00
Daan De Meyer 7eaddbc5d9 editor: Blink cursors only in the focused editor (#61086)
Every editor associated with a window observed window activation. The
handler enabled the blink manager for every editor, including hidden and
unfocused editors. Their independent 500 ms timers invalidated the
window out of phase and caused redundant full-window presents.

Window activation and deactivation are already represented as focus
transitions by GPUI: an inactive window has an empty effective focus
path. Remove the redundant activation observer and rely on the editor
focus and blur handlers to stop blinking on deactivation and restart it
only for the editor that owns focus on activation.

In a 40-second idle diagnostic run before this change, the steady-state
tail repeatedly contained invalidations from one or two editors per
frame. After the change, no unfocused-editor invalidations appeared.
Bounded scrollbar fades and visible activity animations remain
unchanged.

Add a regression test with focused and unfocused editors that covers
activation, deactivation, and reactivation.

Release Notes:

- Fixed cursors blinking in unfocused editors, reducing idle redraws.

---------

Signed-off-by: Daan De Meyer <daan@amutable.com>
2026-07-16 11:43:27 +00:00
David 919ec316f3 search: Add LSP location pickers for references, definitions, and diagnostics (#59838)
# Objective

Closes #59829

Provide a filterable, preview-backed picker for LSP results as an
alternative to the multi-buffer view, for references, definitions,
implementations.

## Solution

Update the 3 existing LSP actions (definitions, implementations, find
all references) to add a `open_results_in` parameter which accepts
either `multi_buffer` (default) or `picker` to show the results in a
filterable picker with preview. This behavior can be configured globally
in the settings via `lsp_results_location`.

UX:

- The 3 existing LSP actions each accept a `open_results_in` parameter
so that each action can be configuring individually with a custom
keybind
- The `lsp_results_location` global setting can be used to set a default
behavior with `open_results_in == None`
- Go to definition falls back to find all references (if configured) on
empty results which is consistent with the non-picker path
- Results are grouped by file; each row shows the line number and the
syntax-highlighted source line with the match emphasized.
- Typing filters by line text or path; the preview updates with the
selection.
- Enter/click opens the selection, `cmd/ctrl-enter` opens it in a split,
and re-invoking the command toggles the picker closed.
- Empty results show a toast so the command never silently does nothing.
- Note: the new pickers do not open on cmd-click, only when invoked via
the command palette or keybind

## Testing

- No automated tests yet — holding for first-round feedback on the
approach and UX before adding tests.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable

## Showcase


https://github.com/user-attachments/assets/41538f23-9b54-4dfc-bfa7-a61564a675a8

---

Release Notes:

- The find all references, go to definitions, and go to implementations
LSP actions can be configured to open results in a picker with preview
instead of a multibuffer.
2026-07-15 14:36:43 +00:00
Ben Kunkle 27a3512d00 Classify edit prediction lifecycle triggers (#60983)
# Objective

Closes EP-89

- Replace ambiguous `Other` edit prediction telemetry for known editor
lifecycle events.

## Solution

- Classify editor creation, provider changes, user information changes,
Vim mode changes, and settings changes through the existing trigger
pipeline.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- N/A
2026-07-15 13:14:36 +00:00
Apoorva VermaandKirill Bulatov 87c805c61e Use buffer line numbers when copying file locations (#60781)
# Objective

Fixes #54250

`editor: copy file location` copies the row you're on in the
multi-buffer, not the row in the actual file. In a git diff view with
collapsed lines it copies the wrong line number.

## Solution

It read the rows straight off the selection, which is in multi-buffer
coordinates. `ClipboardSelection::for_buffer` already handles this with
`range_to_buffer_range`, so I used the same thing. Path and line now
come from the same buffer.

`range_to_buffer_range` returns nothing when the selection ends in a
different buffer than it starts in, which you can do in a git diff view.
Rather than copy nothing, it falls back to the cursor's buffer.

## Testing

Three tests: a multi-buffer excerpt, a selection dragged across two
files, and a plain single-file editor. The multi-buffer ones fail on
main; the singleton one passes either way, so normal editors are
unaffected.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed `editor: copy file location` copying the wrong line number in
multibuffers
([#54250](https://github.com/zed-industries/zed/issues/54250)).

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-13 10:51:59 +00:00
Lukas Wirth d9316bbcfd Invalidate hover state when a multibuffers paths change (#60443)
Fixes a panic when multibuffer paths change under a cursor hover
Fixes ZED-9W1
Closes FR-112

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-07-09 09:20:36 +00:00
Neel 883bb315fd editor: Use raw head selection for rename (#60594)
Follow up to https://github.com/zed-industries/zed/pull/55542, which
reused the shifted offset for the rename input's *initial selection*,
cutting it one character short.

<img width="524" height="512" alt="image"
src="https://github.com/user-attachments/assets/37032614-2cfd-4ad4-9005-f2eac57924a1"
/>
<img width="435" height="158" alt="image"
src="https://github.com/user-attachments/assets/7b1b9c52-08d6-48ce-928a-873f6e175f65"
/>

---

Release Notes:

- Fixed symbol rename in vim mode omitting the last character of the
symbol out of the rename input's initial selection
2026-07-08 14:19:58 +00:00
Guilherme TavaresandKirill Bulatov 1abef8fadf Suggest language extensions for untitled buffers (#55263)
Fixes #53527.

## Summary

- Suggest `untitled.<extension>` when saving an untitled editor buffer
with a selected non-Plain Text language.
- Preserve the existing title-based suggestion for existing files, Plain
Text buffers, and buffers without a language extension.
- Add a regression test for an untitled Rust buffer suggesting
`untitled.rs`.

## Testing

- `mise exec rust@1.95.0 -- cargo fmt --check -p editor`
- `mise exec rust@1.95.0 -- cargo test -p editor
test_suggested_filename_uses_language_extension_for_untitled_buffer
--lib`

## Suggested .rules additions

None.

Release Notes:

- Fixed Save As suggestions for untitled buffers with a selected
language.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-08 12:29:04 +00:00
48192372a0 Git partially staged changes (#46541)
This PR explores the addition of a new feature and UI to improve
visibility into partially staged commits.

Currently, the Git panel shows tracked and untracked changes, but it
does not clearly distinguish between staged and unstaged changes.

As a result, it’s difficult to quickly see which changes are not staged
in the current UI. Both staged and unstaged changes are combined into
the `Uncommitted Changes` multibuffer. This developer experience differs
from other editors, most notably VS Code; which presents separate Staged
Changes and Changes lists.

### Staged and unstaged diffs in multibuffers

This PR introduces an alternative UI for unstaged changes that aligns
with the overall Zed experience. Instead of showing changes on a
per-file basis, staged and unstaged diffs are each displayed in their
own multibuffers, similar to how `Uncommitted Changes` currently works.

For example the following screenshot shows the current `Uncommitted
Changes` on the left, the `Staged Changes` in the middle and the
`Unstaged Changes` buffer on the right for comparison

<img width="1408" height="859"
src="https://github.com/user-attachments/assets/aa709f7a-041d-4cb1-95d6-84c0f5fff688"
/>

### Indicators/interactions

The new multibuffers can be opened in two ways:

1. Via a new `U` chip, which appears when a file has unstaged changes
2. Via new menu options

(See screenshots below for both interaction paths.)


<table>
  <tr>
    <td style="text-align: center; vertical-align: top;">
      <p>via the chip</p>
      <img
        height="400"

src="https://github.com/user-attachments/assets/3ef69f02-b787-499c-959a-25f50b3728e8"
        alt="Via the chip"
      />
    </td>
    <td style="text-align: center; vertical-align: top;">
      <p>via the menu</p>
      <img
        height="400"

src="https://github.com/user-attachments/assets/f5be8b6d-ccdc-4420-bd29-75570b558016"
        alt="Via the menu"
      />
    </td>
  </tr>
</table>

### Design goals
- minimally intrusive UI changes (small new badge and menu items)
- adhere by Zed'ism (use multibuffer where possible)
- avoid disabling any current interactions (Uncommitted Changes ui is
unchanged)
- avoid introducing an app level view mode (no new settings needed)

### Experience goals
- make it easy to see what changes are not staged
- make it easy to see that a file has unstaged changes (avoid developers
accidently leaving out changes in a commit; a personal issue that I have
when using Zed)
- elegantly handle large file's unstaged changes (follows the same
collapse and expanding seen in `Uncommitted Changes`)

### How to try

- Clone the repo and run `cargo run`
- Make a change to a file and stage it
- Make another change to the file (the `U` indicator will appear)
- Click the `U` to see the unstaged view

### Open questions/rough edges
- [ ] determine if this user experience is useful for others
- [ ] ensure all interactions work as expected (response to all update
cases)

In general I'm really interested in hearing the community's feedback
about this interface, more than happy to make any changes or explore a
different solution!

### Related issue:
- https://github.com/zed-industries/zed/pull/36646
- https://github.com/zed-industries/zed/issues/26560

Release Notes:

- Support partially staged commit multibuffers via a staged and unstaged
changes view.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cole Miller <cole@zed.dev>
2026-07-07 06:55:29 +00:00
Danilo Leal e41a55c3c0 Improve diff tabs toolbar design (#60464)
This PR adds a bunch of design improvements to the toolbar of (tab)
views that display diffs: the uncommitted changes, branch diff, and
agent diff tabs. This involves adjusting spacing, sizing, and other
small tweaks across all of these views, including touching up the
divider component API a little bit, adjusting Git icons design, adding
diff stat numbers to the uncommitted changes tab so its consistent with
the others, and more (e.g., moving the split buttons into its own
component to ensure they look the same across all uses). Ended up also
going on a slight de-tour to make all uses of the split button in the
Git panel consistent design-wise.

All in all, this is just tidying up the design of all of these surfaces
that are all relatively similar.

| Branch Diff | Uncommitted Diff | Single-file Diff | Git Panel |
|--------|--------|--------|--------|
| <img width="800" alt="Screenshot 2026-07-06 at 11  25@2x"
src="https://github.com/user-attachments/assets/4ebf87e7-c52d-41d9-9de3-7944125114a1"
/> | <img width="800" alt="Screenshot 2026-07-06 at 11  25 2@2x"
src="https://github.com/user-attachments/assets/51ccd2eb-904b-455a-a708-b4cb50b3a7cb"
/> | <img width="800" alt="Screenshot 2026-07-06 at 11  26@2x"
src="https://github.com/user-attachments/assets/6ae7df68-d1bd-4d36-a250-ba16e43c4e8e"
/> | <img width="800" alt="Screenshot 2026-07-06 at 11  26 2@2x"
src="https://github.com/user-attachments/assets/e032bc60-4551-41f0-b578-90ed305167c2"
/> |

Release Notes:

- Added diff stat numbers to the uncommitted changes view.
2026-07-06 15:46:44 +00:00
João SoaresandChris Biscardi b3acc7518a Fix blame hover popover not showing on first trigger when inline blame is disabled (#50769)
● Closes #50285

## Summary

When `inline_blame` is disabled in settings and `editor::BlameHover` is
triggered,
the blame popover fails to appear on the first invocation because
`start_git_blame`
kicks off an async task to fetch blame data, but `blame_hover`
immediately tries to
read that data synchronously before it's available.

This fix registers a one-shot observation on the blame entity when it's
freshly
created, so the popover is shown once blame data has finished
generating.

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [ ] ~Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)~
(No UI changes)

## Videos:
### Before:

https://github.com/user-attachments/assets/d2ca4f8e-8186-49af-9908-5a82bfca0de2


Ps: pressed the keybind two times

### After:

https://github.com/user-attachments/assets/08575cd9-2bbc-462d-92fa-f0e7ef23d8d6



## Release Notes:

- Fixed blame hover popover not appearing on first trigger when inline
blame is disabled (#50285)

---------

Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
2026-07-06 08:51:35 +00:00
saberoueslatiandDanilo Leal a955005b6f editor: Update gutter hover tooltip on modifier changes (#58880)
## Context

The gutter hover button can represent either adding a breakpoint or
adding a bookmark depending on whether the secondary modifier is
pressed. Previously, the visible tooltip did not update when the
modifier changed while the popover was already open. This moves the
gutter hover intent into a shared state used by both the button and
tooltip, so the label, metadata, icon, color, click action, and
displayed keybinding all stay in sync.

Closes #58821

## How to Review

`crates/editor/src/editor.rs` adds a shared gutter hover intent type and
a custom tooltip view that reads the current modifier state while
rendering. Review that bookmark and breakpoint behavior map consistently
across the button icon/color, click action, tooltip label, metadata, and
keybinding.

`crates/editor/src/editor_tests.rs` adds a regression test covering the
tooltip intent selection with and without the secondary modifier.

Manual test after the fix below :

[Screencast from 2026-06-09
01-30-23.webm](https://github.com/user-attachments/assets/ef465eb9-e659-44da-93a6-a511c84e9401)

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed the breakpoint/bookmark gutter popover not updating when
modifier keys change.

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2026-07-02 14:38:04 +00:00
Neel 27b7fc4cbb editor: Fix panic when restoring empty selections on undo/redo (#59372)
Closes FR-81.

Also updates the error log, as the linked issue is closed.

Release Notes:

- Fixed panic when restoring empty selections on undo/redo
2026-07-02 13:07:42 +00:00
6bfbd4d09d Fix relative line number calculation when the first row is wrapped (#53759)
fixes #53726
Compute the base delta from the first visible, non-filtered row instead
of using rows.start. This avoids off-by-one numbering when rows.start is
a wrapped continuation that gets filtered out. Ensure deleted lines
still advance the relative counter even when they are not numbered. Add
a test for the wrapped scrolling case.
P.S. This is my first time using rust for a serious pull request and
let's say I'm a little bit rusty with it.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #ISSUE

Release Notes:

- N/A or Added/Fixed/Improved ...

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2026-07-02 09:49:52 +00:00
Kai KozlovandKirill Bulatov 21b0a6821e editor: Add intelligent bracket colorization (#51580)
Closes #50210

Bracket colorization currently runs theme accents through
`ensure_minimum_contrast`, which can significantly alter authored
palette colors in order to satisfy a single foreground-vs-background
target. In practice, that makes rainbow brackets drift away from the
theme colors they are supposed to reflect.

This PR keeps bracket colorization as a single automatic behavior, but
changes how the palette is derived:

- preserve authored accent colors when they already work
- adjust only the specific accents that are too weak against the editor
background
- only reorder the palette when adjacent bracket levels are still too
similar after that

The implementation is staged because bracket colorization has to handle
two separate problems:

- **Bracket-vs-Background Readability**: is an individual bracket
visible against the editor background?
- **Adjacent Bracket Separation**: can you still distinguish one nesting
level from the next?

Those two constraints are also why the implementation cannot simply
defer to whatever accent colors the theme provides. Some themes,
including the bundled One and Ayu, do not define explicit accents at
all, so bracket colorization falls back to Zed's shared default accent
palette. That palette was not designed with any particular theme's
background in mind, which makes the background contrast check especially
important for those cases.

That is why the previous `ensure_minimum_contrast(..., 55.0)` path is
not enough on its own. It addresses foreground-vs-background
readability, but if lightness-only adjustment cannot satisfy that target
it escalates to saturation reduction and then black/white fallback.

This PR instead keeps the bracket-specific background fix bounded and
lightness-only in OKLCH, so the resulting color stays much closer to the
authored accent.

### How it works

- **Background Contrast Correction**: accents that fall below the APCA
floor against the editor background are adjusted by changing OKLCH
lightness only, preserving hue and chroma
- **Adjacency Correction**: if the resulting palette is still too weak
between neighboring nesting levels, the palette is reordered
conservatively to improve adjacent separation

That ordering matters. Doing the reorder first can easily be undone by
the background-fix step.

### Color measurement

- background contrast uses APCA, via the existing `apca_contrast` path
- adjacent bracket separation uses OKLab Euclidean distance

APCA is the right tool for bracket-vs-background readability, but it is
not designed to compare two foreground colors against each other. OKLab
distance is a better fit for detecting when neighboring bracket levels
are perceptually too close.

### Thresholds

- background APCA floor: `30` on dark themes, `35` on light themes
- adjacent OKLab target: `0.08` on dark themes, `0.10` on light themes
- light-theme reorder tolerance band: reorder only triggers below
`0.095`, avoiding threshold-artifact reordering on palettes that are
visually fine but narrowly miss `0.10`

### Validation

- `cargo test -p editor bracket_colorization`
- manual comparison on bundled One, Ayu, and Gruvbox theme families

Release Notes:

- Improved bracket colorization by preserving theme accent colors when
possible and applying targeted contrast fixes only when needed.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2026-07-01 17:36:23 +00:00
Yara 🏳️‍⚧️ 9177c5e747 Make the existing bookmark action add an unnamed bookmark again (#60185)
Zed don't surface the fact that bookmarks can have labels/names now
anywhere except opening the bookmark name editor every time you place
one. This keeps the label/name mechanism but makes the default add
bookmark action add an unnamed one.

Next step is probably to enable holding shift (or some other modifier)
to place a named bookmark, or even a setting to switch between default
named vs unnamed.

Release Notes:

- N/A
2026-07-01 09:34:33 +00:00