aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-26 09:31:15 -0400
committerCraig Jennings <c@cjennings.net>2026-06-26 09:31:15 -0400
commit1e4ddabe69741b62d2ce1cfd84671093c6978d2d (patch)
treeaa3acdd343ec3f286bee2b285cdd1f24280fba4a
parent1f10ea49e33c5f09a43e95bc30e818899bf4826d (diff)
downloaddotemacs-1e4ddabe69741b62d2ce1cfd84671093c6978d2d.tar.gz
dotemacs-1e4ddabe69741b62d2ce1cfd84671093c6978d2d.zip
fix(eat): forward word-motion arrows to the terminal in agent buffers
C-/M-left/right were in EAT's default eat-semi-char-non-bound-keys, so they fell through to Emacs and ran left-word/right-word, moving point in the EAT buffer instead of being sent to the program. The terminal's own cursor never moved, so the next keystroke snapped point back to the real cursor -- the "cursor jumps back" symptom when editing claude's input. Bind them to eat-self-input so they forward as word motion, the way ghostel did. Window arrows (S-, C-M-) still reach Emacs for windmove and buffer-move.
-rw-r--r--modules/eat-config.el10
-rw-r--r--tests/test-term-tmux-history.el8
2 files changed, 17 insertions, 1 deletions
diff --git a/modules/eat-config.el b/modules/eat-config.el
index de919a00a..425bbb5ed 100644
--- a/modules/eat-config.el
+++ b/modules/eat-config.el
@@ -431,13 +431,21 @@ pty; without tmux, moves point up in EAT's emacs-mode buffer."
(defvar eat-mode-map)
(declare-function eat-semi-char-mode "eat")
+(declare-function eat-self-input "eat")
(with-eval-after-load 'eat
(keymap-set eat-semi-char-mode-map "C-<up>" #'cj/term-copy-mode-up)
;; Escape forwards ESC to the pty, so it cancels tmux copy-mode (tmux binds
;; Escape to cancel) and works in TUIs; in EAT's own emacs/char mode it returns
;; to semi-char. One key gets out of either copy view.
(keymap-set eat-semi-char-mode-map "<escape>" #'cj/term-send-escape)
- (keymap-set eat-mode-map "<escape>" #'eat-semi-char-mode))
+ (keymap-set eat-mode-map "<escape>" #'eat-semi-char-mode)
+ ;; Word-motion arrows edit the terminal program's input (claude, readline), so
+ ;; forward them to the pty. EAT's default leaves them in the non-bound-keys
+ ;; list, which moved Emacs point instead and desynced it from the real cursor
+ ;; (point jumped back on the next keystroke). Window arrows (S-, C-M-) keep
+ ;; reaching Emacs for windmove / buffer-move.
+ (dolist (key '("C-<left>" "C-<right>" "M-<left>" "M-<right>"))
+ (keymap-set eat-semi-char-mode-map key #'eat-self-input)))
(provide 'eat-config)
;;; eat-config.el ends here
diff --git a/tests/test-term-tmux-history.el b/tests/test-term-tmux-history.el
index c7154e5d2..1dbf6b0bf 100644
--- a/tests/test-term-tmux-history.el
+++ b/tests/test-term-tmux-history.el
@@ -288,5 +288,13 @@ returns to semi-char from EAT's emacs/char mode -- one exit key for both."
(cj/term-send-escape)
(should (equal sent '("\e"))))))
+(ert-deftest test-term-word-motion-arrows-forwarded-not-window-arrows ()
+ "Normal: C-/M-left/right forward to the terminal (word motion in the program's
+input) instead of moving Emacs point; windmove's S-arrows still reach Emacs."
+ (dolist (key '("C-<left>" "C-<right>" "M-<left>" "M-<right>"))
+ (should (eq (keymap-lookup eat-semi-char-mode-map key) #'eat-self-input)))
+ (dolist (key '("S-<left>" "S-<right>"))
+ (should-not (eq (keymap-lookup eat-semi-char-mode-map key) #'eat-self-input))))
+
(provide 'test-term-tmux-history)
;;; test-term-tmux-history.el ends here