diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-09 14:48:01 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-09 14:48:01 -0500 |
| commit | 7ad613f96380319c037f367a1b6b1beda03846ca (patch) | |
| tree | b442ddc79de803e042505df84ff1d8acb8c812cb /modules/eshell-vterm-config.el | |
| parent | a29ac8d9f31443279ba5897b13cf5cda49519975 (diff) | |
| download | dotemacs-7ad613f96380319c037f367a1b6b1beda03846ca.tar.gz dotemacs-7ad613f96380319c037f367a1b6b1beda03846ca.zip | |
refactor: extract window-geometry helpers shared by F9 and F12
`ai-vterm.el` (F9) and `eshell-vterm-config.el` (F12) both grew the same geometry-preservation pattern: classify a window's position, capture its body size, map cardinal direction to its frame-edge variant. The shared helpers were sitting as near-duplicates in both modules. With two real consumers established, the abstraction has the right shape. I pulled them into `cj-window-geometry.el`.
The new module exposes three pure helpers:
- `cj/window-direction` returns right/below/left/above based on edges relative to `frame-root-window`. Takes an optional DEFAULT for the single-window-frame fallback so each consumer picks its own (ai-vterm wants 'right, vterm-toggle wants 'below).
- `cj/window-body-size` returns body-cols (right/left) or body-lines (below/above). Same body-vs-total reasoning as before: divider-independent, matches what the user sees.
- `cj/cardinal-to-edge-direction` maps right/left/below/above to rightmost/leftmost/bottom/top, used by each consumer's `display-saved` action.
`ai-vterm.el` and `eshell-vterm-config.el` now `(require 'cj-window-geometry)` and call the shared helpers directly. The consumer-specific `capture-state` and `display-saved` bodies stay in each module because they bind to consumer-specific state vars. Extracting those would either need parameter-passing-via-symbol or a macro, both heavier than the duplication they would remove.
Tests: 15 in `test-cj-window-geometry.el` covering all four directions, body-size on both axes, cardinal-to-edge mapping, default-arg fallback, and the unknown-direction nil case. Deleted `test-ai-vterm--window-geometry.el` (now redundant) and trimmed four duplicate window-direction/size tests from `test-vterm-toggle--display.el`. Net LOC: each consumer ~40-50 lines lighter, with the new module + tests paying roughly half that back. Full make test green. make validate-modules green.
Diffstat (limited to 'modules/eshell-vterm-config.el')
| -rw-r--r-- | modules/eshell-vterm-config.el | 50 |
1 files changed, 9 insertions, 41 deletions
diff --git a/modules/eshell-vterm-config.el b/modules/eshell-vterm-config.el index ed257893..34738fa1 100644 --- a/modules/eshell-vterm-config.el +++ b/modules/eshell-vterm-config.el @@ -261,6 +261,7 @@ ai-vterm.el is loaded." (require 'cl-lib) (require 'seq) +(require 'cj-window-geometry) (defcustom cj/vterm-toggle-window-height 0.7 "Default fraction of frame height for the F12 vterm window. @@ -306,43 +307,14 @@ FRAME defaults to the selected frame. Minibuffer is excluded." (cj/--vterm-toggle-buffer-p (window-buffer w))) (window-list (or frame (selected-frame)) 'never))) -(defun cj/--vterm-toggle-window-direction (window) - "Return the side WINDOW occupies in its frame. - -Returns one of right, below, left, above. Falls back to 'below -(F12's traditional bottom split) when WINDOW fills its frame's -root area. Comparison uses `frame-root-window' edges so the -minibuffer doesn't make every full-area window look like it -fails to span the full height." - (let* ((root (frame-root-window (window-frame window))) - (edges (window-edges window)) - (root-edges (window-edges root)) - (left (nth 0 edges)) - (top (nth 1 edges)) - (right (nth 2 edges)) - (bottom (nth 3 edges)) - (root-left (nth 0 root-edges)) - (root-top (nth 1 root-edges)) - (root-right (nth 2 root-edges)) - (root-bottom (nth 3 root-edges)) - (spans-full-width (and (= left root-left) (= right root-right))) - (spans-full-height (and (= top root-top) (= bottom root-bottom)))) - (cond - ((not spans-full-width) (if (= left root-left) 'left 'right)) - ((not spans-full-height) (if (= top root-top) 'above 'below)) - (t 'below)))) - -(defun cj/--vterm-toggle-window-size (window direction) - "Return WINDOW's body size in cols (right/left) or lines (below/above)." - (if (memq direction '(right left)) - (window-body-width window) - (window-body-height window))) - (defun cj/--vterm-toggle-capture-state (window) - "Capture WINDOW's direction + body size into module-level state." + "Capture WINDOW's direction + body size into module-level state. + +Default direction is 'below to match F12's traditional bottom +split when WINDOW fills the frame's root area." (when (window-live-p window) - (let* ((dir (cj/--vterm-toggle-window-direction window)) - (size (cj/--vterm-toggle-window-size window dir))) + (let* ((dir (cj/window-direction window 'below)) + (size (cj/window-body-size window dir))) (setq cj/--vterm-toggle-last-direction dir cj/--vterm-toggle-last-size size)))) @@ -359,12 +331,8 @@ in a `(body-columns . N)' / `(body-lines . N)' cons so the body width or height is set explicitly, divider-independent. A float size passes through as a fraction of the new window's parent." (let* ((direction (or cj/--vterm-toggle-last-direction 'below)) - (edge-direction (pcase direction - ('right 'rightmost) - ('left 'leftmost) - ('below 'bottom) - ('above 'top) - (_ 'bottom))) + (edge-direction (or (cj/cardinal-to-edge-direction direction) + 'bottom)) (size (or cj/--vterm-toggle-last-size cj/vterm-toggle-window-height)) (size-key (if (memq direction '(right left)) 'window-width |
