Closes#46516
The previous fix only worked for non-nested folds, whereas this one also
considers nested folds properly. Also makes this more straightforward to
read.
Release Notes:
- Fixed an issue where relative line numbering would break with nested
folds.
Fixes an issue where `editor::AddSelectionAbove` and
`editor::AddSelectionBelow`, when set with `skip_soft_wrap: true` ,
would lose track of the original cursor column when passing through
short lines, as `editor::Editor.add_selection` was not using the oldest
selection's column range when adding a new selection.
These changes update the `editor::Editor.add_selection` method so as to
keep track of the olde selection's column range for each group, as well
as extracting `find_next_columnar_selection_by_display_row` and
`find_next_columnar_selection_by_buffer_row` helper methods to clarify
the two navigation strategies.
Closes#46842
Release Notes:
- Fixed `editor::AddSelectionAbove` and `editor::AddSelectionBelow` when
skipping over soft-wrapped lines to preserve the original cursor column
when adding selections through lines shorter than the starting position
Closes #ISSUE
Moves the settings content definitions into their own crate, so that
they are compiled+cached separately from settings, primarily to avoid
recompiles due to changes in gpui. In that vain many gpui types such as
font weight/features, and `SharedString` were replaced in the content
crate, either with `*Content` types for font/modifier things, or
`String`/`Arc<str>` for `SharedString`. To make the conversions easy a
new trait method in the settings crate named `IntoGpui::into_gpui`
allows for `into()` like conversions to the gpui types in
`from_settings` impls.
Release Notes:
- N/A
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Happy New Years! This PR is a second take at
https://github.com/zed-industries/zed/pull/38127 (cc @ConradIrwin)
This PR is significantly less complicated than the last attempt: while
we still keep our data on the `NavigationHistory` object, we no longer
tightly integrate it with the existing back/forward "browser history."
Instead, we keep our own stack of `(origin, target)` pairs (in a struct
to make it easy to extend with e.g., tag names in the future).
The PR is split into two separable commits. Most of the implementation
is in the second commit, which:
- Defines the stack data structure
- Implements `pane::GoToOlderTag` and `pane::GoToNewerTag` in terms of
the stack
- Hooks into `navigate_to_hover_links` to push tag stack entries
This last bit is the most fiddly. The core challenge is that we need to
keep track of the `origin` location and calculate the `target` location
across three codepaths that might involve creating a new editor and/or
splitting the pane. One thing in particular I found difficult was that
an editor's `nav_history` (an `ItemNavHistory`) seems to be populated
asynchronously. Instead of relying on it, I decided in this code to make
my own `ItemNavHistory`. I briefly tried to refactor the code in
question, but it seemed like it would significantly increase the scope
of the change.
I prefer this all-in-one tracking centered around
`navigate_to_hover_links ` to the `start/finish` approach taken in
b69a2ea200
because I find it easier to convince myself that the right data is being
populated at the right times. Of course, let me know if you think
there's a better solution.
Closes#14206
Release Notes:
- ??? I don't know what to write here! Suggestions welcome
Release Notes:
- Opening bundled files, keymap, and local release notes now opens in
remote windows instead of opening a new local zed window
- Opening the settings files, keymap files, task files, debug files and
logs will now open within wsl windows instead of opening a new local zed
window
Doesn't support editing or deleting comments yet, but inputs work:
<img width="797" height="881" alt="Screenshot 2026-01-14 at 11 51 36 AM"
src="https://github.com/user-attachments/assets/746e085b-a919-475a-b804-ee0377e40a0b"
/>
<img width="698" height="178" alt="Screenshot 2026-01-14 at 11 47 51 AM"
src="https://github.com/user-attachments/assets/3edac0e8-62e5-4af5-a324-df2bd293f3ca"
/>
<img width="695" height="695" alt="Screenshot 2026-01-14 at 11 47 58 AM"
src="https://github.com/user-attachments/assets/64795ffd-62b4-48ea-a46c-7724221095d7"
/>
### Features implemented:
- **Local comment storage**: Comments are stored per-hunk in the Editor,
with chronological ordering
- **Expandable comments section**: Shows "N Comments" header that can
expand/collapse
- **Inline editing**: Click edit to transform a comment row into an
editable text field with confirm/cancel buttons
- **Delete functionality**: Remove individual comments
- **Send Review to Agent**: Toolbar button with badge showing comment
count, batch-submits all comments across all files/hunks to the Agent
panel
- **User avatars**: Shows the current user's avatar (from their Zed
account) next to comments, falls back to Person icon when not logged in
- **Visual tests**: Added tests for one comment, multiple comments
expanded, and comments collapsed
Note that this is behind a feature flag, so no release notes yet.
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: David Baldwin <baldwindavid@gmail.com>
Release Notes:
- When copying and pasting from a multibuffer view (e.g. into the agent
panel), the line numbers from the selection corresponded to the line
numbers in the multibuffer view (incorrect), instead of the actual line
numbers from the file itself.
- I also handled the case in which the selection spans multiple excerpts
(different files in the multibuffer) by just returning None for that
case, but maybe it should instead be split into two selections?
Left is before (bugged, should be lines 8:16, instead it is 38:46),
right is after (fixed).
<div style="display:flex; gap:12px;">
<img
src="https://github.com/user-attachments/assets/b1bfce1d-8b6a-41c0-ac7e-51f7bd7b284e"
width="48%" />
<img
src="https://github.com/user-attachments/assets/2a4c33a0-a969-4a3e-9aa5-d2c2fefba3b2"
width="48%" />
</div>
Release Notes:
- Added two actions `move_to_start_of_larger_syntax_node` and
`move_to_end_of_larger_syntax_node` that move cursors to the start or
end of the parent tree-sitter node
Following up on my PR #41321, this PR only adds the actions that are
used to enable code navigation across syntax nodes, without binding them
to any keys (such as tab) by default. Both actions use the tree-sitter
syntax tree to find parent nodes of the nodes the cursors are currently
in. `move_to_start_of_larger_syntax_node` will then move each cursor to
the first position of the parent nodes while
`move_to_end_of_larger_syntax_node` to a position right after the parent
nodes.
Related issues and discussions: #22349, #14803, #42828, #13736.
This PR doesn't achieve "tab out" functionality in the exact sense as is
requested in these issues as it does not bind the actions to the tab
key. I hope this PR can start some discussion on what the best way
forward for these issues is. In the meantime, users can configure keys
to use these actions as they see fit to emulate "tab out" behavior. For
example,
```
"context": "Editor && vim_mode == insert && !in_snippet && !showing_completions",
"bindings": {
"tab": "editor::MoveToEndOfLargerSyntaxNode",
"shift-tab": "editor::Tab"
}
```
This will enable tab to skip past code structures like brackets when the
cursor is not in a snippet or the autocomplete menu is not open. At the
same time, shift tab will act as a backup tab.
This PR adds the ability to open local terminals when working in remote
projects. When working in a remote (often actually remoting into a local
container) I always need to run separate terminals outside Zed so I can
run local build tools, scripts, agents, etc. for the related project.
I'd like to be able to run all of these in the same Zed window and this
adds that ability via one-off local terminals.
## Changes
Adds an optional `local` parameter to terminal commands. When set to
`true`, creates a local shell on your machine instead of connecting to
the remote.
### Implementation
- Added `force_local` parameter to terminal creation logic
- Created `create_local_terminal()` method that bypasses remote client
- Updated terminal actions (`NewTerminal`, `NewCenterTerminal`) to
accept optional `local: bool` field (defaults to `false`)
### Usage
**Via keybinding:**
```json
{
"bindings": {
"cmd-t": "workspace::NewCenterTerminal",
"cmd-T": ["workspace::NewCenterTerminal", { "local": true }]
}
},
{
"context": "Terminal",
"bindings": {
"cmd-n": "workspace::NewTerminal",
"cmd-N": ["workspace::NewTerminal", { "local": true }],
},
},
```
**Behavior:**
- Default terminal commands continue to work as before (remote in remote
projects, local in local projects)
- The `local` parameter is optional and defaults to `false`
Release Notes:
- Added support for opening local terminals in remote projects via
`local` parameter on terminal commands.
When using the `editor::actions::CopyAndTrim` action with a multi-line
selection in vim's Visual Line mode, pasting would crash Zed.
The bug occurred because trimming splits a selection into per-line
ranges, creating multiple `editor::ClipboardSelection` entries. However,
when `is_entire_line` was true (Visual Line mode), no newline separators
were added between these entries in the clipboard text. The paste code
then assumed separators existed and read past the end of the text.
The fix ensures newline separators are always added between trimmed line
ranges, regardless of whether the original selection was in line mode.
Closes#46616
Release Notes:
- Fixed a crash when pasting after using `editor: copy and trim` in
vim's Visual Line mode
Adds a very simple diff review button behind a feature flag, which
appears in the gutter of people who have the flag (currently just me;
it's not even enabled for staff, since it doesn't do anything yet).
Mostly this PR just adds the feature flag, the button, and tests.
Release Notes:
- N/A
Stumbled across this upon a PR review - `unfold_ranges` takes a slice of
Ranges and already clones the ranges itself, so we do not need to clone
the selections prior to passing these.
Release Notes:
- N/A
Closes#40110
Changes:
- `DeleteToPreviousSubwordStart` now deletes `\n` separately from
preceding subwords and whitespace.
- `DeleteToNextSubwordEnd` now deletes `\n` and any following whitespace
separately from subsequent subwords.
- Added an `ignore_newlines` flag to both actions to optionally retain
the old behavior.
These modifications align the subword commands with their word
counterparts and with other popular editors like VSCode and Sublime.
Related to: https://github.com/zed-industries/zed/pull/16848
Release Notes:
- Improved `DeleteToPreviousSubwordStart` and `DeleteToNextSubwordEnd`
interactions around newlines. You can opt-in into the previous behavior
by adding `{"ignore_newlines": true}` to either action's binds in your
keymap.
---
This is my first contribution to Zed! If anything should be done
differently, please let me know. Happy to learn :)
## Motivation
This PR unifies the async execution infrastructure between GPUI and
other components that depend on the `scheduler` crate (such as our cloud
codebase). By having a scheduler that lives independently of GPUI, we
can enable deterministic testing across the entire stack - testing GPUI
applications alongside cloud services with a single, unified scheduler.
## Summary
This PR completes the integration of the `scheduler` crate into GPUI,
unifying async execution and enabling deterministic testing of GPUI
combined with other components that depend on the scheduler crate.
## Key Changes
### Scheduler Integration (Phases 1-5, previously completed)
- `TestDispatcher` now delegates to `TestScheduler` for timing, clock,
RNG, and task scheduling
- `PlatformScheduler` implements the `Scheduler` trait for production
use
- GPUI executors wrap scheduler executors, selecting `TestScheduler` or
`PlatformScheduler` based on environment
- Unified blocking logic via `Scheduler::block()`
### Dead Code Cleanup
- Deleted orphaned `crates/gpui/src/platform/platform_scheduler.rs`
(older incompatible version)
## Intentional Removals
### `spawn_labeled` and `deprioritize` removed
The `TaskLabel` system (`spawn_labeled`, `deprioritize`) was removed
during this integration. It was only used in a few places for test
ordering control.
cc @maxbrunsfeld @as-cii - The new priority-weighted scheduling in
`TestScheduler` provides similar functionality through
`Priority::High/Medium/Low`. If `deprioritize` is important for specific
test scenarios, we could add it back to the scheduler crate. Let me know
if this is blocking anything.
### `start_waiting` / `finish_waiting` debug methods removed
Replaced by `TracingWaker` in `TestScheduler` - run tests with
`PENDING_TRACES=1` to see backtraces of pending futures when parking is
forbidden.
### Realtime Priority removed
The realtime priority feature was unused in the codebase. I'd prefer to
reintroduce it when we have an actual use case, as the implementation
(bounded channel with capacity 1) could potentially block the main
thread. Having a real use case will help us validate the design.
## Testing
- All GPUI tests pass
- All scheduler tests pass
- Clippy clean
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ GPUI │
│ ┌──────────────────────┐ ┌────────────────────────────┐ │
│ │ gpui::Background- │ │ gpui::ForegroundExecutor │ │
│ │ Executor │ │ - wraps scheduler:: │ │
│ │ - scheduler: Arc< │ │ ForegroundExecutor │ │
│ │ dyn Scheduler> │ └────────────┬───────────────┘ │
│ └──────────┬───────────┘ │ │
│ │ │ │
│ └──────────┬──────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Arc<dyn Scheduler> │ │
│ └───────────┬───────────┘ │
│ ┌──────────────┴──────────────┐ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌────────────────────┐ │
│ │ PlatformScheduler│ │ TestScheduler │ │
│ │ (production) │ │ (deterministic) │ │
│ └──────────────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
Release Notes:
- N/A
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Yara <git@yara.blue>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
This PR adds a right-click action to the breadcrumb button to copy the
path, when there is some (i.e., untitled buffers and others won't have
this feature).
https://github.com/user-attachments/assets/94ece12c-3071-4a07-a04d-8d89e10fd59e
Release Notes:
- Added the ability to right-click the breadcrumb button when it's a
file path and copy the path.
## Summary
Fixes#33633 - folds corrupting after external file modifications.
The existing fold persistence stored raw byte offsets, which become
stale when files are modified externally (git operations, other editors,
sync tools). This caused folds to capture wrong content on restore -
users reported "wrong lines getting folded" with systematic offsets.
**Solution: Content fingerprinting**
- Store 32-byte content samples at fold boundaries
- On restore, validate fingerprints match; if not, search buffer for new
positions
- Handles edge cases: short folds (< 32 bytes), duplicate content,
boundary positioning
**Bonus fix: Ungraceful exit survival**
- Entity IDs change between sessions, but workspace cleanup's CASCADE
DELETE was wiping folds before new editors could save
- Now migrates folds to new entity_id immediately after restore
## Test plan
- [x] Unit test for fingerprint storage/retrieval
(`test_save_and_get_editor_folds_with_fingerprints`)
- [x] Manual test: fold sections, add content at file start externally,
reopen → folds restore at correct positions
- [x] Manual test: fold sections, Ctrl+C, reopen → folds survive
- [x] Existing fold tests pass (`cargo test -p editor`)
## Release Notes
- N/A
---------
Co-authored-by: Hector <hector@cyberneticwilderness.com>
Fixing a regression I introduced in
https://github.com/zed-industries/zed/pull/45625. Diagnostic hover
popovers should only scroll vertically, not horizontally, as the content
should wrap.
Release Notes:
- N/A
Also improves the commit view to use the same status-based buffer header
visual overrides as the project diff as a driveby.
Fixes https://github.com/zed-industries/zed/issues/45735
Release Notes:
- git: Binary files are no longer shown in garbled form when viewing an
old commit.
Adds various useful things to the repl inspired by ipynb and the julia
vscode extension which can be best seen with this video:

https://github.com/user-attachments/assets/6589715e-3783-456c-8f4b-e2d5a1c4090d
To summarize:
## Inline outputs
Added small, single-line outputs displayed inline at the end of the code
line instead of in a separate block. This provides a cleaner, more
compact view for simple results like numbers or short strings. This
occurs for execution views who only output a single mimetype/plain OR
output nothing, otherwise the default behavior of creating a block will
occur.
It looks like this:
<img width="258" height="35" alt="image"
src="https://github.com/user-attachments/assets/ccdeca3f-c3b7-4387-a4de-53d8b9a25132"
/>
or with a Output
<img width="346" height="55" alt="image"
src="https://github.com/user-attachments/assets/0b4effc9-1bd7-4e8c-802f-8733cdcc77d1"
/>
This was inspired by julia vscode extension, but now it can be used with
any replanguage! Hooray!
<img width="524" height="450" alt="image"
src="https://github.com/user-attachments/assets/a3551e51-f5f7-4d3e-994a-213c9d2f948c"
/>
It saves lots of space compared to the ugly and distracting:
<img width="531" height="546" alt="image"
src="https://github.com/user-attachments/assets/7cf65bae-8ec1-4279-ab19-f0d4ec4052a2"
/>
## Gutters and execution numbers
Added gutters + execution number to display exactly what was executed.
The gutter highlighting is useful for when selecting multiple cells
manually to run, but you dont remember which ones
Ran at different times:
<img width="257" height="58" alt="image"
src="https://github.com/user-attachments/assets/6002ab16-156a-4598-9964-5a6b188e989c"
/>
Ran together:
<img width="306" height="64" alt="image"
src="https://github.com/user-attachments/assets/2690ea35-2bd3-4207-b039-6c0f98dad6e4"
/>
The execution number is useful in the same way that a normal jupyter
notebook execution number is useful.
If a gutter-region does not have a block assigned to it, when you edit
the text in the gutter region, the gutter will disappear, which is
useful for telling when you have modified your code, but does not delete
useful experiment results in blocks:
<img width="280" height="38" alt="image"
src="https://github.com/user-attachments/assets/d7f29224-87e4-4c14-8d9f-41cb10ab5009"
/>
<img width="254" height="31" alt="image"
src="https://github.com/user-attachments/assets/586c9e1d-f53c-4973-affb-c8ca05a7563b"
/>
<img width="264" height="29" alt="image"
src="https://github.com/user-attachments/assets/f306c364-1c92-44bd-9050-ecce1b7822a0"
/>
## Skip empty line
This is a minor fix which is intended to make lab workflow less tedious.
Currently when you execute on an empty line (which might be there for
formatting purposes) nothing will occur. This PR adds the ability to,
when executing from an empty line, skip ahead the range of inclusion
until you reach actual code, and then execute.
Before:
```
code //run execute
//empty space, so you have to move your cursor down or use arrow key
code //run execute
code //run execute
```
After:
```
code //run execute
//empty space, you can now run execute on it and it will include the next line of code
//empty space
code //automatically executed
code //run execute
```
Currently the only piece of tested code is related to this, i still have
to write tests for the gutter annotation api i added and all of the
gutter + inline related code. Also still have to add more config for
this stuff.
@rgbkrk would appreciate a review :D
Closes#22678
Release Notes:
- repl: Added an inline display of execution results (as opposed to the
large execution view) for simple REPL cells
- repl: Improved how execution of empty lines are handled
- repl: Added gutter execution display
in release mode: found many log error as `ERROR [rope::chunk] byte index
48 is not a char boundary; it is inside ',' (bytes 46..49)`
This is easy testing,
- enable signature help
- typing any CJK character
- crash in debug mode
Release Notes:
- N/A
Holding control while dragging text to copy it was being blocked by link
handling stopping the propogation of the mouse event; solution: don't
handle link clicks when selection_drag_state is Dragging.
Issue found & fix tested on Linux (since the modifier key on mac is
apparently different, the issue likely doesn't occur there, but I'm
assuming it does apply to Windows).
I didn't see an issue open for it, and since I fixed it myself I'm
unsure whether it needs one or if the PR is enough.
Release Notes:
- Fix an issue where Ctrl+drag to duplicate selected text on Linux and
Windows when the selection is inside a link.
Breadcrumb visual reorchestration which makes a couple of key changes:
- Breadcrumbs are now displayed in file headers for multibuffer views.
Singleton buffers are unchanged.
- Multibuffer views now have collapse/expand all buttons available in
the toolbar
- Search in multibuffer views now takes up less space, by occupying the
primary toolbar location erstwhile taken up by breadcrumbs
<img width="1721" height="823" alt="Screenshot 2025-12-22 at 4 15 41 PM"
src="https://github.com/user-attachments/assets/38e924f7-fe9e-4c83-84fb-2eee98137f43"
/>
<img width="1722" height="762" alt="Screenshot 2025-12-22 at 4 15 51 PM"
src="https://github.com/user-attachments/assets/ccc98ca3-75ce-4aca-bceb-890817b0f04d"
/>
Release Notes:
- Moved breadcrumbs to file headers in multibuffer views
- Added collapse/expand all options for multibuffer views
- Improved use of space for multibuffer search by taking the place of
the former breadcrumb toolbar location
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Found while profiling #38927
When the query is not a regex, the same replacement can be applied to
all matches. Previously, `replacement_for` allocated a new String on
every call, while `replacement` returns a reference.
Release Notes:
- N/A
---------
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
We use `block_with_timeout` to give the reparse task a millisecond to
complete, and if it takes longer we put the work off to the background.
The reason for this is that we want tree-sitter based features to feel
snappy.
The reparse task is non-cooperative though, it has no yield points,
giving us no place to actually check for our timeout, meaning we will
always drive it to completion and block for the entire duration.
This kicks out the `block_with_timeout` in favor of using the treesitter
progress callback to handle timeouts instead.
Release Notes:
- Improved responsiveness with very language language files on edits
When adding selections above/below with `skip_soft_wrap: true`, use
buffer column positions instead of pixel positions. This ensures
selections are placed at the same column offset in the buffer rather
than at the same visual position, which was incorrect for soft-wrapped
lines.
For example, selecting "how" in a wrapped line:
````
1. Very long line to
show [how] a wrapped
line would look
2. Very long line to
show how a wrapped
line would look
````
Now correctly adds a selection at the same buffer column in the next
line:
````
1. Very long line to
show [how] a wrapped
line would look
2. Very long line to
show [how] a wrapped
line would look
````
Closes#42137
Release Notes:
- Improved `editor: add selection above` and `editor: add selection
below` to select at the same text column when skipping soft-wrapped
lines, instead of the same visual position
Closes#45046
The root of the issue is anchor resolution. When we apply adjacent
edits, they get merged into a single edit. In the scenario described in
the issue, this is what happens:
1. We create an anchor at the end of each selection (bias::right) on the
snapshot before the edits.
2. We collect the edits and apply them to the buffer.
3. Since the edits are adjacent (>=), the buffer merges them into a
single edit.
4. As a result, we apply one edit to the text buffer, creating a single
visible fragment with length = 3.
5. The buffer ends up with fragments like: [F(len = 3, visible = true),
F(len = 1, visible = false), ...]
6. After the edits, we resolve the previously created anchors to produce
zero-width selections (cursors).
7. All anchors resolve into deleted fragments, so their resolved offset
equals the cumulative visible offset, which is 3.
8. We now have 3 cursors with identical coordinates (0;3).
9. These cursors get merged into a single cursor.
I tried several approaches, but they either felt wrong or didn’t work.
In particular, I tried adjusting anchor resolution using the delta
stored in handle_input, but this doesn’t help because selections are
merged immediately after anchor resolution.
The only workable solution I found is to avoid anchors entirely for the
adjacent-edit case. Instead, we can compute the final cursor positions
directly from the edits and create the selections based on that
information.
Release Notes:
- Fixed an issue where adjacent selection insert would merge cursors
---------
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
This mimics VSCode's `files.readonlyExclude` setting, to allow setting
specific path matches as readonly locations like lockfiles and generated
sources etc.
Also renders a lock icon to the right side of the path names for
readonly files now.
This does a couple more things for completion sake:
- Tabs of readonly buffers now render a file lock icon
- Multibuffer buffer headers now render a file lock icon if the excerpts
buffer is readonly
- ReadWrite multibuffers now no longer allow edits to read only buffers
contained within
Release Notes:
- Added `read_only_files` setting to allow specifying glob patterns of
files that should not be editable by default
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
## Summary
Fixes#44812
The hover highlight for clickable inlay hints was not covering the last
character when the label contained multi-byte UTF-8 characters (e.g.,
`→`).
## Problem
When hovering over an inlay hint like `→ app/Livewire/UserProfile.php`,
the highlight/underline stopped one character short, leaving the final
character unhighlighted.
**Root cause:** `find_hovered_hint_part()` in `hover_popover.rs` used
`part.value.chars().count()` (character count) but `InlayOffset` wraps
`MultiBufferOffset(pub usize)` which is byte-based.
For a label like `→ app/Livewire/UserProfile.php`:
- Byte length: 32 (the `→` character is 3 bytes in UTF-8)
- Character count: 30
This mismatch caused the calculated highlight range to end 2 bytes
short.
## Changes
1. **Use byte length instead of character count** (line 112):
```rust
// Before (buggy)
let part_len = part.value.chars().count();
// After (correct)
let part_len = part.value.len();
```
2. **Fix boundary condition** (line 113): Changed `>` to `>=` for
correct `[start, end)` range semantics when hovering at part boundaries.
3. **Rename variable** for clarity: `hovered_character` →
`offset_in_hint` since it's a byte offset, not a character position.
4. **Add unit test** reproducing the exact scenario from the issue with
multi-byte UTF-8 characters.
## Testing
Added `test_find_hovered_hint_part_with_multibyte_characters` which:
- Verifies the label `→ app/Livewire/UserProfile.php` has 32 bytes but
30 characters
- Tests hovering at the last byte correctly returns the full range
- Tests boundary behavior with multiple label parts containing
multi-byte characters
Release Notes:
- Fixed inlay hint hover highlight not covering the last character when
the label contains multi-byte UTF-8 characters
Closes#45496
Should help #43460
And probably also #44503
The minimap usually renders about 10x more lines of code and shaped text
than the editor. With expensive fonts such as Google Sans Code, this can
cause noticeable lag, since we attempt to synthesize 300+ lines of code
using a heavy font. Because minimap text is rendered at around 2px and
is essentially illegible, it doesn’t make sense to use the custom buffer
font.
Release Notes:
- Improved minimap performance when using custom fonts
---------
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Closes#45960
Release Notes:
- Made the `extension` key context case-insensitive. This e.g. enables
the `markdown: Open Preview` action to also handle files where the
extension is capitalised as MD (case-sensitive file system).
This PR reworks the (still feature-gated) side-by-side diff view to use
a different approach to representing the multibuffers on the left- and
right-hand sides.
Previously, these two multibuffers used identical sets of buffers and
excerpts, and were made to behave differently by adding a new knob to
the multibuffer controlling how diffs are displayed. Specifically, the
left-hand side multibuffer would filter out the added range of each hunk
from the excerpts using a new `FilteredInsertedHunk` diff transform, and
the right-hand side would simply not show the deleted sides of expanded
hunks. This approach has some problems:
- Line numbers, and actions that navigate by line number, behaved
incorrectly for the left-hand side.
- Syntax highlighting and other features that use the buffer syntax tree
also behaved incorrectly for the left-hand side.
In this PR, we've switched to using independent buffers to build the
left-hand side. These buffers are constructed using the base texts for
the corresponding diffs, and their lifecycle is managed by `BufferDiff`.
The red "deleted" regions on the left-hand side are represented by
`BufferContent` diff transforms, not `DeletedHunk` transforms. This
means each excerpt on the left represents a contiguous slice of a single
buffer, which fixes the above issues by construction.
The tradeoff with this new approach is that we now have to manually
synchronize excerpt ranges from the right side to the left, which we do
using `BufferDiffSnapshot::row_to_base_text_row`.
Release Notes:
- N/A
---------
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Co-authored-by: HactarCE <6060305+HactarCE@users.noreply.github.com>
Co-authored-by: Miguel Raz Guzmán Macedo <miguel@zed.dev>
Co-authored-by: Anthony <anthony@zed.dev>
Co-authored-by: Cameron <cameron@zed.dev>
Closes https://github.com/zed-industries/zed/issues/45630
Remote host location alone is not enough to distinguish between remote
worktrees: different remote projects open in different windows will have
the same remote host location and _will_ have the same `WorktreeId`.
Thus, require an associated `WorktreeStore` with all
`WorktreeId`-related trust questions, and store those IDs based on the
store key.
Release Notes:
- Fixed worktree trust handling of multiple projects on the same remote
host
There were several places adding a copy icon button, so thought of
encapsulating the logic to copy a given string into the clipboard (and
other small details like swapping the icon and tooltip if copied) into a
component, making it easier to introduce this sort of functionality in
the future, with fewer lines of code.
All it takes (for the simplest case) is:
```rs
CopyButton::new(your_message)
```
<img width="600" height="714" alt="Screenshot 2025-12-29 at 10 50@2x"
src="https://github.com/user-attachments/assets/e6949863-a056-4855-82d8-e4ffb5d62c90"
/>
Release Notes:
- N/A