workspace: Add configurable window title formatting (#54379)
## Summary
- Add `window_title_format` and `window_title_separator` settings for
customizing the window title
- Expose `${projectName}`, `${fileName}`, `${filePath}`,
`${relativePath}`, `${fileStem}`, `${remoteName}`, `${remoteHost}`,
`${appName}`, and `${separator}` as the native Zed window-title
variables
- Keep the collab `↗/↙` indicator hard-appended
- Translate VS Code `window.title` / `window.titleSeparator` aliases
into Zed's canonical variables during settings import, including
`${appName}` passthrough support and mapping VS Code's
`${activeEditorMedium}` onto Zed's `${relativePath}`
- Gate path-, remote-, and release-channel-derived lookups on whether
the active template references the corresponding variable, so the
default template avoids the extra work and still uses the existing
`last_window_title` cache to skip redundant platform updates
An alternative approach is at #49638. I went with `${variable}` names
over `$ZED_*`, canonical Zed variable names with VS Code aliases handled
at import time, kept `${separator}` as the only structural token, and
left `${dirty}` out of scope.
## Implementation reasoning and notes
### Variables considered but not included
- **collab/shared indicator variable**: kept hard-appended instead.
Folding it into the template would need whitespace/separator logic the
other variables don't need, and I'd rather not bake those semantics in
without a concrete need for it.
- **dirty variable**: The glyph choice and interaction with OS-level
edited indicators (like macOS's titlebar dot via `set_window_edited`)
felt like a separate design call I wasn't confident making here.
A separator-style config for each of collab/shared/dirty would solve the
above, but I didn't want to add too many additional settings initially.
### Performance
`update_window_title` is on a hot path, so two short-circuits apply:
- Path-, remote-, and release-channel-derived lookups (`absolute_path`,
relative-path string, `file_stem`, `remote_connection_options`,
`ReleaseChannel::try_global`) are gated on `template.contains(...)` via
`WindowTitleNeeds::from_template`, so the default template avoids the
extra work.
- The existing `last_window_title` cache still skips the platform call
when the rendered title is unchanged.
## Screenshots
Settings Editor entries for `window_title_format` and
`window_title_separator`:
<img width="774" height="324" alt="Settings Editor screenshot"
src="https://github.com/user-attachments/assets/b3378ec7-5649-4de3-9de6-164a42bce3fd"
/>
Customized Zed window titles in AltTab app switcher (remote, local,
empty):
<img width="774" height="324" alt="AltTab app switcher screenshot"
src="https://github.com/user-attachments/assets/a189945e-fc68-41b9-aab9-6dc04d5ef4ab"
/>
## 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 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
Closes #14534
Release Notes:
- Added configurable window title formatting with `window_title_format`
/ `window_title_separator`, including `${appName}` / `${remoteName}` /
`${remoteHost}` variables and VS Code `window.title` import support
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This commit is contained in:
1 parent
f659fcc000
commit
1aab982b0a
11 files changed
+1008
-32
No files matched your search
@@ -5273,6 +5273,50 @@ Run the {#action theme_selector::Toggle} action in the command palette to see a
|
||||
- `show_menus`: Whether to show the menus in the titlebar
|
||||
- `button_layout`: The layout of window control buttons in the title bar (Linux only). Can be set to `"platform_default"` to follow the system setting, `"standard"` to use Zed's built-in layout, or a custom format like `"close:minimize,maximize"`
|
||||
|
||||
## Window Title Format
|
||||
|
||||
- Description: Template for the window title. Use `${separator}` to insert a
|
||||
separator that is omitted when adjacent variables are empty. The collaboration
|
||||
indicator, when present, is appended after the rendered template. If the
|
||||
template renders to nothing (for example `${branch}` outside a Git
|
||||
repository), the default template is used instead.
|
||||
- Setting: `window_title_format`
|
||||
- Default: `"${projectName}${separator}${fileName}"`
|
||||
|
||||
Available variables:
|
||||
|
||||
| Variable | Description |
|
||||
| -------------- | ----------------------------------------------------- |
|
||||
| `projectName` | Name of the current project |
|
||||
| `fileName` | Name of the active file (e.g. `main.rs`) |
|
||||
| `filePath` | Absolute path of the active file |
|
||||
| `relativePath` | Path of the active file relative to its worktree root |
|
||||
| `fileStem` | File name without extension (e.g. `main`) |
|
||||
| `remoteName` | Display name of the remote connection, if any |
|
||||
| `remoteHost` | Host of the remote connection, if any |
|
||||
| `appName` | Zed release channel name (e.g. `Zed`, `Zed Nightly`) |
|
||||
| `branch` | Git branch checked out in the active repository |
|
||||
| `separator` | Separator string, omitted when neighbors are empty |
|
||||
|
||||
```json [settings]
|
||||
{
|
||||
"window_title_format": "${projectName}${separator}${fileName}"
|
||||
}
|
||||
```
|
||||
|
||||
## Window Title Separator
|
||||
|
||||
- Description: The string substituted for `${separator}` in the window title
|
||||
format. Include any surrounding whitespace in the value.
|
||||
- Setting: `window_title_separator`
|
||||
- Default: `" — "`
|
||||
|
||||
```json [settings]
|
||||
{
|
||||
"window_title_separator": " — "
|
||||
}
|
||||
```
|
||||
|
||||
## Window Decorations
|
||||
|
||||
- Description: Controls whether Zed or the window manager or compositor draws window decorations.
|
||||
|
||||
Reference in new issue
Block a user