From 512308ae07a4e67378a31e77102f6fa3cec7b630 Mon Sep 17 00:00:00 2001 From: froppa <5844892+froppa@users.noreply.github.com> Date: Tue, 6 Oct 2026 19:04:06 +0200 Subject: [PATCH] ghostty: make the herdr key table actually pass Hyper chords through In Ghostty 1.3.1, unbind inside a key table only removes the table's own entry, so the lookup fell through to the default bindings and Hyper-C still ran new_tab with the table active. Each table entry is now a performable activate_key_table:herdr. With herdr already innermost that is a no-op returning false, and an unperformed performable binding sends the key to the pty. --- home/dot_config/ghostty/config | 75 ++++++++++++++++++---------------- test.sh | 3 +- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/home/dot_config/ghostty/config b/home/dot_config/ghostty/config index a36f000..c81010b 100644 --- a/home/dot_config/ghostty/config +++ b/home/dot_config/ghostty/config @@ -168,44 +168,47 @@ keybind = ctrl+alt+super+u=ignore # Herdr is NOT Ghostty's shell. The zsh `herdr` wrapper activates this # table on its surface through Ghostty's AppleScript `perform action` -# and deactivates it when Herdr exits. Unbinding here sends the chord -# to the pty, so Herdr handles it; Hyper-= still equalizes Ghostty splits. +# and deactivates it when Herdr exits. `unbind` cannot work here: it +# empties the table entry and the lookup falls through to the default +# bindings. Re-activating the already-innermost table is a no-op, so the +# performable binding matches, does nothing, and Ghostty sends the chord +# to the pty for Herdr. Hyper-= still equalizes Ghostty splits. keybind = herdr/ -keybind = herdr/ctrl+alt+super+i=unbind -keybind = herdr/ctrl+alt+super+slash=unbind -keybind = herdr/ctrl+alt+super+z=unbind -keybind = herdr/ctrl+alt+super+x=unbind -keybind = herdr/ctrl+alt+super+arrow_left=unbind -keybind = herdr/ctrl+alt+super+arrow_down=unbind -keybind = herdr/ctrl+alt+super+arrow_up=unbind -keybind = herdr/ctrl+alt+super+arrow_right=unbind -keybind = herdr/ctrl+alt+super+shift+arrow_left=unbind -keybind = herdr/ctrl+alt+super+shift+arrow_down=unbind -keybind = herdr/ctrl+alt+super+shift+arrow_up=unbind -keybind = herdr/ctrl+alt+super+shift+arrow_right=unbind -keybind = herdr/ctrl+alt+super+c=unbind -keybind = herdr/ctrl+alt+super+p=unbind -keybind = herdr/ctrl+alt+super+n=unbind -keybind = herdr/ctrl+alt+super+comma=unbind -keybind = herdr/ctrl+alt+super+shift+comma=unbind -keybind = herdr/ctrl+alt+super+shift+period=unbind -keybind = herdr/ctrl+alt+super+digit_1=unbind -keybind = herdr/ctrl+alt+super+digit_2=unbind -keybind = herdr/ctrl+alt+super+digit_3=unbind -keybind = herdr/ctrl+alt+super+digit_4=unbind -keybind = herdr/ctrl+alt+super+digit_5=unbind -keybind = herdr/ctrl+alt+super+digit_6=unbind -keybind = herdr/ctrl+alt+super+digit_7=unbind -keybind = herdr/ctrl+alt+super+digit_8=unbind -keybind = herdr/ctrl+alt+super+digit_9=unbind -keybind = herdr/ctrl+alt+super+w=unbind -keybind = herdr/ctrl+alt+super+digit_0=unbind -keybind = herdr/ctrl+alt+super+tab=unbind -keybind = herdr/ctrl+alt+super+b=unbind -keybind = herdr/ctrl+alt+super+j=unbind -keybind = herdr/ctrl+alt+super+m=unbind -keybind = herdr/ctrl+alt+super+u=unbind +keybind = herdr/performable:ctrl+alt+super+i=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+slash=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+z=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+x=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+arrow_left=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+arrow_down=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+arrow_up=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+arrow_right=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+shift+arrow_left=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+shift+arrow_down=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+shift+arrow_up=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+shift+arrow_right=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+c=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+p=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+n=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+comma=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+shift+comma=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+shift+period=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_1=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_2=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_3=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_4=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_5=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_6=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_7=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_8=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_9=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+w=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+digit_0=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+tab=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+b=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+j=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+m=activate_key_table:herdr +keybind = herdr/performable:ctrl+alt+super+u=activate_key_table:herdr # ======================================= diff --git a/test.sh b/test.sh index e7cc4ba..956de49 100755 --- a/test.sh +++ b/test.sh @@ -115,7 +115,8 @@ grep -Fq 'config-file = ?config.local' home/dot_config/ghostty/config || fail "G ! grep -qE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+=text:' home/dot_config/ghostty/config || fail "Hyper chords must reach herdr, not be rewritten into tmux prefix bytes" ! grep -qE '^keybind = ctrl\+alt\+super\+[^=]+=[^i]' home/dot_config/ghostty/config || fail "Hyper actions must be performable: a menu shortcut fires before the herdr key table" grep -q 'activate_key_table:herdr' home/dot_zshrc || fail "the herdr wrapper must hand Ghostty's Hyper chords to herdr" -[[ "$(grep -oE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+' home/dot_config/ghostty/config | sed -E 's/^keybind = (performable:)?//' | grep -v '+equal$')" == "$(grep -E '^keybind = herdr/.+=unbind$' home/dot_config/ghostty/config | sed 's/^keybind = herdr\///; s/=unbind$//')" ]] || fail "the herdr key table must unbind every Hyper chord Ghostty binds" +[[ "$(grep -oE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+' home/dot_config/ghostty/config | sed -E 's/^keybind = (performable:)?//' | grep -v '+equal$')" == "$(grep -E '^keybind = herdr/performable:.+=activate_key_table:herdr$' home/dot_config/ghostty/config | sed 's/^keybind = herdr\/performable://; s/=activate_key_table:herdr$//')" ]] || fail "the herdr key table must pass every Hyper chord Ghostty binds through to herdr" +! grep -qE '^keybind = herdr/.+=unbind$' home/dot_config/ghostty/config || fail "unbind in a key table falls through to the default binding; use a performable no-op" [[ ! -e home/dot_config/ghostty/herdr.ghostty ]] || fail "herdr is the default; the herdr.ghostty overlay is gone" grep -Fq "bind -n M-C-a if -F '#{@ssht}' 'send-keys M-C-a' 'switch-client -T prefix'" home/dot_config/tmux/tmux.conf || fail "Hyper chords must drive the remote tmux in an ssht pane" grep -Fq 'tmux*:RGB:extkeys' home/dot_config/tmux/tmux.conf || fail "a remote tmux nested by ssht must get extended keys for Claude Code's Shift-Enter"