diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-09 11:03:10 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-09 11:03:10 -0500 |
| commit | 26e97633c2141051dee418aff5d8993700cf39b2 (patch) | |
| tree | 7dbe6fa685c0b3093f6e7952a340bb61e44ccbea /tests/test-ai-vterm--capture-state.el | |
| parent | 1945df4bf5f34256908fdf221da8a6f7767ad427 (diff) | |
| download | dotemacs-26e97633c2141051dee418aff5d8993700cf39b2.tar.gz dotemacs-26e97633c2141051dee418aff5d8993700cf39b2.zip | |
fix(ai-vterm): harden F9 toggle across multi-window and buffer-move
Live-testing surfaced four edge-case failures in the F9 toggle geometry preservation. Each gets a dedicated regression test.
- Multi-window squeeze: a captured fraction-of-frame replayed at the wrong size in 3+ window layouts because `display-buffer-in-direction` interprets float widths as fractions of the new window's parent, not the frame. In a flat 3-window layout the parent is the root, but in nested splits it's a sub-tree, and the captured fraction blew the layout up. I switched to absolute integer body-cols and body-lines as the captured unit. The unit is layout-independent.
- One-col peek: a claude window captured rightmost (no right divider, body=total) replayed into a middle position (with divider, body=total-1) showed 1 col of the sibling buffer peeking through where claude should have ended. I wrap the integer size in a `(body-columns . N)` / `(body-lines . N)` cons so `display-buffer-in-direction` sets the body explicitly, divider-independent.
- Position swap and compounding gap: `direction=right` in `display-buffer-in-direction` splits the selected window, not the frame edge. In multi-window layouts the new claude landed mid-frame instead of where it came from. Each toggle compounded a 1-col loss because the new position picked up a divider the original lacked. I map the cardinal direction to its frame-edge variant (`right` -> `rightmost`, `below` -> `bottom`, etc.) so claude always returns to the captured edge.
- Extra window after buffer-move: buffer-move (C-M-arrows) doesn't update the claude window's `quit-restore` parameter, so `quit-window` falls through to bury rather than delete. The window stays alive showing some other buffer. Toggle-on doesn't recognize it and creates a fresh side window, landing at N+1 windows. I switched to `delete-window` with a `one-window-p` guard for the single-window-frame case.
One tradeoff: in a layout where claude was deliberately in a middle position (e.g. agenda | claude | todo), the next toggle pulls it to the frame edge rather than the middle. The side-panel pattern is the design intent and the common case.
7 new regression tests covering each scenario. 80 ai-vterm tests pass. Full make test green.
Diffstat (limited to 'tests/test-ai-vterm--capture-state.el')
| -rw-r--r-- | tests/test-ai-vterm--capture-state.el | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/tests/test-ai-vterm--capture-state.el b/tests/test-ai-vterm--capture-state.el index cecb3ab8b..88a7784b2 100644 --- a/tests/test-ai-vterm--capture-state.el +++ b/tests/test-ai-vterm--capture-state.el @@ -15,7 +15,7 @@ (require 'ai-vterm) (ert-deftest test-ai-vterm--capture-state-right-split-sets-direction () - "Normal: right-split window -> direction=right, size in (0.4, 0.6)." + "Normal: right-split window -> direction=right, integer body-cols matching window." (save-window-excursion (delete-other-windows) (let ((right (split-window (selected-window) nil 'right)) @@ -23,12 +23,11 @@ (cj/--ai-vterm-last-size nil)) (cj/--ai-vterm-capture-state right) (should (eq cj/--ai-vterm-last-direction 'right)) - (should (numberp cj/--ai-vterm-last-size)) - (should (and (> cj/--ai-vterm-last-size 0.4) - (< cj/--ai-vterm-last-size 0.6)))))) + (should (integerp cj/--ai-vterm-last-size)) + (should (= cj/--ai-vterm-last-size (window-body-width right)))))) (ert-deftest test-ai-vterm--capture-state-below-split-sets-direction () - "Normal: below-split window -> direction=below, size in (0.4, 0.6)." + "Normal: below-split window -> direction=below, integer body-lines matching window." (save-window-excursion (delete-other-windows) (let ((below (split-window (selected-window) nil 'below)) @@ -36,8 +35,8 @@ (cj/--ai-vterm-last-size nil)) (cj/--ai-vterm-capture-state below) (should (eq cj/--ai-vterm-last-direction 'below)) - (should (and (> cj/--ai-vterm-last-size 0.4) - (< cj/--ai-vterm-last-size 0.6)))))) + (should (integerp cj/--ai-vterm-last-size)) + (should (= cj/--ai-vterm-last-size (window-body-height below)))))) (ert-deftest test-ai-vterm--capture-state-noop-on-dead-window () "Boundary: nil window -> state remains unchanged." |
