diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-10 03:48:44 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-10 03:48:44 -0500 |
| commit | 3003683a24cf38dbd2eeeaee6244ad0c1bbe72ee (patch) | |
| tree | 7dec1d786aeccdf77f99fb5af9a602eba65cc96f /tests/test-vterm-copy-mode-cursor.el | |
| parent | b099c779343119ce40f2636469e118ec104002e0 (diff) | |
| download | dotemacs-3003683a24cf38dbd2eeeaee6244ad0c1bbe72ee.tar.gz dotemacs-3003683a24cf38dbd2eeeaee6244ad0c1bbe72ee.zip | |
fix(vterm): force a visible cursor in vterm-copy-mode
vterm's C module sets `cursor-type' to nil whenever the underlying TUI sends DECTCEM (`\e[?25l') to hide the terminal cursor. Most full-screen TUIs do this on startup — Claude Code in an ai-vterm being a daily example. Once the cursor is hidden at the buffer level, vterm-copy-mode inherits that nil and the user can't see where point is when navigating to select text. Selection still works, but you're flying blind.
Add a `vterm-copy-mode-hook' that forces `cursor-type' to a 3-pixel bar on entry and kills the buffer-local override on exit. The bar shape is drawn between characters rather than by inverting one, so heavy TUI face properties don't hide it either. On exit the live terminal goes back to whatever vterm's tracking says, so the TUI's chosen cursor state resumes.
4 ERT tests cover the hook's enter/exit behavior and confirm registration on `vterm-copy-mode-hook'.
Diffstat (limited to 'tests/test-vterm-copy-mode-cursor.el')
| -rw-r--r-- | tests/test-vterm-copy-mode-cursor.el | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/tests/test-vterm-copy-mode-cursor.el b/tests/test-vterm-copy-mode-cursor.el new file mode 100644 index 00000000..ee72a0bb --- /dev/null +++ b/tests/test-vterm-copy-mode-cursor.el @@ -0,0 +1,51 @@ +;;; test-vterm-copy-mode-cursor.el --- Tests for cursor visibility in vterm-copy-mode -*- lexical-binding: t; -*- + +;;; Commentary: +;; vterm's C module sets `cursor-type' to nil when the underlying TUI +;; sends DECTCEM (`\e[?25l'). Most full-screen TUIs (Claude Code, htop, +;; etc.) hide the cursor on startup. In `vterm-copy-mode' the user is +;; navigating the buffer, not watching the TUI, so the cursor must be +;; forced visible -- the hook in `vterm-config.el' handles that. On +;; exit, the buffer-local override is killed so the live terminal goes +;; back to the TUI's chosen cursor state. + +;;; Code: + +(require 'ert) + +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(defvar vterm-copy-mode nil) +(require 'vterm-config) + +(ert-deftest test-vterm-copy-mode-cursor-restored-on-enter () + "Normal: entering copy-mode with cursor-type nil sets a visible cursor." + (with-temp-buffer + (setq-local cursor-type nil) + (let ((vterm-copy-mode t)) + (cj/--vterm-copy-mode-restore-cursor)) + (should (equal cursor-type '(bar . 3))))) + +(ert-deftest test-vterm-copy-mode-cursor-restored-when-prior-was-box () + "Boundary: entering copy-mode overrides any prior cursor-type with the bar." + (with-temp-buffer + (setq-local cursor-type 'box) + (let ((vterm-copy-mode t)) + (cj/--vterm-copy-mode-restore-cursor)) + (should (equal cursor-type '(bar . 3))))) + +(ert-deftest test-vterm-copy-mode-cursor-override-killed-on-exit () + "Normal: exiting copy-mode kills the buffer-local cursor-type override." + (with-temp-buffer + (setq-local cursor-type '(bar . 3)) + (should (local-variable-p 'cursor-type)) + (let ((vterm-copy-mode nil)) + (cj/--vterm-copy-mode-restore-cursor)) + (should-not (local-variable-p 'cursor-type)))) + +(ert-deftest test-vterm-copy-mode-cursor-hook-installed () + "Normal: the cursor-restoration hook is registered on vterm-copy-mode-hook." + (should (memq #'cj/--vterm-copy-mode-restore-cursor + vterm-copy-mode-hook))) + +(provide 'test-vterm-copy-mode-cursor) +;;; test-vterm-copy-mode-cursor.el ends here |
