This PR fixes an issue where the horizontal scrollbar was sometimes not
rendered despite being needed for the outline and project panels.
The issue occured since `self.width` does not neccessarily have to be
set when the scrollbar is rendered (it is only set on panel resize).
However, the check for a `width` is not needed at all since the
scrollbar constructor determines whether a scrollbar has to be rendered
or not. Hence, this does not need to be special-cased.
Furthermore, since `Scrollbar::horizontal()` returns `Some(...)` when a
scrollbar needs to be rendered, we do not have to check for this
seperately on the scroll handle and can just map on the option. This
simplifies the code a bit.
| `main` | This PR |
| --- | --- |
|

|

|
Release Notes:
- Fixed an issue where the horizontal scrollbar would not render in the
project and outline panels.
https://github.com/zed-industries/zed/issues/30972 brought up another
case where our context is not enough to track the actual source of the
issue: we get a general top-level error without inner error.
The reason for this was `.ok_or_else(|| anyhow!("failed to read HEAD
SHA"))?; ` on the top level.
The PR finally reworks the way we use anyhow to reduce such issues (or
at least make it simpler to bubble them up later in a fix).
On top of that, uses a few more anyhow methods for better readability.
* `.ok_or_else(|| anyhow!("..."))`, `map_err` and other similar error
conversion/option reporting cases are replaced with `context` and
`with_context` calls
* in addition to that, various `anyhow!("failed to do ...")` are
stripped with `.context("Doing ...")` messages instead to remove the
parasitic `failed to` text
* `anyhow::ensure!` is used instead of `if ... { return Err(...); }`
calls
* `anyhow::bail!` is used instead of `return Err(anyhow!(...));`
Release Notes:
- N/A
Closes#27642
Currently, the `Open (cmd-o)` action is used to open a local folder
picker when in a local project, and Zed's remote path modal in the case
of a remote project. While this looks intentional, there is now no way
to open a local project when you are in a remote project window. Neither
by shortcut, nor by UI, as the "Open Local Folder" button uses the same
`Open` action.
The reverse is not true, as we already have an `Open Remote
(ctrl-cmd-o)` action to open the remote modal, where you can select "Add
Folder" which opens the same Zed's remote path modal. This already works
in both local and remote window cases.
This PR makes two changes:
1. It changes `Open (cmd-o)` action such that it should always open the
local file picker regardless of which project is currently open, local
or remote. This way we have two non-ambiguios actions `Open` and `Open
Remote`.
2. It also changes the "Open a project" button (which shows up when no
project is open in the project panel) to open the recent modal (which
contains buttons to open either local or remote) instead of choosing on
behalf of the user.
P.S. If we want to open Zed's remote path modal directly, it should be
different action altogether. Not covered for now.
Release Notes:
- Fixed issue where "Open local folder" was not opening folder picker
when connected to a remote host.
- Added `from_existing_connection` flag to `OpenRemote` action to
directly open path picker for current connection, bypassing the Remote
Projects modal.
Closes#27834
This PR changes project panel, outline panel and collab panel
serialization from global to per-workspace, so configurations are
restored only within the same workspace. Handles remote workspaces too.
Opening a new window will start with a fresh panel defaults e.g. width.
Release Notes:
- Improved project panel, outline panel, and collab panel to persist
width on a per-workspace basis. New windows will use the width specified
in the `default_width` setting.
### Todo
* [x] Allow opening `ssh://username@host:/` from the CLI
* [x] Allow selecting `/` in the `open path` picker
* [x] Allow selecting the home directory in the `open path` picker
Release Notes:
- Changed the initial state of the SSH project picker to show the full
path to your home directory on the remote machine, instead of `~`.
- Added the ability to open `/` as a project folder over SSH
---------
Co-authored-by: Agus Zubiaga <hi@aguz.me>
Nathan here: I also tacked on a bunch of UI refinement.
Release Notes:
- Introduced the ability to follow the agent around as it reads and
edits files.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
resolves#24655resolves#23945
I haven't yet added a default binding for the new command. #27797 added `:ls` and
`:buffers` which in my opinion should use the global searchable version
given that that matches the vim semantics of those commands better than
just showing the tabs in the local pane.
There's also a question of what to do when you select a tab from another
pane, should the focus jump to that pane or should that tab move to the
currently focused pane? For now I've implemented the former.
Release Notes:
- Added `tab_switcher::ToggleAll` to search open tabs from all panes and focus the selected one.
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Things this doesn't currently handle:
- [x] ~testing~
- ~we really need an snapshot test that takes a vscode settings file
with all options that we support, and verifies the zed settings file you
get from importing it, both from an empty starting file or one with lots
of conflicts. that way we can open said vscode settings file in vscode
to ensure that those options all still exist in the future.~
- Discussed this, we don't think this will meaningfully protect us from
future failures, and we will just do this as a manual validation step
before merging this PR. Any imports that have meaningfully complex
translation steps should still be tested.
- [x] confirmation (right now it just clobbers your settings file
silently)
- it'd be really cool if we could show a diff multibuffer of your
current settings with the result of the vscode import and let you pick
"hunks" to keep, but that's probably too much effort for this feature,
especially given that we expect most of the people using it to have an
empty/barebones zed config when they run the import.
- [x] ~UI in the "welcome" page~
- we're planning on redoing our welcome/walkthrough experience anyways,
but in the meantime it'd be nice to conditionally show a button there if
we see a user level vscode config
- we'll add it to the UI when we land the new walkthrough experience,
for now it'll be accessible through the action
- [ ] project-specific settings
- handling translation of `.vscode/settings.json` or `.code-workspace`
settings to `.zed/settings.json` will come in a future PR, along with UI
to prompt the user for those actions when opening a project with local
vscode settings for the first time
- [ ] extension settings
- we probably want to do a best-effort pass of popular extensions like
vim and git lens
- it's also possible to look for installed/enabled extensions with `code
--list-extensions`, but we'd have to maintain some sort of mapping of
those to our settings and/or extensions
- [ ] LSP settings
- these are tricky without access to the json schemas for various
language server extensions. we could probably manage to do translations
for a couple popular languages and avoid solving it in the general case.
- [ ] platform specific settings (`[macos].blah`)
- this is blocked on #16392 which I'm hoping to address soon
- [ ] language specific settings (`[rust].foo`)
- totally doable, just haven't gotten to it yet
~We may want to put this behind some kind of flag and/or not land it
until some of the above issues are addressed, given that we expect
people to only run this importer once there's an incentive to get it
right the first time. Maybe we land it alongside a keymap importer so
you don't have to go through separate imports for those?~
We are gonna land this as-is, all these unchecked items at the bottom
will be addressed in followup PRs, so maybe don't run the importer for
now if you have a large and complex VsCode settings file you'd like to
import.
Release Notes:
- Added a VSCode settings importer, available via a
`zed::ImportVsCodeSettings` action
---------
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
Release Notes:
- Added the ability to copy external files into remote projects by
dragging them onto the project panel.
---------
Co-authored-by: Peter Tripp <petertripp@gmail.com>
Closes#23449
Release Notes:
- Fixed a bug causing shift to get stuck down when the window focus
changes
---------
Co-authored-by: Dino <dinojoaocosta@gmail.com>
- Show yellow warning (instead or error) for leading/trailing
whitespace.
- Do not block user from creating it.
- If you rename existing file/dir which contains leading/trailing
whitespace, it will show error right away.
<img width="250" alt="image"
src="https://github.com/user-attachments/assets/562895ee-3a86-4ecd-bb38-703d1d8b8599"
/>
Release Notes:
- Added warning for leading or trailing whitespace while renaming or
creating new file or directory in Project Panel.
This adds a "workspace-hack" crate, see
[mozilla's](https://hg.mozilla.org/mozilla-central/file/3a265fdc9f33e5946f0ca0a04af73acd7e6d1a39/build/workspace-hack/Cargo.toml#l7)
for a concise explanation of why this is useful. For us in practice this
means that if I were to run all the tests (`cargo nextest r
--workspace`) and then `cargo r`, all the deps from the previous cargo
command will be reused. Before this PR it would rebuild many deps due to
resolving different sets of features for them. For me this frequently
caused long rebuilds when things "should" already be cached.
To avoid manually maintaining our workspace-hack crate, we will use
[cargo hakari](https://docs.rs/cargo-hakari) to update the build files
when there's a necessary change. I've added a step to CI that checks
whether the workspace-hack crate is up to date, and instructs you to
re-run `script/update-workspace-hack` when it fails.
Finally, to make sure that people can still depend on crates in our
workspace without pulling in all the workspace deps, we use a `[patch]`
section following [hakari's
instructions](https://docs.rs/cargo-hakari/0.9.36/cargo_hakari/patch_directive/index.html)
One possible followup task would be making guppy use our
`rust-toolchain.toml` instead of having to duplicate that list in its
config, I opened an issue for that upstream: guppy-rs/guppy#481.
TODO:
- [x] Fix the extension test failure
- [x] Ensure the dev dependencies aren't being unified by Hakari into
the main dependencies
- [x] Ensure that the remote-server binary continues to not depend on
LibSSL
Release Notes:
- N/A
---------
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
This PR completes the process of moving git repository state storage and
scanning logic from the worktree crate to `project::git_store`.
Release Notes:
- N/A
---------
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Conrad <conrad@zed.dev>
Closes https://github.com/zed-industries/zed/issues/11626
Part of https://github.com/zed-industries/zed/issues/12853
`"restore_on_file_reopen": true` in workspace settings can now be used
to enable and disable editor data between file reopens in the same pane:
https://github.com/user-attachments/assets/8d938ee1-d854-42a8-bbc3-2a4e4d7d5933
The settings are generic and panes' data store can be extended for
further entities, beyond editors.
---------------
Impl details:
Currently, the project entry IDs seem to be stable across file reopens,
unlike BufferIds, so those were used.
Originally, the DB data was considered over in-memory one as editors
serialize their state anyway, but managing and exposing PaneIds out of
the DB is quite tedious and joining the DB data otherwise is not
possible.
Release Notes:
- Started to restore editor state on reopen
This is another in the series of PRs to make the GitStore own all
repository state and enable better concurrency control for git
repository scans.
After this PR, the `RepositoryEntry`s stored in worktree snapshots are
used only as a staging ground for local GitStores to pull from after
git-related events; non-local worktrees don't store them at all,
although this is not reflected in the types. GitTraversal and other
places that need information about repositories get it from the
GitStore. The GitStore also takes over handling of the new
UpdateRepository and RemoveRepository messages. However, repositories
are still discovered and scanned on a per-worktree basis, and we're
still identifying them by the (worktree-specific) project entry ID of
their working directory.
- [x] Remove WorkDirectory from RepositoryEntry
- [x] Remove worktree IDs from repository-related RPC messages
- [x] Handle UpdateRepository and RemoveRepository RPCs from the
GitStore
Release Notes:
- N/A
---------
Co-authored-by: Max <max@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Closes: #17543
Release Notes:
- **New Feature:** Introduced the ability to automatically remove files
and directories from the Zed project panel that are specified in
`.gitignore`.
- **Configuration Option:** This behavior can be controlled via the new
`project_panel.hide_gitignore` setting. By setting it to `true`, files
listed in `.gitignore` will be excluded from the project panel.
- **Toggle:** Ability to toggle this setting using the action
`ProjectPanel::ToggleHideGitIgnore`
```json
"project_panel": {
"hide_gitignore": true
},
```
This results in a cleaner and easier to browse project panel for
projects that generate a lot of object files like `xv6-riscv` or `linux`
without needing to tweak `file_scan_exclusions` on `settings.json`
**Preview:**
- With `"project_panel.hide_gitignore": false` (default, this is how zed
currently looks)

- With `"project_panel.hide_gitignore": true`

- Action `ProjectPanel::ToggleHideGitIgnore`

Temporary Workaround For: #27283
This PR can (and should!) be reverted once the underlying inefficiencies
are resolved
Release Notes:
- Files that are 6GB or larger will now not open. This is a temporary
workaround for inefficient handling of large files resulting in
extremely high memory usage, often resulting in system freezing,
requiring a restart of Zed or the entire system.
It doesn't make sense to have `Pixels: Mul<Pixels, Output = Pixels>` as
the output should be `Pixels^2` (area), so these impls are removed. All
code where these impls were used are improved by instead multiplying by
`f32` or `usize`.
Also adds math op impls that are present for `Pixels` but absent for
`ScaledPixels`. Adds missing `Mul<Pixels> for usize` to both.
Release Notes:
- N/A
This is a pure refactoring PR that goes through all the git-related APIs
exposed by the worktree crate and minimizes their use outside that
crate, migrating callers of those APIs to read from the GitStore
instead. This is to prepare for evacuating git repository state from
worktrees and making the GitStore the new source of truth.
Other drive-by changes:
- `project::git` is now `project::git_store`, for consistency with the
other project stores
- the project panel's test module has been split into its own file
Release Notes:
- N/A
---------
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This PR reworks the `FakeGitRepository` type that we use for testing git
interactions, to make it more realistic. In particular, the `status`
method now derives the Git status from the differences between HEAD, the
index, and the working copy. This way, if you modify a file in the
`FakeFs`, the Git repository's `status` method will reflect that
modification.
Release Notes:
- N/A
---------
Co-authored-by: Junkui Zhang <364772080@qq.com>
This is the core change:
https://github.com/zed-industries/zed/pull/26758/files#diff-044302c0d57147af17e68a0009fee3e8dcdfb4f32c27a915e70cfa80e987f765R1052
TODO:
- [x] Use AsyncFn instead of Fn() -> Future in GPUI spawn methods
- [x] Implement it in the whole app
- [x] Implement it in the debugger
- [x] Glance at the RPC crate, and see if those box future methods can
be switched over. Answer: It can't directly, as you can't make an
AsyncFn* into a trait object. There's ways around that, but they're all
more complex than just keeping the code as is.
- [ ] Fix platform specific code
Release Notes:
- N/A
This PR adds a failing test `test_staging_hunks_with_delayed_fs_event`
and makes it pass
Also skips a queued read for git diff states if another read was
requested (less work)
This still doesn't catch all race conditions, but the PR is getting long
so I'll yield this and start another branch
Release Notes:
- N/A
If the user has the `auto_reveal` option enabled, as well as
`file_scan_inclusions` and opens a file that is gitignored but is also
set to be always included, that file won't be revealed in the project
panel. I've personally found this annoying, as the project panel can
provide useful context on where you are in a codebase. It also just
feels weird for it to be out of sync with the editor state.
Release Notes:
- Fixed the interaction between `auto_reveal`, `file_scan_inclusions`,
and `.gitignore` within the Project Panel. Files that are always
included will now be auto-revealed in the Project Panel, even if those
files are also gitignored.
Modified version of #25950. We still use worktree paths, but repo paths
with a status that lie outside the worktree are not excluded; instead,
we relativize them by adding `..`. This makes the list in the git panel
match what you'd get from running `git status` (with the repo's worktree
root as the working directory).
- [x] Implement + test new unrelativization logic
- [x] ~~When collecting repositories, dedup by .git abs path, so
worktrees can share a repo at the project level~~ dedup repos at the
repository selector layer, with repos coming from larger worktrees being
preferred
- [x] Open single-file worktree with diff when activating a path not in
the worktree
Release Notes:
- N/A
Closes#10167
This is take 2 on https://github.com/zed-industries/zed/pull/2341 which
was closed due to lack of migrator.
This PR contains rename of following keymap actions:
```sh
1. ["editor::GoToPrevHunk", { "center_cursor": true }] -> ["editor::GoToPreviousHunk", { "center_cursor": true }]
2. "editor::GoToPrevDiagnostic" -> "editor::GoToPreviousDiagnostic"
3. "editor::ContextMenuPrev" -> "editor::ContextMenuPrevious"
4. "search::SelectPrevMatch" -> "search::SelectPreviousMatch"
5. "file_finder::SelectPrev" -> "file_finder::SelectPrevious"
6. "menu::SelectPrev" -> "menu::SelectPrevious"
7. "editor::TabPrev" -> "editor::Backtab"
```
Release Notes:
- Renamed several keymap actions for consistency (e.g., `GoToPrevHunk` →
`GoToPreviousHunk`, `TabPrev` → `Backtab`). Your existing configured
keybindings will still work. You can click **"Backup and Update"** at
the top of your keymap file to easily update to the new actions.
Co-authored-by: Joseph T. Lyons <JosephTLyons@gmail.com>
This PR fixes a bug where using the project diff editor to restore hunks
from a file that's not open in its own buffer would cause those reverts
to be lost once the project diff drops its excerpts for that file.
The fix is to save the buffers after restoring them but before the
excerpts are (potentially) dropped. This is done for the project diff
editor only. If we fail to save the affected files, we add their buffers
to the active workspace, so that the reverted contents are preserved and
the user can try again to save them.
- [x] Get it working
- [x] Test
- [ ] ~~Clean up boolean soup~~
Co-authored-by: Max <max@zed.dev>
Release Notes:
- N/A
Add support for `stop_at_indent` option for MoveToBeginningOfLine and SelectToBeginningOfLine instead of mixing that with `stop_at_soft_wraps`.
Add emacs mapping for `alt-m` (`back-to-indentation`)
This is follow-up for https://github.com/zed-industries/zed/pull/25457
If you open a project without any open buffer, focus on the project
panel, navigate with arrows to a given entry, and hit space, you will
mark and open the file in the buffer. This is all correct. If you then
hit `escape` to clear the marked entries, nothing happens to the open
buffer, and the marked styled in the project panel entry go away. This
is all correct. The wrong behavior happens if you now hit space again on
the active entry. That should mark it, and thus change its styles, but
it doesn't happen. You just see it upon moving to a different entry with
arrow up/down.
Release Notes:
- Fixed project panel entry not being marked when triggering open action
via keyboard.
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Closes#25145
Now, upon pasting a file into the project panel after a copy or cut
operation, it will open in the editor. This buffer in the editor will be
in focus if there is no need to rename the newly pasted file. If a
rename is pending, it simply focuses on the rename editor.
https://github.com/user-attachments/assets/563b22ec-d1f6-4d92-af18-29d10620832c
Future: After the rename is completed, we can decide to focus on the
editor buffer, but this will be addressed in a follow-up, as there will
be multiple cases, such as renaming via a paste action where we want to
focus, and renaming directly via a rename action where we might not want
to focus.
Release Notes:
- Fixed scenario where pasting a file in the project panel after a
copy/cut operation wouldn't automatically open it in the editor.
Follow up to @0xtimsb's PR
https://github.com/zed-industries/zed/pull/22658.
- We're now changing the marked entry as we change the active buffer via
the pane tabs. If all tabs are closed, we clear all marked entries, too.
That means: if we have no open buffer, we don't have any highlighted
entry (i.e., background color) in the project panel.
- Also, now only marked entries have a different, more distinct
background color. The `is_active` state doesn't change an item's
background color anymore.
- This improves an edge case where you could have multiple entries
marked—where all of them would have a background color—and upon
unmarking one of them, that entry would continue to have a bg color.
Now, once you click or move your focus to unmark that entry, the bg
color goes away.
We discovered some new problems by doing these changes that we want to
fix:
1. If you open a project without any open buffer, focus on the project
panel, navigate with arrows to a given entry, and hit space, you will
mark and open the file in the buffer. This is all correct. If you then
hit `escape` to clear the marked entries, nothing happens to the open
buffer, and the marked styled in the project panel entry go away. This
is all correct. The wrong behavior happens if you now hit space _again_
on the active entry. That should mark it, and thus change its styles,
but it doesn't happen. You just see it upon moving to a different entry
with arrow up/down.
2. If you mark multiple entries on the project panel and then click on
an open buffer, we still see all the multiple entries marked. This feels
incorrect. We should only allow one marked entry at a time.
These fixes should happen in follow up PRs, though.
Release Notes:
- Improved the scenario where there'd be a project panel entry
highlighted/marked even if there is no open buffer.
---------
Co-authored-by: smit <0xtimsb@gmail.com>
Done automatically with
> ast-grep -p '$A.background_executor().spawn($B)' -r
'$A.background_spawn($B)' --update-all --globs "\!crates/gpui"
Followed by:
* `cargo fmt`
* Unexpected need to remove some trailing whitespace.
* Manually adding imports of `gpui::{AppContext as _}` which provides
`background_spawn`
* Added `AppContext as _` to existing use of `AppContext`
Release Notes:
- N/A
This Pull Request tackles the issue outline in #14287 by changing the
way `KeyBinding`s for vim mode are displayed in the command palette.
It's worth pointing out that this whole thing was pretty much
implemented by Conrad Irwin during a pairing session, I just tried to
clean up some other changes introduced for a different issue, while
improving some comments.
Here's a quick list of the changes introduced:
- Update `KeyBinding` with a new `vim_mode` field to determine whether
the keybinding should be displayed in vim mode.
- Update the way `KeyBinding` is rendered, so as to detect if the
keybinding is for vim mode, if it is, only display keys in uppercase if
they require the shift key.
- Introduce a new global state – `VimStyle(bool)` - use to determine
whether `vim_mode` should be enabled or disabled when creating a new
`KeyBinding` struct. This global state is automatically set by the `vim`
crate whenever vim mode is enabled or disabled.
- Since the app's context is now required when building a `KeyBinding` ,
update a lot of callers to correctly pass this context.
And before and after screenshots, for comparison:
| before | after |
|--------|-------|
| <img width="1050" alt="SCR-20250205-tyeq"
src="https://github.com/user-attachments/assets/e577206d-2a3d-4e06-a96f-a98899cc15c0"
/> | <img width="1050" alt="SCR-20250205-tylh"
src="https://github.com/user-attachments/assets/ebbf70a9-e838-4d32-aee5-0ffde94d65fb"
/> |
Closes#14287
Release Notes:
- Fix rendering of vim commands to preserve case sensitivity
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This PR adds the ability for icon themes to provide their own file
associations.
The old `file_types.json` that was previously used to make these
associations has been removed in favor of storing them on the default
theme.
Icon themes have two new fields on them:
- `file_stems`: A mapping of file stems to icon keys.
- `file_suffixes`: A mapping of file suffixes to icon keys.
These mappings produce icon keys which can then be used in `file_icons`
to associate them to a particular icon:
```json
{
"file_stems": {
"Makefile": "make"
},
"file_suffixes": {
"idr": "idris"
},
"file_icons": {
"idris": { "path": "./icons/idris.svg" },
"make": { "path": "./icons/make.svg" }
}
}
```
When loading an icon theme, the `file_stems` and `file_icons` fields
will be merged with the ones from the base icon theme, with the values
from the icon theme being loaded overriding ones in the base theme.
Release Notes:
- Added the ability for icon themes to provide their own file
associations.
I spent an hour with @marcospb19 this morning debugging an issue with
adding `Copy Path` and `Copy Relative Path` actions to the editor
context menu. Turned out that the problem was using
`workspace::CopyPath` in the menu and `editor::CopyPath` in the action
handler.
This is an easy mistake to make, so let's fix it for everyone.
Release Notes:
- N/A
Supercedes #24561Closes#21059
Before this change we would skip saving multibuffers regardless of the
save intent. Now we correctly save them.
Along the way:
* Prompt to save when closing the last singleton copy of an item (even
if it's still open in a multibuffer).
* Update our file name prompt to pull out dirty project items from
multibuffers instead of counting multibuffers as untitled files.
* Fix our prompt test helpers to require passing the button name instead
of the index. A few tests were passing invalid responses to save
prompts.
* Refactor the code a bit to hopefully clarify it for the next bug.
Release Notes:
- Fixed edge-cases when closing multiple items including multibuffers.
Previously no prompt was generated when closing an item that was open in
a multibuffer, now you will be prompted.
- vim: Fix :wq in a multibuffer