feat(pet): gate Unicode placeholders to kitty and Ghostty

WezTerm speaks kitty APC but not U+10EEEE, so detect_terminal_graphics()
== "kitty" is the wrong gate for the placeholder path.
This commit is contained in:
Brooklyn Nicholson
2026-08-28 23:27:47 -05:00
committed by brooklyn!
parent ee742fe1bc
commit d889758521
2 changed files with 47 additions and 2 deletions
+16
View File
@@ -90,6 +90,22 @@ def detect_terminal_graphics() -> str:
return "unicode"
def supports_kitty_placeholders() -> bool:
"""True when the terminal can paint kitty Unicode placeholders (U+10EEEE).
Narrower than ``detect_terminal_graphics() == "kitty"``. WezTerm speaks
kitty APC transmits but does not implement the placeholder grid, so those
cells render as tofu. Ghostty and kitty do. VS Code already falls out of
``detect_terminal_graphics`` as ``unicode``.
"""
if detect_terminal_graphics() != "kitty":
return False
term_program = os.environ.get("TERM_PROGRAM", "").lower()
if term_program == "wezterm" or os.environ.get("WEZTERM_PANE"):
return False
return True
def resolve_mode(configured: str | None, *, stream=None) -> str:
"""Resolve the effective render mode from config + the environment.
+31 -2
View File
@@ -239,13 +239,17 @@ def test_kitty_payload_structure(boba_like):
def _clear_graphics_env(monkeypatch):
for key in ("KITTY_WINDOW_ID", "TERM_PROGRAM", "ITERM_SESSION_ID", "WEZTERM_PANE", "TERM"):
monkeypatch.delenv(key, raising=False)
def test_vscode_terminal_ignores_leaked_graphics_env(monkeypatch):
# The VS Code / Cursor integrated terminal can't show inline images by
# default, yet inherits ITERM_SESSION_ID/KITTY_WINDOW_ID when launched from
# those terminals. TERM_PROGRAM=vscode must win → unicode, never a protocol
# whose escapes the embedded terminal would silently drop.
for key in ("KITTY_WINDOW_ID", "TERM_PROGRAM", "ITERM_SESSION_ID", "WEZTERM_PANE", "TERM"):
monkeypatch.delenv(key, raising=False)
_clear_graphics_env(monkeypatch)
monkeypatch.setenv("TERM_PROGRAM", "vscode")
assert render.detect_terminal_graphics() == "unicode"
@@ -253,3 +257,28 @@ def test_vscode_terminal_ignores_leaked_graphics_env(monkeypatch):
monkeypatch.setenv(leaked, "1")
assert render.detect_terminal_graphics() == "unicode"
monkeypatch.delenv(leaked)
assert render.supports_kitty_placeholders() is False
def test_kitty_placeholders_on_kitty_and_ghostty(monkeypatch):
_clear_graphics_env(monkeypatch)
monkeypatch.setenv("TERM", "xterm-kitty")
monkeypatch.setenv("KITTY_WINDOW_ID", "1")
assert render.supports_kitty_placeholders() is True
_clear_graphics_env(monkeypatch)
monkeypatch.setenv("TERM", "xterm-ghostty")
monkeypatch.setenv("TERM_PROGRAM", "ghostty")
assert render.supports_kitty_placeholders() is True
def test_wezterm_is_not_placeholder_capable(monkeypatch):
# WezTerm speaks kitty APC but not U+10EEEE. Placeholders would tofu.
_clear_graphics_env(monkeypatch)
monkeypatch.setenv("TERM", "xterm-256color")
monkeypatch.setenv("TERM_PROGRAM", "WezTerm")
assert render.detect_terminal_graphics() == "kitty"
assert render.supports_kitty_placeholders() is False
monkeypatch.setenv("WEZTERM_PANE", "1")
assert render.supports_kitty_placeholders() is False