diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-13 15:39:40 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-13 15:39:40 -0500 |
| commit | 84944a8572a84862fa39e52a62ccba24cdee9891 (patch) | |
| tree | c25a48ea537955974606d2eb085d3802d47a16cc | |
| parent | df2b59b9d6e75d7d9139cac1919eab558751d816 (diff) | |
| download | dotemacs-84944a8572a84862fa39e52a62ccba24cdee9891.tar.gz dotemacs-84944a8572a84862fa39e52a62ccba24cdee9891.zip | |
feat(vterm): show tmux scrollback history in place
`cj/vterm-tmux-history' previously used `pop-to-buffer', which routed the history view through display-buffer-alist -- in an agent window that often meant a split or a hand-off to another window, costing the agent its frame slot. `switch-to-buffer' instead drops the history into the selected window directly; the existing quit handler already restores the origin in that same window via `set-window-buffer'.
New test asserts the in-place behavior: starting single-window with a vterm origin, invoking the command leaves `(one-window-p)` t with the history buffer in the original slot. The existing render test no longer needs its `pop-to-buffer' stub since `switch-to-buffer' works in batch.
| -rw-r--r-- | modules/vterm-config.el | 9 | ||||
| -rw-r--r-- | tests/test-vterm-tmux-history.el | 48 |
2 files changed, 47 insertions, 10 deletions
diff --git a/modules/vterm-config.el b/modules/vterm-config.el index 764c9dcd7..954e096ab 100644 --- a/modules/vterm-config.el +++ b/modules/vterm-config.el @@ -121,7 +121,12 @@ returns to the vterm without copying. RET is left unbound." The history buffer uses normal Emacs navigation and selection. `M-w' copies the active region and stays open, so several pieces can be copied in a row; `q', `<escape>', or `C-g' returns point to the vterm -buffer that launched it." +buffer that launched it. + +The history view replaces the origin vterm buffer in the same window +(via `switch-to-buffer'), not a split or a popped-up window -- reading +past output should keep the agent's frame slot intact, and quit puts +the live terminal back where it was." (interactive) (let* ((origin-buffer (current-buffer)) (origin-window (selected-window)) @@ -139,7 +144,7 @@ buffer that launched it." (setq-local cj/vterm-tmux-history--origin-window origin-window) (setq-local cj/vterm-tmux-history--origin-point origin-point) (goto-char (point-max))) - (pop-to-buffer buffer))) + (switch-to-buffer buffer))) (defun cj/vterm-copy-mode-cancel () "Exit `vterm-copy-mode' without copying." diff --git a/tests/test-vterm-tmux-history.el b/tests/test-vterm-tmux-history.el index eec6c6220..c0a71421d 100644 --- a/tests/test-vterm-tmux-history.el +++ b/tests/test-vterm-tmux-history.el @@ -63,15 +63,12 @@ RESPONSES is an alist of (ARGS EXIT-CODE OUTPUT)." "Normal: command renders tmux history in a normal Emacs buffer." (let ((origin (cj/test--make-fake-vterm-buffer "*test-vterm-history-origin*"))) (unwind-protect - (with-current-buffer origin + (save-window-excursion + (switch-to-buffer origin) (cl-letf (((symbol-function 'get-buffer-process) (lambda (_buffer) 'fake-process)) ((symbol-function 'process-tty-name) - (lambda (_process) "/dev/pts/8")) - ((symbol-function 'pop-to-buffer) - (lambda (buffer &rest _) - (set-buffer buffer) - buffer))) + (lambda (_process) "/dev/pts/8"))) (test-vterm-tmux-history--with-tmux-mock '((("list-clients" "-F" "#{client_tty}\t#{pane_id}") 0 "/dev/pts/8\t%8\n") @@ -81,10 +78,45 @@ RESPONSES is an alist of (ARGS EXIT-CODE OUTPUT)." (should (eq major-mode 'cj/vterm-tmux-history-mode)) (should buffer-read-only) (should (string-match-p "history http://example.com" - (buffer-string))))))) + (buffer-string)))))) + (cj/test--kill-buffers-matching-prefix "*vterm tmux history") + (when (buffer-live-p origin) + (kill-buffer origin))))) + +(ert-deftest test-vterm-tmux-history-replaces-origin-buffer-in-same-window () + "Normal: the history view replaces the origin in the selected window. + +Before the in-place change, `cj/vterm-tmux-history' used `pop-to-buffer' +which could split or hand the buffer to a different window. The fix +uses `switch-to-buffer' so reading scrollback keeps the agent's frame +slot." + (let ((origin (cj/test--make-fake-vterm-buffer "*test-vterm-history-inplace*"))) + (unwind-protect + (save-window-excursion + (delete-other-windows) + (switch-to-buffer origin) + (let ((win (selected-window))) + (should (eq (window-buffer win) origin)) + (should (one-window-p)) + (cl-letf (((symbol-function 'get-buffer-process) + (lambda (_buffer) 'fake-process)) + ((symbol-function 'process-tty-name) + (lambda (_process) "/dev/pts/8"))) + (test-vterm-tmux-history--with-tmux-mock + '((("list-clients" "-F" "#{client_tty}\t#{pane_id}") 0 + "/dev/pts/8\t%8\n") + (("capture-pane" "-p" "-J" "-S" "-" "-E" "-" "-t" "%8") 0 + "scrollback line\n")) + (cj/vterm-tmux-history))) + ;; Same window, no split, history buffer now in the slot. + (should (one-window-p)) + (should (eq (selected-window) win)) + (should (string-prefix-p + "*vterm tmux history:" + (buffer-name (window-buffer win)))))) (cj/test--kill-buffers-matching-prefix "*vterm tmux history") (when (buffer-live-p origin) - (kill-buffer origin)))) + (kill-buffer origin))))) (ert-deftest test-vterm-tmux-history-quit-returns-to-origin () "Normal: q / <escape> / C-g (cj/vterm-tmux-history-quit) kills the history |
