Fixes#8406
Spatial split navigation now wraps at the edges.
We first attempt the nearest spatial target using the existing slot geometry.
If there is no candidate in the requested direction, we synthesize a wrapped
target by shifting the current slot by one full grid in the opposite
direction and reuse the same nearest-distance logic.
This fake target works because the grid is 1x1, so by moving it a full
grid size in the opposite direction, we effectively wrap around to the
other side of the grid.
Closes#9266.
Big Note: I noticed that this worked properly under `NixOS`, but on my
`Ubuntu` VM it didnt.
The reason is in
[src/build/GhosttyI18n.zig](73a93abf7b/src/build/GhosttyI18n.zig (L24-L31))
because the locale is expected in the `<lang>_<region>` without the
encoding suffix. `<lang>_<region>_<encoding>`
```
// There is no encoding suffix in the LC_MESSAGES path on FreeBSD,
// so we need to remove it from `locale` to have a correct destination string.
// (/usr/local/share/locale/en_AU/LC_MESSAGES)
const target_locale = comptime if (builtin.target.os.tag == .freebsd)
std.mem.trimRight(u8, locale, ".UTF-8")
else
locale;
```
If i force it to always trim the encoding it works, but I am guessing
its there for a reason ,so maybe some of the maintainer can shed some
light in the best way forward, as I am not an expert in how other
systems deal with it. Here you see `Open in Ghostty` -> Abrir con
Ghostty
<img width="353" height="372" alt="image"
src="https://github.com/user-attachments/assets/2c0266f7-cfb3-49e3-aef1-9e98acb16ad8"
/>
- I wanted to format the `py` file with `ruff` but didnt want to drown
the changes, so maybe something that could be worth doing so that also
our `py` files have std formatting.
> [!NOTE]
> Used AI only for helping me debug where the locales could be and why
was it not detected, but no code help whatsoever
This changes the way Ghostty assigns itself and subprocesses to
cgroups and how resource controls are applied.
* Ghostty itself no longer modifies it's own cgroup or moves itself
to a transient scope. To modify the main Ghostty process' resource
controls ensure that you're launching Ghostty with a systemd unit and
use the standard systemd methods for overriding and applying changes
to systemd units.
* If configured (on by default), the process used to run your command
will be moved to a transient systemd scope after it is forked from
Ghostty but before the user's command is executed. Resource controls
will be applied to the transient scope at this time. Changes to
the `linux-cgroup*` configuration entries will not alter existing
commands. If changes are made to the `linux-cgroup*` configuration
entries commands will need to be relaunched. Resource limits can also
be modified after launch outside of Ghostty using systemd tooling. The
transient scope name can be shown by running `systemctl --user whoami`
in a shell running inside Ghostty.
Fixes#2084.
Related to #6669
Example of `systemctl status` showing main Ghostty process and one
surface:
<img width="1132" height="135" alt="Screenshot From 2026-02-07 16-31-14"
src="https://github.com/user-attachments/assets/81dffd0b-8801-4695-adf4-213647cdf0c3"
/>
This fixes the issue where our palette generation was changing our
default palette. The default palette is based on some well known values
chosen from various terminals and it was a bit jarring to have it
change.
We now only auto-generate the palette if the user has customized at
least one entry.
This changes the way Ghostty assigns itself and subprocesses to
cgroups and how resource controls are applied.
* Ghostty itself no longer modifies it's own cgroup or moves itself
to a transient scope. To modify the main Ghostty process' resource
controls ensure that you're launching Ghostty with a systemd unit and
use the standard systemd methods for overriding and applying changes
to systemd units.
* If configured (on by default), the process used to run your command
will be moved to a transient systemd scope after it is forked from
Ghostty but before the user's command is executed. Resource controls
will be applied to the transient scope at this time. Changes to
the `linux-cgroup*` configuration entries will not alter existing
commands. If changes are made to the `linux-cgroup*` configuration
entries commands will need to be relaunched. Resource limits can also
be modified after launch outside of Ghostty using systemd tooling. The
transient scope name can be shown by running `systemctl --user whoami`
in a shell running inside Ghostty.
Fixes#2084.
Related to #6669
We continue to support bash 3.2 for compatibility with /bin/bash on
macOS. `mapfile` was introduced in bash 4.0, so this change introduces a
`read -r`-based helper function for populating COMPREPLY from a list of
lines.
See: #3042
We continue to support bash 3.2 for compatibility with /bin/bash on
macOS. `mapfile` was introduced in bash 4.0, so this change introduces a
`read -r`-based helper function for populating COMPREPLY from a list of
lines.
Discussed in https://github.com/ghostty-org/ghostty/discussions/10739
## Summary
Remove the hardcoded opaque background (alpha=255) from IME preedit
cells so they respect `background-opacity` like all other cells.
When `background-opacity` is less than 1, preedit (composition) text was
rendered with a fully opaque background, causing the text to appear
highlighted and hard to read. This change removes the explicit per-cell
background from `addPreeditCell`, letting preedit cells fall through to
the global background. The underline indicator is preserved to mark the
preedit region.
---
`background-opacity` が 1
未満のとき、IME入力中(preedit)のセルが完全不透明な背景で描画され、ハイライトされたように見えて読みづらくなる問題を修正しました。
`addPreeditCell` のセル背景描画を削除し、グローバル背景に委ねることで通常セルと同じ透過表示になります。
preedit領域のアンダーラインは維持されます。
## Test plan
- Set `background-opacity` to a value less than 1 (e.g. 0.5)
- Type Japanese (or other IME input) to trigger preedit
- Verify preedit text no longer appears highlighted
- Verify the underline indicator is still drawn under preedit text
AI disclosure: I used Claude Code to investigate the source code and
generate code changes in this PR.
Fixes#10424
Replaces #10431
The issue is that when the row where preedit was wasn't dirty, we were
layering more preedit cells (identical ones) on top, so it'd appear to
get "thicker".
Closes#9880.
https://github.com/user-attachments/assets/7110fae1-a7ca-42b6-8956-833b8bdd5d98
> [!NOTE]
>
> Used AI to get to explain to me some of the APIs and functionality
between `windows` and `tabs` and their connections. But the code itself,
I implemented everything, just used it for help with explaining some
things
## If you feel like reading more:
- I feel there is a lot of duplication now with the `prompt surface
title` functionality. For the dialog creation, i basically copied-pasted
the `surface_title_dialog`, and some of the `titleOverride` and the
`TabDialogSet` functionality is identical to that of the
`prompt_surface_title`
- I would think about abstracting it out, but first I think Id be nice
to think what the maintainers think about this approach before doing
anything else.
Fixes#10424
Replaces #10431
The issue is that when the row where preedit was wasn't dirty, we were
layering more preedit cells (identical ones) on top, so it'd appear to
get "thicker".
The `cursor` shell feature always used a blinking bar (beam), often to
the surprise of users who set `cursor-style-blink = false`.
This change extends our GHOSTTY_SHELL_FEATURES format to include either
`cursor:blink` (default) or `cursor:steady` based on cursor-style-blink
when the `cursor` feature is enabled, and all shell integrations have
been updated to use that additional information to choose the DECSCUSR
cursor value (5=blinking bar, 6=steady bar).
I also considered passing a DECSCUSR value in GHOSTTY_SHELL_FEATURES
(e.g. `cursor:5`). This mostly worked well, but zsh also needs the blink
state on its own for its block cursor. We also don't support any other
shell feature cursor configurability (e.g. the shape), so this was an
over generalization.
This does change the behavior for users who like the blinking bar in the
shell but have `cursor-blink-style = false` for other reasons. We could
provide additional `cursor` shell feature configurability (e.g.
`cursor:blink` in `shell-integration-features`), but I'll propose that
as its own change.
See: #2812Closes: #8681
---
**AI Disclosure:** I did a lot of rubber ducking with Claude Code while
trying out various ideas. It was particularly useful for this kind of
feature because I could try out one thing and have it evaluate the
impact on all of the shell integration scripts at once.
Our PS1 cleanup code (where we remove any markers we added) was still
looking for the previous 133;A form. Update it to include 'cl=line',
which was added in 8595558.
## Summary
- Fixes#10345 — `copy_title_to_clipboard` now copies the user-set
custom title instead of the raw terminal title
- Adds a new `copy_title` apprt action as [suggested by
@mitchellh](https://github.com/ghostty-org/ghostty/issues/10345#issuecomment-2601002974)
- Each platform (GTK + macOS) resolves the effective title (user
override → terminal title fallback) before copying to clipboard
## Changes
- **`src/apprt/action.zig`** — New `copy_title` void action
- **`include/ghostty.h`** — C ABI enum entry
- **`src/Surface.zig`** — Binding handler now dispatches apprt action
instead of inline logic
- **`src/apprt/gtk/class/surface.zig`** — `getEffectiveTitle()` helper
(returns `title_override orelse title`)
- **`src/apprt/gtk/class/application.zig`** — GTK action handler
- **`macos/.../Ghostty.App.swift`** — macOS handler using
`surfaceView.title` + `NSPasteboard`
*Note*: This PR was *AI* assisted.
The printf was part of the original script (9d6121245), and at the time,
this was the only place we'd emit the 133;A mark.
A PS1-based 133;P;k=i mark was introduced in 2bf1f80f7, and then it
become a full 133;A mark in aa47047a6, making the original printf line
redundant (because bash will also redraw PS1 on SIGWINCH).
The PS1-based 133;A was only missing the aid= option, and with that
added, it handles all of our cases (prompts, initial draw, and resizes).
For a hardcoded set of control characters, replace them with spaces when
encoding pasted text. This is to prevent unsafe control characters from being
pasted which could trick a user into executing commands unexpectedly.
This happens regardless of bracketed paste mode, because certain
characters processed by the kernel pty line discipline can break
bracketed paste (source from zsh:
https://zsh-workers.zsh.narkive.com/Kd3evJ7t/bracketed-paste-mode-in-xterm-and-urxvt).
This behavior is based on xterm's behavior, including the list of
characters. Note that as a comment in the code says, we should be
sourcing some of these from a tcgetattr call instead of hardcoding them,
but this is a good start.
This pull request addresses some of the remaining issues when matching
`~`, `$VAR`, `.directory/`, and embedded commas. It does not address
issues with embedded line breaks.
The PR is split in multiple commits carefully applying a set of changes
to
1. make the big regex more composable / readable
2. update some doc strings
3. add more test cases for the issues mentioned
4. two simple commits, each fixing the issues
Changes:
- **url: refactor regex into documented branches**
Break up the big monolithic URL and path regex into named sub-pattern
constants and compose the final expression from three commented
branches:
- URLs with a scheme
- absolute or dot-relative paths
- bare relative paths
This commit only breaks up the regex. It keeps the existing matching
behavior unchanged.
- **url: update top-level comment**
- **url: carefully extend test cases**
Extend existing test cases with `~`, `$VAR`, and bare .-prefixed paths
and embedded `,` comma handling.
See following issue comments:
-
https://github.com/ghostty-org/ghostty/pull/10570#issuecomment-3853842036
-
https://github.com/ghostty-org/ghostty/issues/1972#issuecomment-3859329233
-
https://github.com/ghostty-org/ghostty/issues/1972#issuecomment-3857881196
- **url: remove `,` from path_chars**
Related to #1972
Fixes an issue when paths have embedded comma, e.g.:
shared/src/foo/SomeItem.m:12, shared/src/
with path_chars greedily consuming the rest of the string.
Now file path matching stops at comma. Scheme URLs are unchanged and
still using the comma.
- **url: fix matching `~`, `$VAR`, `.directory/`**
Related to #1972
This commit adds three new alternatives for
`rooted_or_relative_path_prefix`:
- `~/`
- `$VAR` and
- `.local/`, `.config/` etc. for dot-prefixed directory names
Remaining commits fix edge cases one by one:
- **url: fix mid-string dot partial matches**
`"foo.local/share"` (was partial match) → now matches fully
- **url: fix $-numeric character matches**
`"$10/$20"` → no match
- **url: fix partial match of mid string $-variable**
`"foo/$BAR/baz"` (was partial match) → matches fully now
- **url: fix incomplete $-numeric behavior**
`"$10/bar.txt"` (was partial match) → but should not match at all
We were previously overwriting PS0 on every PROMPT_COMMAND. We now
append to PS0, but only if it doesn't already contain our hook.
This is also more consistent with the bash-preexec behavior we maintain
for older bash versions.
Paths like `./.config/ghostty:` and `./Downloads:` were incorrectly
including the trailing colon. Add a `no_trailing_colon` lookbehind to
all path branches and prevent space segments from starting after a colon
so that `": text"` is not consumed as part of the path.
When a user renames a surface via "Change Terminal Title" and then
uses copy_title_to_clipboard, the raw terminal title was copied
instead of the custom name.
This adds a new `copy_title` apprt action so each platform resolves
the effective title (user override or terminal-set) before copying
to clipboard.
Fixes#10345
We were previously overwriting PS0 on every PROMPT_COMMAND. We now
append to PS0, but only if it doesn't already contain our hook.
This is also more consistent with the bash-preexec behavior we maintain
for older bash versions.
The draw timer should only be activated in case a custom shader
is configured and the option custom-shader-animation is either always
or true. If the timer is kept alive CPU usage spiked enourmously.
Fixes#10667