This PR adds word/character diff for expanded diff hunks that have both
a deleted and added section, as well as a setting `word_diff_enabled` to
enable/disable word diffs per language.
- `word_diff_enabled`: Defaults to true. Whether or not expanded diff
hunks will show word diff highlights when they're able to.
### Preview
<img width="1502" height="430" alt="image"
src="https://github.com/user-attachments/assets/1a8d5b71-449e-44cd-bc87-d6b65bfca545"
/>
### Architecture
I had three architecture goals I wanted to have when adding word diff
support:
- Caching: We should only calculate word diffs once and save the result.
This is because calculating word diffs can be expensive, and Zed should
always be responsive.
- Don't block the main thread: Word diffs should be computed in the
background to prevent hanging Zed.
- Lazy calculation: We should calculate word diffs for buffers that are
not visible to a user.
To accomplish the three goals, word diffs are computed as a part of
`BufferDiff` diff hunk processing because it happens on a background
thread, is cached until the file is edited, and is only refreshed for
open buffers.
My original implementation calculated word diffs every frame in the
Editor element. This had the benefit of lazy evaluation because it only
calculated visible frames, but it didn't have caching for the
calculations, and the code wasn't organized. Because the hunk
calculations would happen in two separate places instead of just
`BufferDiff`. Finally, it always happened on the main thread because it
was during the `EditorElement` layout phase.
I used Zed's
[`diff_internal`](02b2aa6c50/crates/language/src/text_diff.rs (L230-L267))
as a starting place for word diff calculations because it uses
`Imara_diff` behind the scenes and already has language-specific
support.
#### Future Improvements
In the future, we could add `AST` based word diff highlights, e.g.
https://github.com/zed-industries/zed/pull/43691.
Release Notes:
- git: Show word diff highlight in expanded diff hunks with less than 5
lines.
- git: Add `word_diff_enabled` as a language setting that defaults to
true.
---------
Co-authored-by: David Kleingeld <davidsk@zed.dev>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Co-authored-by: Lukas Wirth <lukas@zed.dev>
Release Notes:
- Added a keybinding to open the `settings.json` file when the Settings
UI is in focus: `cmd-,` (macOS) / `ctrl-,` (Windows / Linux).
- A tooltip was added to the `Edit in settings.json` button to show this
keybinding.
We were using `std::path::Path::strip_prefix` to determine which
repository an absolute path belongs to, which doesn't work when the
paths are Windows-style but the code is running on unix. Replace it with
a platform-agnostic implementation of `strip_prefix`.
Release Notes:
- Fixed git features not working when a Windows host collaborates with a
unix guest
Previously, this was controllable via the undocumented
ZED_WINDOW_DECORATIONS environment variable (added in #13866). Using an
environment variable for this is inconvenient because it requires users
to set that environment variable somehow before starting Zed, such as in
the .desktop file or persistently in their shell. Controlling this via a
Zed setting is more convenient.
This does not modify the design of the titlebar in any way. It only
moves the existing option from an environment variable to a Zed setting.
Fixes#14165
Client-side decorations (default):
<img width="3840" height="2160" alt="image"
src="https://github.com/user-attachments/assets/525feb92-2f60-47d3-b0ca-47c98770fa8c"
/>
Server-side decorations in KDE Plasma:
<img width="3840" height="2160" alt="image"
src="https://github.com/user-attachments/assets/7379c7c8-e5e3-47ba-a3ea-4191fec9434d"
/>
Release Notes:
- Changed option for Wayland server-side decorations from an environment
variable to settings.json field
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Deals with https://github.com/zed-industries/zed/issues/5259
Highlights brackets with different colors based on their depth.
Uses existing tree-sitter queries from brackets.scm to find brackets,
uses theme's accents to color them.
https://github.com/user-attachments/assets/cc5f3aba-22fa-446d-9af7-ba6e772029da
1. Adds `colorize_brackets` language setting that allows, per language
or globally for all languages, to configure whether Zed should color the
brackets for a particular language.
Disabled for all languages by default.
2. Any given language can opt-out a certain bracket pair by amending the
brackets.scm like `("\"" @open "\"" @close) ` -> `(("\"" @open "\""
@close) (#set! rainbow.exclude))`
3. Brackets are using colors from theme accents, which can be overridden
as
```jsonc
"theme_overrides": {
"One Dark": {
"accents": ["#ff69b4", "#7fff00", "#ff1493", "#00ffff", "#ff8c00", "#9400d3"]
}
},
```
Release Notes:
- Added bracket colorization (rainbow brackets) support. Use
`colorize_brackets` language setting to enable.
---------
Co-authored-by: MrSubidubi <dev@bahn.sh>
Co-authored-by: Lukas Wirth <lukas@zed.dev>
Co-authored-by: MrSubidubi <finn@zed.dev>
Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Closes _unknown_
<img width="1212" height="463" alt="image"
src="https://github.com/user-attachments/assets/ec00fcf0-7eb9-4291-b1e2-66e014dc30ac"
/>
This PR places the file_name before the file_path so that when the panel
is slim it is still usable, mirrors the behaviour of the file picker
(cmd+P)
Release Notes:
- Improved readability of files in the git changes panel
Closes https://github.com/zed-industries/zed/issues/42094
This will make it consistent with the regular/main page. Also ended up
fixing a bug along the way where this button wouldn't work for subpage
items.
Release Notes:
- settings ui: Fixed a bug where the "Edit in settings.json" wouldn't
work for subpages like all the Language pages.
Closes#4533 (partly at least)
Release Notes:
- Added `project_panel.sort_mode` option to control explorer file sort
(directories first, mixed, files first)
## Summary
Adds three sorting modes for the project panel to give users more
control over how files and directories are displayed:
- **`directories_first`** (default): Current behaviour - directories
grouped before files
- **`mixed`**: Files and directories sorted together alphabetically
- **`files_first`**: filed grouped before directories
## Motivation
Users coming from different editors and file managers have different
expectations for file sorting. Some prefer directories grouped at the
top (traditional), while others prefer the macOS Finder-style mixed
sorting where "Apple1/", "apple2.tsx" and "Apple3/" appear
alphabetically mixed together.
### Screenshots
New sort options in settings:
<img width="515" height="160" alt="image"
src="https://github.com/user-attachments/assets/8f4e6668-6989-4881-a9bd-ed1f4f0beb40"
/>
Directories first | Mixed | Files first
-------------|-----|-----
<img width="328" height="888" alt="image"
src="https://github.com/user-attachments/assets/308e5c7a-6e6a-46ba-813d-6e268222925c"
/> | <img width="327" height="891" alt="image"
src="https://github.com/user-attachments/assets/8274d8ca-b60f-456e-be36-e35a3259483c"
/> | <img width="328" height="890" alt="image"
src="https://github.com/user-attachments/assets/3c3b1332-cf08-4eaf-9bed-527c00b41529"
/>
### Agent usage
Copilot-cli/claude-code/codex-cli helped out a lot. I'm not from a rust
background, but really wanted this solved, and it gave me a chance to
play with some of the coding agents I'm not permitted to use for work
stuff
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This PR makes the `OpenProjectSettings` action open the settings UI in
project settings mode for the first visible worktree, instead of opening
the file. It also adds a `OpenProjectSettingsFile` action that maintains
the old behavior.
Finally, this PR partially fixes a bug where the settings UI won't load
project settings when the settings window is loaded before opening a
project/workspace. This happens because the global `app_state` isn't
correct in the `Subscription` that refreshes the available setting files
to open. The bug is still present in some cases, but it's out of scope
for this PR.
Release Notes:
- settings ui: Project Settings action now opens settings UI instead of
a file
There was a TODO in `crates/settings/src/settings_content/theme.rs` to
make this rename.
This PR is just splitting off this change from
https://github.com/zed-industries/zed/pull/40035 to make reviewing that
one a bit easier since that PR is a bit more involved than expected.
Release Notes:
- N/A
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Closes#41533
Both of the issues in the release notes that are fixed in this PR, were
caused by incorrect usage of the `window.use_state` API.
The first issue was caused by calling `window.use_state` in a render
helper, resulting in the element ID used to share state being the same
across different pages, resulting in the state being re-used when it
should have been re-created. The fix for this was to move the
`window.state` (and rendering logic) into a `impl RenderOnce` component,
so that the IDs are resolved during the render, avoiding the state
conflicts.
The second issue is caused by using a `move` closure in the
`window.use_state` call, resulting in stale closure values when the
window state is re-used.
Release Notes:
- settings_ui: Fixed an issue where some dropdown menus would show
options from a different dropdown when clicked
- settings_ui: Fixed an issue where attempting to change a setting in a
dropdown back to it's original value after changing it would do nothing
## Add relative line numbers on wrapped lines, take 2
This is a rework of https://github.com/zed-industries/zed/pull/39268
that excludes
e7096d27a6.
This commit introduced some line number rendering issues as described in
https://github.com/zed-industries/zed/issues/41422.
While @ConradIrwin suggested we try to pass in the buffer rows from the
calling method instead of the snapshot, that
appears to have had unintended consequences and I don't think the two
calculations were intended to do the same thing. Hence, this PR has
removed those changes.
This PR also includes the migration fix originally done by @MrSubidubi
in https://github.com/zed-industries/zed/pull/41351.
## Original PR description and release notes.
**Problem:** Current relative line numbering creates a mismatch with
vim-style navigation when soft wrap is enabled. Users must mentally
calculate whether target lines are wrapped segments or logical lines,
making `<n>j/k` navigation unreliable and cognitively demanding.
**How things work today:**
- Real line navigation (`j/k` moves by logical lines): Requires
determining if visible lines are wrapped segments before jumping. Can't
jump to wrapped lines directly.
- Display line navigation (`j/k` moves by display rows): Line numbers
don't correspond to actual row distances for multi-line jumps.
**Proposed solution:** Count and number each display line (including
wrapped segments) for relative numbering. This creates direct
visual-to-navigational correspondence, where the relative number shown
always matches the `<n>j/k` distance needed.
**Benefits:**
- Eliminates mental overhead of distinguishing wrapped vs. logical lines
- Makes relative line numbers consistently actionable regardless of wrap
state
- Preserves intuitive "what you see is what you navigate" principle
- Maintains vim workflow efficiency in narrow window scenarios
Also explained and discussed in
https://github.com/zed-industries/zed/discussions/25733.
Release Notes:
- Added support for counting wrapped lines as relative lines and for
displaying line numbers for wrapped segments. Changes
`relative_line_numbers` from a boolean to an enum: `enabled`,
`disabled`, or `wrapped`.
This PR adds the ability to configure which files are considered
"hidden" in the project panel and toggle their visibility with a
keyboard shortcut. Previously, the editor hardcoded dotfiles as hidden -
now users can customize the pattern and quickly show/hide them.
### Release Notes
- Added `project_panel::ToggleHideHidden` action with keyboard shortcuts
to toggle visibility of hidden files
- Added configurable `hidden_files` setting to customize which files are
marked as hidden (defaults to `**/.*` for dotfiles)
### Motivation
This change allows users to:
1. Quickly toggle hidden file visibility with a keyboard shortcut
2. Customize which files are considered "hidden" beyond just dotfiles
3. Better organize their project panel by hiding build artifacts, logs,
or other generated files
### Usage
**Toggle hidden files:**
- **macOS:** `cmd-alt-.`
- **Linux:** `ctrl-alt-.`
- **Windows:** `ctrl-alt-.`
**Customize patterns in settings:**
```json
{
"hidden_files": ["**/.*", "**/*.tmp", "**/build/**"]
}
```
### Changes
**Core Implementation:**
- Added `hidden_files` setting (defaults to `**/.*` to match current
dotfile behavior)
- Replaced hardcoded `name.starts_with('.')` logic with configurable
pattern matching using `PathMatcher`
- Hidden status propagates through directory hierarchies (if a directory
is hidden, all children inherit that status)
**User-Facing:**
- Added `ToggleHideHidden` action in the project panel
- Added keyboard shortcuts for all platforms
- Added settings UI entry for configuring `hidden_files` patterns
**Testing:**
- Added comprehensive test coverage validating default behavior, custom
patterns, propagation, and settings changes
### Implementation Notes
- Uses `PathMatcher` for efficient glob matching
- Settings changes automatically trigger worktree re-indexing
- No breaking changes - defaults maintain current behavior (hiding
dotfiles)
---
**Disclaimer:** This was implemented with a fair amount of copy/paste
(particularly the gitignore handling), trial and error, and a healthy
dose of Claude.
### Screenshots
**Project Panel with hidden files visible:**
<img width="1368" height="935" alt="Screenshot 2025-10-30 at 3 15 53 AM"
src="https://github.com/user-attachments/assets/1cbe90ce-504c-4f9b-bca8-bef02ab961be"
/>
**Project Panel with hidden files hidden:**
<img width="1363" height="917" alt="Screenshot 2025-10-30 at 3 16 07 AM"
src="https://github.com/user-attachments/assets/9297f43e-98c7-4b19-be8f-3934589d6451"
/>
**Toggle action in command palette:**
<img width="565" height="161" alt="Screenshot 2025-10-30 at 3 17 26 AM"
src="https://github.com/user-attachments/assets/4dc9e7b6-9c29-4972-b886-88d8018905da"
/>
Release Notes:
- Added the ability to configure glob patterns for files treated as
hidden in the project panel using the `hidden_files` setting.
- Added an action `project panel: toggle hidden files` to quickly show
or hide hidden files in the project panel.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
A user on Discord requested this feature:
https://discord.com/channels/869392257814519848/1434188637389717556/1434188637389717556
I added a scrollbar setting called `completion_menu_scrollbar` to the
completion menu and defaulted it to "Never" to match past behavior.
Release Notes:
- editor: Add `editor.completion_menu_scrollbar` setting to show a
scrollbar in the completion menu
Release Notes:
- settings_ui: Added the ability to copy a link to a given setting,
allowing users to quickly open the settings window at the correct
location in a faster way.
---------
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Co-authored-by: Ben Kunkle <ben@zed.dev>
Closes#41422
This completely broke line numbering as described in the linked issue
and scrolling up does not have the correct numbers any more.
Release Notes:
- NOTE: The `relative_line_numbers` change
(https://github.com/zed-industries/zed/pull/39268) was reverted and did
not make the release cut!
**Problem:** Current relative line numbering creates a mismatch with
vim-style navigation when soft wrap is enabled. Users must mentally
calculate whether target lines are wrapped segments or logical lines,
making `<n>j/k` navigation unreliable and cognitively demanding.
**How things work today:**
- Real line navigation (`j/k` moves by logical lines): Requires
determining if visible lines are wrapped segments before jumping. Can't
jump to wrapped lines directly.
- Display line navigation (`j/k` moves by display rows): Line numbers
don't correspond to actual row distances for multi-line jumps.
**Proposed solution:** Count and number each display line (including
wrapped segments) for relative numbering. This creates direct
visual-to-navigational correspondence where the relative number shown
always matches the `<n>j/k` distance needed.
**Benefits:**
- Eliminates mental overhead of distinguishing wrapped vs. logical lines
- Makes relative line numbers consistently actionable regardless of wrap
state
- Preserves intuitive "what you see is what you navigate" principle
- Maintains vim workflow efficiency in narrow window scenarios
Also explained an discussed in
https://github.com/zed-industries/zed/discussions/25733.
Release Notes:
Release Notes:
- Added support for counting wrapped lines as relative lines and for
displaying line numbers for wrapped segments. Changes
`relative_line_numbers` from a boolean to an enum: `enabled`,
`disabled`, or `wrapped`.
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
1. Settings Viewed: Whenever someone opens or refocus the settings ui
via an action
2. Settings Closed: When the settings ui window is closed
3. Settings Navigation Clicked: The category and subcategory that a user
clicked on
4. Settings Error Shown: Whenever an error banner shows up
5. Settings Changed: The setting a user changed through the UI
cc: @katie-z-geer
Release Notes:
- N/A
Using the cool, [recently
added](https://github.com/zed-industries/zed/pull/40940) `focus-visible`
support in some components. This will be particularly nice in the
settings UI, as it will not display the focus styles if you're
navigating it with a pointer device as opposed to the keyboard.
Release Notes:
- N/A
Closes#40351
The leak mainly showed up in the appearance page because it had a lot of
dropdown menus. The problem occurred because the drop-down menus were
creating a new entity on each frame instead of using the
`window.use_state...` API.
Release Notes:
- settings ui: Fixed memory leak in UI
---------
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
I made three significant changes in this PR.
1. `SettingsWindow::fetch_files` now creates
`SettingsUiFile::Project(..)` for any worktree that contains no project
settings.
2. `update_settings_file` now creates an empty settings file if a
worktree doesn't contain one.
3. `open_current_settings_file` also creates a settings file if the
current one doesn't exist.
Release Notes:
- settings ui: Enable editing project settings for worktrees that don't
have a project setting file.
This PR gets the `SettingsWindow` struct to subscribe to all
`Entity<Project>` events and any future project entities that are
created. When a project emits an event that signals a worktree has been
added or removed, the settings window refetches all settings files it
can find.
This fixes a bug where the settings ui would notice some project
settings that were created or opened after the `SettingsWindow` has been
initialized.
I also renamed `LOCAL` file mask to `PROJECT` to be inline with the
`SettingsFile` naming convention.
Release Notes:
- settings ui: Fix bug where project setting files wouldn't be detected
if they were created or opened after while an active settings window is
open
Just tidying this up a bit. Really have to fix this Banner component at
some point 😅 Having to add some spacing hacks to make it perfect here
that are not ideal and should be baked into the component.
Release Notes:
- N/A
Now that we have two surface areas that open as separate windows, it's
important they're consistent with one another. This PR make the settings
UI and rules library windows more similar by having them use the same
minimum window size and similar styles for their navbar given they have
fundamentally the same design (nav on the left and content on the
right).
Release Notes:
- N/A
After clicking on the file drop-down and selecting a file, both the
selected file and the first drop-down entry would be the same file name
instead of overwriting a file name.
Release Notes:
- settings ui: Fix bug where duplicate file names showed in the header
files
Closes#39172
This refactors when we resolve UI keybindings in an effort to reduce
flickering whilst painting these: Previously, we would always resolve
these upon creating the binding. This could lead to cases where the
corresponding context was not yet available and no binding could be
resolved, even if the binding was then available on the next presented
frame. Following that, on the next rerender of whatever requested this
keybinding, the keybind for that context would then be found, we would
render that and then also win a layout shift in that process, as we went
from nothing rendered to something rendered between these frames.
With these changes, this now happens less often, because we only look
for the keybinding once the context can actually be resolved in the
window.
| Before | After |
| --- | --- |
|
https://github.com/user-attachments/assets/adebf8ac-217d-4c7f-ae5a-bab3aa0b0ee8
|
https://github.com/user-attachments/assets/70a82b4b-488f-4a9f-94d7-b6d0a49aada9
|
Also reduced cloning in the keymap editor in this process, since that
requiered changing due to this anyway.
Release Notes:
- Fixed some cases where keybinds would appear with a slight delay,
causing a flicker in the process