@@ -88,6 +88,11 @@ If nil do not quit and notify the unregistered key pressed."
88
88
:type 'boolean
89
89
:group 'resize-window )
90
90
91
+ (defcustom resize-window-stack-size 16
92
+ " Size of the stack for holding window configurations."
93
+ :type 'integer
94
+ :group 'resize-window )
95
+
91
96
(defcustom resize-window-swap-capital-and-lowercase-behavior nil
92
97
" Reverse default behavior of lower case and uppercase arguments."
93
98
:type 'boolean
@@ -102,7 +107,10 @@ If nil do not quit and notify the unregistered key pressed."
102
107
" List of background overlays." )
103
108
104
109
(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." )
106
114
107
115
(defface resize-window-background
108
116
'((t (:foreground " gray40" )))
@@ -247,6 +255,9 @@ If SCALED, then call action with the `resize-window-uppercase-argument'."
247
255
Press n to resize down, p to resize up, b to resize left and f
248
256
to resize right."
249
257
(interactive )
258
+ (resize-window--refresh-stack)
259
+ ; ; NOTE: Do not trim the stack here. Let stack requests to handle
260
+ ; ; window configurations in excess.
250
261
(resize-window--add-backgrounds)
251
262
(resize-window--notify " Resize mode: enter character, ? for help" )
252
263
(condition-case nil
@@ -398,13 +409,111 @@ Restore the help menu only if it is currently open."
398
409
(resize-window--display-menu 'open )
399
410
(resize-window--add-backgrounds)))))
400
411
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
+
401
465
(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)))
404
489
405
490
(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)))
408
517
409
518
(defun resize-window--kill-other-windows ()
410
519
" Delete other windows."
0 commit comments