diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-05 05:43:43 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-05 05:43:43 -0500 |
| commit | 854aa53a96476ccaae0c93bd9af0493ef8431e4b (patch) | |
| tree | a102ae33bbe0341819df900228460263ee83b6c2 /modules | |
| parent | ebdf9e466b0e1f86e9b7d76650ac32408273e7a7 (diff) | |
| download | dotemacs-854aa53a96476ccaae0c93bd9af0493ef8431e4b.tar.gz dotemacs-854aa53a96476ccaae0c93bd9af0493ef8431e4b.zip | |
fix(term): make F9 and F12 reach Emacs inside ghostel buffers
F9 did nothing in an agent buffer: ghostel's semi-char mode forwards every key not in ghostel-keymap-exceptions to the pty, and ghostel-semi-char-mode-map outranks the major-mode map, so the F9-family and F12 bindings I'd put in ghostel-mode-map never fired. The keys went to Claude/the shell, which ignored them.
I added the F9 family (in ai-term) and F12 plus C-; (in term-config) to ghostel-keymap-exceptions and rebuilt the semi-char map with ghostel--rebuild-semi-char-keymap. add-to-list updates the list but not the already-built map, so the rebuild is what actually lets the keys through. C-; had the same latent bug for the same reason.
Two regression tests assert the keys are in the exceptions and that the rebuilt semi-char map no longer forwards them. I also corrected the spec note that claimed binding in ghostel-mode-map was enough (true for vterm, wrong for ghostel) and codified the gotcha.
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/ai-term.el | 13 | ||||
| -rw-r--r-- | modules/term-config.el | 12 |
2 files changed, 22 insertions, 3 deletions
diff --git a/modules/ai-term.el b/modules/ai-term.el index 85b84a12..1384f812 100644 --- a/modules/ai-term.el +++ b/modules/ai-term.el @@ -74,6 +74,8 @@ (declare-function ghostel "ghostel" (&optional arg)) (declare-function ghostel-send-string "ghostel" (string)) +(declare-function ghostel--rebuild-semi-char-keymap "ghostel" ()) +(defvar ghostel-keymap-exceptions) (defvar ghostel-mode-map) (defvar ghostel-buffer-name) (defvar ghostel-buffer-name-function) @@ -923,7 +925,16 @@ interrupt work in progress. Bound to M-<f9> (primary) and C-S-<f9>." (keymap-set ghostel-mode-map "<f9>" #'cj/ai-term) (keymap-set ghostel-mode-map "C-<f9>" #'cj/ai-term-pick-project) (keymap-set ghostel-mode-map "M-<f9>" #'cj/ai-term-close) - (keymap-set ghostel-mode-map "C-S-<f9>" #'cj/ai-term-close)) + (keymap-set ghostel-mode-map "C-S-<f9>" #'cj/ai-term-close) + ;; The bindings above live in `ghostel-mode-map', but in semi-char mode + ;; ghostel's own `ghostel-semi-char-mode-map' forwards every key not in + ;; `ghostel-keymap-exceptions' to the pty -- and that map outranks the + ;; major-mode map, so it would swallow the F9 family before the bindings + ;; above fire. Add the family to the exceptions and rebuild the semi-char + ;; map so the keys fall through to `ghostel-mode-map' inside agent buffers. + (dolist (key '("<f9>" "C-<f9>" "M-<f9>" "C-S-<f9>")) + (add-to-list 'ghostel-keymap-exceptions key)) + (ghostel--rebuild-semi-char-keymap)) ;; ---------- emacsclient: keep opened files off the agent terminal ---------- ;; diff --git a/modules/term-config.el b/modules/term-config.el index 84ba7b3b..b327777a 100644 --- a/modules/term-config.el +++ b/modules/term-config.el @@ -53,6 +53,7 @@ (declare-function ghostel-next-prompt "ghostel" (&optional n)) (declare-function ghostel-previous-prompt "ghostel" (&optional n)) (declare-function ghostel-send-next-key "ghostel" ()) +(declare-function ghostel--rebuild-semi-char-keymap "ghostel" ()) (defvar ghostel-mode-map) (defvar ghostel-keymap-exceptions) (defvar ghostel-buffer-name) @@ -220,9 +221,16 @@ run its own project-named tmux session instead of a bare, auto-named one. :ensure t :commands (ghostel) :init - ;; C-; must reach Emacs so the personal prefix keymap works in terminals. + ;; C-; and F12 must reach Emacs (not the terminal program) inside ghostel + ;; buffers. In semi-char mode ghostel forwards every key NOT in + ;; `ghostel-keymap-exceptions' to the pty, and `ghostel-semi-char-mode-map' + ;; is rebuilt from that list by `ghostel--rebuild-semi-char-keymap' -- + ;; `add-to-list' alone updates the list but not the already-built map, so the + ;; rebuild is what actually lets the key through to `ghostel-mode-map'. (with-eval-after-load 'ghostel - (add-to-list 'ghostel-keymap-exceptions "C-;")) + (dolist (key '("C-;" "<f12>")) + (add-to-list 'ghostel-keymap-exceptions key)) + (ghostel--rebuild-semi-char-keymap)) :hook ((ghostel-mode . cj/turn-off-chrome-for-term) (ghostel-mode . cj/term-launch-tmux)) |
