diff options
| -rw-r--r-- | modules/term-config.el | 24 | ||||
| -rw-r--r-- | tests/test-term-tmux-history.el | 23 |
2 files changed, 32 insertions, 15 deletions
diff --git a/modules/term-config.el b/modules/term-config.el index 7cd386dc..2daebe9b 100644 --- a/modules/term-config.el +++ b/modules/term-config.el @@ -29,10 +29,12 @@ ;; Two ways to lift text out of a terminal, both with the same key story: ;; - C-; x c enters copy-mode via `cj/term-copy-mode-dwim'. When a tmux ;; client is attached (typical -- `cj/term-launch-tmux' auto-starts tmux), -;; sends tmux's prefix C-b [ so the user lands in tmux's own copy-mode with -;; the full pane history available. Without tmux, falls back to +;; sends tmux's prefix C-b [ then C-a, so the user lands in tmux's own +;; copy-mode with the full pane history and the cursor at column 0 (so +;; scrolling up runs up the left, not the right). Without tmux, falls back to ;; `ghostel-copy-mode' (read-only standard-Emacs navigation over the -;; scrollback; M-w copies and stays, q / C-g exit). +;; scrollback; M-w copies and stays, q / C-g exit) and moves point to the +;; start of the line for the same column-0 reason. ;; - C-; x h captures the current tmux pane's full history into a temporary ;; Emacs buffer. ;; In both copy surfaces, M-w copies the active region and stays open so several @@ -190,13 +192,19 @@ cheap boolean predicate." "Enter copy-mode using the engine appropriate to this terminal. When tmux is attached, write tmux's default prefix sequence (C-b [) into the -pty so the user lands in tmux's copy-mode with the full pane history. Without -tmux, falls through to `ghostel-copy-mode', a read-only standard-Emacs view of -the scrollback (M-w copies and stays, q / C-g exit)." +pty so the user lands in tmux's copy-mode with the full pane history, then +C-a to land the cursor at the start of the line. Without the trailing C-a +the copy cursor inherits the live column (far right after a prompt) and +scrolling up runs up the right edge; tmux's emacs copy-mode binds C-a to +start-of-line, so column 0 makes it run up the left. Without tmux, falls +through to `ghostel-copy-mode' (a read-only standard-Emacs view of the +scrollback; M-w copies and stays, q / C-g exit), then moves point to the +start of the line for the same column-0 reason." (interactive) (if (cj/term--in-tmux-p) - (ghostel-send-string "\C-b[") - (ghostel-copy-mode))) + (ghostel-send-string "\C-b[\C-a") + (ghostel-copy-mode) + (beginning-of-line))) ;; ----------------------------- ghostel package ------------------------------- diff --git a/tests/test-term-tmux-history.el b/tests/test-term-tmux-history.el index b7ab5351..51e9725c 100644 --- a/tests/test-term-tmux-history.el +++ b/tests/test-term-tmux-history.el @@ -260,8 +260,11 @@ ghostel-mode terminal." (should-not tmux-called))))) (ert-deftest test-term-copy-mode-dwim-sends-tmux-prefix-when-attached () - "Normal: with tmux attached, dwim writes C-b [ into the pty so tmux enters -its own copy-mode against the full pane history." + "Normal: with tmux attached, dwim writes C-b [ then C-a into the pty so +tmux enters its own copy-mode and lands the cursor at the start of the +line. Without the trailing C-a the cursor inherits the live column (far +right after a prompt) and scrolling up runs up the right edge; start-of-line +puts it at column 0 so it runs up the left." (let ((agent (cj/test--make-fake-ghostel-buffer "agent [emacs.d]")) (sent nil) (copy-mode-called nil)) @@ -279,16 +282,20 @@ its own copy-mode against the full pane history." '((("list-clients" "-F" "#{client_tty}\t#{pane_id}") 0 "/dev/pts/8\t%8\n")) (cj/term-copy-mode-dwim) - (should (equal sent '("\C-b["))) + (should (equal sent '("\C-b[\C-a"))) (should-not copy-mode-called)))) (when (buffer-live-p agent) (kill-buffer agent))))) (ert-deftest test-term-copy-mode-dwim-falls-back-without-tmux () - "Boundary: without tmux, dwim calls `ghostel-copy-mode' and sends nothing." + "Boundary: without tmux, dwim calls `ghostel-copy-mode' then moves point +to the start of the line and sends nothing to the pty. The +`beginning-of-line' must run after `ghostel-copy-mode' so it repositions +inside the copy view; column 0 keeps the cursor on the left edge while +scrolling, parity with the tmux branch's trailing C-a." (let ((agent (cj/test--make-fake-ghostel-buffer "agent [emacs.d]")) (sent nil) - (copy-mode-called nil)) + (dwim-order nil)) (unwind-protect (with-current-buffer agent (cl-letf (((symbol-function 'get-buffer-process) @@ -298,13 +305,15 @@ its own copy-mode against the full pane history." ((symbol-function 'ghostel-send-string) (lambda (s) (push s sent))) ((symbol-function 'ghostel-copy-mode) - (lambda () (setq copy-mode-called t)))) + (lambda () (push 'copy-mode dwim-order))) + ((symbol-function 'beginning-of-line) + (lambda (&optional _n) (push 'beginning-of-line dwim-order)))) (test-term-tmux-history--with-tmux-mock '((("list-clients" "-F" "#{client_tty}\t#{pane_id}") 1 "no server running")) (cj/term-copy-mode-dwim) (should-not sent) - (should copy-mode-called)))) + (should (equal (reverse dwim-order) '(copy-mode beginning-of-line)))))) (when (buffer-live-p agent) (kill-buffer agent))))) |
