d4e43845fa1086512dedafdd2c852d167d005bb0
5107
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7387a146a4 |
Unify behavior of delete/cut to line boundary actions (#59627)
I noticed that our line deletion actions are inconsistent. For `DeleteToBeginningOfLine`: - `one «two threeˇ» four` -> ` four` ✅ - `one «ˇtwo three» four` -> ` four` ✅ Great, these have the same results, regardless of selection direction. For `DeleteToEndOfLine`: - `one «two threeˇ» four` -> ` one ` ✅ - `one «ˇtwo three» four` -> `one two three` ❌ Whoops, that second one should be the same, assuming that selection direction again shouldn't matter, as in the case of `DeleteToBeginningOfLine`. The same issue exists for `CutToEndOfLine`: - `The quick «brownˇ» fox` -> `The quick ` ✅ - `The quick «ˇbrown» fox` -> `The quick brown` ❌ I unified the end-of-line actions to match `DeleteToBeginningOfLine`: selection direction no longer matters, so the whole selection is always included. --- - [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: delete to end of line` to behave consistently regardless of selection direction. - Fixed `editor: cut to end of line` to behave consistently regardless of selection direction. |
||
|
|
19e85945cc |
git: Use version control colors in diff hunk line numbers (#59973)
# Objective When diff hunks are expanded, reading the line numbers can be a little hard due to the contrast between `editor.line_number` and both `editor.diff_hunk.deleted.background` and `editor.diff_hunk.added.background`. In order to make it easier for these line numbers to stand out, the actual `version_control` colors, respective to each diff hunk, can be used to color the line number. ## Solution Luckily, the line numbers color was already dynamically decided on `EditorElement::layout_line_numbers` depending on whether the line had a breakpoint or it was active (part of a selection). The information on whether the row for which the line was being laid out belonged to a diff hunk is also already available on the `Gutter::row_infos`. As such, this change was easy to achieve by simply updating `EditorElement::layout_line_numbers` to take into consideration each row's `RowInfo::diff_status` and mapping each status to a `version_control` color, ignoring the `Modified` variant, as that should never happen. ## Testing Manually tested against a repository that has added, deleted and modified changes. Differences can be seen in the `Showcase` section. ## 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) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase <details> <summary>Before</summary> <img width="2744" height="2994" alt="version_control_line_numbers_before" src="https://github.com/user-attachments/assets/75d160a7-e0cc-4c9d-8fdd-4cab5cc6eefb" /> </details> <details> <summary>After</summary> <img width="2744" height="2994" alt="version_control_line_numbers_after" src="https://github.com/user-attachments/assets/887fdb6a-34c6-4331-b750-4d3bea6fcd77" /> </details> --- Release Notes: - Improved line number colors in diff hunks to match the version control colors |
||
|
|
4a0537bc52 |
editor: Fix grammar in comment (#59951)
This is less of an actual fix as more something to test some GitHub stuff with. Release Notes: - N/A |
||
|
|
acd55213d1 |
solo_diff_view: Add git action to open file diff and other improvements (#59752)
# Objective - Polish the solo diff review UI by reducing redundant controls and hiding inactive fold controls in split diff views. ## Solution - Collapse the solo diff header's `Stage File` / `Unstage File` actions into one button that shows the action relevant to the file's current staging state. - Stop reserving fold gutter space and rendering fold crease toggles for editors with companion snapshots, matching the existing LHS split diff behavior. ## Testing - `cargo fmt --check` - `cargo check -p git_ui` ## 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, the solo diff header showed both file-level staging actions at once, and the RHS split diff gutter could show fold arrows that did not work in that view. After this change, the header shows the relevant file-level staging action and split companion panes no longer show inactive fold controls. Release Notes: - Improved solo diff controls by showing the relevant file staging action and hiding inactive fold toggles in split diffs. |
||
|
|
028ebbb43e |
editor: Fix showing completion list with selection does not include the selection (#57405)
Fix the completion list not showing the current selection when you execute `editor: show completions`, the stated reason by comment before is that if you are in a tabstop snippet already it wont give you the correct options. So my change is to just check if you are in such a snippet and if not give the new desired behavior. before: https://github.com/user-attachments/assets/1b2f3594-7361-4636-9ef3-f8c9419faa26 after: https://github.com/user-attachments/assets/1be35582-464a-40f3-b6be-ee74f9961796 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 #57386 Release Notes: - editor: include text from selection in completion list. --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com> |
||
|
|
5bf85b2149 |
text_finder: Send selected word to text finder query (#59766)
## Objective Make text finder match project search and buffer search by pre-populating its query from the active editor according to `seed_search_query_from_cursor`. ## Solution - Seed text finder from the active editor's query suggestion when opening it. - Pass the seeded query into the picker and select the query text so typing replaces it immediately. ## Testing - Manually tested visually by opening text finder from an editor with a selection and with the cursor on text, confirming the query is pre-populated and selected. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved text finder to seed its query from the active editor. Co-authored-by: ozacod <ozacod@users.noreply.github.com> Co-authored-by: Yara 🏳️⚧️ <git@yara.blue> |
||
|
|
9079f2fa95 |
Add named bookmark support (#57491)
Adds support for named bookmarks while preserving the existing unnamed bookmark workflow. Main changes: - Keeps `ToggleBookmark` as the quick unnamed bookmark action. - Adds `ToggleNamedBookmark`, which prompts for a bookmark name when adding a new bookmark and removes an existing bookmark on the same line, including unnamed ones. - Adds `EditBookmark` support for renaming existing bookmarks. - Persists bookmark names in workspace storage. - Adds a project bookmarks picker that supports filtering by bookmark name and relative path, with highlighted matches. - Updates bookmark storage and tests to carry bookmark names through serialization, restoration, navigation, and project-level listing. 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 Video toggle: https://github.com/user-attachments/assets/a725b9cf-ac37-4ebc-85cc-ee820452c043 rename: https://github.com/user-attachments/assets/a6d0d0c1-511b-4fb7-ae5d-22c55d1a075f Release Notes: - Add named bookmark support --------- Co-authored-by: Yara 🏳️⚧️ <git@yara.blue> |
||
|
|
9d696a585c |
editor: Fix Python docstring formatting in hover popovers (#59480)
# Objective Fixes #59426 Python (and possible others like JS/TS ) docstrings in hover popovers currently have broken indentation and alignment. This happens because markdown soft breaks (single newlines) are parsed and replaced with spaces by default. This collapses multi-line Python docstrings into single wraps, ruining code example layouts and line-wrapped formatting. ## Solution Configure the `MarkdownStyle` returned by `hover_markdown_style` in `crates/editor/src/hover_popover.rs` to treat soft breaks as hard breaks (`soft_break_as_hard_break: true`). This ensures single newlines in docstrings are preserved and rendered correctly in the hover popover. ## Testing - Verified hover popovers locally on Python methods/classes to confirm that multi-line docstring indentation and alignment are preserved. ## 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 Python and Markdown docstring formatting/alignment in hover popovers. --------- Co-authored-by: Martin Ye <martin@zed.dev> |
||
|
|
6a6fcbebc4 |
Add preview to pickers and make them resizable (#59604)
Overhauls Zed's pickers to make them resizable and give them a preview. Closes #8279 ### Background The most requested Zed feature has the last year has been a [Telescope like search box](https://github.com/zed-industries/zed/issues/8279) [discussion](https://github.com/zed-industries/zed/discussions/22581). To understand why this is so popular we need to understand search can serve thee goals: - Navigation: fuzzy search is faster & easier then clicking in a file tree - Exploration: example, find a function by a word in its doc comment - Collecting: example, getting a list of functions to change The project search which shows results in a multibuffer is the perfect way to operate on a list of items. Navigation and Exploration need a lot of context around each result and offer fast navigation between them. For both of these live searching is also critical. The `telescope UI` is a picker with a preview to the right or below. It's offered in various editors and IDE's most famously Neovim (through the Telescope plugin), IntelliJ (natively), Helix (natively) and of course VScode (plugins) and it's _many_ forks. While having a UI like that for text search (our project search) is most requested the UX pattern is applied widely, from `find_all_references` to `bookmarks`. It enhances most pickers. Note that we have over 50 different picker modals! The community has tried to build something like this for Zed: - https://github.com/zed-industries/zed/pull/44530 - https://github.com/zed-industries/zed/pull/45307 - https://github.com/zed-industries/zed/pull/46478 - https://github.com/zed-industries/zed/pull/43790 These all became huge PR's that we could not merge for various reasons. This is a really hard feature to integrate in Zed! This PR got started as https://github.com/zed-industries/zed/pull/46478 and supercedes that. ### Design - Extend pickers to support an optional preview with minimal changes to the pickers themselves. - Make pickers resizable. - Complement the existing search do not replace it by having both UI's share the underlying search and allow freely switching between them. - Allow extending the preview to things other then files. - Maintain a clean design on all the pickers. ### Heigh level Implementation overview - Adds an `Option<Preview>` to `Picker` - Gives `PickerDelegate` a method to communicate a preview to the Picker - Overhaul the way pickers are drawn to allow for resizing them. Implemented on the `Shape` and `SizeBouds` structs. - Adds a high level way to draw the `footer` and `editor` so we do not need to change much to the pickers. - Adds a new text finder Picker - Adds a way to take a running search from project search and hand it to the text finder Picker and the other way round - Give the file finder a preview ### Next steps A more detailed list and how to help out will be added to the tracking issue for [Pickes with previews](https://github.com/zed-industries/zed/issues/56037) - Add more previews to more pickers! - Enable selectioning multiple items in pickers and performing actions on those - Open selected items in a multibuffer - Add a way to restore the last picker - Make popovers (picker attached to some menu) resizable as 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 TODO (will be done post merge) --- Release Notes: - Added resizing via dragging to all picker modals. - Added a preview to the File finder, the preview can be to the right or below. - Added a Text finder picker with a preview as alternative project search UI. The search is shared and allowes switch between UIs while running. --------- Co-authored-by: ozacod <47009516+ozacod@users.noreply.github.com> Co-authored-by: ozacod <ozacod@users.noreply.github.com> Co-authored-by: Danilo Leal <daniloleal09@gmail.com> |
||
|
|
63c88eced0 |
workspace: Allow user to pick arbitrary parent path as a trustee (#59562)
This allows one to "bless" arbitrary parent path, without making assumptions about the structure of the project storage on users machine. ## Testing - Did you test these changes? If so, how? - Are there any parts that need more testing? - How can other people (reviewers) test your changes? Is there anything specific they need to know? - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? ## 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 > This section is optional. If this PR does not include a visual change or does not add a new user-facing feature, you can delete this section. - Help others understand the result of this PR by showcasing your awesome work! - If this PR includes a visual change, consider adding a screenshot, GIF, or video - A before/after comparison is very useful for changes to existing features! While a showcase should aim to be brief and digestible, you can use a toggleable section to save space on longer showcases: <details> <summary>Click to view showcase</summary> My super cool demos here </details> --- Release Notes: - When opening a project for the first time, you can now auto-trust arbitrary parent path; previously Zed offered affordance for auto-trusting a parent of a parent only. |
||
|
|
44487855ad |
editor: Add the git blame toggle to gutter context menu (#59460)
# Objective
- Add a quick way to toggle the **Column Git Blame** gutter directly
from the editor's gutter context menu, so users don't have to move the
cursor to the top-right corner or status bar to enable/disable blame
annotations.
## Solution
- Added a `toggleable_entry("Column Git Blame", ...)` item to the
existing gutter context menu in `crates/editor/src/editor.rs`.
- Selecting it calls `Editor::toggle_git_blame`, which flips
`show_git_blame_gutter` on or off, matching the behavior of the existing
toolbar/status-bar control.
- The entry appears as a toggleable item with the git blame icon,
reflects the current blame state, and reuses the existing
`toggle_git_blame` action/handler so behavior stays consistent with the
rest of the UI.
## Testing
- Added a unit test in `crates/editor/src/editor_tests.rs`
(`test_gutter_context_menu_git_blame_toggle`) that builds the gutter
context menu and verifies selecting the Column Git Blame entry toggles
`show_git_blame_gutter` on and then back off.
- Ran `cargo test -p editor --lib
test_gutter_context_menu_git_blame_toggle` — passes.
- Ran `./script/clippy -p editor` — clean.
- Are there any parts that need more testing? I think No — the change is
a straightforward menu hook into existing state.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
1. Right-click the gutter of any file in the editor.
2. Confirm **Column Git Blame** appears in the menu.
3. Click it — the blame gutter should appear.
4. Open the menu again and click it — the blame gutter should disappear.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test? Tested via unit tests on macOS.
No platform-specific code was added.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments — no unsafe blocks
- [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 — reuses
existing toggle handler, no extra work
## Showcase
> No visual redesign; just a new menu entry.
- Right-click the editor gutter to access the new **Column Git Blame**
toggle.
![Gutter context menu showing Column Git Blame option]
<img width="369" height="248" alt="image"
src="https://github.com/user-attachments/assets/7c83ad91-ae7e-4562-8faf-a17c8b92bdc1"
/>
and not toggled
<img width="409" height="389" alt="image"
src="https://github.com/user-attachments/assets/206a40c0-0933-4720-bc3e-5627786eae43"
/>
---
Release Notes:
- Added a git blame toggle to the gutter's context menu
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
|
||
|
|
76f258b504 |
Refactor editor's select inside/around delimiter actions (#59472)
# Objective Both https://github.com/zed-industries/zed/pull/59005 and https://github.com/zed-industries/zed/pull/53789 introduced actions, at the editor context, which allow to select the content between brackets/delimiters, with the latter also adding an action to include the brackets/delimiters too. Shipping both would mean we end up with three distinct, but similar actions: * `editor: select inside enclosing bracket` * `editor: select inside delimiters` * `editor: select around delimiters` As such, in order to simplify this, the changes in this Pull Request remove the first action, while updating the logic for both `editor: select inside delimiters` and `editor: select around delimiters` in order to support continuous outwards expansion, like `editor: select inside enclosing bracket` supported. ## Solution * Remove `editor::SelectInsideEnclosingBracket` action, it's related method and tests * Updated `editor::selection::Editor::select_delimiters_impl` to use `MultiBufferSnapshot::enclosing_bracket_ranges` instead of `MultiBufferSnapshot::innermost_enclosing_bracket_ranges` so we can traverse all bracket ranges and expand to the next one ## Testing Besides manual testing, a new test case was added specifically for the selection expansion support, namely `editor::editor_tests::test_select_delimiters_expansion`. ## 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: - N/A |
||
|
|
afa22f66fe |
editor: Add SelectInsideDelimiters and SelectAroundDelimiters actions (#53789)
## Summary
Adds two new editor actions:
- `editor::SelectInsideDelimiters`: selects the content inside the
nearest enclosing delimiters. Works for `()`, `[]`, `{}`, and string
literals (`""`, `''`, `` ` ` ``).
- `editor::SelectAroundDelimiters`: same as above, but the selection
includes the surrounding delimiters themselves.
This addresses the request in #50042
## Why not `select_larger_syntax_node`?
`SelectLargerSyntaxNode` walks up the AST one level at a time. It's an
incremental, history-aware operation: press repeatedly to expand outward
by syntax tree level. The number of presses needed to reach a specific
delimiter pair depends on the language's AST shape and is unpredictable:
sometimes one press, sometimes three, sometimes overshoot.
`SelectInsideDelimiters` is delimiter-based and stateless: one
invocation jumps directly to the nearest enclosing pair, regardless of
AST nodes. It's the equivalent of Vim's `vi(`, `vi{`, `vi"` text
objects, available without requiring Vim mode. The two actions solve
different problems.
## Implementation
Both actions use
`MultiBufferSnapshot::innermost_enclosing_bracket_ranges`, which already
handles nesting, multi-buffer excerpts, and language-specific bracket
definitions, including languages where quotes are declared as bracket
pairs (Rust, Python, JavaScript, JSON, etc.).
For string-like content where the language does not register quotes as
brackets (notably Markdown inline content), `SelectInsideDelimiters`
additionally falls back to a `syntax_ancestor` check for tree-sitter
node kinds `string_content` and `inline`. This is the same set of node
kinds already used in `select_larger_syntax_node`.
Multi-cursor support comes from `move_offsets_with`.
## Tests
Two new tests in `editor_tests.rs` covering:
- Basic delimiter selection (parens, brackets, braces)
- Innermost detection with nested pairs
- String content selection (TypeScript)
- Selection expansion when starting from an existing selection
- No-op when cursor is not inside any delimiter
## Notes
No default keybindings are provided. Users can bind via their keymap.
Can add defaults if reviewers prefer.
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 #50042
Release Notes:
- Added `editor::SelectInsideDelimiters` and
`editor::SelectAroundDelimiters` actions for selecting content within
the nearest enclosing brackets, braces, parentheses, or quotes.
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
|
||
|
|
2bdbd0ef18 |
editor: Reuse display-map cursors when converting word diffs (#58658)
layout_word_diff_highlights converted each visible word diff to display points via isomorphic_display_point_ranges_for_buffer_range, which walks the inlay/fold/tab/wrap/block trees from the root on every call. With many word diffs on screen this re-walks the same trees repeatedly each frame. Add a DisplayPointConverter that holds a forward-only cursor for each display-map layer (mirroring the cursor reuse already done in BlockMap::sync) so consecutive conversions amortize to near-constant work. New forward cursors BufferOffsetToInlayPointCursor and BlockPointCursor back the inlay and block layers; the fold/tab/wrap layers reuse existing cursors. Each cursor gains a cheap reset() that delegates to the underlying SumTree cursor; the converter resets its cursors if an input range starts before the previous one ended, so it stays correct for overlapping inputs (e.g. the base and buffer word diffs of an inline modified hunk). layout_word_diff_highlights now sorts the visible word diffs and feeds them through a single converter. isomorphic_display_point_ranges_for_buffer_range is reimplemented on top of the converter to keep one code path. Release Notes: - Improved scrolling performance in diff views containing large hunks |
||
|
|
a41ccd1206 |
editor: Speed up multi cursor editing (#58510)
Early draft for #32051 (multi-cursor editing is very slow, and basically hangs at high cursor counts). Opening it early like @Anthony-Eid suggested so we can agree on direction before I go further. ## Root cause Typing with a cursor on every line is mostly O(N)-per-keystroke work spread across a few places. I profiled it with `sample` and per-phase timers around `handle_input`. At 1000 cursors (~24ms before this PR): the post-edit display-map sync is ~11.8ms, the CRDT edit (`apply_local_edit`) ~3.7ms, resolving all N selections plus the per-cursor input loop ~3.5ms, the post-edit selection round-trip ~2.6ms, and `change_selections` plus transact machinery ~2.4ms. The display sync re-runs per-edit `SumTree` work through every layer even when nothing transforms (the plain-text case), and selections get re-resolved through the full display round-trip several times per keystroke. ## What this does - Display fast paths: `InlayMap::sync` (no inlays) and `WrapMap::interpolate` (no soft-wrap) skip the O(edits) transform-tree rebuild and return the passthrough snapshot, gated so a pending inlay splice or existing wraps still take the slow path. - Selection fast path: when nothing collapses buffer content (`!has_folds() && !has_replacement_blocks()`), resolve `Anchor` to `Point` to `Offset` batched and skip the per-selection display round-trip (the `todo(lw)`). - Render and autoscroll resolve only the first/last/newest selections instead of all N per frame. - A parameterized `Multi-cursor input/cursors/{1000,10000,100000}` benchmark. ## Results - Typing (`handle_input`): ~2.1x faster (24ms to 11.7ms at 1k). - Type plus two word-deletes (criterion): 29% faster (89.9 to 63.8ms) at 1k, 37% (959 to 606ms) at 10k. - Post-edit display sync alone: 11.8 to 3.8ms at 1k, 133 to 45ms at 10k. All `editor` (759), `display_map` (67), `multi_buffer` (58), and `text` (36) tests pass, and `./script/clippy` is clean. ## Direction This is ~2x, and I can get the current architecture to roughly 3.5-4.5x with a few more safe changes (hoisting the per-cursor language/editability checks, cheaper snapshot clones). Genuine VS Code numbers (~1-2us/cursor) aren't reachable while the buffer is a CRDT rope of fragments with anchor selections and a 5-layer transform stack. That would need a plain-offset cursor model and/or decoupling display layout from the edit path, which is a bigger effort I'd want to design with you. One thing I'd need your call on: `set_active_selections` sends an `UpdateSelections` collab op every keystroke (building N anchors); can that be debounced to transaction end, or do presence/follow-mode features rely on per-keystroke cursor broadcast? Release Notes: - editor: Improved multi cursor editing performance --------- Co-authored-by: Anthony Eid <anthony@zed.dev> |
||
|
|
0361eff982 |
editor: Refresh active debug line highlight on theme change (#59274)
# Objective Fixes #58736 Pause the debugger on a breakpoint, switch your theme, and the active debug line keeps its old highlight color until you step again or restart Zed. ## Solution The highlight stores a concrete color grabbed from the theme back when `go_to_active_debug_line` ran. A theme switch goes through `theme_changed`, which refreshes brackets, semantic tokens, and outline symbols but never re-applies that highlight, so it stays stale. Re-running `go_to_active_debug_line` from `theme_changed` re-resolves the color against the current theme. ## Testing Added a regression test in `debugger_ui` that stops at a debug line, swaps the theme's `editor.debugger_active_line.background`, and checks the highlight follows. It fails on `main` and passes with the fix. Also tested by hand on Windows: started a debugpy session, paused at a breakpoint, switched themes from the theme selector, and watched the active line recolor live without stepping or restarting. ## 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 - [x] Performance impact has been considered and is acceptable ## Showcase Paused at a breakpoint, switching themes from the theme selector. | Before | After | | --- | --- | | https://github.com/user-attachments/assets/653a7e1b-3a99-4316-b1c9-b16ed7a7a8ba | https://github.com/user-attachments/assets/22a4c876-30f2-44c5-aad9-0f860639074c | --- Release Notes: - Fixed the active debug line color not updating when switching themes while the debugger is paused ([#58736](https://github.com/zed-industries/zed/issues/58736)). --------- Co-authored-by: dino <dinojoaocosta@gmail.com> |
||
|
|
a9bba5bf71 |
editor: Show file icon in breadcrumbs when tab bar is hidden (#56267)
[Screencast_20260509_113456.webm](https://github.com/user-attachments/assets/8165246f-6266-4e23-bede-0755e8636a19) Release Notes: - Added file icons to the breadcrumbs when the tab bar is hidden Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
7d516a1a91 |
Anchor sticky scroll to symbol name rows (#56333)
## Context Sticky scroll was anchoring multiline signatures to the first outline context row instead of the row containing the symbol name, which could leave the sticky header showing unhelpful context. This change carries each outline item’s `selection_range` through the tree-sitter, LSP, multi-buffer, and editor paths, then uses that range to choose the sticky header row. This is intended to improve sticky scroll generically, not only for one language. It should help wherever symbol data distinguishes the symbol name from the larger symbol range: - tree-sitter outlines that provide a distinct `@name` capture - LSP document symbols whose `selectionRange` is more precise than `range` The actual improvement is still language-dependent, because it relies on the quality of each language’s outline query or language server symbol metadata. Closes #55587 Manual video of the test : [Screencast from 2026-05-10 14-05-46.webm](https://github.com/user-attachments/assets/40f327d3-cab2-4b85-887b-08b541a102bf) ## How to Review `crates/language/src/outline.rs`, `crates/language/src/buffer.rs`, and `crates/language/src/buffer_tests.rs`: Adds `selection_range` to tree-sitter outline items and verifies that multiline signatures can anchor sticky scroll on the symbol-name row while preserving the existing displayed outline text. `crates/project/src/lsp_store/document_symbols.rs`: Threads LSP document symbol `selection_range` into `OutlineItem`, keeping enriched labels and highlight ranges intact while preserving the distinction between the full symbol range and the selected name range. `crates/multi_buffer/src/multi_buffer.rs`, `crates/editor/src/document_symbols.rs`, `crates/editor/src/editor.rs`, `crates/outline/src/outline.rs`, and `crates/outline_panel/src/outline_panel.rs`: Propagates `selection_range` through the places that remap outline items between buffers, multi-buffers, editors, and outline views. `crates/editor/src/element.rs` and `crates/editor/src/editor_tests.rs`: Uses `selection_range` when computing sticky header rows and adds a regression test covering a multiline signature case from the issue. `crates/language/Cargo.toml` and `Cargo.lock`: Adds `tree-sitter-c` for the language-level regression test fixture. ## 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 sticky scroll anchoring to unhelpful context rows for multiline signatures when symbol metadata provides a more precise name range. |
||
|
|
c3c589168b |
editor: Fix blocks not appearing or lingering when anchored past a soft wrap (#59018)
I came across this while tackling another block map sync issue. When a block is anchored past the point where its line soft wraps, inserting or removing it invalidated the wrong range of rows. Inserting such a block alone could silently not show it, and removing it could leave the block on screen. To reproduce: ```sh SEED=113 ITERATIONS=1 cargo test -p editor test_random_blocks ``` Release Notes: - Fixed inline assistant prompt sometimes not appearing, or lingering after dismissal, when that line was soft-wrapped. |
||
|
|
d5ddf73568 |
editor: Fix splitting brackets inside line comments (#59260)
# Objective Closes #59229 When adding a newline, Zed has a bit of intelligence to do more work than just inserting a `\n`. For comment lines, it simply extends the comment: ```rust Before // This is a comment, ˇThis is another comment After // This is a comment, // ˇThis is another comment ``` And when the cursor is inside bracket pairs, Zed inserts another newline to move the closing bracket to a new line: ```rust Before fn main() {ˇ} After fn main() { ˇ } ``` However, when we have a comment line with the cursor inside a bracket pair, both mechanisms apply, resulting in an unintended state where the closing bracket is kicked out of the comment: ```rust Before // {ˇ} After // { // ˇ } ``` We definitely do not need the bracket extension rule when we are adding a newline inside comments. We want comment lines inside brackets to be split like this: ```rust // { // ˇ} ``` ## Solution - Disable Bracket Extra Newline in Comments: When a line comment delimiter is detected, we override the default `newline_config` to set `extra_line_additional_indent` to `None` . - Avoid Rule Conflicts (Short-circuiting): The three newline customization helpers (line comment, block comment, and list item) are mutually exclusive. I refactored their execution from a sequential list into an `if let Some ... else if let Some` branch. This prevents subsequent rules from having side effects on `newline_config` when a match has already occurred. ## Testing A new test named `test_newline_comments_with_brackets` is introduced in `crates/editor/src/editor_tests.rs`, All tests in the `editor` crate were verified using `cargo test -p editor` . ## 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 an issue where splitting brackets inside line comments inserted an extra line and broke the comment formatting |
||
|
|
a262fbb749 |
file_finder: Adjust list item design (#59164)
Follow up to https://github.com/zed-industries/zed/pull/59072 adjusting some UI design for the file finder that got regressed. Release Notes: - N/A |
||
|
|
70e690effd |
editor: Align split buffer headers with scrollbar layout (#53782)
Clip split buffer headers to the editor's content bounds so they no longer paint into the horizontal scrollbar area. Reuse the editor's computed right margin and horizontal scrollbar visibility instead of reimplementing scrollbar detection in split_editor_view. This keeps split headers aligned when minimap, inline blame, or scrollbar visibility change the available content area. Release Notes: - Fixed horizontal scrollbars not being rendered behind buffer headers in split editors --------- Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com> Co-authored-by: dino <dinojoaocosta@gmail.com> |
||
|
|
423d5b64b5 |
multi_buffer: Don't eagerly clone BufferSnapshot in range_to_buffer_ranges (#59190)
Both cloning and dropping of these has quite a bit of overhead (despite them being snapshots), so avoid where possible, especially in display map syncing Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
fc94e24d79 |
editor: Fix columnar selection alignment on rows with multi-byte chars (#57097)
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](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 #56748 ## Summary Block / column selection (Shift+Ctrl+drag on Linux, Shift+Cmd+drag on macOS) anchored its rectangle on a single byte column applied to every row in the dragged range. On a row whose text contained a multi-byte character before that column (for example `ã`), the same byte offset mapped to a different visual `x`, so the per-row cursor drifted off the column. `select_columns` now anchors the rectangle in `x` pixels via `x_for_display_point` and resolves each row's byte column with `display_column_for_x` — the same pair of helpers already used by vertical cursor motion and Vim VisualBlock. ## Before / After **Before** — cursor on the `ã` row drifts one column to the left: <img width="1068" height="366" alt="image" src="https://github.com/user-attachments/assets/0559ef89-852e-40f3-9d43-f5f44277f99e" /> **After** — rectangle stays visually aligned across rows: <img width="866" height="408" alt="image" src="https://github.com/user-attachments/assets/bce13c1a-1ddb-4fd6-8216-2c0e902f6668" /> ## Test plan - `cargo test -p editor test_columnar_selection_with_multibyte_chars` (new regression test covers the buggy case past the `ã` byte boundary, plus a control case where old and new logic agree). - Manual: Shift+Ctrl+drag down a five-line buffer where row 3 contains `ã` — selection rectangle stays aligned (see screenshots). - Manual: Shift+Alt+drag (`FromSelection` branch) over the same buffer — same result. - Manual: drag past EOL on the `ã` row — each row extends to its own EOL with no panic. Release Notes: - Fixed misalignment of column selection on rows that contain multi-byte characters --------- Co-authored-by: Tom Houlé <tom@tomhoule.com> |
||
|
|
d46ad937fe |
gpui: Add builder API for BoxShadow (#57743)
Replaces the verbose struct-literal construction of `gpui::BoxShadow` with a builder API: - `BoxShadow::new(offset_x, offset_y, color)` takes the required fields, with arguments ordered to match the CSS `box-shadow` property. - `.blur_radius(_)`, `.spread_radius(_)`, and `.inset()` set the optional fields. All in-tree call sites are migrated, including the Tailwind-style `shadow_xs`..`shadow_2xl` helpers in `gpui_macros`, the `ElevationIndex` shadows in `ui`, and various widgets across `editor`, `workspace`, `agent_ui`, and `ai_onboarding`. The fields on `BoxShadow` remain public, so external code using struct-literal construction continues to work. 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) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A |
||
|
|
75cb7330bd |
Fix shadow and gradient artifacts on transparent windows (#58981)
On transparent or blurred window backgrounds, several agent panel surfaces and the multibuffer header rendered drop shadows and fade gradients that have no opaque surface to blend into, so they showed up as dark halos or colored patches: - agent message boxes and the activity bar (drop shadows) - diff-hunk Reject/Keep controls (drop shadow) - the diff review pane (double-painted `editor_background`) - agent thread-list rows, the conversation title edit affordance, and sidebar project headers (fade gradient) - the multibuffer buffer header (`editor_subheader_background` + sticky shadow) These are skipped when `window_background_appearance` isn't `Opaque`. Opaque windows are unchanged; on transparent windows the elements stay delineated by their borders and truncate text with an ellipsis instead of fading. ## Screenshots Before: <img width="1920" height="1200" alt="Screenshot 2026-06-09 at 3 26 26 PM" src="https://github.com/user-attachments/assets/7dc9c76c-7de9-4c50-8719-05957d091706" /> After: <img width="1728" height="1117" alt="Screenshot 2026-06-09 at 3 26 29 PM" src="https://github.com/user-attachments/assets/889a53ad-9f11-41b9-9f51-ffcbd5c37821" /> 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 dark shadow and gradient artifacts in the agent panel and multibuffer headers when using a transparent or blurred window background |
||
|
|
915de507cd |
Add action to select inside enclosing brackets (#59005)
## Summary - add an editor action for selecting the contents of the innermost enclosing bracket pair - register the action without assigning a default key binding - cover cursor, selection, nested bracket, no-op, and multi-cursor cases ## Tests - cargo fmt --check - cargo test -p editor test_select_inside_enclosing_bracket --lib - cargo test -p editor test_move_to_enclosing_bracket --lib Release Notes: - Added action to select the contents enclosed by brackets |
||
|
|
032a1ed498 |
tab_switcher: Middle-truncate long picker filenames (#59072)
## Context This follow-up was inspired by Christopher’s suggestion in the review comment on #58483: long filenames should truncate in the middle so both the beginning and the suffix/extension remain visible. Previously, very long filenames in picker rows could still be clipped or end-truncated, making files with shared prefixes hard to distinguish. This adds middle-truncation support to GPUI text overflow and applies it to filename-focused picker surfaces: the tab switcher and the Ctrl-P file finder. Normal editor tab bar behavior remains unchanged and continues to use the existing title length cap. ## How to Review - **`crates/gpui/src/style.rs`, `crates/gpui/src/styled.rs`, `crates/gpui/src/elements/text.rs`, `crates/gpui/src/text_system/line_wrapper.rs`**: Adds `TextOverflow::TruncateMiddle`, wires it through text layout, and implements middle truncation while preserving valid text runs. Very narrow widths now show the truncation affix instead of falling back to the abruptly clipped original text. - **`crates/ui/src/components/label/label_like.rs`, `crates/ui/src/components/label/label.rs`, `crates/ui/src/components/label/highlighted_label.rs`**: Exposes middle truncation through the shared label components. - **`crates/workspace/src/item.rs`, `crates/editor/src/items.rs`, `crates/workspace/src/pane.rs`, `crates/tab_switcher/src/tab_switcher.rs`**: Adds an explicit tab-content opt-in for middle truncation. The tab switcher enables it, while the normal tab bar and dragged tabs keep their existing behavior. - **`crates/file_finder/src/file_finder.rs`**: Applies middle truncation to Ctrl-P file finder filenames and lets the path shrink from the start so long paths do not hide important filename suffixes. Manual test before change : [Screencast from 2026-06-10 22-59-28.webm](https://github.com/user-attachments/assets/5e032646-a48c-45f2-8fe2-0424507fd576) Manual test after change : [Screencast from 2026-06-10 22-54-48.webm](https://github.com/user-attachments/assets/4b9253da-f169-4ed1-bdd5-ee71dcf49a83) ## 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: - Improved long filename truncation in the tab switcher and file finder so extensions remain visible. |
||
|
|
bf09844984 |
editor: Don't treat scheme-prefixed text as a URL when pasting in Markdown (#59071)
Pasting text that merely starts with a scheme-like prefix (for example a commit message like `editor: Fix crash in project panel`) over a selection in a Markdown buffer would wrap the selection in a Markdown link, because `url::Url::parse` accepts `editor:` as a valid URL scheme. Paste now only treats clipboard text as a URL when the whole text is a single standalone URL, using `linkify` (already a workspace dependency) instead of `url::Url::parse`. Added a regression test covering the scheme-like prefix case. 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 Closes #59070 Release Notes: - Fixed pasting text starting with a scheme-like prefix (such as `editor: ...`) over a selection in a Markdown buffer incorrectly creating a Markdown link. |
||
|
|
38a688b921 |
editor: Expand the gutter width to contain new timestamp format (#59008)
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 Closes #58922 In #57973, a new timestamp format was introduced. For example, for a commit from 13 months ago, the old formatter would output `"1 year ago"`, whereas the new format outputs `"1 year, 1 month ago"`. This new compound format is significantly longer than `"60 minutes ago"`, which is currently used to calculate the maximum width of the blame column here: https://github.com/zed-industries/zed/blob/568abf04f349080d333e8028ce9de432995dc8ab/crates/editor/src/editor.rs#L11376-L11391 As a result, when a blame entry uses the `"{M} years, {N} months ago"` format, its width exceeds the pre-calculated maximum, causing the text to overlap with the line numbers. This PR updates the placeholder string used for the maximum width calculation to `"2 years, 11 months ago"`, ensuring the column is wide enough to accommodate the longest possible compound timestamp. Before: <img width="1407" height="598" alt="before" src="https://github.com/user-attachments/assets/f025f423-9ccc-432d-813c-4b861227a7a1" /> After: <img width="1481" height="594" alt="after" src="https://github.com/user-attachments/assets/c60cbd17-fdd4-471c-a4fc-3c2e7a3ccd5d" /> Release Notes: - Fixed an issue where Git blame text would overlap with line numbers in the gutter. |
||
|
|
6d9ddb96b2 |
Bench app context phase 2 (#58202)
This PR builds out GPUI's benchmark harness so render benchmarks measure
realistic frame costs using GPUI-owned, runtime-gated instrumentation.
It adds measurements for frame draw time, dirty-to-draw latency,
invalidation coalescing, and frame-budget overruns, and runs benchmark
workloads with production-like concurrency.
## How it works
**Frame timings flow through the GPUI profiler.** `Window::draw` emits a
`FrameTiming { window_id, dirty_at, invalidations, draw_start, draw_end
}` event into a global ring buffer in `gpui::profiler`, mirroring the
existing task-timing channel. Collection is runtime-gated by
`profiler::set_frame_trace_enabled` (one relaxed atomic load when
disabled — no `Instant::now` calls in production). `BenchReport` is a
pure listener: it drains events through a cursor-based
`FrameTimingCollector` and builds histograms in the bench layer.
`Window` carries no bench-only cfg fields, and the same event channel
can later feed the miniprofiler UI or an in-app frame-time HUD.
**`BenchDispatcher`** is a multithreaded `PlatformDispatcher` for
benchmarks: background tasks run on a worker pool (same priority queue
as `LinuxDispatcher`, with task-profiler hooks), timers fire in real
time on a dedicated thread, and foreground tasks queue until the bench
thread drains them with a blocking `run_until_idle()`. Unlike
`TestDispatcher`, work executes in parallel in real time, so wall-clock
measurements reflect production concurrency. In-flight accounting is
panic-safe via drop guards.
**`gpui::bench_platform()`** returns a per-process `TestPlatform` backed
by the `BenchDispatcher`, cached in a thread-local so worker threads
persist across Criterion calibration passes. This replaces the earlier
approach of constructing a real platform per invocation, which had
process-global singleton issues, never ran foreground tasks (no run loop
pumped the main queue), and couldn't open windows on headless CI.
**Text shaping** uses `NoopTextSystem`: deterministic across
machines/font installations and CI-portable. Measured cost of this
trade: ~10% of editor draw time vs `MacTextSystem` (Noop still emits one
glyph per character at fixed advances, so downstream layout/paint
structure is preserved).
**GPU coverage (macOS only for now).** `PlatformHeadlessRenderer` gained
`render_scene`, which encodes and submits the scene to Metal against a
cached offscreen target without blocking on completion or reading pixels
back — matching production `present()` CPU cost (`render_scene_to_image`
would overstate it: it waits for the GPU and copies pixels back).
`TestWindow::draw` forwards scenes to the renderer, the real
`MetalAtlas` means glyph/SVG rasterization happens during paint, and
`bench_renderer` presents after each measured update. Platforms without
a headless renderer degrade to discarding the scene.
## Example
```rust
#[gpui::bench]
fn editor_render(cx: &mut BenchAppContext) {
init_context(cx);
let buffer = cx.update(|cx| { /* build a MultiBuffer */ });
let mut window = cx.add_empty_window();
let editor = window.update(|window, cx| {
let editor = window.replace_root(cx, |window, cx| {
let mut editor = Editor::new(EditorMode::full(), buffer, None, window, cx);
editor.set_style(editor::EditorStyle::default(), window, cx);
editor
});
window.focus(&editor.focus_handle(cx), cx);
editor
});
let mut move_down = true;
cx.bench_renderer(editor, move |editor, window, cx| {
if move_down {
editor.move_down(&MoveDown, window, cx);
} else {
editor.move_up(&MoveUp, window, cx);
}
move_down = !move_down;
});
}
```
## Example output (release, M-series)
```
editor_render time: [329.75 µs 330.17 µs 330.69 µs]
GPUI bench report (all observed iterations): editor_render
note: includes Criterion warmup/calibration
window dirty-to-draw:
samples: 31533
mean: 0.321ms
p50: 0.322ms
p90: 0.336ms
p95: 0.342ms
p99: 0.360ms
max: 0.504ms
frame budget overruns total: 0
frame budget overruns max: 0
window draw:
samples: 31533
mean: 0.295ms
p50: 0.295ms
p90: 0.307ms
p95: 0.313ms
p99: 0.330ms
max: 0.455ms
frame budget overruns total: 0
frame budget overruns max: 0
invalidations per frame: mean 5.00, max 5
```
(`invalidations per frame: mean 5.00` is real signal: each `move_down`
notifies the window five times before the draw.)
## Known limitations
- **Draw-per-flush**: the harness draws synchronously when effects flush
rather than coalescing invalidations to a vsync tick, so `dirty-to-draw`
excludes queueing delay, and `frame budget overruns` is a draw-time
budget proxy rather than actual missed presents. A frame-paced mode is
natural follow-up work.
- **GPU submission is measured on macOS only**; other platforms have no
headless renderer yet.
- The GPUI report includes Criterion warmup/calibration samples (noted
in the output); Criterion's `time` is the regression-gating number.
- `run_until_idle` waits for queued, running, and already-due work, but
not for timers that haven't reached their due time — the dispatcher runs
in real time and can't skip ahead like `TestDispatcher`'s virtual clock.
## Future work
- A vsync-like frame-pacing mode (suppress draw-on-flush; tick-driven
draw + present) so dirty-to-draw captures queueing delay
- Record present duration in `FrameTiming` so the report can split draw
vs present
- Benches that scroll through novel content (cold layout caches) and an
agent-panel render bench
- Headless renderers for Windows/Linux
- Move benches into a dedicated crate
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
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
|
||
|
|
ba93284c6a |
Fix miscellaneous typos (#58979)
Some typos I found while reading the code 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: - N/A |
||
|
|
7a469725d3 |
Refactor BufferDiff to allow multiple diffs to share the same base text buffer (#58266)
This PR changes how base texts are managed by the `buffer_diff` crate, to enable keeping two diff entities alive that share the same base text buffer entity. Previously, each diff owned its own base text buffer and edited it when calling `BufferDiff::set_snapshot`, so the only way to reuse the same base text between two diffs was to have two independent buffers for it, which is pretty inefficient. After this PR, each diff still has a base text buffer, but `set_snapshot` doesn't edit it. Instead, that responsibility moves into the caller. For updating the base text buffer, this PR also introduces a new pair of APIs, `Buffer::snapshot_with_edits` and `Buffer::fast_forward`, which allow us to move the parsing of the new base text into the background and then install the new syntax tree synchronously on the foreground. The git store uses the low-level APIs `set_snapshot` and `fast_forward` directly, and manages the head text and index text buffers itself (garbage-collecting them when they're no longer needed); this enables adding an `open_staged_diff` API which returns a diff between the managed index buffer and the managed head buffer (the latter is also used for the uncommitted diff's base text). Other downstreams don't need to reuse a base text buffer, and those have been migrated to use the high-level `set_base_text` API, which now calls `set_snapshot` and `fast_forward` internally, with a guard to prevent concurrent updates. Another change worthy of note is that we now always diff the old base text with the new base text to create `snapshot_with_edits`. There are also some incidental bug fixes: - Fixed an issue where a dangling weak unstaged diff could stick around in the git store forever - Restored the `IndexMatchesHead` optimization that had become inoperative in the remote case - Fixed a crash in the multibuffer due to the handling of `BufferDiffEvent::LanguageChanged`, which could cause the multibuffer to have transforms that were inconsistent with the diff base text. 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 ZED-81P Release Notes: - Fixed a rare crash that could occur while using the uncommitted diff. --------- Co-authored-by: Ben Kunkle <ben@zed.dev> Co-authored-by: Anthony Eid <hello@anthonyeid.me> |
||
|
|
714a12f478 |
editor: Register toggle inline values action (#58921)
The `ToggleInlineValues` action was added when inline value hints were introduced, but the action was never registered, so it was not dispatchable: it never appeared in the command palette and any keybinding bound to it had no effect. Follow-up to #28656. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] 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) - [ ] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Closes #58890. Release Notes: - Fixed “editor: toggle inline values” not appearing in the command palette or responding to keybindings |
||
|
|
4405738fab |
editor: Show format selections for cursor ranges (#56571)
Resolves https://github.com/zed-industries/zed/issues/56556 This diff fixes format selections being unavailable when the selection is a cursor range. The action was gated on having at least one non-empty selection, which hid it even when the active formatter supported range formatting. With this change, cursor ranges are included when checking whether the selected buffers support range formatting. This restores the cursor-based `Format Selections` behavior while preserving the existing formatter-capability gate, so the action still stays hidden for formatters that cannot format ranges. https://github.com/user-attachments/assets/fc2ab2b7-1af3-4849-841a-b57a685d748f Release Notes: - Fixed format selections not being available for cursor ranges when the active formatter supports range formatting. Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com> |
||
|
|
787a597c2a |
Make sure we display keybindings on gutter menu (#58856)
Closes https://github.com/zed-industries/zed/issues/58820 Some menu items there don't have have a bindable action and/or a default keybinding, so they won't show anything by default. Right now, only "Set Breakpoint" and "Set Log Breakpoint" will show something right off the bat. Release Notes: - N/A |
||
|
|
b1ba025093 |
Use unstable sorts if deduplicating (#58751)
# Impact Recent Project picker, `find all references`, the sidebar's `rebuild_contents` might get a slight speed boost. # Reasoning Unstable sort variants https://doc.rust-lang.org/stable/std/primitive.slice.html#method.sort_unstable are non-allocating but potentially destructive. Since we're deduplicating elements anyways, use the unstable variant. This call will use ipnsort https://github.com/Voultapher/sort-research-rs/blob/main/writeup/unreasonable/text.md#various-generic-algorithms I expect the speedups to be at least 30%, though it's highly input dependent. 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 Release Notes: - N/A |
||
|
|
28a179639d |
Improve warning display UI related to skills (#58838)
This PR tackles how we communicate errors/warnings relative to skills. It touches three major surfaces: callouts in the thread view, menu items in the completion menu, and settings UI. These are all the places where we display something to tell the user a skill might have a problem. In the settings UI, we now clamp the skill description to five lines. And if there's a warning, we show the warning icon and the description in a tooltip when hovering it: <img width="600" alt="Screenshot 2026-06-08 at 10 51@2x" src="https://github.com/user-attachments/assets/1a1233b0-c24a-4082-9fe6-2ab1d00ba9fd" /> In the thread view, we display callouts with the warnings. I simplified the long-description one specifically given we can click on each skill item right there, so no need for a "manage global skills" button or descriptions in each item: <img width="600" alt="Screenshot 2026-06-08 at 10 52@2x" src="https://github.com/user-attachments/assets/4b9aad23-7362-40cd-8ab5-6dfceb46badd" /> In the code completion menu, I removed the icon that appeared at the far right and instead added the ability for it to render a colored warning icon instead of the icon it'd already display in the left; I think this simplifies it nicely: <img width="350" alt="Screenshot 2026-06-08 at 10 53@2x" src="https://github.com/user-attachments/assets/8d0c731a-31a0-4d30-abab-1eb40f61031e" /> Release Notes: - Agent: Improved how we communicate problems relative to skills, in both the agent panel and the settings UI. --------- Co-authored-by: Martin Ye <martin@zed.dev> |
||
|
|
5b71e46f2e |
outline: Switch the outline search to use fuzzy_nucleo (#56477)
Nucleo tracking issue: https://github.com/zed-industries/zed/issues/55872 This PR switches the outline picker to use `fuzzy_nucleo`. with that I refactored the outline fuzzy picking to take advantage of nucleo and its multi-atom query support. The previous implementation had a lot going on specifically to work around the lack of multiple atoms, basically taking matters into its own hands to accomplish the same goals within the constraints it had. Instead of having two lists of candidates that we have to run the query against, we just run a single query and take advantage of the fact that nucleo chooses the matches that are the furtherest towards the end of the haystack to implement the same ancestor/leaf filtering. It retains the leaf only matching on single atom queries. video: https://github.com/user-attachments/assets/64baa8d7-fd77-452c-86d1-e08561422d85 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 Release Notes: - outline: switch to fuzzy_nucleo |
||
|
|
1b7e58bce8 |
Typed workspace errors (#57649)
This migrates the `Workspace::show_error` method to take a generic type that implements `WorkspaceError` instead. That trait containts methods to show a proper error message but most importantly means to help with providing actions given certain errors. The intention for this is rather easy: Whenever we show an error to the user on the workspace level, that error should be - actionable to a degree, even if that is only opening logs or whatnot - show a message that is understandable to the user - for not-too-critical errors, should hide after a certain delay and not force the user to dismiss it using their mouse. For now, there exist trait implementations for string error types and anyhow errors. The long term goal here is to get rid of these altogether and migrate everything to be strongly typed and especially actionable instead. Self-Review Checklist: - [ ] I've reviewed my own diff for quality, security, and reliability - [ ] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [X] Performance impact has been considered and is acceptable Release Notes: - N/A --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com> |
||
|
|
69946b28da |
agent: Warn about long skill descriptions (#58356)
Closes #58046 Closes AI-353 Skills with descriptions over the 1024-byte limit now load with a warning instead of failing. The warning appears in the thread footer with clickable skill file rows, and the skill picker keeps the skill icon while showing a right-aligned warning badge whose hover text explains the issue. Warning for single out-of-spec skill <img width="2790" height="870" alt="image" src="https://github.com/user-attachments/assets/f454b55a-8e05-438e-b4ff-356259ff6843" /> Warning for multiple out-of-spec skills <img width="2796" height="646" alt="image" src="https://github.com/user-attachments/assets/a0808cdd-4857-4a6b-a26e-15156afbffe9" /> Skill selection popup <img width="1234" height="1118" alt="image" src="https://github.com/user-attachments/assets/5bb463f6-7adb-4e39-8522-e322bf078aff" /> Skill management in settings <img width="1768" height="1390" alt="image" src="https://github.com/user-attachments/assets/85c6b179-e268-4518-8ca7-c73b55f92355" /> Release Notes: - Allow loading skills whose descriptions exceed the 1024-byte limit by showing warnings instead of failing to load them. --------- Co-authored-by: Martin Ye <martin@zed.dev> Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
34c47afbc1 |
Fix split diff stale scroll anchor crash (#58688)
This crash occurred when the left hand side (LHS) editor in the split diff retained a stale shared scroll handler after the split editor unsplits. I added an invariant check to our randomized companion display map tests to prevent regressions here and explicitly make LHS editor set a native scroll anchor when unsplitting. 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 Release Notes: - Fix crash that could occur when unsplitting a side by side diff view |
||
|
|
b36b31a94a |
sidebar: Debounce Sidebar::update_entries (#57803)
Follow up on https://github.com/zed-industries/zed/pull/57717 Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
024cfa2c69 |
editor: Only compute word-diff highlights for visible rows (#58639)
Word diffs are stored per-hunk for the entire hunk range, but layout_word_diff_highlights converted every word diff of every hunk touching the viewport to display points each frame, even for the off-screen portion of a large, partially-visible hunk. Each conversion walks the inlay/fold/tab/wrap/block trees, so scrolling through a large modified hunk (especially in split diff mode, where both editors lay out every frame) caused frame drops proportional to the hunk's total size rather than its visible portion. Filter word diffs by the visible buffer-offset window before converting. Buffer offset to display point is order-preserving, so this is equivalent to the existing per-row filtering applied to the converted ranges. Release Notes: - Improved scrolling performance in diff views containing large hunks with many computed word diffs |
||
|
|
84ebc5be71 |
Correctly handle file links in markdown and agent threads (#56024)
Closes https://github.com/zed-industries/zed/issues/54840 There are likely more places we can use this new workspace function in, but these are the known ones to me right now Release Notes: - Fixed file hyperlinks in the agent panel not opening files when clicked Co-authored-by: saberoueslati <saberoueslati12@gmail.com> |
||
|
|
b7b5d0c1a0 |
Agent: Improved auto scroll location when using read-file tool (#58640)
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](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Closes #58612 Release Notes: - Agent: Improved auto scroll location when using read-file tool. |
||
|
|
2d18262735 |
Prevent auto-restart of language servers after Stop All Servers (#51468)
Release Notes: - When stopping all language servers, Zed will now no longer restart language servers when language files change until the user restarts all language servers explicitly |
||
|
|
6e471ec777 |
Use no-op hasher for TypeId hashing (#58629)
TypeId is effectively already a hash, so re-hashing it with fxhash is unnecessary. Release Notes: - N/A or Added/Fixed/Improved ... --------- Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
552b6a5dc4 |
editor: Don't bypass show_edit_predictions when navigating diagnostics (#56055)
`go_to_diagnostic_impl` was calling `refresh_edit_prediction(false, true)` with `user_requested = true`, which skips the `should_show_edit_predictions` check inside `refresh_edit_prediction` (`crates/editor/src/editor.rs`). As a result, navigating between diagnostics in a buffer where the user has set `show_edit_predictions: false` would still trigger `EditPredictionProvider::refresh`. With the Zed provider this fans out into many `textDocument/definition` and `textDocument/typeDefinition` LSP requests for every identifier near the cursor (`RelatedExcerptStore::fetch_excerpts`), which is surprising for users who have explicitly disabled edit predictions for that language. Jumping to a diagnostic is a navigation action, not a request for an edit prediction, so pass `user_requested = false` and enable debouncing here. Release Notes: - Fixed diagnostic navigation triggering unnecessary LSP requests when edit predictions are disabled. Co-authored-by: Oleksiy Syvokon <oleksiy@zed.dev> |
||
|
|
27cdd42f8a |
editor: Reduce number of language server requests in go to definition (#58429)
These changes are a follow-up to #58244. That PR changed how Zed sends `textDocument/definition` requests so that, once the language server has answered for a given position, Zed doesn't re-query that same position as the mouse jiggles within the same character, avoiding spamming the server on every tiny mouse movement. This PR adds two more cases on top of that: **1. Preserve the deduplication state when the server returns an empty response** * Previously, an empty response called `Editor::hide_hovered_link`, which sets `Editor::hovered_link_state` to `None`, discarding the recorded `HoveredLinkState::last_trigger_point`. * We now clear `HoveredLinkState::links` instead, resetting the links while keeping `last_trigger_point`, so we don't re-query the same position when the response was empty. **2. Fall back to the surrounding word as the symbol range for no-origin servers** * The `editor::hover_links::show_link_definition` function already used `surrounding_word` to pick the highlight range when the server returned no symbol range. * For servers that return a link (or links) but no `originSelectionRange`, we now also treat that `surrounding_word` range as the symbol range, so moving across characters of the same symbol will not re-query the language server. * There's caveat to this approach, for a language where something like `run_function` is not a single symbol/node, if the server returns a response for one character, we won't re-query for the others in `run_function`, even if the server would have returned something different for `_` or `function`. I believe this should be rare, can't think of a language where this would be an issue, but I'm happy to revisit or drop this part if we decide it's not worth 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 Release Notes: - Improve go to definition in order to avoid repeatedly querying the language server while moving the mouse over the same symbol or an unresolved position |