aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-05 09:55:41 -0500
committerCraig Jennings <c@cjennings.net>2026-06-05 09:55:41 -0500
commit81ececd67b23e42163c970edb4e9a4c0d824612e (patch)
tree66c6558000c8675ed63c8b0e2ae9518e383d581c /modules
parent854aa53a96476ccaae0c93bd9af0493ef8431e4b (diff)
downloaddotemacs-81ececd67b23e42163c970edb4e9a4c0d824612e.tar.gz
dotemacs-81ececd67b23e42163c970edb4e9a4c0d824612e.zip
fix(term): forward C-SPC and window-nav keys in ghostel buffers
Two keystrokes weren't reaching Emacs inside a ghostel terminal, both because of how ghostel routes keys in semi-char mode. C-SPC was the worse one. ghostel forwards the `C-@' event but not the distinct `C-SPC' event GUI Emacs produces, so C-Space fell through to the global `set-mark-command' and set an Emacs region in the terminal buffer. That region followed point as output streamed (a stuck "selection" Escape and C-g couldn't clear), and it meant tmux copy-mode's begin-selection never started, so M-w copied nothing. I bind C-SPC to cj/term-send-C-SPC, which forwards NUL like a terminal key. The C-M-arrows (buffer-move, window swap) were being forwarded to the terminal program the same way the F9 family was. I added the windmove S-arrows and buffer-move C-M-arrows to ghostel-keymap-exceptions and rebuilt the semi-char map. The S-arrows already reached Emacs by keymap precedence, but listing them makes the window-nav contract explicit rather than accidental. Regression tests cover all three: C-SPC bound to the forwarder, and the window-nav keys in the exceptions with the semi-char map no longer forwarding them.
Diffstat (limited to 'modules')
-rw-r--r--modules/term-config.el32
1 files changed, 26 insertions, 6 deletions
diff --git a/modules/term-config.el b/modules/term-config.el
index b327777a..5753edde 100644
--- a/modules/term-config.el
+++ b/modules/term-config.el
@@ -221,14 +221,19 @@ run its own project-named tmux session instead of a bare, auto-named one.
:ensure t
:commands (ghostel)
:init
- ;; C-; and F12 must reach Emacs (not the terminal program) inside ghostel
+ ;; These keys 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'.
+ ;; rebuild is what actually lets the key through to `ghostel-mode-map' / the
+ ;; global map. C-; and F12 are the prefix + toggle; the modified arrows are
+ ;; windmove (S-arrows, focus) and buffer-move (C-M-arrows, swap), which the
+ ;; ai-term workflow expects to work from inside an agent buffer.
(with-eval-after-load 'ghostel
- (dolist (key '("C-;" "<f12>"))
+ (dolist (key '("C-;" "<f12>"
+ "S-<up>" "S-<down>" "S-<left>" "S-<right>"
+ "C-M-<up>" "C-M-<down>" "C-M-<left>" "C-M-<right>"))
(add-to-list 'ghostel-keymap-exceptions key))
(ghostel--rebuild-semi-char-keymap))
:hook
@@ -377,12 +382,27 @@ Excludes agent-prefixed buffers; those have their own F9 dispatch via
(keymap-set cj/term-map "q" #'ghostel-send-next-key)
(keymap-set cj/term-map "t" #'cj/term-toggle)
+(defun cj/term-send-C-SPC ()
+ "Forward C-SPC (NUL) to the terminal instead of setting an Emacs mark.
+
+ghostel forwards the `C-@' event but not the distinct `C-SPC' event GUI
+Emacs produces, so a bare C-SPC in a ghostel buffer falls through to the
+global `set-mark-command'. That sets an Emacs region in the terminal buffer
+that follows point as output streams (a stuck \"selection\" C-g / Escape
+can't clear) and, worse, never reaches tmux -- so tmux copy-mode's
+begin-selection (C-Space) never starts and M-w then copies nothing.
+Forwarding NUL makes C-Space behave like a terminal key."
+ (interactive)
+ (ghostel-send-string "\C-@"))
+
(defun cj/term-install-keys ()
- "Make `C-;' resolve as the personal keymap inside ghostel buffers, and bind
-the F-key toggles so they reach Emacs from inside a terminal buffer."
+ "Make `C-;' resolve as the personal keymap inside ghostel buffers, bind the
+F12 toggle, and forward C-SPC so it reaches the terminal (see
+`cj/term-send-C-SPC')."
(when (boundp 'ghostel-mode-map)
(keymap-set ghostel-mode-map "C-;" cj/custom-keymap)
- (keymap-set ghostel-mode-map "<f12>" #'cj/term-toggle)))
+ (keymap-set ghostel-mode-map "<f12>" #'cj/term-toggle)
+ (keymap-set ghostel-mode-map "C-SPC" #'cj/term-send-C-SPC)))
(cj/term-install-keys)
(with-eval-after-load 'ghostel