aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/ai-vterm.el14
-rw-r--r--modules/cj-window-toggle-lib.el23
-rw-r--r--modules/vterm-config.el9
-rw-r--r--tests/test-cj-window-toggle-lib.el46
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