This removes around 900 unnecessary clones, ranging from cloning a few
ints all the way to large data structures and images.
A lot of these were fixed using `cargo clippy --fix --workspace
--all-targets`, however it often breaks other lints and needs to be run
again. This was then followed up with some manual fixing.
I understand this is a large diff, but all the changes are pretty
trivial. Rust is doing some heavy lifting here for us. Once I get it up
to speed with main, I'd appreciate this getting merged rather sooner
than later.
Release Notes:
- N/A
Currently, the terminal search function doesn't work well with ViMode.
It matches the search terms, scrolls the active match in the view, but
it doesn't move the cursor to the match, which makes it useless for
navigating the scrollback in vimode.
With this improvement, if a user activates ViMode before the search Zed
moves the cursor to the active search terms. So, when the search dialog
is dismissed the cursor is places on the latest active search term and
it's possible to navigate the scrollback via ViMode using this place as
the starting point.
https://github.com/user-attachments/assets/63325405-ed93-4bf8-a00f-28ded5511f31
Release Notes:
- Improved the search function in the terminal when ViMode is activated
It's unfortunate to need to have access to a GPUI window in order to
create a terminal, because it forces to take a `Window` parameter in
entities that otherwise would have been pure models.
This pull request changes it so that we pass the `Project`'s entity id,
which is equally stable as the window id.
Release Notes:
- N/A
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
when `terminal.detect_venv.activate_script` setting is default, pick the
appropriate activate script as per the `terminal.shell` settings
specified by the user. Previously when the activate_script setting is
default, zed always try to use the `activate` script, which only works
when the user shell is `bash or zsh`. But what if the user is using
`fish` shell in zed?
Release Notes:
- python: value of `activate_script` setting is now automatically
inferred based on the kind of shell the user is running with.
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This solves problems where users couldn't shut down sessions while
locators or build tasks are running.
I renamed `debugger::Session::Mode` enum to `SessionState` to be more
clear when it's referenced in other crates. I also embedded the boot
task that is created in `SessionState::Building` variant. This allows
sessions to shut down all created threads in their boot process in a
clean and idiomatic way.
Finally, I added a method on terminal that allows killing the active
task.
Release Notes:
- Debugger: Allow shutting down debug sessions while they're booting up
Closes#18263
Improvements:
• **Batch text rendering** - Combine adjacent cells with identical
styling into single text runs to reduce draw calls
• **Throttle hyperlink searches** - Limit hyperlink detection to every
100ms or when mouse moves >5px to reduce CPU usage
• **Pre-allocate collections** - Use `Vec::with_capacity()` for cells,
runs, and regions to minimize reallocations
• **Optimize background regions** - Merge adjacent background rectangles
to reduce number of draw operations
• **Cache selection text** - Only compute terminal selection string when
selection exists
Release Notes:
- Improved terminal rendering performance.
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Closes#33253 in a way that doesn't regress #32175 - namely,
automatically adjusts the contrast between the foreground and background
text in the terminal such that it's above a certain threshold. The
threshold is configurable in settings, and can be set to 0 to turn off
this feature and use exactly the colors the theme specifies even if they
are illegible.
## One Light Theme Before
<img width="220" alt="Screenshot 2025-07-07 at 6 00 47 PM"
src="https://github.com/user-attachments/assets/096754a6-f79f-4fea-a86e-cb7b8ff45d60"
/>
(Last row is highlighted because otherwise the text is unreadable; the
foreground and background are the same color.)
## One Light Theme After
(This is with the new default contrast adjustment setting.)
<img width="215" alt="Screenshot 2025-07-07 at 6 22 02 PM"
src="https://github.com/user-attachments/assets/b082fefe-76f5-4231-b704-ff387983a3cb"
/>
This approach was inspired by @mitchellh's use of automatic contrast
adjustment in [Ghostty](https://ghostty.org/) - thanks, Mitchell! The
main difference is that we're using APCA's formula instead of WCAG for
[these
reasons](https://khan-tw.medium.com/wcag2-are-you-still-using-it-ui-contrast-visibility-standard-readability-contrast-f34eb73e89ee).
Release Notes:
- Added automatic dynamic contrast adjustment for terminal foreground
and background colors
Closes#33858
Changes Shift+Enter in the built-in terminal to send line feed (`\x0a`)
instead of carriage return (`\x0d`), enabling multi-line input in Claude
Code and other terminal applications.
Release Notes:
- Fixed the issue where Claude Code and other multi-line terminal
applications couldn't use Shift+Enter for newlines.
Closes#21262
Introduces a new setting `keep_selection_on_copy`, which controls
whether the current text selection is preserved after copying in the
terminal. The default behavior remains the same (`true`), but setting it
to `false` will clear the selection after the copy operation, matching
VSCode's behavior.
Additionally, the terminal context now exposes a `selection` flag
whenever text is selected.
This allows users to match VSCode and other terminal's smart copy
behavior.
Release Notes:
- Expose `selection` to terminal context when there is text selected in
the terminal
- Add `keep_selection_on_copy` terminal setting. Can be set to false to
clear the text selection when copying text.
**VSCode Behavior Example:**
**settings.json:**
```json
"terminal": {
"keep_selection_on_copy": false
},
```
**keymap.json:**
```json
{
"context": "Terminal && selection",
"bindings": {
"ctrl-c": "terminal::Copy"
}
}
```
Closes #ISSUE
Adds a new `documentation` method to actions, that is extracted from doc
comments when using the `actions!` or derive macros.
Additionally, this PR adds doc comments to as many action definitions in
Zed as possible.
Release Notes:
- N/A *or* Added/Fixed/Improved ...
The major change in schemars 1.0 is that now schemas are represented as
plain json values instead of specialized datatypes. This allows for more
concise construction and manipulation.
This change also improves how settings schemas are generated. Each top
level settings type was being generated as a full root schema including
the definitions it references, and then these were merged. This meant
generating all shared definitions multiple times, and might have bugs in
cases where there are two types with the same names.
Now instead the schemar generator's `definitions` are built up as they
normally are and the `Settings` trait no longer has a special
`json_schema` method. To handle types that have schema that vary at
runtime (`FontFamilyName`, `ThemeName`, etc), values of
`ParameterizedJsonSchema` are collected by `inventory`, and the schema
definitions for these types are replaced.
To help check that this doesn't break anything, I tried to minimize the
overall [schema
diff](https://gist.github.com/mgsloan/1de549def20399d6f37943a3c1583ee7)
with some patches to make the order more consistent + schemas also
sorted with `jq -S .`. A skim of the diff shows that the diffs come
from:
* `enum: ["value"]` turning into `const: "value"`
* Differences in handling of newlines for "description"
* Schemas for generic types no longer including the parameter name, now
all disambiguation is with numeric suffixes
* Enums now using `oneOf` instead of `anyOf`.
Release Notes:
- N/A
For #31827
# URL Decoding Fix for Terminal File Path Clicking
## Discussion
This change does not allow for paths that literally have `%XX` inside of
them. If any such paths exist, they will fail to ctrl+click. A larger
change would be needed to handle that.
## Problem
In the terminal, you could ctrl+click file paths to open them in the
editor, but this didn't work when the paths contained URL-encoded
characters (percent-encoded sequences like `%CE%BB` for Greek letter λ).
### Example Issue
- This worked: `dashboardλ.mts:3:8`
- This didn't work: `dashboard%CE%BB.mts:3:8`
The URL-encoded form `%CE%BB` represents the Greek letter λ (lambda),
but the terminal wasn't decoding these sequences before trying to open
the files.
## Solution
Added URL decoding functionality to the terminal path detection system:
1. **Added urlencoding dependency** to `crates/terminal/Cargo.toml`
2. **Created decode_file_path function** in
`crates/terminal/src/terminal.rs` that:
- Attempts to decode URL-encoded paths using `urlencoding::decode()`
- Falls back to the original string if decoding fails
- Handles malformed encodings gracefully
3. **Applied decoding to PathLikeTarget creation** for both:
- Regular file paths detected by word regex
- File:// URLs that are treated as paths
## Code Changes
### New Function
```rust
/// Decodes URL-encoded file paths to handle cases where terminal output contains
/// percent-encoded characters (e.g., %CE%BB for λ).
/// Falls back to the original string if decoding fails.
fn decode_file_path(path: &str) -> String {
urlencoding::decode(path)
.map(|decoded| decoded.into_owned())
.unwrap_or_else(|_| path.to_string())
}
```
### Modified PathLikeTarget Creation
The function is now called when creating `PathLikeTarget` instances:
- For file:// URLs: `decode_file_path(path)`
- For regular paths: `decode_file_path(&maybe_url_or_path)`
## Testing
Added comprehensive test coverage in `test_decode_file_path()` that
verifies:
- Normal paths remain unchanged
- URL-encoded characters are properly decoded (λ, spaces, slashes)
- Paths with line numbers work correctly
- Invalid encodings fall back gracefully
- Mixed encoding scenarios work
## Impact
This fix enables ctrl+click functionality for file paths containing
non-ASCII characters that appear URL-encoded in terminal output, making
the feature work consistently with tools that output percent-encoded
file paths.
The change is backward compatible - all existing functionality continues
to work unchanged, and the fix only activates when URL-encoded sequences
are detected.
Release Notes:
* File paths printed in the terminal that have `%XX` escape sequences
will now be properly decoded so that ctrl+click will open them
Part of #28238
This PR refactors `FindHyperlink` handling and associated code in
`terminal.rs` into its own file for improved testability, and adds
tests.
Release Notes:
- N/A
Fixes rendering of colors in the terminal to use XTerm's idiosyncratic standard steps instead of the range that was previously in use. Matches the behavior of Alacritty, Ghostty, iTerm2, and every other terminal emulator I've looked at.
Release Notes:
- Fixed rendering of terminal colors for the XTerm 256-color indexed color palette.
The core change here is the following:
```rust
fn write_to_pty(&self, input: impl Into<Vec<u8>>);
// into
fn write_to_pty(&self, input: impl Into<Cow<'static, [u8]>>);
```
This matches the trait bounds that's used by the Alacritty crate. We are
now allowed to effectively pass `&'static str` instead of always needing
a `String`.
The main benefit comes from making the `to_esc_str` function return a
`Cow<'static, str>` instead of `String`. We save an allocation in the
following instances:
- When the user presses any special key that isn't alphanumerical (in
the terminal)
- When the uses presses any key while a modifier is active (in the
terminal)
- When focusing/un-focusing the terminal
- When completing or undoing a terminal transaction
- When starting a terminal assist
This basically saves us an allocation on **every key** press in the
terminal.
NOTE: This same optimization can be done for **nearly all** keypresses
in the entirety of Zed by changing the signature of the `Keystroke`
struct in gpui. If the Zed team is interested in a PR for it, let me
know.
Release Notes:
- N/A
By consuming the event during processing we save a few clones during
event processing.
Overall in this PR we save one Clone each during:
- Paste to the terminal
- Writing to the terminal
- Setting the title
- On every terminal transaction
- On every ViMotion when not using shift
Release Notes:
- N/A
Closes https://github.com/zed-industries/zed/issues/25110https://github.com/user-attachments/assets/4624c256-8dfb-48eb-a726-6cf130d946da
Terminal may update its hovered word way before reporting it to the
terminal view, and that processing the file check later.
Hence, store the terminal hover data in the terminal view and avoid
highlights when it's different from what the terminal has (as the source
of truth here).
In addition, now only does hover refreshes when the terminal hover
actually changes, not on every event report.
Release Notes:
- Fixed underline flicker when switching cmd-hovered words in terminal
To-dos:
- [x] Expose the command to defend against cases where that's just super
long
- [x] Tackle the vertical scroll conflict with panel scroll
- [x] Reduce default font-size
Release Notes:
- N/A
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Agus Zubiaga <hi@aguz.me>
main was failing to build on FreeBSD.
[joblink](https://github.com/zed-industries/zed/actions/runs/14721383651/job/41315738893)
```
error[E0425]: cannot find value `platform` in this scope
--> crates/terminal/src/terminal_settings.rs:298:36
|
298 | let shell_name = format!("{platform}Exec");
| ^^^^^^^^ not found in this scope
error[E0425]: cannot find value `platform` in this scope
--> crates/terminal/src/terminal_settings.rs:304:46
|
304 | .read_value(&name(&format!("env.{platform}")))
| ^^^^^^^^ not found in this scope
```
CC: @P1n3appl3
Release Notes:
- N/A
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>
Split `locator` out of DebugTaskDefinition to make it clearer when
location needs to happen.
Release Notes:
- N/A
---------
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Anthony <anthony@zed.dev>
Co-authored-by: Cole Miller <m@cole-miller.net>
This PR adds functionality to right click in terminal create new
selection if none present. The selection is identical with double click
a text in terminal, plus the logic is moved from the double-click in the
terminal::mouse_down.
Closes#28237
Release Notes:
- Adds functionality to right click in terminal create new selection if
none present
Release Notes:
- agent: Replace `bash` tool with `terminal` tool which uses the current
shell
---------
Co-authored-by: Bennet <bennet@zed.dev>
Co-authored-by: Antonio <antonio@zed.dev>
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>
Reverts the error behavior introduced in #27558. Upper-case keys in
keybindings no longer generate errors, instead they are transformed into
`shift-{KEY}`
e.g. `ctrl-N` becomes `ctrl-shift-n`
The behavior introduced in #27558 where "special" keys such as function
keys, `control`, `shift`, etc. Are parsed case-insensitively is
preserved.
Release Notes:
- Improved how upper-case characters are handled in keybinds. "special"
keys such as the function keys, `control`, `shift`, etc. are now parsed
case-insensitively, so for example `F8`, `CTRL`, `SHIFT` are now
acceptable alternatives to `f8`, `ctrl`, and `shift` when declaring
keybindings. Additionally, upper-case (ascii) characters will now be
converted explicitly to `shift` + the lowercase version of the
character, to match the Vim behavior.
NOTE: Release notes above should replace the release notes from #27558
## Summary
This PR starts the process of adding debug task locators to Zed's
debugger system. A task locator is a secondary resolution phase that
allows a debug task to run a command before starting a debug session and
then uses the output of the run command to configure itself.
Locators are most applicable when debugging a compiled language but will
be helpful for any language as well.
## Architecture
At a high level, this works by adding a debug task queue to `Workspace`.
Which add's a debug configuration associated with a `TaskId` whenever a
resolved task with a debug config is added to `TaskInventory`'s queue.
Then, when the `SpawnInTerminal` task finishes running, it emits its
task_id and the result of the ran task.
When a ran task exits successfully, `Workspace` tells `Project` to start
a debug session using its stored debug config, then `DapStore` queries
the `LocatorStore` to configure the debug configuration if it has a
valid locator argument.
Release Notes:
- N/A