This PR adds the ability to change both the terminal and agent panels
between fixed and flexible sizing using the status bar button right
click menu. The value persists in your settings, similar to the dock
position.
I've also slightly tweaked the styling of the "Dock Left" and "Dock
Right" items in the right-click menu, adding the current value as an
item with a check beside it, to make it clear that it's a selectable
option.
Release Notes:
- N/A
## Context
**Current Behavior:** Middle click pastes multiple lines of text and
runs each as an individual terminal command
**Expected Behavior:** On Linux middle click should use bracketed paste
to paste multiple lines and wait for the user to hit "Enter" before
running all commands together like when pressing Ctrl+Shift+V
Steps to reproduce old behavior:
1. Open terminal
2. Copy multiple lines of text from outside the terminal
3. Middle click to paste text in terminal
## Self-Review Checklist
<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
Fixed multiple line paste behavior in terminal on middle click
Co-authored-by: Bryan Mehall <1575089+bryanmehall@users.noreply.github.com>
Self-Review Checklist:
- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A
Closes https://github.com/zed-industries/zed/issues/38901
Supersedes https://github.com/zed-industries/zed/pull/39082
This PR fixes an issue where the terminal tab would stay open after the
user exits a shell that has a non-zero exit code (e.g. running `false`
then `exit`, or pressing Ctrl-C followed by Ctrl-D). We now track
whether any keyboard input was sent to distinguish user-initiated exits
from shell spawn failures.
Release Notes:
- Fixed terminal tab not closing when the shell exits with a non-zero
code.
Co-authored-by: Glenn Miao <one.lemorage@gmail.com>
This PR fixes test flakiness introduced in
https://github.com/zed-industries/zed/pull/52111
The flakiness was because the test was using its own RNG, rather than
using gpui's built-in support for consistently-seeded RNGs in tests. The
fix was just to adjust the test to use the same logic for computing row
and column count as was introduced in the above PR.
Release Notes:
- N/A
## Context
`TerminalBounds::num_lines()` uses `floor(height / line_height)` to
compute the terminal grid row count. When the height is derived from `N
* line_height` (as it is for inline/embedded terminals in the Agent
Panel), IEEE 754 float32 arithmetic can produce `N - epsilon` instead of
`N`, causing `floor()` to return `N - 1`. This makes the terminal grid
one row too small, leaving the first line of output in invisible
scrollback (since `display_offset = 0`). The same issue applies to
`num_columns()`.
The fix adds a small tolerance (`0.01`) before flooring, which absorbs
float precision errors without affecting genuine fractional results.
Closes#51609
## How to Review
Small PR — focus on the tolerance value (`0.01`) in `num_lines()` and
`num_columns()` in `crates/terminal/src/terminal.rs`. The two new tests
(`test_num_lines_float_precision`, `test_num_columns_float_precision`)
verify the fix across 1,000+ float combinations that previously
triggered the bug.
## Self-Review Checklist
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed the first line of terminal output sometimes missing in Agent
Panel terminal blocks.
## Summary
- Implements `icon_label` on `GitPanel` to return the total count of
uncommitted changes (`new_count + changes_count`) when non-zero, capped
at `"99+"` for large repos.
- Updates `PanelButtons::render()` to render that label as a small green
badge overlaid on the panel's sidebar icon, using absolute positioning
within a `div().relative()` wrapper.
- The badge uses `version_control_added` theme color and
`LabelSize::XSmall` text with `LineHeightStyle::UiLabel` for accurate
vertical centering, positioned at the top-right corner of the icon
button.
The `icon_label` method already existed on the `Panel`/`PanelHandle`
traits with a default `None` impl, and was already implemented by
`NotificationPanel` (unread notification count) and `TerminalPanel`
(open terminal count) — but was never rendered. This wires it up for all
three panels at once.
## Notes
- Badge is positioned with non-negative offsets (`top(0)`, `right(0)`)
to stay within the parent container's bounds. The status bar's
`render_left_tools()` uses `.overflow_x_hidden()`, which in GPUI clips
both axes (the `overflow_mask` returns a full content mask whenever any
axis is non-`Visible`), so negative offsets would be clipped.
- `LineHeightStyle::UiLabel` collapses line height to `relative(1.)` so
flex centering aligns the visual glyph rather than a
taller-than-necessary line box.
- No new data tracking logic — `GitPanel` already maintains `new_count`
and `changes_count` reactively.
- No feature flag or settings added per YAGNI.
## Suggested .rules additions
The following pattern came up repeatedly and would prevent future
sessions from hitting the same issue:
```
## GPUI overflow clipping
`overflow_x_hidden()` (and any single-axis overflow setter) clips **both** axes in GPUI.
The `overflow_mask()` implementation in `style.rs` returns a full `ContentMask` (bounding box)
whenever any axis is non-`Visible`. Absolute-positioned children that extend outside the element
bounds will be clipped even if only the X axis is set to Hidden.
Avoid negative `top`/`right`/`bottom`/`left` offsets on absolute children of containers
that have any overflow hidden — keep badge/overlay elements within the parent's bounds instead.
```
Release Notes:
- Added a numeric badge to the git panel sidebar icon showing the count
of uncommitted changes.
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This will help with test times (in some cases), as nextest cannot figure
out whether a given rdep is actually an alive edge of the build graph
Closes #ISSUE
Before you mark this PR as ready for review, make sure that you have:
- [ ] Added a solid test coverage and/or screenshots from doing manual
testing
- [ ] Done a self-review taking into account security and performance
aspects
- [ ] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- N/A
Closes#49800
Adds `handle_drop` to Item & ItemHandle, which allows an active item in
a pane to consume drop events before the pane does.
Release Notes:
- terminal: Fix drag-and-drop not working in vertical terminal panels
The path hyperlink regex's middle-char pattern
[[:(][^0-9()]](cci:2://file:///d:/zed/crates/fs/src/fs.rs:89:0-157:1)
allowed colon+space because space was not in the exclusion set. This
caused `0: foo/bar.txt` to be matched as a single path instead of just
`foo/bar.txt`.
Fix: add space to the exclusion class: [[:(][^0-9()\\
]](cci:2://file:///d:/zed/crates/fs/src/fs.rs:89:0-157:1)
Closes#50531
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [ ] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
(N/A)
Release Notes:
- Fixed terminal Ctrl-click path detection failing when path is preceded
by a prefix like `0:` (#50531)
Follow-up to #45600.
## Summary
Fix mouse scroll reports sending only one event when scrolling down in
terminal apps with mouse mode (tmux, neovim, etc.), regardless of how
many lines were scrolled.
## The Problem
After #45600, trackpad scrolling speed was fixed. But when scrolling
**down** (negative `scroll_lines`), the terminal was still sending only
**one** scroll report per gesture, no matter how many lines the user
scrolled. Scrolling up worked correctly.
## Root Cause
In `scroll_report()` we had:
https://github.com/zed-industries/zed/blob/94851aff196bfb5b91d68cb52fa1502d6b4c5b29/crates/terminal/src/mappings/mouse.rs#L96
`scroll_lines` can be negative (scroll down) or positive (scroll up).
For negative values:
| scroll_lines | max(scroll_lines, 1) | Reports sent | Verdict |
|--------------|---------------------|--------------|------|
| 3 (up) | 3 | 3 |Right
| -3 (down) | 1 | 1 |WRONG|
So we always sent exactly 1 report when scrolling down, losing the
scroll magnitude.
Use `scroll_lines.unsigned_abs()` instead of `max(scroll_lines, 1)`.
This matches how `alt_scroll()` in the same file already handles
`scroll_lines`. Now both directions send the correct number of reports.
https://github.com/zed-industries/zed/blob/94851aff196bfb5b91d68cb52fa1502d6b4c5b29/crates/terminal/src/mappings/mouse.rs#L102
## Testing
- Added unit tests: `scroll_report_repeats_for_negative_scroll_lines`
and `scroll_report_repeats_for_positive_scroll_lines`
- Manually tested scrolling in tmux and neovim with mouse mode
---
Release Notes:
- Fixed mouse scroll in terminal apps (tmux, neovim, etc.) only sending
one scroll event when scrolling down, regardless of scroll amount
Closes#46795
This PR aims to correctly detect the hyperlinks in cases like the
following, where box-drawing characters immediately precede the path
(without spaces in between).
```
╭─[Cargo.toml:55:1]
...
╰────
```
The only false negative with the fix in this PR would be that a file
path really contains leading box drawing characters which I think is
very unlikely.
---
Release Notes:
- Fixed an issue where the hyperlinks would not be properly detected in
the terminal if they were preceded by box-drawing characters (like ─, │,
┌, ┐)
Signed-off-by: Charlie-XIAO <yx2436@nyu.edu>
## Summary
This PR extends the `always_allow` tool permission patterns to work with
Nushell, Elvish, and Rc shells. Previously, these shells were
incorrectly excluded because they don't use `&&`/`||` operators for
command chaining. However, brush-parser can safely parse their command
syntax since they all use `;` for sequential execution.
## Changes
- Add `ShellKind::Nushell`, `ShellKind::Elvish`, and `ShellKind::Rc` to
`supports_posix_chaining()`
- Split `ShellKind::Unknown` into `ShellKind::UnknownWindows` and
`ShellKind::UnknownUnix` to preserve platform-specific fallback behavior
while still denying `always_allow` patterns for unrecognized shells
- Add comprehensive tests for the new shell support
- Clarify documentation about shell compatibility
## Shell Notes
- **Nushell**: Uses `;` for sequential execution. The `and`/`or`
keywords are boolean operators on values, not command chaining.
- **Elvish**: Uses `;` to separate pipelines. Does not have `&&` or `||`
operators. Its `and`/`or` are special commands operating on values.
- **Rc (Plan 9)**: Uses `;` for sequential execution and `|` for piping.
Does not have `&&`/`||` operators.
## Security
Unknown shells still return `false` from `supports_posix_chaining()`, so
`always_allow` patterns are denied for safety when we can't verify the
shell's syntax.
(No release notes because granular tool permissions are still
feature-flagged.)
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Closes#38168Closes#42414
We were already using `ExitStatusExt::from_raw()` to construct an
`ExitStatus`, but we were passing in the exit code from
alacritty_terminal's `ChildExit` event. This worked fine on Windows
where `from_raw()` expects an exit code, but on Unix, `from_raw()`
([read
more](https://doc.rust-lang.org/std/os/unix/process/trait.ExitStatusExt.html#tymethod.from_raw))
expects a raw wait status from `waitpid()` and not an exit code.
When a child process was killed by a signal (e.g., SIGSEGV),
`ExitStatus::code()` returns `None` since only normal exits have an exit
code. This caused the terminal to hang because we weren't properly
detecting the exit.
One fix would have been to remove the dependency on `ExitStatus`
entirely, but using the raw wait status gives us more information, we
can now detect exit codes, signal terminations, and more.
The actual fix was upstream in `alacritty_terminal` to send the raw wait
status instead of just the exit code.
Currently using forked patch
https://github.com/zed-industries/alacritty/tree/v0.16-child-exit-patch
which is based on v0.25.1.
Upstream PR: https://github.com/alacritty/alacritty/pull/8825
Release Notes:
- Fixed terminal hanging when a child process is killed by a signal
(e.g., SIGSEGV from null pointer dereference).
We might interface with the LSP using URL heres across remotes that have
differing path styles which then breaks every now and then when we have
windows to unix connections. This should helps us fix these occurences
more correctly
Release Notes:
- N/A *or* Added/Fixed/Improved ...
It turns out Alacritty sends `AlacTermEvent::ColorRequest` when using
the fish shell. That path relies on `cx.theme`, so this change is needed
for it to pass.
Co-authored-by: Lukas <lukas@zed.dev>
Release Notes:
- N/A
Closes#18930
### Summary
- Fix fast Macbook trackpad/mouse scrolling in terminal applications
with mouse mode enabled
### The Problem
Scrolling with a trackpad in tmux, neovim, or any terminal app that
enables mouse mode was too fast. A gentle swipe would send me through
hundreds of lines, making these apps practically unusable in Zed's
terminal.
### Root Cause
When the terminal is in mouse mode, we send escape sequences to report
scroll events to the application. The bug was in `scroll_report()`:
https://github.com/zed-industries/zed/blob/3f8f7da2595116744439794fafacea6f570775db/crates/terminal/src/terminal.rs#L1983-L1988
That `max(scroll_lines, 1)` meant we'd send **at least 1 scroll event
even when `scroll_lines` was 0**.
https://github.com/zed-industries/zed/blob/3f8f7da2595116744439794fafacea6f570775db/crates/terminal/src/mappings/mouse.rs#L96
On macOS, trackpad gestures fire many small pixel deltas due to scroll
acceleration. Each tiny movement triggered a scroll event, even though
we hadn't accumulated enough pixels for a full line yet. This is a known
issue alacritty/alacritty#2869 - macOS sends fractional line deltas
(like 0.1) instead of whole lines.
### The Fix
Don't send mouse reports when no full line has accumulated
This aligns with Alacritty's approach - accumulate partial scroll
amounts and only report when complete lines are ready.
https://github.com/alacritty/alacritty/blob/6ee6e53ee3457c24137f117237b0ff1d84f6f836/alacritty/src/input/mod.rs#L700-L730
### Testing
Tested trackpad scrolling in:
- tmux (pane navigation, scrollback)
- neovim (buffer scrolling)
- opencode (TUI navigation)
All scroll smoothly now.
### Demo
The demo shows the behavior of the scrolling. I can go fast or I can go
slow
https://github.com/user-attachments/assets/14bfc2f4-f286-4341-bf55-4ced894d63f9
Release Notes:
- Fixed trackpad scrolling being too fast in terminal applications with
mouse mode enabled (tmux, neovim, opencode, etc.)
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>
## 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>
Previously, if you stopped the terminal prematurely, the agent would
assume the terminal process had timed out. Now it knows what happened
and can see the output:
<img width="718" height="885" alt="Screenshot 2026-01-07 at 12 40 23 AM"
src="https://github.com/user-attachments/assets/a5ea14b2-249c-4ada-9f20-d6b608f829e5"
/>
Release Notes:
- Stopping the terminal tool now allows the agent to see its output up
to that point.
## Problem
When clicking Stop button on a terminal tool call (or using terminal
kill bindings), only the shell process was killed. Child processes (like
`sleep`, `npm run`, etc.) continued running as orphans.
## Solution
On Unix, use `killpg()` instead of `sysinfo::Process::kill()` to
terminate the entire foreground process group.
`tcgetpgrp()` already returns the foreground process group ID, so
`killpg()` is the correct syscall to use here.
## Testing
1. Run a long command in terminal tool (e.g. `sleep 30`)
2. Click Stop button
3. Verify with `ps aux | grep sleep` that the process is actually killed
## Notes
- This fix is Unix-only (Linux, macOS)
- Windows behavior unchanged — may need separate investigation with Job
Objects
## Release Notes
- Fixed terminal Stop button not killing child processes on Unix (Linux,
macOS)
Now that the edit mode in number fields is finally working well, we can
make the UX of editing font sizes much nicer because you can now type
inside the number field :)
https://github.com/user-attachments/assets/8df7c6ee-e82b-4e10-a175-e0ca5f1bab1f
Release Notes:
- settings UI: Improved the UX of editing font size fields as you can
now type the desired value as opposed to just using the
decrement/increment buttons.
Related to
- #44407
This PR further improves performance for regex hyperlink finding by
eliminating unnecessary regex matching. Currently, we repeatedly search
for matches from the start of the line until the match contains the
hovered point. This is only required to support custom regexes which
match strings containing spaces, with multiple matches on a single line.
This isn't actually a useful scenario, and is no longer supported. This
PR changes to only search twice, the first match starting from the start
of the line, and the hovered word (space-delimited). The most dramatic
improvement is for long lines with many words.
In addition to the above changes, this PR:
- Adds test for the scenarios from #44407 and #44510
- Simplifies the logic added in #44407
Performance measurements
For the scenario from #44407, this improves the perf test's iteration
time from 1.22ms to 0.47ms.
main:
| Branch | Command | Iter/sec | Mean [ms] | SD [ms] | Iterations |
Importance (weight) |
|:---|:---|---:|---:|---:|---:|---:|
| main |
terminal_hyperlinks::tests::path::perf::pr_44407_hyperlink_benchmark |
819.64 | 937.60 | 2.20 | 768 | average (50) |
| this PR |
terminal_hyperlinks::tests::path::perf::pr_44407_hyperlink_benchmark |
2099.79 | 1463.20 | 7.20 | 3072 | average (50) |
Release Notes:
- terminal: Improve path hyperlink performance for long lines
Closes#41994
This PR introduces Element-bounded drag tolerance for Ctrl/Cmd+click in
terminal.
Previously, Ctrl/Cmd+click on terminal links required pixel-perfect
accuracy. Any mouse movement during the click would cancel the
navigation, making it frustrating to click on links, especially on
high-DPI displays or with sensitive mice.
Users can now click anywhere within a clickable element (file path, URL,
hyperlink), drag the cursor anywhere within that same element's
boundaries and release to trigger navigation
Implementation:
- Stores detected element metadata (`text` and `grid_range`) on
Ctrl/Cmd+mouse-down
- Tracks cursor position during drag, preserving click state while
within element bounds
- Verifies element match on mouse-up before triggering navigation
- Uses existing `find_from_grid_point()` for element detection
Before:
[before.webm](https://github.com/user-attachments/assets/ee80de66-998e-4d8e-94d0-f5e65eb06d22)
After:
[after.webm](https://github.com/user-attachments/assets/7c9ddd9e-cfc1-4c79-b62c-78e9d909e6f4)
Release Notes:
- terminal: Fixed an issue where `ctrl|cmd+click` on links was very
sensitive to mouse movement. Clicking links now tolerates mouse movement
within the same clickable element, making link navigation more reliable
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
Related to:
- #44510
- #44407
Previously we were searching for hyperlinks on every scroll, even if Cmd
was not held. With this PR,
- We only search for hyperlinks on scroll if Cmd is held
- We now clear `last_hovered_word` in all cases where Cmd is not held
- Renamed `word_from_position` -> `schedule_find_hyperlink`
- Simplified logic in `schedule_find_hyperlink`
Performance measurements
The test scrolls up and down 20,000x in a loop. However, since this PR
is just removing a code path that was very dependent on the length of
the line in terminal, it's not super meaningful as a comparison. The
test uses a line length of "long line ".repeat(1000), and in main the
performance is directly proportional to the line length, so for
benchmarking it in main it only scrolls up and down 20x. I think all
that is really useful to say is that currently scrolling is slow, and
proportional to the line length, and with this PR it is buttery-smooth
and unaffected by line length. I've included a few data points below
anyway. At least the test can help catch future regressions.
| Branch | Command | Scrolls | Iter/sec | Mean [ms] | SD [ms] |
Iterations | Importance (weight) |
|:---|:---|---:|---:|---:|---:|---:|---:|
| main | tests::perf::scroll_long_line_benchmark | 40 | 16.85 | 712.00 |
2.80 | 12 | average (50) |
| this PR | tests::perf::scroll_long_line_benchmark | 40 | 116.22 |
413.60 | 0.50 | 48 | average (50) |
| this PR | tests::perf::scroll_long_line_benchmark | 40,000 | 9.19 |
1306.40 | 7.00 | 12 | average (50) |
| only overhead | tests::perf::scroll_long_line_benchmark | 0 | 114.29 |
420.90 | 2.00 | 48 | average (50) |
Release Notes:
- terminal: Improved scroll performance
Adds an optional `timeout_ms` parameter to the terminal tool that allows
bounding the runtime of shell commands. When the timeout expires, the
running terminal task is killed and the tool returns with the partial
output captured so far.
## Summary
This PR adds the ability for the agent to specify a maximum runtime when
invoking the terminal tool. This helps prevent indefinite hangs when
running commands that might wait for network, user prompts, or long
builds/tests.
## Changes
- Add `timeout_ms` field to `TerminalToolInput` schema
- Extend `TerminalHandle` trait with `kill()` method
- Implement `kill()` for `AcpTerminalHandle` and `EvalTerminalHandle`
- Race terminal exit against timeout, killing on expiry
- Update system prompt to recommend using timeouts for long-running
commands
- Add test for timeout behavior
- Update `.rules` to document GPUI executor timers for tests
## Testing
- Added `test_terminal_tool_timeout_kills_handle` which verifies that
when a timeout is specified and expires, the terminal handle is killed
and the tool returns with partial output.
- All existing agent tests pass.
Release Notes:
- agent: Added optional `timeout_ms` parameter to the terminal tool,
allowing the agent to bound command runtime and prevent indefinite hangs
Fixes#33958
## Problem
When opening a terminal in Zed, `SHLVL` incorrectly starts at 2 instead
of 1. On `workspace: reload`, it increases by 2 instead of 1.
## Root Cause
1. Zed's `shell_env::capture()` spawns a login shell (`-l -i -c`) to
capture the user's environment, which increments `SHLVL`
2. The captured `SHLVL` is passed through to the PTY options
3. When alacritty_terminal spawns the user's shell, it increments
`SHLVL` again
Result: `SHLVL` = captured value + 1 = 2 (when launched from Finder)
## Solution
Remove `SHLVL` from the environment in `TerminalBuilder::new()` before
passing it to alacritty_terminal. This allows the spawned shell to
initialize `SHLVL` to 1 on its own, matching the behavior of standalone
terminal emulators like iTerm2, Kitty, and Alacritty.
## Testing
- Launch Zed from Finder → open terminal → `echo $SHLVL` → should output
`1`
- Launch Zed from shell → open terminal → `echo $SHLVL` → should output
`1`
- `workspace: reload` → open terminal → `echo $SHLVL` → should remain
`1`
- Tested with bash, zsh, fish
Release Notes:
- Fixed terminal `$SHLVL` starting at 2 instead of 1
([#33958](https://github.com/zed-industries/zed/issues/33958))
Problem statement: When given a line that contained a lot of matches of
your hyperlink regex of choice (thanks to #40305), we would look for
matches
that intersected with currently hovered point. This is *hella*
expensive, because we would re-walk the whole alacritty grid for each
match. With the repro that Joseph shared, we had to go through 4000 such
matches on each frame render.
Problem solution: We now convert the hovered point into a range within
the line (byte-wise) in order to throw away matches that do not
intersect the
hovered range. This lets us avoid performing the unnecessary conversion
when we know it's never going to yield a match range that intersects the
hovered point.
Release Notes:
- terminal: Fixed performance regression when handling long lines.
---------
Co-authored-by: Dave Waggoner <waggoner.dave@gmail.com>
The fix for this is emitting a wake-up event to tell the terminal to
recalculate its search highlights on resize.
Release Notes:
- terminal: Fix bug where search match highlights wouldn't update their
position when resizing the terminal.
Closes:
- #12338
- #40202
1. Adds two new settings which allow customizing the set of regexes used
to identify path hyperlinks in terminal
1. Fixes path hyperlinks for paths containing unicode emoji and
punctuation, for example, `mojo.🔥`
1. Fixes path hyperlinks for Windows verbatim paths, for example,
`\\?\C:\Over\here.rs`.
1. Improves path hyperlink performance, especially for terminals with a
lot of content
1. Replaces existing custom hard-coded default path hyperlink parsing
logic with a set of customizable default regexes
## New settings
(from default.json)
### terminal.path_hyperlink_regexes
Regexes used to identify paths for hyperlink navigation. Supports
optional named capture
groups `path`, `line`, `column`, and `link`. If none of these are
present, the entire match
is the hyperlink target. If `path` is present, it is the hyperlink
target, along with `line`
and `column` if present. `link` may be used to customize what text in
terminal is part of the
hyperlink. If `link` is not present, the text of the entire match is
used. If `line` and
`column` are not present, the default built-in line and column suffix
processing is used
which parses `line:column` and `(line,column)` variants. The default
value handles Python
diagnostics and common path, line, column syntaxes. This can be extended
or replaced to
handle specific scenarios. For example, to enable support for
hyperlinking paths which
contain spaces in rust output,
```
[
"\\s+(-->|:::|at) (?<link>(?<path>.+?))(:$|$)",
"\\s+(Compiling|Checking|Documenting) [^(]+\\((?<link>(?<path>.+))\\)"
],
```
could be used. Processing stops at the first regex with a match, even if
no link is
produced which is the case when the cursor is not over the hyperlinked
text. For best
performance it is recommended to order regexes from most common to least
common. For
readability and documentation, each regex may be an array of strings
which are collected
into one multi-line regex string for use in terminal path hyperlink
detection.
### terminal.path_hyperlink_timeout_ms
Timeout for hover and Cmd-click path hyperlink discovery in
milliseconds. Specifying a
timeout of `0` will disable path hyperlinking in terminal.
## Performance
This PR fixes terminal to only search the hovered line for hyperlinks
and adds a benchmark. Before this fix, hyperlink detection grows
linearly with terminal content, with this fix it is proportional only to
the hovered line. The gains come from replacing
`visible_regex_match_iter`, which searched all visible lines, with code
that only searches the line hovered on (including if the line is
wrapped).
Local benchmark timings (terminal with 500 lines of content):
||main|this PR|Δ|
|-|-|-:|-|
| cargo_hyperlink_benchmark | 1.4 ms | 13 µs | -99.0% |
| rust_hyperlink_benchmark | 1.2 ms | 11 µs | -99.1% |
| ls_hyperlink_benchmark | 1.3 ms | 7 µs | -99.5% |
Release Notes:
- terminal: New settings to allow customizing the set of regexes used to
identify path hyperlinks in terminal
- terminal: Fixed terminal path hyperlinks for paths containing unicode
punctuation and emoji, e.g. mojo.🔥
- terminal: Fixed path hyperlinks for Windows verbatim paths, for
example, `\\?\C:\Over\here.rs`
- terminal: Improved terminal hyperlink performance, especially for
terminals with a lot of content visible
The "Option" key only exists on a Mac. On other operating systems, it is
always expected that the Alt key generates escaped characters.
Fixes https://github.com/zed-industries/zed/issues/40583
Release Notes:
- N/A