From 4000330e5e6536f64f404c1cabc8dc86d9556bb5 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Mon, 11 May 2026 07:18:20 -0500 Subject: refactor(ai-vterm): rename Claude-specific names to a generic "agent" I may add other terminal agents to this launcher (aider, an open-source LLM TUI), so the buffer prefix, the user knob, and the internal helpers shouldn't say "Claude". The module name (ai-vterm) and the `cj/ai-vterm-*` customs were already generic. This finishes the job: - buffer prefix `claude []` -> `agent []` (the `defconst` and the matching display-buffer-alist regex move together) - `cj/ai-vterm-claude-command` -> `cj/ai-vterm-agent-command` (the default still runs the `claude` CLI, with a docstring note on swapping it) - `cj/--ai-vterm-claude-buffers` / `-displayed-claude-window` / `-reuse-existing-claude` -> `-agent-*`, and their test files renamed to match - prose in the module commentary and docstrings, plus the matching test docstrings and buffer-name literals `vterm-config.el` hardcodes the same buffer prefix in `cj/--vterm-toggle-buffer-p` (F12 excludes agent buffers from its candidate set), so that literal moved too. Collapsing it into the shared `cj/--ai-vterm-name-prefix` is a cleanup for another day. After a reload, a project's buffer opens as `agent [foo]` instead of `claude [foo]`. Old buffers keep their names until killed. I also corrected two stale `eshell-vterm-config.el` references in ai-vterm.el docstrings (that module was split into `vterm-config.el`). Two things keep saying "Claude": the `cj/ai-vterm-agent-command` default value (the actual CLI), and the "Claude Code" example in `vterm-config.el`'s cursor-restore docstring (a concrete TUI example, not branding). 90 tests pass. `make validate-modules` clean. --- tests/test-ai-vterm--reuse-existing-agent.el | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 tests/test-ai-vterm--reuse-existing-agent.el (limited to 'tests/test-ai-vterm--reuse-existing-agent.el') diff --git a/tests/test-ai-vterm--reuse-existing-agent.el b/tests/test-ai-vterm--reuse-existing-agent.el new file mode 100644 index 00000000..e6848014 --- /dev/null +++ b/tests/test-ai-vterm--reuse-existing-agent.el @@ -0,0 +1,99 @@ +;;; test-ai-vterm--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-vterm-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-vterm) +(require 'testutil-vterm-buffers) + +(ert-deftest test-ai-vterm--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-vterm-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-vterm--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-vterm-reuse-existing-agent new-buf nil))) + (kill-buffer new-buf))))) + +(ert-deftest test-ai-vterm--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-vterm-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-vterm--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-vterm-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-vterm--reuse-existing-agent) +;;; test-ai-vterm--reuse-existing-agent.el ends here -- cgit v1.2.3