Skip to content

Commit 3a6e761

Browse files
committed
Window configurations stack management
The stack size is now customizable. Always remove the oldest window configurations in excess to respect the stack size. Avoid stack duplicates and add the current window configuration to the tail of the stack before reverting to a previous configuration. Update: - readme.md
1 parent 72215eb commit 3a6e761

File tree

2 files changed

+115
-5
lines changed

2 files changed

+115
-5
lines changed

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ There are a few things that you can do. There are customizable variables:
6262
- resize-window-fine-argument (default: 1)
6363
- resize-window-allow-backgrounds (default: t)
6464
- resize-window-unregistered-key-quit (default: nil)
65+
- resize-window-stack-size (default: 16)
6566
- resize-window-swap-capital-and-lowercase-behavior (default: nil)
6667
- resize-window-notify-with-messages (default: t)
6768

resize-window.el

Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ If nil do not quit and notify the unregistered key pressed."
8888
:type 'boolean
8989
:group 'resize-window)
9090

91+
(defcustom resize-window-stack-size 16
92+
"Size of the stack for holding window configurations."
93+
:type 'integer
94+
:group 'resize-window)
95+
9196
(defcustom resize-window-swap-capital-and-lowercase-behavior nil
9297
"Reverse default behavior of lower case and uppercase arguments."
9398
:type 'boolean
@@ -102,7 +107,10 @@ If nil do not quit and notify the unregistered key pressed."
102107
"List of background overlays.")
103108

104109
(defvar resize-window--window-stack ()
105-
"Stack for holding window configurations.")
110+
"Stack for holding window configurations.
111+
112+
It is an alist of format ((configuration . time)...), where time
113+
is the time when the configuration was saved/visited.")
106114

107115
(defface resize-window-background
108116
'((t (:foreground "gray40")))
@@ -247,6 +255,9 @@ If SCALED, then call action with the `resize-window-uppercase-argument'."
247255
Press n to resize down, p to resize up, b to resize left and f
248256
to resize right."
249257
(interactive)
258+
(resize-window--refresh-stack)
259+
;; NOTE: Do not trim the stack here. Let stack requests to handle
260+
;; window configurations in excess.
250261
(resize-window--add-backgrounds)
251262
(resize-window--notify "Resize mode: enter character, ? for help")
252263
(condition-case nil
@@ -398,13 +409,111 @@ Restore the help menu only if it is currently open."
398409
(resize-window--display-menu 'open)
399410
(resize-window--add-backgrounds)))))
400411

412+
(defun resize-window--apply-config (config)
413+
"Return the window configuration CONFIG after applying it.
414+
Return nil if CONFIG isn't a proper window configuration.
415+
Do not change the current window configuration."
416+
(when (window-configuration-p config)
417+
(save-excursion
418+
(save-window-excursion
419+
(set-window-configuration config)
420+
(resize-window--window-config)))))
421+
422+
(defun resize-window--refresh-stack ()
423+
"Refresh the stack and remove adjacent duplicates.
424+
Each window configuration is restored and saved again.
425+
426+
The configurations saved time is not changed. Always remove the
427+
older configuration when a duplicate is found.
428+
429+
A refresh reveals duplicate configurations. When a configuration
430+
is restored that takes account of the current state of the frame.
431+
Since killed buffers cannot be dug up, applying a state will use
432+
what it finds, and so two configurations may end up the same."
433+
(let (stack)
434+
(dotimes (n (length resize-window--window-stack))
435+
(let* ((this-member (nth n resize-window--window-stack))
436+
(this-config (resize-window--apply-config (car this-member)))
437+
(this-svtime (cdr this-member))
438+
(prev-config (caar stack))
439+
(prev-svtime (cdar stack)))
440+
(if (and this-config prev-config
441+
(compare-window-configurations this-config prev-config))
442+
(when (time-less-p prev-svtime this-svtime)
443+
(setcar stack this-member))
444+
(when this-config
445+
(push this-member stack)))))
446+
(setq resize-window--window-stack (nreverse stack))))
447+
448+
(defun resize-window--window-trim ()
449+
"Trim the oldest window configurations in excess from the stack.
450+
Return the removed configurations."
451+
(let* ((size (length resize-window--window-stack))
452+
(trim (- size resize-window-stack-size)))
453+
(when (> trim 0)
454+
(let ((oldest-members
455+
(sort (copy-sequence resize-window--window-stack)
456+
(lambda (a b)
457+
(time-less-p (cdr a) (cdr b))))))
458+
(nbutlast oldest-members (- size trim))
459+
(dotimes (n (length oldest-members))
460+
(let ((old-member (nth n oldest-members)))
461+
(setq resize-window--window-stack
462+
(delq old-member resize-window--window-stack))))
463+
oldest-members))))
464+
401465
(defun resize-window--window-push ()
402-
"Save the current state in the stack."
403-
(push (resize-window--window-config) resize-window--window-stack))
466+
"Save the current window configuration in the stack.
467+
Return the configuration if saved.
468+
469+
Trim adjacent duplicates and old configurations when necessary.
470+
471+
See also `resize-window-stack-size'."
472+
(let* ((curr-config (resize-window--window-config))
473+
(curr-member (cons curr-config (current-time)))
474+
(prev-config nil))
475+
;; trim duplicates from the tail
476+
(while (and (setq prev-config (caar (last resize-window--window-stack)))
477+
(setq prev-config (resize-window--apply-config prev-config))
478+
(compare-window-configurations curr-config prev-config)
479+
(nbutlast resize-window--window-stack)))
480+
;; trim duplicates from the head
481+
(while (and (setq prev-config (caar resize-window--window-stack))
482+
(setq prev-config (resize-window--apply-config prev-config))
483+
(compare-window-configurations curr-config prev-config)
484+
(pop resize-window--window-stack)))
485+
(push curr-member resize-window--window-stack)
486+
(resize-window--window-trim)
487+
(when resize-window--window-stack
488+
curr-member)))
404489

405490
(defun resize-window--window-pop ()
406-
"Return the first element and remove it from the stack."
407-
(pop resize-window--window-stack))
491+
"Restore a previous window configuration.
492+
Return the configuration if restored.
493+
494+
Save the current configuration to the tail of the stack.
495+
496+
Trim adjacent duplicates and old configurations when necessary.
497+
498+
See also `resize-window-stack-size'."
499+
(resize-window--window-trim)
500+
(let* ((curr-config (resize-window--window-config))
501+
(curr-member (cons curr-config (current-time)))
502+
(prev-config nil))
503+
;; trim duplicates from the tail
504+
(while (and (setq prev-config (caar (last resize-window--window-stack)))
505+
(setq prev-config (resize-window--apply-config prev-config))
506+
(compare-window-configurations curr-config prev-config)
507+
(nbutlast resize-window--window-stack)))
508+
;; trim duplicates from the head
509+
(while (and (setq prev-config (car (pop resize-window--window-stack)))
510+
(setq prev-config (resize-window--apply-config prev-config))
511+
(compare-window-configurations curr-config prev-config)))
512+
(when prev-config
513+
(setq resize-window--window-stack
514+
(append resize-window--window-stack (list curr-member)))
515+
(resize-window--restore-config prev-config)
516+
prev-config)))
408517

409518
(defun resize-window--kill-other-windows ()
410519
"Delete other windows."

0 commit comments

Comments
 (0)