@@ -82,6 +82,11 @@ This is also valuable to see that you are in resize mode."
82
82
:type 'boolean
83
83
:group 'resize-window )
84
84
85
+ (defcustom resize-window-stack-size 16
86
+ " Size of the stack for holding window configurations."
87
+ :type 'integer
88
+ :group 'resize-window )
89
+
85
90
(defcustom resize-window-swap-capital-and-lowercase-behavior nil
86
91
" Reverse default behavior of lower case and uppercase arguments."
87
92
:type 'boolean
@@ -96,7 +101,10 @@ This is also valuable to see that you are in resize mode."
96
101
" List of background overlays." )
97
102
98
103
(defvar resize-window--window-stack ()
99
- " Stack for holding window configurations." )
104
+ " Stack for holding window configurations.
105
+
106
+ It is an alist of format ((configuration . time)...), where time
107
+ is the time when the configuration was saved/visited." )
100
108
101
109
(defface resize-window-background
102
110
'((t (:foreground " gray40" )))
@@ -241,6 +249,9 @@ If SCALED, then call action with the `resize-window-uppercase-argument'."
241
249
Press n to resize down, p to resize up, b to resize left and f
242
250
to resize right."
243
251
(interactive )
252
+ (resize-window--refresh-stack)
253
+ ; ; NOTE: Do not trim the stack here. Let stack requests to handle
254
+ ; ; window configurations in excess.
244
255
(resize-window--add-backgrounds)
245
256
(resize-window--notify " Resize mode: enter character, ? for help" )
246
257
(condition-case nil
@@ -391,13 +402,111 @@ Restore the help menu only if it is currently open."
391
402
(resize-window--display-menu 'open )
392
403
(resize-window--add-backgrounds)))))
393
404
405
+ (defun resize-window--apply-config (config )
406
+ " Return the window configuration CONFIG after applying it.
407
+ Return nil if CONFIG isn't a proper window configuration.
408
+ Do not change the current window configuration."
409
+ (when (window-configuration-p config)
410
+ (save-excursion
411
+ (save-window-excursion
412
+ (set-window-configuration config)
413
+ (resize-window--window-config)))))
414
+
415
+ (defun resize-window--refresh-stack ()
416
+ " Refresh the stack and remove adjacent duplicates.
417
+ Each window configuration is restored and saved again.
418
+
419
+ The configurations saved time is not changed. Always remove the
420
+ older configuration when a duplicate is found.
421
+
422
+ A refresh reveals duplicate configurations. When a configuration
423
+ is restored that takes account of the current state of the frame.
424
+ Since killed buffers cannot be dug up, applying a state will use
425
+ what it finds, and so two configurations may end up the same."
426
+ (let (stack)
427
+ (dotimes (n (length resize-window--window-stack))
428
+ (let* ((this-member (nth n resize-window--window-stack))
429
+ (this-config (resize-window--apply-config (car this-member)))
430
+ (this-svtime (cdr this-member))
431
+ (prev-config (caar stack))
432
+ (prev-svtime (cdar stack)))
433
+ (if (and this-config prev-config
434
+ (compare-window-configurations this-config prev-config))
435
+ (when (time-less-p prev-svtime this-svtime)
436
+ (setcar stack this-member))
437
+ (when this-config
438
+ (push this-member stack)))))
439
+ (setq resize-window--window-stack (nreverse stack))))
440
+
441
+ (defun resize-window--window-trim ()
442
+ " Trim the oldest window configurations in excess from the stack.
443
+ Return the removed configurations."
444
+ (let* ((size (length resize-window--window-stack))
445
+ (trim (- size resize-window-stack-size)))
446
+ (when (> trim 0 )
447
+ (let ((oldest-members
448
+ (sort (copy-sequence resize-window--window-stack)
449
+ (lambda (a b )
450
+ (time-less-p (cdr a) (cdr b))))))
451
+ (nbutlast oldest-members (- size trim))
452
+ (dotimes (n (length oldest-members))
453
+ (let ((old-member (nth n oldest-members)))
454
+ (setq resize-window--window-stack
455
+ (delq old-member resize-window--window-stack))))
456
+ oldest-members))))
457
+
394
458
(defun resize-window--window-push ()
395
- " Save the current state in the stack."
396
- (push (resize-window--window-config) resize-window--window-stack))
459
+ " Save the current window configuration in the stack.
460
+ Return the configuration if saved.
461
+
462
+ Trim adjacent duplicates and old configurations when necessary.
463
+
464
+ See also `resize-window-stack-size' ."
465
+ (let* ((curr-config (resize-window--window-config))
466
+ (curr-member (cons curr-config (current-time )))
467
+ (prev-config nil ))
468
+ ; ; trim duplicates from the tail
469
+ (while (and (setq prev-config (caar (last resize-window--window-stack)))
470
+ (setq prev-config (resize-window--apply-config prev-config))
471
+ (compare-window-configurations curr-config prev-config)
472
+ (nbutlast resize-window--window-stack)))
473
+ ; ; trim duplicates from the head
474
+ (while (and (setq prev-config (caar resize-window--window-stack))
475
+ (setq prev-config (resize-window--apply-config prev-config))
476
+ (compare-window-configurations curr-config prev-config)
477
+ (pop resize-window--window-stack)))
478
+ (push curr-member resize-window--window-stack)
479
+ (resize-window--window-trim)
480
+ (when resize-window--window-stack
481
+ curr-member)))
397
482
398
483
(defun resize-window--window-pop ()
399
- " Return the first element and remove it from the stack."
400
- (pop resize-window--window-stack))
484
+ " Restore a previous window configuration.
485
+ Return the configuration if restored.
486
+
487
+ Save the current configuration to the tail of the stack.
488
+
489
+ Trim adjacent duplicates and old configurations when necessary.
490
+
491
+ See also `resize-window-stack-size' ."
492
+ (resize-window--window-trim)
493
+ (let* ((curr-config (resize-window--window-config))
494
+ (curr-member (cons curr-config (current-time )))
495
+ (prev-config nil ))
496
+ ; ; trim duplicates from the tail
497
+ (while (and (setq prev-config (caar (last resize-window--window-stack)))
498
+ (setq prev-config (resize-window--apply-config prev-config))
499
+ (compare-window-configurations curr-config prev-config)
500
+ (nbutlast resize-window--window-stack)))
501
+ ; ; trim duplicates from the head
502
+ (while (and (setq prev-config (car (pop resize-window--window-stack)))
503
+ (setq prev-config (resize-window--apply-config prev-config))
504
+ (compare-window-configurations curr-config prev-config)))
505
+ (when prev-config
506
+ (setq resize-window--window-stack
507
+ (append resize-window--window-stack (list curr-member)))
508
+ (resize-window--restore-config prev-config)
509
+ prev-config)))
401
510
402
511
(defun resize-window--kill-other-windows ()
403
512
" Delete other windows."
0 commit comments