13622 Commits

Author SHA1 Message Date
Mitchell Hashimoto
38664afde0 Update iTerm2 colorschemes (#10079)
Upstream release:
https://github.com/mbadolato/iTerm2-Color-Schemes/releases/tag/release-20251222-150520-0add1e1
tip
2025-12-27 17:06:15 -08:00
mitchellh
03ecc9fdbf deps: Update iTerm2 color schemes 2025-12-28 00:16:19 +00:00
Mitchell Hashimoto
c00d7fc5c4 shell-integration: ensure clean env on failure (#10035)
Our shell integration routines can now fail when resources are missing.
This change introduces tests to ensure that they leave behind a clean
environment upon failure.

The bash integration needed a little reordering to support this.
2025-12-26 13:29:27 -08:00
Mitchell Hashimoto
9eceea18ec macOS: Don't duplicate command palette entries for terminal commands (#10069)
This is a regression introduced when we added macOS support for custom
entries. I mistakingly thought that only custom entries were in the
config, but we do initialize it with all!
2025-12-26 11:13:21 -08:00
Mitchell Hashimoto
14f592b8d4 macOS: Don't duplicate command palette entries for terminal commands
This is a regression introduced when we added macOS support for custom
entries. I mistakingly thought that only custom entries were in the
config, but we do initialize it with all!
2025-12-26 11:03:50 -08:00
Mitchell Hashimoto
78e895dfae terminal: Fix possible crash on RenderState with invalid mouse point (#10067)
Fixes #10032
2025-12-26 10:48:24 -08:00
Mitchell Hashimoto
26b104c9e0 terminal: Fix possible crash on RenderState with invalid mouse point
Fixes #10032
2025-12-26 10:45:15 -08:00
Mitchell Hashimoto
ebcc350018 datastruct/circ_buf: fix n=0 edge cases (#10066)
From #10063

This fixes and tests various edge cases around noop operations.
2025-12-26 10:36:36 -08:00
Mitchell Hashimoto
23addb3c67 terminal: fix crash when sliding window sees empty node (#10065)
Related to #10063

This fixes a crash that can happen if the SlidingWindow search portion
sees a zero-byte page.

We have more fixes to implement in the circular buffer handling but
putting the fix at this layer also prevents some unnecessary allocations
for zero-byte data.
2025-12-26 10:36:15 -08:00
Mitchell Hashimoto
eb5d2e034b datastruct/circ_buf: fix n=0 edge cases
From #10063

This fixes and tests various edge cases around noop operations.
2025-12-26 10:33:52 -08:00
Mitchell Hashimoto
79cc22e186 terminal: fix crash when sliding window sees empty node
Related to #10063

This fixes a crash that can happen if the SlidingWindow search portion
sees a zero-byte page. 

We have more fixes to implement in the circular buffer handling but
putting the fix at this layer also prevents some unnecessary allocations
for zero-byte data.
2025-12-26 10:26:12 -08:00
Mitchell Hashimoto
90075045c7 fix(iOS): fix iOS app startup failure (#10060)
Fixes #7643

This commit address the issue with 3 minor fixes:
1. Initialize ghostty lib before app start, or global allocator will be
null.
2. `addSublayer` should be called on CALayer object, which is the
property 'layer' of UIView
3. According to apple's
[document](https://developer.apple.com/documentation/metal/mtlstoragemode/managed?language=objc),
managed storage mode is not supported by iOS. So always use shared mode.

FYI, another [fix](https://github.com/mitchellh/libxev/pull/204) in
libxev is also required to make iOS app work.
2025-12-26 07:17:47 -08:00
Zongyuan Li
88e471e015 fix(iOS): fix iOS app startup failure
Fixes #7643

This commit address the issue with 3 minor fixes:
1. Initialize ghostty lib before app start, or global allocator will
   be null.
2. `addSublayer` should be called on CALayer object, which is the
   property 'layer' of UIView
3. According to apple's [document](https://developer.apple.com/documentation/metal/mtlstoragemode/managed?language=objc),
   managed storage mode is not supported by iOS. So always use shared
   mode.

FYI, another [fix](https://github.com/mitchellh/libxev/pull/204) in libxev
is also required to make iOS app work.
2025-12-26 18:53:45 +08:00
Mitchell Hashimoto
f705b9f46a terminal: search will re-scroll to navigate to a single match (#10056)
Fixes #9958
Replaces #9989

This changes the search navigation logic to always scroll if there is a
selected search result so long as the search result isn't already within
the viewport.
2025-12-25 13:54:13 -08:00
Mitchell Hashimoto
2415116ad0 Revert "macOS: move NSGlassEffectView into TerminalViewContainer (#10046)"
This reverts commit b8490f40c5, reversing
changes made to 050278feae.
2025-12-25 13:52:59 -08:00
Mitchell Hashimoto
f54ac11080 terminal: search will re-scroll to navigate to a single match
Fixes #9958
Replaces #9989

This changes the search navigation logic to always scroll if there is a
selected search result so long as the search result isn't already within
the viewport.
2025-12-25 13:50:02 -08:00
Mitchell Hashimoto
b8490f40c5 macOS: move NSGlassEffectView into TerminalViewContainer (#10046)
Fixes #9991, modifying the subview of `NSThemeFrame` seems "dangerous"
and unpredictable.

> [!NOTE]
> AI Proofread some of my comments



https://github.com/user-attachments/assets/c443cf71-8a00-4c37-b008-d89b7f1564a3
2025-12-25 12:51:47 -08:00
Mitchell Hashimoto
050278feae chore: fixed some typo (#10054)
Author: rezky_nightky <with dot rezky at gmail dot com>
Repository: ghostty
Branch: main
Signing: GPG (4B65AAC2)
HashAlgo: BLAKE3

[ Block Metadata ]
BlockHash:
c37f4ee817412728a8058ba6087f5ca6aaff5a845560447d595d8055972d0eac
PrevHash:
3510917a780936278debe21786b7bae3a2162cb3857957314c3b8702e921b3d4
PatchHash:
5e5bb4ab35df304ea13c3d297c6d9a965156052c82bccf852b1f00b7bcaa7dd4

FilesChanged: 18
Lines: +92 / -92

Timestamp: 2025-12-25T17:27:08Z
Signature1:
c1970dbb94600d1e24dfe8efcc00f001664db7b777902df9632a689b1d9d1498
Signature2:
30babb1e3ca07264931e067bfe36c676fb7988c2e06f8c54e0c9538fe7c7fc9a
2025-12-25 12:50:31 -08:00
rezky_nightky
bf73f75304 chore: fixed some typo
Author: rezky_nightky <with dot rezky at gmail dot com>
Repository: ghostty
Branch: main
Signing: GPG (4B65AAC2)
HashAlgo: BLAKE3

[ Block Metadata ]
BlockHash: c37f4ee817412728a8058ba6087f5ca6aaff5a845560447d595d8055972d0eac
PrevHash: 3510917a780936278debe21786b7bae3a2162cb3857957314c3b8702e921b3d4
PatchHash: 5e5bb4ab35df304ea13c3d297c6d9a965156052c82bccf852b1f00b7bcaa7dd4

FilesChanged: 18
Lines: +92 / -92

Timestamp: 2025-12-25T17:27:08Z
Signature1: c1970dbb94600d1e24dfe8efcc00f001664db7b777902df9632a689b1d9d1498
Signature2: 30babb1e3ca07264931e067bfe36c676fb7988c2e06f8c54e0c9538fe7c7fc9a
2025-12-26 00:27:08 +07:00
Mitchell Hashimoto
4af425e11c macOS: command-palette-entry shows up in command palette (#10050)
Fixes #7158

This has worked on GTK for awhile. This exposes custom command palette
entries to the macOS app now.
2025-12-24 14:42:35 -08:00
Mitchell Hashimoto
f7f29934f3 macos: ghostty.command should be part of iOS build 2025-12-24 14:41:41 -08:00
Mitchell Hashimoto
12523ca61c macOS: command-palette-entry is now visible in macOS 2025-12-24 14:33:21 -08:00
Mitchell Hashimoto
017021787c config: RepeatableCommand cval 2025-12-24 14:26:47 -08:00
Lukas
574ee470bd macOS: move NSGlassEffectView into TerminalViewContainer 2025-12-24 23:10:31 +01:00
Lukas
7ce88b6811 macOS: fix initial surface color scheme in quickTerminal 2025-12-24 21:46:42 +01:00
Jon Parise
141e64cede shell-integration: always call setupFeatures (#10033)
Our existing logic already ensured that setupFeatures() was always
called, but that was happening from two code paths: explicitly when
shell integration is .none and implicitly via setup().

We can simplify this by always calling setupFeatures() once, outside of
the (automatic) shell integration path.

There's one small behavioral change: we previously didn't set up shell
features in the automatic shell integration path if we didn't have a
resources directory (as a side effect). Resources are required for shell
integrations, but we don't need them to export GHOSTTY_SHELL_FEATURES,
which could potentially still be useful on its on.
2025-12-24 09:08:28 -05:00
Mitchell Hashimoto
df1c8120da Invalid key sequence does not encode if a catch_all has ignore (#10038)
This adds some new special case handling for key sequences when an
unbound keyboard input is received. If the current keybinding set scope
(i.e. active tables) has a `catch_all` binding that would `ignore`
input, then the entire key sequence is dropped.

Normally, when an unbound key sequence is received, Ghostty encodes it
and sends it to the running program.

This special behavior is useful for things like Vim mode which have
`g>g` to scroll to top, and a `catch_all=ignore` to drop all other
input. If the user presses `g>h` (unbound), you don't want `gh` to show
up in your terminal input, because the `catch_all=ignore` indicates that
the user wants that mode to drop all unbound input.
2025-12-23 20:37:39 -08:00
Mitchell Hashimoto
0db0655ea5 Invalid key sequence does not encode if a catch_all has ignore
This adds some new special case handling for key sequences when an
unbound keyboard input is received. If the current keybinding set scope
(i.e. active tables) has a `catch_all` binding that would `ignore`
input, then the entire key sequence is dropped.

Normally, when an unbound key sequence is received, Ghostty encodes it
and sends it to the running program. 

This special behavior is useful for things like Vim mode which have `g>g`
to scroll to top, and a `catch_all=ignore` to drop all other input. If
the user presses `g>h` (unbound), you don't want `gh` to show up in your 
terminal input, because the `catch_all=ignore` indicates that the user
wants that mode to drop all unbound input.
2025-12-23 20:31:05 -08:00
Jon Parise
256c3b9ffb shell-integration: ensure clean env on failure
Our shell integration routines can now fail when resources are missing.
This change introduces tests to ensure that they leave behind a clean
environment upon failure.

The bash integration needed a little reordering to support this.
2025-12-23 14:51:09 -05:00
Mitchell Hashimoto
634c3353fe GTK: UI for key sequences and tables (#10034)
Fixes #2127 

This adds a UI similar to macOS to show the current state of key
sequences and/or key tables.


https://github.com/user-attachments/assets/4399d2af-a88c-4b70-922b-7727dc4d2053

**AI disclosure:** AI was used for various things, but I did write most
of the code myself, especially around the memory management of
properties since agents can't get that quite right yet. 😄
2025-12-23 11:27:03 -08:00
Mitchell Hashimoto
f2fe979bab update valgrind suppressions 2025-12-23 11:23:03 -08:00
Mitchell Hashimoto
71d5ae5a51 apprt/gtk: key state overlay text is dynamic 2025-12-23 11:06:10 -08:00
Mitchell Hashimoto
7ca3f41f6f apprt/gtk: key state overlay take bindings from surface 2025-12-23 10:35:44 -08:00
Mitchell Hashimoto
481490bd11 apprt/gtk: add getters for key-sequence and key-table 2025-12-23 10:26:25 -08:00
Mitchell Hashimoto
85ce7d0b04 apprt/gtk: write StringList for boxed type of strings 2025-12-23 10:19:29 -08:00
Jon Parise
3d2aa9bd82 shell-integration: always call setupFeatures
Our existing logic already ensured that setupFeatures() was always
called, but that was happening from two code paths: explicitly when
shell integration is .none and implicitly via setup().

We can simplify this by always calling setupFeatures() once, outside of
the (automatic) shell integration path.

There's one small behavioral change: we previously didn't set up shell
features in the automatic shell integration path if we didn't have a
resources directory (as a side effect). Resources are required for shell
integrations, but we don't need them to export GHOSTTY_SHELL_FEATURES,
which could potentially still be useful on its on.
2025-12-23 13:17:22 -05:00
Mitchell Hashimoto
1562967d51 apprt/gtk: key state overlay 2025-12-23 09:46:09 -08:00
Jon Parise
e56f28ac7b shell-integration: add failure regression test (#10031)
Add a unit test to prevent regressions in our failure state.

For example, we always want to set GHOSTTY_SHELL_FEATURES, even if
automatic shell integration fails, because it's also used for manual
shell integration (e.g. #5048).
2025-12-23 12:41:24 -05:00
Jon Parise
8f44b74b33 shell-integration: add failure regression test
Add a unit test to prevent regressions in our failure state.

For example, we always want to set GHOSTTY_SHELL_FEATURES, even if
automatic shell integration fails, because it's also used for manual
shell integration (e.g. #5048).
2025-12-23 12:27:59 -05:00
Mitchell Hashimoto
a1ee2f0764 apprt/gtk: store key sequences/tables in surface state 2025-12-23 09:26:53 -08:00
Mitchell Hashimoto
6b7a7aacf2 macos: apply window position after setting content size (#10007)
> **Note**: This is a re-submission of #9952, which was closed in favor
of #9975. However, as noted in my [comment on
#9975](https://github.com/ghostty-org/ghostty/pull/9975#issuecomment-3677916608),
the issue still persists.

## Summary

- Fix `window-position-x/y` not being applied when `window-width/height`
is also configured

## Problem

When both `window-position-x/y` and `window-width/height` are
configured, the window position was not being applied correctly. The
window would appear near the center of the screen instead of the
specified position.

This worked correctly in v1.2.3 but regressed afterwards.

## Root Cause

This is a regression introduced in c75bade89 (#9747).

The commit refactored the default size logic from a computed `NSRect?`
property to a `DefaultSize` enum with `.frame` and
`.contentIntrinsicSize` cases.

**Before (working):**
```swift
private var defaultSize: NSRect? {
    // ... calculate frame ...
    return adjustForWindowPosition(frame: frame, on: screen)  // ← position was applied
}
```

**After (broken):**
```swift
enum DefaultSize {
    case frame(NSRect)
    case contentIntrinsicSize
    
    func apply(to window: NSWindow) {
        case .contentIntrinsicSize:
            window.setContentSize(size)
            window.constrainToScreen()
            // ← adjustForWindowPosition call was lost
    }
}
```

When `window-width/height` is configured, the `.contentIntrinsicSize`
case is used. This case only called `setContentSize` and
`constrainToScreen`, but did not apply the window position adjustment.

## Why This Fix is Correct

`DefaultSize.apply()` is intentionally **not** responsible for
position—it only handles **size**:

1. `apply()` is also called from `returnToDefaultSize(_:)` menu action
2. When user triggers "Return to Default Size", only the **size** should
reset—**not the position**
3. If we added position logic inside `apply()`, the window would
unexpectedly jump back to its initial position

Therefore, position adjustment belongs **outside** of `apply()`,
specifically during initial window setup in `windowDidLoad`.

## Fix

Call `adjustForWindowPosition` after applying the content intrinsic size
to ensure the window position is correctly set during initial window
creation.
2025-12-23 07:08:16 -08:00
Mitchell Hashimoto
2fac92bb39 feat(cli): list keybindings from key tables (#10028)
Closes #9995

**Problem**: `ghostty +list-keybinds` doesn't display bindings from key
tables.

**Solution**: Iterate over `keybinds.tables` and collect bindings from
each table, prefixing them with `table_name/` in the output. Bindings
are sorted with default bindings first, then table bindings grouped
alphabetically by table name.



https://github.com/user-attachments/assets/de73b66a-fc23-4913-a083-7a4aa992c5ec

> _My theme is "Monokai Pro Octagon" which makes `blue` → `orange`_


<details>
<summary>Default theme output</summary>
<img width="942" height="824" alt="Screenshot 2025-12-23 at 08 34 10"
src="https://github.com/user-attachments/assets/21b3a746-930c-4795-b538-f92455cf5fa5"
/>
</details>


I chose `8` (for `table_style`) since table names are secondary (thus,
dim gray color) and color is distinct without overpowering. Obviously,
open to whatever is preferred.

**Testing**: Manual verification with configs containing multiple key
tables, chained bindings within tables, and mixed default/table
bindings.

---

> **AI Disclosure**: Claude Code for research and review. All code typed
by me.
2025-12-23 07:07:35 -08:00
Mitchell Hashimoto
2846e9e01c ci: update macOS builds to use Xcode 26.2 (#10023)
We were fixed on 26.0 previously.
2025-12-23 07:06:22 -08:00
kadekillary
12815f7fa3 feat(cli): list keybindings from key tables
- Display keybindings grouped by their source table, with table name as prefix
- Sort default bindings before table bindings, maintaining visual hierarchy
- Support keybindings defined in key tables alongside default bindings
- Enable users to discover all available keybindings across the entire config
2025-12-23 08:19:45 -06:00
Mitchell Hashimoto
6720076c95 ci: update macOS builds to use Xcode 26.2
We were fixed on 26.0 previously.
2025-12-22 21:19:04 -08:00
Mitchell Hashimoto
fbed63b047 config: improve key table parsing robustness (#10022)
Fixes #10020

This improves parsing key tables so that the following edge cases are
now handled correctly, which were regressions from prior tip behavior:

  - `/=action`
  - `ctrl+/=action`
  - `table//=action` (valid to bind `/` in a table)
  - `table/a>//=action` (valid to bind a table with a sequence)
2025-12-22 21:03:43 -08:00
Mitchell Hashimoto
56f5a14dde config: improve key table parsing robustness
Fixes #10020

This improves parsing key tables so that the following edge cases
are now handled correctly, which were regressions from prior tip
behavior:

  - `/=action`
  - `ctrl+/=action`
  - `table//=action` (valid to bind `/` in a table)
  - `table/a>//=action` (valid to bind a table with a sequence)
2025-12-22 20:58:21 -08:00
Mitchell Hashimoto
7ad1e6e2ea Chained Keybinds (#10015)
Fixes #9961 

This implements chained keybinds as described in #9961. 

```
keybind = ctrl+shift+f=toggle_fullscreen
keybind = chain=toggle_window_decorations
```

These work with tables and sequences. For tables, the chain is unique
per table, so the following works:

```
keybind = foo/ctrl+shift+f=toggle_fullscreen
keybind = foo/chain=toggle_window_decorations
```

For sequences, it applies to the most recent sequence:

```
keybind = ctrl+b>f=toggle_fullscreen
keybind = chain=toggle_window_decorations
```

## TODO

Some limitations to resolve in future PRs (make an issue) or commits:

- [x] GTK: Global shortcuts cannot be chained: #10019
- [x] Inspector doesn't show chained keybinds
- [x] `+list-keybinds` doesn't show chains

**AI disclosure:** AI helped write tests, but everything else was
organic. AI did surprisingly bad at trying to implement this feature, so
I threw all of its work away! 😄
2025-12-22 20:52:20 -08:00
Mitchell Hashimoto
c11febd0dd cli/list-keybinds: support chained keybindings 2025-12-22 20:43:52 -08:00
Mitchell Hashimoto
dcbb3fe56f inspector: show chained bindings 2025-12-22 20:37:39 -08:00