aboutsummaryrefslogtreecommitdiff
path: root/modules/cj-window-toggle.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-10 03:19:03 -0500
committerCraig Jennings <c@cjennings.net>2026-05-10 03:19:03 -0500
commit9712c2e122bd6923298910fcb53b33ca675ddd82 (patch)
tree8c31197d5e5ab17d71f654d0107ce4746602ddb0 /modules/cj-window-toggle.el
parentb4f2b1d7d18f9246b06baf1e573b2cd990af83c8 (diff)
downloaddotemacs-9712c2e122bd6923298910fcb53b33ca675ddd82.tar.gz
dotemacs-9712c2e122bd6923298910fcb53b33ca675ddd82.zip
refactor: extract toggle-state helpers shared by F9 and F12
The F12 commit (554b32d) flagged this as a follow-up: ~120 lines of capture-state and display-saved logic were duplicated between modules/ai-vterm.el and modules/eshell-vterm-config.el. The only differences were the default direction (right for F9, below for F12) and the customization name for the fallback size. Extract the shared logic into modules/cj-window-toggle.el so both consumers reduce to thin delegates that pass their state-var symbols and defaults. The state vars stay where they were, so existing tests against each consumer's helpers keep working. 10 new tests cover the parameterized helpers in isolation. All consumer tests still pass.
Diffstat (limited to 'modules/cj-window-toggle.el')
-rw-r--r--modules/cj-window-toggle.el85
1 files changed, 85 insertions, 0 deletions
diff --git a/modules/cj-window-toggle.el b/modules/cj-window-toggle.el
new file mode 100644
index 00000000..016b1967
--- /dev/null
+++ b/modules/cj-window-toggle.el
@@ -0,0 +1,85 @@
+;;; cj-window-toggle.el --- Shared toggle-state helpers for display-buffer dispatchers -*- lexical-binding: t; -*-
+
+;; Author: Craig Jennings <c@cjennings.net>
+
+;;; Commentary:
+
+;; Parameterized helpers used by ai-vterm.el (F9) and
+;; eshell-vterm-config.el (F12) to capture a window's geometry at
+;; toggle-off and replay it on the next toggle-on. Each consumer
+;; holds its own pair of state variables (last-direction symbol +
+;; last-size integer/float) and passes the variable symbols to the
+;; helpers. Both helpers are pure with respect to their arguments;
+;; the side effects are confined to the named state variables.
+;;
+;; Pulls the geometry primitives in from cj-window-geometry.el.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'cj-window-geometry)
+
+(defun cj/window-toggle-capture-state (window default-direction
+ direction-var size-var)
+ "Write WINDOW's direction and body size into DIRECTION-VAR and SIZE-VAR.
+
+DEFAULT-DIRECTION is the symbol used by `cj/window-direction' when
+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'.
+
+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))))
+
+(defun cj/window-toggle-display-saved (buffer alist
+ direction-var default-direction
+ size-var default-size)
+ "Display-buffer action: split per saved DIRECTION-VAR and SIZE-VAR.
+
+Reads the consumer's stored direction and size through DIRECTION-VAR
+and SIZE-VAR (symbols); falls back to DEFAULT-DIRECTION and
+DEFAULT-SIZE when the stored values are nil. The cardinal direction
+is mapped to its frame-edge variant via
+`cj/cardinal-to-edge-direction' so the new buffer always lands at
+the same frame edge regardless of the selected window. An integer
+size is wrapped in a `(body-columns . N)' / `(body-lines . N)' cons
+so `display-buffer-in-direction' sets the body explicitly,
+divider-independent. A float size passes through as a fraction of
+the new window's parent.
+
+Caller-supplied ALIST entries for direction, window-width, or
+window-height are stripped before delegating to
+`display-buffer-in-direction' so the saved-state values control
+placement; the remaining alist entries are passed through."
+ (let* ((stored-dir (and (boundp direction-var) (symbol-value direction-var)))
+ (stored-size (and (boundp size-var) (symbol-value size-var)))
+ (direction (or stored-dir default-direction))
+ (edge-direction (or (cj/cardinal-to-edge-direction direction)
+ (cj/cardinal-to-edge-direction default-direction)))
+ (size (or stored-size default-size))
+ (size-key (if (memq direction '(right left))
+ 'window-width
+ 'window-height))
+ (body-tag (if (memq direction '(right left))
+ 'body-columns
+ 'body-lines))
+ (size-value (if (integerp size)
+ (cons body-tag size)
+ size))
+ (filtered (cl-remove-if
+ (lambda (cell)
+ (memq (car-safe cell)
+ '(direction window-width window-height)))
+ alist))
+ (effective (append
+ (list (cons 'direction edge-direction)
+ (cons size-key size-value))
+ filtered)))
+ (display-buffer-in-direction buffer effective)))
+
+(provide 'cj-window-toggle)
+;;; cj-window-toggle.el ends here