Skip to content

fix(rtk): use matchesKey for tab navigation in zellij settings modal#18

Open
EstebanForge wants to merge 1 commit into
MasuRii:mainfrom
EstebanForge:fix/kitty-arrow-tab-navigation
Open

fix(rtk): use matchesKey for tab navigation in zellij settings modal#18
EstebanForge wants to merge 1 commit into
MasuRii:mainfrom
EstebanForge:fix/kitty-arrow-tab-navigation

Conversation

@EstebanForge

Copy link
Copy Markdown

What

Fixes tab navigation in the RTK Optimizer config modal under kitty-keyboard-protocol terminals. Left/right arrows now switch tabs again in Ghostty, kitty, and WezTerm when running against pi-tui 0.80.x.

Why

ZellijSettingsModal.handleInput switched tabs with a strict byte compare against \x1b[D and \x1b[C. pi-tui 0.80.x enables the kitty keyboard protocol with flags 1, 2, and 4 (disambiguate, report event types, report alternate keys). Under that protocol, bare arrow keys arrive re-encoded as \x1b[1;1D and \x1b[1;1C. The strict compare never matched, so the modal tabs were unreachable on any kitty-protocol terminal.

This is not keyboard-layout specific. It reproduces on any layout the moment the terminal speaks kitty protocol. I verified it on a Spanish LA layout in Ghostty; a US-layout Ghostty user hits the same wall.

How

I replaced the byte compares with matchesKey(data, "left") and matchesKey(data, "right") from @earendil-works/pi-tui. matchesKey normalizes legacy (\x1b[D, \x1bOD), kitty disambiguated (\x1b[1;1D), and xterm modifyOtherKeys encodings, so bare arrows keep working and the kitty-encoded forms now switch tabs. Modified arrows (Shift, Ctrl, Alt) do not match and fall through to the settings list, same as before.

Testing

  • npm test passes (all 7 test files, exit 0).
  • Added three regression tests in src/config-modal.test.ts:
    • Legacy arrow sequences (\x1b[D, \x1b[C) switch tabs, with wrap-around in both directions.
    • Kitty-encoded arrow sequences (\x1b[1;1D, \x1b[1;1C) switch tabs. This is the exact regression.
    • Modified arrows (Ctrl+Right, Alt+Left) do not switch tabs and forward to the active settings list.
  • Manually confirmed in Ghostty on macOS: arrows now move between General, Compaction, Read & Source, and Truncation tabs.

Tab switching compared raw input bytes against \x1b[D and \x1b[C. When pi-tui enables the kitty keyboard protocol (flags 1, 2, 4), bare arrows arrive re-encoded as \x1b[1;1D and \x1b[1;1C, so the strict compare never matched. Tabs were unswitchable in Ghostty, kitty, and WezTerm under pi-tui 0.80.x.

I replaced the byte compares with matchesKey(data, "left") and matchesKey(data, "right"). matchesKey normalizes legacy, kitty, and modifyOtherKeys encodings, so bare arrows keep working and the kitty-encoded forms now switch tabs too.

I added regression tests that drive handleInput with legacy and kitty-encoded arrow sequences and assert the active tab through the rendered tab bar, plus a guard that modified arrows (Ctrl, Alt) fall through to the settings list instead of switching tabs.
@winder

winder commented Jul 15, 2026

Copy link
Copy Markdown

This fix works on my machine running ghostty 1.3.1 and cosmic-term 0.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants