From 5eccbf7bd3c9780eee6170839dbf3224a32e9ef3 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 10 May 2026 12:39:44 -0500 Subject: refactor(vterm): move vterm prefix to C-; x and add prompt nav The personal vterm map was on `C-; V'. The capital V costs a Shift on every keystroke into the menu, which adds up for the daily `C-; V c' / `C-; V C' bindings. Move the prefix to lowercase `C-; x' -- free, no Shift, faintly mnemonic (xterm/execute). The lowercase `C-; v' stays the version-control menu. Wire `vterm-next-prompt' and `vterm-previous-prompt' into the menu so they're reachable everywhere, not only inside vterm-copy-mode-map. Lowercase `n' and `p' match Emacs's idiom for next/previous; bump "new vterm" up to capital `N' for the rare new-buffer case. Drop the `' binding for `vterm-copy-mode' from `vterm-mode-map'. Modern keyboards rarely have a Pause key and `C-; x c' is the canonical entry now. Update which-key labels and tests; `test-vterm-keymap-includes-history-and-copy-bindings' now asserts the new prefix, and two new tests cover prompt-nav bindings and the dropped `' binding. --- modules/vterm-config.el | 31 +++++++++++++++++-------------- tests/test-vterm-tmux-history.el | 23 ++++++++++++++++++----- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/modules/vterm-config.el b/modules/vterm-config.el index 93a91915..5acf3363 100644 --- a/modules/vterm-config.el +++ b/modules/vterm-config.el @@ -29,8 +29,8 @@ (defvar-keymap cj/vterm-map :doc "Personal vterm command map.") -;; Uppercase V is intentional: lowercase C-; v is the version-control menu. -(keymap-set cj/custom-keymap "V" cj/vterm-map) +;; Lowercase x picked over V for fewer Shift presses; v is the VC menu. +(keymap-set cj/custom-keymap "x" cj/vterm-map) (defvar-local cj/vterm-tmux-history--origin-buffer nil "Buffer active before opening the tmux history buffer.") @@ -188,8 +188,7 @@ ai-vterm.el is loaded." ("" . nil) ("" . nil) ("C-c C-t" . nil) - ("C-y" . vterm-yank) - ("" . vterm-copy-mode)) + ("C-y" . vterm-yank)) :custom (vterm-kill-buffer-on-exit t) (vterm-max-scrollback 100000) @@ -357,8 +356,10 @@ C-F9 / M-F9 dispatch via `cj/ai-vterm'." (keymap-set cj/vterm-map "C" #'cj/vterm-tmux-history) (keymap-set cj/vterm-map "c" #'vterm-copy-mode) (keymap-set cj/vterm-map "l" #'vterm-clear-scrollback) -(keymap-set cj/vterm-map "n" #'vterm) +(keymap-set cj/vterm-map "N" #'vterm) +(keymap-set cj/vterm-map "n" #'vterm-next-prompt) (keymap-set cj/vterm-map "o" #'vterm-other-window) +(keymap-set cj/vterm-map "p" #'vterm-previous-prompt) (keymap-set cj/vterm-map "q" #'vterm-send-next-key) (keymap-set cj/vterm-map "r" #'vterm-reset-cursor-point) (keymap-set cj/vterm-map "t" #'cj/vterm-toggle) @@ -402,15 +403,17 @@ cursor-visibility tracking resumes." (with-eval-after-load 'which-key (which-key-add-key-based-replacements - "C-; V" "vterm menu" - "C-; V C" "tmux scrollback copy" - "C-; V c" "vterm copy mode" - "C-; V l" "clear vterm scrollback" - "C-; V n" "new vterm" - "C-; V o" "vterm other window" - "C-; V q" "send next key to vterm" - "C-; V r" "reset vterm cursor point" - "C-; V t" "toggle vterm")) + "C-; x" "vterm menu" + "C-; x C" "tmux scrollback copy" + "C-; x c" "vterm copy mode" + "C-; x l" "clear vterm scrollback" + "C-; x N" "new vterm" + "C-; x n" "next prompt" + "C-; x o" "vterm other window" + "C-; x p" "previous prompt" + "C-; x q" "send next key to vterm" + "C-; x r" "reset vterm cursor point" + "C-; x t" "toggle vterm")) (provide 'vterm-config) ;;; vterm-config.el ends here. diff --git a/tests/test-vterm-tmux-history.el b/tests/test-vterm-tmux-history.el index 754ddc9c..f5263df5 100644 --- a/tests/test-vterm-tmux-history.el +++ b/tests/test-vterm-tmux-history.el @@ -120,14 +120,27 @@ RESPONSES is an alist of (ARGS EXIT-CODE OUTPUT)." (ert-deftest test-vterm-keymap-includes-history-and-copy-bindings () "Normal: personal vterm map owns the high-level vterm UX commands." (should (member "C-;" vterm-keymap-exceptions)) - (should-not (eq (keymap-lookup cj/custom-keymap "v c") #'vterm-copy-mode)) - (should (eq (keymap-lookup cj/custom-keymap "V C") #'cj/vterm-tmux-history)) - (should (eq (keymap-lookup cj/custom-keymap "V c") #'vterm-copy-mode)) + (should-not (eq (keymap-lookup cj/custom-keymap "X c") #'vterm-copy-mode)) + (should (eq (keymap-lookup cj/custom-keymap "x C") #'cj/vterm-tmux-history)) + (should (eq (keymap-lookup cj/custom-keymap "x c") #'vterm-copy-mode)) (should (equal (keymap-lookup vterm-mode-map "C-;") cj/custom-keymap)) - (should (eq (keymap-lookup vterm-mode-map "C-; V C") #'cj/vterm-tmux-history)) - (should (eq (keymap-lookup vterm-mode-map "C-; V c") #'vterm-copy-mode)) + (should (eq (keymap-lookup vterm-mode-map "C-; x C") #'cj/vterm-tmux-history)) + (should (eq (keymap-lookup vterm-mode-map "C-; x c") #'vterm-copy-mode)) (should-not (keymap-lookup vterm-mode-map "C-c C-t"))) +(ert-deftest test-vterm-keymap-prompt-navigation () + "Normal: n/p navigate prompts, capital N creates a new vterm buffer." + (should (eq (keymap-lookup cj/custom-keymap "x n") #'vterm-next-prompt)) + (should (eq (keymap-lookup cj/custom-keymap "x p") #'vterm-previous-prompt)) + (should (eq (keymap-lookup cj/custom-keymap "x N") #'vterm))) + +(ert-deftest test-vterm-pause-not-bound-to-copy-mode () + "Normal: is no longer wired as a vterm-copy-mode entry point. +The personal `C-; x c' binding is the canonical entry; is rare on +modern keyboards and was redundant." + (let ((binding (keymap-lookup vterm-mode-map ""))) + (should-not (eq binding #'vterm-copy-mode)))) + (ert-deftest test-vterm-copy-mode-cancel-keys () "Normal: copy mode has explicit copy and no-copy exits." (should (eq (keymap-lookup vterm-copy-mode-map "C-g") -- cgit v1.2.3