eb655653f26b9ee142f97da63fc3efcee9e3da33
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
aecaacdb44 |
git: Move diff hunk operations onto buffer diffs (#63556)
# Objective Keep Git-specific diff-base knowledge in `GitStore`, where Git operations are defined. Related to FR-135. ## Solution Give each `BufferDiff` its supported hunk operations. Keep editor hooks limited to rendering custom controls. ## 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 |
||
|
|
677e8174b5 |
Flush all persistence threads for the rest for various shutdown cases (#63213)
Follow-up to https://github.com/zed-industries/zed/pull/60477 Closes #25022 We have more places that need a similar synchronization before quitting the app: restarts on update, reloading the workspace. On top of it, two more findings: * `on_app_will_quit` was redundant: the global `on_app_quit` hook flushes a strict superset of the same tasks and runs before windows are cleared, while the entity hook held only a weak handle and could never flush the `Window`-dependent workspace state anyway. * previously, shutdown was run as `cx.spawn`, yet main threads got parked on app shutdown: now using `cx.background_spawn` instead Release Notes: - Improved data persistence during various app shutdown cases --------- Co-authored-by: Kostia R <k-bx@k-bx.com> |
||
|
|
1155a5becd |
Render control characters in tab titles and project panel entries (#62875)
# Objective Fixes #62664 File names may contain control characters (`\n`, `\r`, `\t`, …) on most platforms. Zed rendered them verbatim, so a file named `notes\ndraft.md` broke the layout of its tab and of its project panel entry instead of showing a readable name. The same held anywhere else a name reached the screen without going through `Label::single_line`. ## Solution The substitution lives in one shared place, `ui::utils::replace_control_characters`, reached through `Label::single_line`. `\n` keeps rendering as the `⏎` Zed already used, so nothing that renders correctly today changes; every other C0 control character maps onto the Unicode "Control Pictures" block by a single rule (`U+2400 + code point`), giving `␉` for tab and `␍` for carriage return. `DEL` maps to `␡`. C1 controls are left alone, having no equivalent there. Where that is wired in: - **`Label::single_line`** — replaces its previous `\n`-only substitution. The project panel already used it everywhere, including folded directory components, so the panel is fixed by this alone. - **Editor tabs** and the **default `Item::tab_content`**, neither of which called `single_line`. - **Terminal tab titles**, which render through their own `tab_content`. Those titles come from OSC escape sequences, so the control characters in them are attacker-controlled. - **`HighlightedLabel::single_line`**, which never substituted anything — not even `\n`. See below. - **The file finder**, for both the file name and the path. - **Nine `tab_content` overrides in git_ui**, by deleting them. - **`HighlightedMatchWithPaths`**, for both the match label and its paths — it backs the tab switcher and the outline panel, among others. ### `HighlightedLabel` needs its offsets moved, not just its text Its highlight indices are byte offsets, and every stand-in is wider in bytes than the character it replaces, so the offsets have to move with the text. Left alone they index into the middle of a character, and `highlight_ranges` slices the string at exactly those offsets — which panics in release builds too. The constructor's `debug_panic!` does not cover this, since `single_line` runs after construction. So `replace_control_characters_remapping_offsets` substitutes and remaps in one pass, over an old-to-new byte offset table built the way `ensure_uniform_list_compatible_label` does it in `lsp_store`. This also fixes the call sites that already asked for a single line, including the branch picker and the tabular column filter values. ### Deleting the git_ui overrides Nine files replicated the default `Item::tab_content` verbatim except for the colour, hardcoding `selected ? Default : Muted` instead of `params.text_color()`. Deleting them lets those tabs inherit the fixed default, and fixes a second bug along the way: none of them dimmed when the pane lost focus. Titles and icons are unaffected — they come from `tab_content_text` and `tab_icon`, which the default calls. `git_graph.rs` already did it this way. ### Tabular column headers These never went through a `Label` at all: the raw `SharedString` was a child of a `div`. They now display stand-ins, while right-click-copy still yields the real column name. Two notes for reviewers: - Both helpers avoid allocating when there is nothing to replace, so the common path is untouched. The previous `self.label.replace('\n', "⏎")` allocated a `String` on every render for every label — including every visible project panel entry, every frame. - Every stand-in is exactly one character, so character offsets are preserved and the existing `truncate_and_trailoff` math on tab titles stays correct. ## Testing - Unit tests cover both helpers: each control character's substitution, repeated occurrences, multi-byte characters (accents, emoji), the borrow-vs-own behaviour, the preserved character count, C1 passthrough, and — for the remapping — offsets before, at and after a replacement, offsets at and past the end, and the invariant that every remapped offset lands on a character boundary. - Unit tests cover `Label::single_line` and `HighlightedLabel::single_line`, the entry points every call site uses. `highlighted_label.rs` had no tests before. - `cargo test -p ui -p file_finder -p workspace -p project_panel -p git_ui -p git_ui_core -p terminal_view -p tabular_data_preview` passes (774 tests), as do `cargo clippy` and `cargo fmt --check`. - No existing test changes behaviour: tests assert on `tab_content_text`, which is untouched; only rendering paths changed. - Verified manually on macOS (aarch64) — see Showcase. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments — none added - [x] The content adheres to Zed's UI standards - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase A directory holding `report<TAB>table.csv`, `notes<LF>draft.md`, `carriage<CR>return.txt` and a normally named `normal.txt`, all four open as tabs. **Before**  **After**  Three things change: 1. **The `notes<LF>draft.md` tab** is the clearest one. Before, the literal newline splits the tab across two lines — `notes` above `draft.md` — distorting the whole tab bar. After, it stays on one line. 2. **`carriage<CR>return.txt` in the project panel** renders as `carriagereturn.txt` before: the `\r` is completely invisible, so the name reads as one word and there is no way to tell a character is there. After, it renders as `carriage␍return.txt`. 3. **`report<TAB>table.csv`** shows a bare gap before, indistinguishable from a space. After, it renders as `report␉table.csv`. Note that `notes<LF>draft.md` looks the same in the project panel in both shots: that entry already called `single_line`, which already handled `\n`. That is precisely the asymmetry this PR removes. ### File finder Before, the newline also breaks the list itself — the `notes<LF>draft.md` row grows to two lines and overlaps the row beneath it. **Before**  **After**  Searching for `table` exercises the offset remapping, the match falling after the control character: **Before**  **After**  One thing this PR does **not** cover: the breadcrumb below the tab bar still renders the raw tab character, as it goes through a different path. ## Release Notes: - Fixed file names containing control characters, such as tabs and newlines, rendering unreadably in tabs, the project panel, the file finder, the tab switcher and terminal tab titles. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
0500fd9ee9 |
git: Add diff_base setting for showing changes since the default branch (#61501)
# Objective Let git indicators — the editor gutter, file colors, and `git::Diff` — show all changes on the current branch relative to its merge base with the default branch, instead of only uncommitted changes. Supersedes #60398; thanks to @samuelcolvin for the original implementation and motivation. Closes FR-135 ## Solution - New `git.diff_base` setting (`"head"` | `"default_branch"`), applied live and toggleable per session from the editor controls menu ("Diff Against Default Branch"). - Statuses come from a real merge-base-to-worktree tree diff (`git diff --merge-base`), so local edits that revert branch changes correctly show as unchanged. - `GitStore` shares one `DiffBufferList` per repository with the Branch Diff view; `repo_snapshots` and `project_path_git_status` keep returning index/worktree truth, while display surfaces use separate `display_*` APIs. - `BufferDiff` now records what its base is (`DiffBaseKind`); hunks whose base isn't HEAD are read-only in the gutter — stage/restore buttons and keybindings are inert, so committed work can't be silently rewritten. - `git::Diff` follows the setting; new `git::DiffHead` always opens the HEAD diff; `git::BranchDiff` is renamed `git::DiffBranch` (deprecated alias kept). Tradeoffs / known limitations: - Hunk-level staging is unavailable while in `default_branch` mode (whole-file staging via the git panel still works). Staging just the uncommitted sub-ranges of a branch hunk is a follow-up. - Remote hosts running an older server ignore the new `GetTreeDiff.includes_worktree` proto field and degrade to committed-changes-only branch diffs. - Repositories with no resolvable default branch fall back to HEAD-relative behavior; a failed first resolution retries on the next branch-list change. ## Testing - Real-git-repo tests for the merge-base-to-worktree diff's edge cases: files recreated after index deletion, committed deletions recreated on disk, and symlinks. - GPUI tests for status semantics (a branch change reverted on disk shows clean), `git::Diff` routing, live setting changes, and read-only hunk enforcement (restore/stage leave buffer and index untouched). ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Git: Added a `git.diff_base` setting (`"head"` or `"default_branch"`) that makes the editor gutter, file colors, and diff view show all changes on the current branch since its merge base with the default branch, instead of only uncommitted changes. --------- Co-authored-by: Ben Kunkle <ben@zed.dev> |
||
|
|
48192372a0 |
Git partially staged changes (#46541)
This PR explores the addition of a new feature and UI to improve visibility into partially staged commits. Currently, the Git panel shows tracked and untracked changes, but it does not clearly distinguish between staged and unstaged changes. As a result, it’s difficult to quickly see which changes are not staged in the current UI. Both staged and unstaged changes are combined into the `Uncommitted Changes` multibuffer. This developer experience differs from other editors, most notably VS Code; which presents separate Staged Changes and Changes lists. ### Staged and unstaged diffs in multibuffers This PR introduces an alternative UI for unstaged changes that aligns with the overall Zed experience. Instead of showing changes on a per-file basis, staged and unstaged diffs are each displayed in their own multibuffers, similar to how `Uncommitted Changes` currently works. For example the following screenshot shows the current `Uncommitted Changes` on the left, the `Staged Changes` in the middle and the `Unstaged Changes` buffer on the right for comparison <img width="1408" height="859" src="https://github.com/user-attachments/assets/aa709f7a-041d-4cb1-95d6-84c0f5fff688" /> ### Indicators/interactions The new multibuffers can be opened in two ways: 1. Via a new `U` chip, which appears when a file has unstaged changes 2. Via new menu options (See screenshots below for both interaction paths.) <table> <tr> <td style="text-align: center; vertical-align: top;"> <p>via the chip</p> <img height="400" src="https://github.com/user-attachments/assets/3ef69f02-b787-499c-959a-25f50b3728e8" alt="Via the chip" /> </td> <td style="text-align: center; vertical-align: top;"> <p>via the menu</p> <img height="400" src="https://github.com/user-attachments/assets/f5be8b6d-ccdc-4420-bd29-75570b558016" alt="Via the menu" /> </td> </tr> </table> ### Design goals - minimally intrusive UI changes (small new badge and menu items) - adhere by Zed'ism (use multibuffer where possible) - avoid disabling any current interactions (Uncommitted Changes ui is unchanged) - avoid introducing an app level view mode (no new settings needed) ### Experience goals - make it easy to see what changes are not staged - make it easy to see that a file has unstaged changes (avoid developers accidently leaving out changes in a commit; a personal issue that I have when using Zed) - elegantly handle large file's unstaged changes (follows the same collapse and expanding seen in `Uncommitted Changes`) ### How to try - Clone the repo and run `cargo run` - Make a change to a file and stage it - Make another change to the file (the `U` indicator will appear) - Click the `U` to see the unstaged view ### Open questions/rough edges - [ ] determine if this user experience is useful for others - [ ] ensure all interactions work as expected (response to all update cases) In general I'm really interested in hearing the community's feedback about this interface, more than happy to make any changes or explore a different solution! ### Related issue: - https://github.com/zed-industries/zed/pull/36646 - https://github.com/zed-industries/zed/issues/26560 Release Notes: - Support partially staged commit multibuffers via a staged and unstaged changes view. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cole Miller <cole@zed.dev> |