diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-05 05:28:58 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-05 05:28:58 -0500 |
| commit | ebdf9e466b0e1f86e9b7d76650ac32408273e7a7 (patch) | |
| tree | dab9b453f3a93c324b5388b3843502a088c7ed46 /tests/test-ai-term--reuse-existing-agent.el | |
| parent | c094b2e4e64530379a9cb273303308a9affcabf6 (diff) | |
| download | dotemacs-ebdf9e466b0e1f86e9b7d76650ac32408273e7a7.tar.gz dotemacs-ebdf9e466b0e1f86e9b7d76650ac32408273e7a7.zip | |
feat(term): replace vterm with ghostel as the terminal engine
I swapped the terminal engine from vterm to ghostel (libghostty-vt) everywhere. term-config replaces vterm-config (the F12 terminal, the C-; x menu, tmux history capture), and ai-term replaces ai-vterm (the F9 Claude-agent launcher). ghostel renders the agent TUI without vterm's flicker under heavy streaming, and one engine now covers every terminal workflow.
Two behavior changes fall out of the swap. F9 launches in a terminal frame now: ghostel renders in TTY frames, so the old GUI-only guard is gone. Terminal windows no longer dim when unfocused: ghostel resolves its palette into the native module per-terminal, so there's no per-window color hook to dim through the way vterm had.
auto-dim drops its vterm color-advice path, the dashboard Terminal button launches ghostel, and the vterm and vterm-toggle packages are removed. The tmux pane-history and copy-mode machinery carried over unchanged. It keys on the pty tty, which ghostel exposes.
Diffstat (limited to 'tests/test-ai-term--reuse-existing-agent.el')
| -rw-r--r-- | tests/test-ai-term--reuse-existing-agent.el | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/tests/test-ai-term--reuse-existing-agent.el b/tests/test-ai-term--reuse-existing-agent.el new file mode 100644 index 00000000..3f0c6449 --- /dev/null +++ b/tests/test-ai-term--reuse-existing-agent.el @@ -0,0 +1,99 @@ +;;; test-ai-term--reuse-existing-agent.el --- Tests for reuse-existing-agent action -*- lexical-binding: t; -*- + +;;; Commentary: +;; The action looks for any window in the selected frame whose buffer +;; satisfies `cj/--ai-term-buffer-p'. When found, swaps that +;; window's buffer for the one being displayed and returns the +;; window. When not found, returns nil so the next action in the +;; chain runs. +;; +;; This is the action that keeps C-F9 (project-switch) from stealing +;; a non-agent window when the user is focused inside agent. + +;;; Code: + +(require 'ert) + +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(add-to-list 'load-path (expand-file-name "tests" user-emacs-directory)) +(require 'ai-term) +(require 'testutil-ghostel-buffers) + +(ert-deftest test-ai-term--reuse-existing-agent-swaps-buffer-when-window-exists () + "Normal: an agent window exists -> swap its buffer, return the window." + (cj/test--kill-agent-buffers) + (save-window-excursion + (delete-other-windows) + (let ((existing (get-buffer-create "agent [existing]")) + (new-buf (get-buffer-create "agent [new]")) + (split (split-window (selected-window) nil 'right))) + (unwind-protect + (progn + (set-window-buffer split existing) + (let ((result (cj/--ai-term-reuse-existing-agent new-buf nil))) + (should (eq result split)) + (should (eq (window-buffer split) new-buf)))) + (kill-buffer existing) + (kill-buffer new-buf))))) + +(ert-deftest test-ai-term--reuse-existing-agent-returns-nil-when-no-agent-window () + "Boundary: no agent window in frame -> nil (chain continues to next action)." + (cj/test--kill-agent-buffers) + (save-window-excursion + (delete-other-windows) + (let ((new-buf (get-buffer-create "agent [no-existing]"))) + (unwind-protect + (should (null (cj/--ai-term-reuse-existing-agent new-buf nil))) + (kill-buffer new-buf))))) + +(ert-deftest test-ai-term--reuse-existing-agent-leaves-non-agent-windows-alone () + "Boundary: only non-agent windows in frame -> nil; other windows untouched." + (cj/test--kill-agent-buffers) + (save-window-excursion + (delete-other-windows) + (let ((code-buf (get-buffer-create "*test-code-buffer*")) + (new-agent (get-buffer-create "agent [new-here]")) + (other-win (split-window (selected-window) nil 'right))) + (unwind-protect + (progn + (set-window-buffer (selected-window) code-buf) + (set-window-buffer other-win code-buf) + (let ((result (cj/--ai-term-reuse-existing-agent + new-agent nil))) + (should (null result)) + (should (eq (window-buffer (selected-window)) code-buf)) + (should (eq (window-buffer other-win) code-buf)))) + (kill-buffer code-buf) + (kill-buffer new-agent))))) + +(ert-deftest test-ai-term--reuse-existing-agent-preserves-non-agent-window-when-swapping () + "Normal: swap agent window only; the other window keeps its buffer. + +This is the C-F9-from-agent regression: with agent at the bottom +and code on top, switching projects must replace the bottom window's +buffer, not the top window's." + (cj/test--kill-agent-buffers) + (save-window-excursion + (delete-other-windows) + (let* ((code-buf (get-buffer-create "*test-code-top*")) + (agent-a (get-buffer-create "agent [a]")) + (agent-b (get-buffer-create "agent [b]")) + (top-win (selected-window)) + (bottom-win (split-window top-win nil 'below))) + (unwind-protect + (progn + (set-window-buffer top-win code-buf) + (set-window-buffer bottom-win agent-a) + ;; Focus the agent window -- this is the regression scenario. + (select-window bottom-win) + (let ((result (cj/--ai-term-reuse-existing-agent + agent-b nil))) + (should (eq result bottom-win)) + (should (eq (window-buffer bottom-win) agent-b)) + (should (eq (window-buffer top-win) code-buf)))) + (kill-buffer code-buf) + (kill-buffer agent-a) + (kill-buffer agent-b))))) + +(provide 'test-ai-term--reuse-existing-agent) +;;; test-ai-term--reuse-existing-agent.el ends here |
