diff options
| -rw-r--r-- | modules/ai-vterm.el | 14 | ||||
| -rw-r--r-- | modules/cj-window-toggle-lib.el | 23 | ||||
| -rw-r--r-- | modules/vterm-config.el | 9 | ||||
| -rw-r--r-- | tests/test-cj-window-toggle-lib.el | 46 |
4 files changed, 79 insertions, 13 deletions
diff --git a/modules/ai-vterm.el b/modules/ai-vterm.el index d932b0e9..70395ecc 100644 --- a/modules/ai-vterm.el +++ b/modules/ai-vterm.el @@ -391,10 +391,13 @@ on a desktop -- pairing with the axis chosen by (defvar cj/--ai-vterm-last-direction nil "Last user-chosen direction for the AI-vterm display. -Symbol: right, below, left, or above. nil means no agent window -has been toggled off yet this session, so the default direction -applies. Captured at toggle-off by `cj/--ai-vterm-capture-state' -and consumed by `cj/--ai-vterm-display-saved'.") +Symbol: right, below, or left. `above' is never stored -- the agent +window must not be remembered at the top of the frame, so a top +placement falls back to the host default at capture time. nil means no +agent window has been toggled off yet this session, so the default +direction applies. Captured at toggle-off by +`cj/--ai-vterm-capture-state' and consumed by +`cj/--ai-vterm-display-saved'.") (defvar cj/--ai-vterm-last-was-bury nil "Non-nil when the last F9 toggle-off used `bury-buffer'. @@ -444,7 +447,8 @@ is not live." (cj/window-toggle-capture-state window (cj/--ai-vterm-default-direction) 'cj/--ai-vterm-last-direction - 'cj/--ai-vterm-last-size)) + 'cj/--ai-vterm-last-size + '(right below left))) (defun cj/--ai-vterm-reuse-existing-agent (buffer _alist) "Display-buffer action: reuse any window in this frame already showing diff --git a/modules/cj-window-toggle-lib.el b/modules/cj-window-toggle-lib.el index ef57e5cf..9874a134 100644 --- a/modules/cj-window-toggle-lib.el +++ b/modules/cj-window-toggle-lib.el @@ -20,7 +20,8 @@ (require 'cj-window-geometry-lib) (defun cj/window-toggle-capture-state (window default-direction - direction-var size-var) + direction-var size-var + &optional allowed) "Write WINDOW's direction and body size into DIRECTION-VAR and SIZE-VAR. DEFAULT-DIRECTION is the symbol used by `cj/window-direction' when @@ -28,12 +29,24 @@ WINDOW fills its frame's root area. DIRECTION-VAR and SIZE-VAR are the symbols of the consumer's state variables; they receive the captured values via `set'. +ALLOWED, when non-nil, is a list of permitted direction symbols. If +WINDOW's captured direction isn't in it, fall back to DEFAULT-DIRECTION +and clear SIZE-VAR (set to nil) so the consumer's default size applies -- +the captured body size was measured on the disallowed axis and wouldn't +transfer meaningfully. A consumer that wants to forbid a placement (e.g. +an agent window that should never be remembered at the top of the frame) +passes the directions it does allow. Omit ALLOWED to keep every +direction. + No-op when WINDOW is nil or not live." (when (window-live-p window) - (let* ((dir (cj/window-direction window default-direction)) - (size (cj/window-body-size window dir))) - (set direction-var dir) - (set size-var size)))) + (let ((dir (cj/window-direction window default-direction))) + (if (or (null allowed) (memq dir allowed)) + (progn + (set direction-var dir) + (set size-var (cj/window-body-size window dir))) + (set direction-var default-direction) + (set size-var nil))))) (defun cj/window-toggle-display-saved (buffer alist direction-var default-direction diff --git a/modules/vterm-config.el b/modules/vterm-config.el index e7965c65..c8a57d30 100644 --- a/modules/vterm-config.el +++ b/modules/vterm-config.el @@ -341,8 +341,10 @@ Used as the size fallback when `cj/--vterm-toggle-last-size' is nil (defvar cj/--vterm-toggle-last-direction nil "Last user-chosen direction for the F12 vterm display. -Symbol: right, left, below, above. nil means use the default -`below' for F12's traditional bottom split.") +Symbol: right, left, or below. `above' is never stored -- a top +placement falls back to `below' at capture time, so F12 never reopens +from the top. nil means use the default `below' for F12's traditional +bottom split.") (defvar cj/--vterm-toggle-last-size nil "Last user-chosen body size for the F12 vterm display. @@ -384,7 +386,8 @@ split when WINDOW fills the frame's root area." (cj/window-toggle-capture-state window 'below 'cj/--vterm-toggle-last-direction - 'cj/--vterm-toggle-last-size)) + 'cj/--vterm-toggle-last-size + '(right below left))) (defun cj/--vterm-toggle-display-saved (buffer alist) "Display-buffer action: split per saved direction and body size. diff --git a/tests/test-cj-window-toggle-lib.el b/tests/test-cj-window-toggle-lib.el index ca4b7fef..0762e255 100644 --- a/tests/test-cj-window-toggle-lib.el +++ b/tests/test-cj-window-toggle-lib.el @@ -91,6 +91,52 @@ (should (eq test-cj-window-toggle--last-direction 'sentinel-dir)) (should (= test-cj-window-toggle--last-size 0.123)))) +(ert-deftest test-cj-window-toggle-capture-allowed-keeps-permitted-direction () + "Normal: a captured direction in ALLOWED is stored with its body size." + (save-window-excursion + (delete-other-windows) + (let ((below (split-window (selected-window) nil 'below)) + (test-cj-window-toggle--last-direction nil) + (test-cj-window-toggle--last-size nil)) + (cj/window-toggle-capture-state + below 'below + 'test-cj-window-toggle--last-direction + 'test-cj-window-toggle--last-size + '(right below left)) + (should (eq test-cj-window-toggle--last-direction 'below)) + (should (integerp test-cj-window-toggle--last-size))))) + +(ert-deftest test-cj-window-toggle-capture-allowed-rejects-disallowed-direction () + "Boundary: a direction not in ALLOWED falls back to default, size cleared. +The captured body size was measured on the disallowed axis, so it can't +transfer; clearing it lets the consumer's default size apply." + (save-window-excursion + (delete-other-windows) + (let ((above (split-window (selected-window) nil 'above)) + (test-cj-window-toggle--last-direction 'sentinel) + (test-cj-window-toggle--last-size 99)) + (cj/window-toggle-capture-state + above 'below + 'test-cj-window-toggle--last-direction + 'test-cj-window-toggle--last-size + '(right below left)) + (should (eq test-cj-window-toggle--last-direction 'below)) + (should (null test-cj-window-toggle--last-size))))) + +(ert-deftest test-cj-window-toggle-capture-allowed-nil-keeps-all () + "Boundary: omitting ALLOWED preserves the prior unconstrained behavior." + (save-window-excursion + (delete-other-windows) + (let ((above (split-window (selected-window) nil 'above)) + (test-cj-window-toggle--last-direction nil) + (test-cj-window-toggle--last-size nil)) + (cj/window-toggle-capture-state + above 'below + 'test-cj-window-toggle--last-direction + 'test-cj-window-toggle--last-size) + (should (eq test-cj-window-toggle--last-direction 'above)) + (should (integerp test-cj-window-toggle--last-size))))) + (ert-deftest test-cj-window-toggle-display-saved-uses-defaults-when-state-nil () "Normal: nil state -> direction=edge of default, size=default." (let (received-alist |
