aboutsummaryrefslogtreecommitdiff
path: root/modules/cj-window-toggle.el
blob: 016b19673b9b999cb7d7e69d169fc5bac8cf6513 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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