From 96e89a8d56417b89e9ee3fec32390bf871a835a8 Mon Sep 17 00:00:00 2001 From: Lawrence Chen Date: Tue, 19 May 2026 03:08:26 -0700 Subject: [PATCH 1/2] test: cover cmux theme picker ctrl navigation --- ...est_bundled_ghostty_theme_picker_helper.sh | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/test_bundled_ghostty_theme_picker_helper.sh b/tests/test_bundled_ghostty_theme_picker_helper.sh index 8035fcdabb..e3afc5fee4 100755 --- a/tests/test_bundled_ghostty_theme_picker_helper.sh +++ b/tests/test_bundled_ghostty_theme_picker_helper.sh @@ -62,9 +62,13 @@ fi CONFIG_PATH="$TMP_DIR/config.ghostty" SEARCH_CONFIG_PATH="$TMP_DIR/search-config.ghostty" +CTRL_N_CONFIG_PATH="$TMP_DIR/ctrl-n-config.ghostty" +CTRL_P_CONFIG_PATH="$TMP_DIR/ctrl-p-config.ghostty" RESULTS_PATH="$TMP_DIR/config-paths.txt" export CONFIG_PATH export SEARCH_CONFIG_PATH +export CTRL_N_CONFIG_PATH +export CTRL_P_CONFIG_PATH export RESULTS_PATH export GHOSTTY_RESOURCES_DIR export HELPER_PATH @@ -83,11 +87,44 @@ import time helper_path = os.environ["HELPER_PATH"] config_path = os.environ["CONFIG_PATH"] search_config_path = os.environ["SEARCH_CONFIG_PATH"] +ctrl_n_config_path = os.environ["CTRL_N_CONFIG_PATH"] +ctrl_p_config_path = os.environ["CTRL_P_CONFIG_PATH"] results_path = os.environ["RESULTS_PATH"] ghostty_resources_dir = os.environ["GHOSTTY_RESOURCES_DIR"] -def run_picker(label, scenario_config_path, scripted_input): +theme_dir = os.path.join(ghostty_resources_dir, "themes") +theme_names = sorted( + ( + entry.name + for entry in os.scandir(theme_dir) + if entry.is_file() or entry.is_symlink() + ), + key=lambda name: name.lower(), +) +if len(theme_names) < 2: + sys.stderr.write(f"FAIL: expected at least two bundled themes in {theme_dir}\n") + sys.exit(1) + + +def assert_theme_written(label, scenario_config_path, expected_theme): + try: + with open(scenario_config_path, "r", encoding="utf-8") as config: + contents = config.read() + except FileNotFoundError: + sys.stderr.write(f"FAIL: theme picker did not write config for {label}.\n") + sys.exit(1) + + expected_line = f"theme = light:{expected_theme},dark:{expected_theme}" + if expected_line not in contents: + sys.stderr.write( + f"FAIL: expected {label} to write {expected_line!r}.\n" + ) + sys.stderr.write(contents) + sys.exit(1) + + +def run_picker(label, scenario_config_path, scripted_input, expected_theme=None): env = os.environ.copy() env.update( { @@ -174,13 +211,22 @@ def run_picker(label, scenario_config_path, scripted_input): finally: os.close(master_fd) + if expected_theme is not None: + assert_theme_written(label, scenario_config_path, expected_theme) + +first_theme = theme_names[0] +second_theme = theme_names[1] run_picker("normal mode", config_path, b"\r") run_picker("search mode", search_config_path, b"/tokyo\r") +run_picker("Ctrl-N navigation", ctrl_n_config_path, b"\x0e\r", second_theme) +run_picker("Ctrl-P navigation", ctrl_p_config_path, b"\x0e\x10\r", first_theme) with open(results_path, "w", encoding="utf-8") as results: results.write(config_path + "\n") results.write(search_config_path + "\n") + results.write(ctrl_n_config_path + "\n") + results.write(ctrl_p_config_path + "\n") PY while IFS= read -r CONFIG_PATH; do From 7b0d5675c77ef72c65be9f92a9d45caba238ca79 Mon Sep 17 00:00:00 2001 From: Lawrence Chen Date: Tue, 19 May 2026 03:21:35 -0700 Subject: [PATCH 2/2] fix: support ctrl navigation in cmux themes --- docs/ghostty-fork.md | 13 ++++++++----- ghostty | 2 +- scripts/ghosttykit-checksums.txt | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/ghostty-fork.md b/docs/ghostty-fork.md index 6fcca1db7e..f3ed2692d9 100644 --- a/docs/ghostty-fork.md +++ b/docs/ghostty-fork.md @@ -13,15 +13,16 @@ When we change the fork, update this document and the parent submodule SHA. ## Current fork changes The fork was refreshed from upstream `main` again on May 1, 2026. -Current cmux pinned fork head: `ff6e1260d`, based on `aef980e27`, with the +Current cmux pinned fork head: `176bd550f`, based on `ff6e1260d`, with the manual embedded IO patch in https://github.com/manaflow-ai/ghostty/pull/53, the Metal renderer row rebuild guard for https://github.com/manaflow-ai/cmux/issues/3369, and the URL/path regex bound for spaced file paths followed by prose. This head keeps the cmux theme picker hooks, exposes the manual surface IO needed by libghostty iOS clients, bounds shaped glyph iteration during IME/preedit row rebuilds, and prevents Cmd-hover from highlighting normal sentence text after a file path. +It also supports Ctrl-N and Ctrl-P in the cmux theme picker. The corresponding prebuilt archive is published at -https://github.com/manaflow-ai/ghostty/releases/tag/xcframework-ff6e1260d2e7767de55b8d9307b328e4060545b7-crashsubdir-cmux-crash-v1 +https://github.com/manaflow-ai/ghostty/releases/tag/xcframework-176bd550f6fedd29e85cd92470e5dfadf295ebf7-crashsubdir-cmux-crash-v1 and pinned in `scripts/ghosttykit-checksums.txt`. ### 1) macOS display link restart on display changes @@ -77,6 +78,7 @@ tend to conflict together during rebases. - `eb34bcdd6` (Harden cmux theme override writes) - `04ec69173` (Apply highlighted cmux theme on Enter) - `4265d3428` (Apply cmux theme from picker search) + - `176bd550f` (Add ctrl navigation to cmux theme picker) - Files: - `build.zig` - `src/cli/list_themes.zig` @@ -87,6 +89,7 @@ tend to conflict together during rebases. - Keeps the preview UI readable in light mode, matches upstream picker startup behavior, and hardens writes to the cmux-managed theme override file. - Restores Enter as the cmux apply action by writing the currently highlighted theme before the picker exits. - Applies the highlighted search result when Enter is pressed from search mode in cmux-managed picker sessions. + - Supports Ctrl-N and Ctrl-P as one-row down/up navigation in cmux-managed picker sessions. ### 5) Color scheme mode 2031 reporting @@ -211,9 +214,9 @@ tend to conflict together during rebases. The current cmux pin is the head listed above. It is reachable from `manaflow-ai/ghostty` through the -`xcframework-ff6e1260d2e7767de55b8d9307b328e4060545b7-crashsubdir-cmux-crash-v1` -release tag and branch `issue-cmd-hover-path-range`. -Published `xcframework-ff6e1260d2e7767de55b8d9307b328e4060545b7-crashsubdir-cmux-crash-v1` and pinned its +`xcframework-176bd550f6fedd29e85cd92470e5dfadf295ebf7-crashsubdir-cmux-crash-v1` +release tag and branch `issue-themes-broken-ctrl-np`. +Published `xcframework-176bd550f6fedd29e85cd92470e5dfadf295ebf7-crashsubdir-cmux-crash-v1` and pinned its archive checksum in `scripts/ghosttykit-checksums.txt`. The release and checksum pin must be regenerated whenever this commit changes, even for comment-only amends, because the release tag is keyed by the Ghostty commit SHA. diff --git a/ghostty b/ghostty index ff6e1260d2..176bd550f6 160000 --- a/ghostty +++ b/ghostty @@ -1 +1 @@ -Subproject commit ff6e1260d2e7767de55b8d9307b328e4060545b7 +Subproject commit 176bd550f6fedd29e85cd92470e5dfadf295ebf7 diff --git a/scripts/ghosttykit-checksums.txt b/scripts/ghosttykit-checksums.txt index bbec08c3f9..44a70d5004 100644 --- a/scripts/ghosttykit-checksums.txt +++ b/scripts/ghosttykit-checksums.txt @@ -30,3 +30,4 @@ fe972c09579a7943f6fe9607fdd24f0f7c999cb1 4dde2bc84b27de84b14a38618ade03b2167a039 aef980e27b584a9d914f1ff0499b13c6ed1973e0 c6b8d560ad6b53d73396f80ba6995cb880ae9de9bfe8cae4dbd9ee72629798b5 6eed7af9240789ba18ccc617e51c384663be34a5 68bf3282478a92640d248c0b52b70cb41387aaed5baee9daa32e1019525f2d07 ff6e1260d2e7767de55b8d9307b328e4060545b7 02e5017a0d27ce5ada9ad92f675ce8c80dcebbc4bcfbe4060b6814b12b28cde9 +176bd550f6fedd29e85cd92470e5dfadf295ebf7 60c612900a6101d2fa88e0d5c8debbcbe7f66230cca6b39f8ce24d5fd8c267ed