aboutsummaryrefslogtreecommitdiff
path: root/tests/test-ai-term--sort-candidates.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-05 05:28:58 -0500
committerCraig Jennings <c@cjennings.net>2026-06-05 05:28:58 -0500
commitebdf9e466b0e1f86e9b7d76650ac32408273e7a7 (patch)
treedab9b453f3a93c324b5388b3843502a088c7ed46 /tests/test-ai-term--sort-candidates.el
parentc094b2e4e64530379a9cb273303308a9affcabf6 (diff)
downloaddotemacs-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--sort-candidates.el')
-rw-r--r--tests/test-ai-term--sort-candidates.el74
1 files changed, 74 insertions, 0 deletions
diff --git a/tests/test-ai-term--sort-candidates.el b/tests/test-ai-term--sort-candidates.el
new file mode 100644
index 00000000..f1f6155f
--- /dev/null
+++ b/tests/test-ai-term--sort-candidates.el
@@ -0,0 +1,74 @@
+;;; test-ai-term--sort-candidates.el --- Tests for cj/--ai-term-sort-candidates -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; The project picker lists candidates with a live tmux session first
+;; (so an agent that survived an Emacs crash is easy to get back to),
+;; then everything else. Within the active group, projects opened this
+;; session (`cj/--ai-term-mru') lead, most-recent first; the rest of the
+;; active group, and the whole no-session group, sort alphabetically by
+;; abbreviated path. With an empty MRU it's just active-first-then-alpha.
+
+;;; Code:
+
+(require 'ert)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'ai-term)
+
+(ert-deftest test-ai-term--sort-candidates-active-first-then-alpha ()
+ "Normal: the one project with a live session leads; the rest go alpha."
+ (let ((cj/ai-term-tmux-session-prefix "aiv-"))
+ (should (equal (cj/--ai-term-sort-candidates
+ '("/c/foo" "/c/bar" "/c/baz")
+ '("aiv-bar"))
+ '("/c/bar" "/c/baz" "/c/foo")))))
+
+(ert-deftest test-ai-term--sort-candidates-multiple-active-each-group-alpha ()
+ "Normal: both groups sort alphabetically internally."
+ (let ((cj/ai-term-tmux-session-prefix "aiv-"))
+ (should (equal (cj/--ai-term-sort-candidates
+ '("/c/foo" "/c/bar" "/c/baz")
+ '("aiv-foo" "aiv-bar"))
+ '("/c/bar" "/c/foo" "/c/baz")))))
+
+(ert-deftest test-ai-term--sort-candidates-no-sessions-is-plain-alpha ()
+ "Boundary: nil session set -> a plain alphabetical list."
+ (let ((cj/ai-term-tmux-session-prefix "aiv-"))
+ (should (equal (cj/--ai-term-sort-candidates
+ '("/c/foo" "/c/bar") nil)
+ '("/c/bar" "/c/foo")))))
+
+(ert-deftest test-ai-term--sort-candidates-empty-dirs-yields-nil ()
+ "Boundary: no candidates -> nil."
+ (should (null (cj/--ai-term-sort-candidates nil '("aiv-foo")))))
+
+(ert-deftest test-ai-term--sort-candidates-active-group-mru-first ()
+ "Normal: within the active group, recently-opened projects lead in MRU
+order; active dirs not opened this session fall after them alpha; the
+no-session group trails, alpha."
+ (let ((cj/ai-term-tmux-session-prefix "aiv-")
+ (cj/--ai-term-mru '("/c/baz" "/c/foo")))
+ (should (equal (cj/--ai-term-sort-candidates
+ '("/c/foo" "/c/bar" "/c/baz" "/c/qux")
+ '("aiv-foo" "aiv-bar" "aiv-baz"))
+ '("/c/baz" "/c/foo" "/c/bar" "/c/qux")))))
+
+(ert-deftest test-ai-term--sort-candidates-mru-does-not-bump-inactive ()
+ "Boundary: an MRU dir whose tmux session has died sorts alpha in the
+no-session group, not at the top."
+ (let ((cj/ai-term-tmux-session-prefix "aiv-")
+ (cj/--ai-term-mru '("/c/zed")))
+ (should (equal (cj/--ai-term-sort-candidates
+ '("/c/foo" "/c/zed" "/c/bar")
+ '("aiv-foo"))
+ '("/c/foo" "/c/bar" "/c/zed")))))
+
+(ert-deftest test-ai-term--session-active-p-matches-by-derived-name ()
+ "Normal: a dir is active when its derived session name is in the set."
+ (let ((cj/ai-term-tmux-session-prefix "aiv-"))
+ (should (cj/--ai-term-session-active-p "/c/foo" '("aiv-bar" "aiv-foo")))
+ (should-not (cj/--ai-term-session-active-p "/c/qux" '("aiv-bar" "aiv-foo")))
+ (should-not (cj/--ai-term-session-active-p "/c/foo" nil))))
+
+(provide 'test-ai-term--sort-candidates)
+;;; test-ai-term--sort-candidates.el ends here