Created
July 13, 2025 02:37
-
-
Save rickhull/5a7c4c4c508684a4c692cb0c397e89d1 to your computer and use it in GitHub Desktop.
3 columns in emacs, each 80ch wide. except the LRU gets squeezed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; lru-squeeze-mode.el --- A mode for LRU-based window resizing | |
(require 'cl-lib) | |
(defgroup lru-squeeze-mode nil | |
"Customization group for LRU Squeeze Mode." | |
:group 'applications) | |
(defcustom lru-squeeze-column-count 3 | |
"The number of columns to maintain. Only 2 or 3 are supported." | |
:type '(choice (const :tag "2 Columns" 2) | |
(const :tag "3 Columns" 3)) | |
:group 'lru-squeeze-mode) | |
(defcustom lru-squeeze-target-width 80 | |
"The target width in characters for the active window." | |
:type 'integer | |
:group 'lru-squeeze-mode) | |
(defcustom lru-squeeze-mode-enable-logging nil | |
"When non-nil, log detailed state changes to the *lru-squeeze-log* buffer." | |
:type 'boolean | |
:group 'lru-squeeze-mode) | |
(defvar lru-squeeze-mode-active nil | |
"Non-nil if the multi-column layout is currently active.") | |
(defvar lru-squeeze-mode-lru-windows nil | |
"List of windows, ordered from most- to least-recently-used.") | |
(defun lru-squeeze-mode--log (format-string &rest args) | |
"Log a message to the `*lru-squeeze-log*` buffer if logging is enabled." | |
(when lru-squeeze-mode-enable-logging | |
(let ((log-buffer (get-buffer-create "*lru-squeeze-log*"))) | |
(with-current-buffer log-buffer | |
(goto-char (point-max)) | |
(apply 'insert (apply 'format format-string args)) | |
(insert "\n"))))) | |
(defun lru-squeeze-mode-is-valid-layout-p () | |
"Return t if the layout is a valid N-column side-by-side setup." | |
(let ((windows (window-list))) | |
(and (= (length windows) lru-squeeze-column-count) | |
(let* ((first-win-edges (window-edges (car windows))) | |
(top (nth 1 first-win-edges)) | |
(bottom (nth 3 first-win-edges))) | |
(cl-every (lambda (w) | |
(let ((other-edges (window-edges w))) | |
(and (= top (nth 1 other-edges)) | |
(= bottom (nth 3 other-edges))))) | |
windows))))) | |
(defun lru-squeeze-mode-get-ordered-windows () | |
"Get windows in the selected frame, ordered from left to right." | |
(sort (window-list-1 nil 0) | |
#'(lambda (w1 w2) | |
(< (car (window-edges w1)) (car (window-edges w2)))))) | |
(defun lru-squeeze-mode-update-lru-list () | |
"Move the selected window to the front of the LRU list." | |
(let ((selected (selected-window))) | |
(setq lru-squeeze-mode-lru-windows | |
(cons selected (remq selected lru-squeeze-mode-lru-windows))))) | |
(defun lru-squeeze-mode-resize-windows () | |
"Resize windows based on the LRU-squeeze strategy." | |
(let* ((active-win (selected-window)) | |
(lru-win (car (last lru-squeeze-mode-lru-windows))) | |
(delta (- lru-squeeze-target-width (window-width active-win)))) | |
(unless (or (= delta 0) (eq active-win lru-win)) | |
(let ((ordered (lru-squeeze-mode-get-ordered-windows))) | |
(cond | |
;; --- 2-column case --- | |
((= lru-squeeze-column-count 2) | |
(let ((win-a (nth 0 ordered))) | |
(with-selected-window win-a (enlarge-window (if (eq active-win win-a) delta (- delta)) t)))) | |
;; --- 3-column cases --- | |
((= lru-squeeze-column-count 3) | |
(let* ((win-a (nth 0 ordered)) | |
(win-b (nth 1 ordered)) | |
(win-c (nth 2 ordered))) | |
(cond | |
((or (and (eq active-win win-a) (eq lru-win win-b)) | |
(and (eq active-win win-b) (eq lru-win win-a))) | |
(with-selected-window win-a (enlarge-window (if (eq active-win win-a) delta (- delta)) t))) | |
((or (and (eq active-win win-b) (eq lru-win win-c)) | |
(and (eq active-win win-c) (eq lru-win win-b))) | |
(with-selected-window win-b (enlarge-window (if (eq active-win win-b) delta (- delta)) t))) | |
((or (and (eq active-win win-a) (eq lru-win win-c)) | |
(and (eq active-win win-c) (eq lru-win win-a))) | |
(with-selected-window win-b (enlarge-window (if (eq active-win win-a) delta (- delta)) t)) | |
(with-selected-window win-a (enlarge-window (if (eq active-win win-a) delta (- delta)) t))))))))))) | |
(defun lru-squeeze-mode-log-state (&optional clear-log) | |
"Log window state, widths, active status, and LRU status." | |
(when lru-squeeze-mode-enable-logging | |
(when clear-log | |
(let ((log-buffer (get-buffer "*lru-squeeze-log*"))) | |
(when log-buffer | |
(with-current-buffer log-buffer | |
(erase-buffer))))) | |
(let* ((ordered-windows (lru-squeeze-mode-get-ordered-windows)) | |
(selected (selected-window)) | |
(lru-win (car (last lru-squeeze-mode-lru-windows))) | |
(log-parts '()) | |
(char-code-A (string-to-char "A"))) | |
(dotimes (i (length ordered-windows)) | |
(let* ((win (nth i ordered-windows)) | |
(win-char (char-to-string (+ char-code-A i))) | |
(width (window-width win)) | |
(is-active (eq win selected)) | |
(part (format (if is-active "[%s: %d]" "(%s: %d)") win-char width))) | |
(push part log-parts))) | |
(let* ((lru-pos (cl-position lru-win ordered-windows)) | |
(lru-char (char-to-string (+ char-code-A lru-pos))) | |
(log-line (format "%s | LRU: %s" | |
(mapconcat #'identity (nreverse log-parts) " ") | |
lru-char))) | |
(lru-squeeze-mode--log log-line))))) | |
(defun lru-squeeze-mode-after-switch (&rest _) | |
"Called after C-x o. Updates LRU, resizes, and logs the new state." | |
(when (and lru-squeeze-mode (lru-squeeze-mode-is-valid-layout-p)) | |
(lru-squeeze-mode-update-lru-list) | |
(lru-squeeze-mode-resize-windows) | |
(lru-squeeze-mode-log-state))) | |
(defun lru-squeeze-mode-check-windows () | |
"Check window count and create the layout if there's only one window." | |
(if (or (not lru-squeeze-mode) (/= (length (window-list)) 1)) | |
(setq lru-squeeze-mode-active nil) | |
(unless lru-squeeze-mode-active | |
(setq lru-squeeze-mode-active t) | |
(message "lru-squeeze-mode: Layout active.") | |
(let ((w (selected-window))) | |
(dotimes (_ (1- lru-squeeze-column-count)) | |
(select-window w) | |
(split-window-right))) | |
(select-window (car (lru-squeeze-mode-get-ordered-windows))) | |
(setq lru-squeeze-mode-lru-windows (lru-squeeze-mode-get-ordered-windows)) | |
(lru-squeeze-mode-resize-windows) | |
(lru-squeeze-mode-log-state t)))) | |
(define-minor-mode lru-squeeze-mode | |
"A minor mode for LRU-based window resizing.\nWhen enabled, waits for a single window, then creates a 2- or\n3-column layout. It then resizes the active window toward a\ntarget width by shrinking the least-recently-used window." | |
:init-value nil | |
:lighter " LruSqueeze" | |
:group 'lru-squeeze-mode | |
(if lru-squeeze-mode | |
(progn | |
(setq lru-squeeze-mode-active nil) | |
(add-hook 'window-configuration-change-hook #'lru-squeeze-mode-check-windows) | |
(advice-add 'other-window :after #'lru-squeeze-mode-after-switch) | |
(lru-squeeze-mode-check-windows) | |
(message "lru-squeeze-mode enabled.")) | |
(progn | |
(remove-hook 'window-configuration-change-hook #'lru-squeeze-mode-check-windows) | |
(advice-remove 'other-window #'lru-squeeze-mode-after-switch) | |
(message "lru-squeeze-mode disabled.")))) | |
(provide 'lru-squeeze-mode) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment