From: Mark Wooding Date: Wed, 6 Dec 2023 14:25:28 +0000 (+0000) Subject: el/dot-emacs.el: Override the default `display-buffer' logic. X-Git-Url: https://git.distorted.org.uk/~mdw/profile/commitdiff_plain/5ea0bc530190075d6b444e4f2ceadffaa37648c5 el/dot-emacs.el: Override the default `display-buffer' logic. Just use the `next' window in a fairly obvious sort of way. The objective here is to be less surprising and random. --- diff --git a/el/dot-emacs.el b/el/dot-emacs.el index abe67b0..a04ac26 100644 --- a/el/dot-emacs.el +++ b/el/dot-emacs.el @@ -253,6 +253,12 @@ fringes is not taken out of the allowance for WIDTH, unlike (other-window 1)) (select-window win))) +(defun mdw-frame-width-quantized-p (frame-width column-width) + "Return whether the FRAME-WIDTH was chosen specifically for COLUMN-WIDTH." + (let ((sb-width (mdw-horizontal-window-overhead))) + (zerop (mod (+ frame-width sb-width) + (+ column-width sb-width))))) + (defun mdw-frame-width-for-columns (columns width) "Return the preferred width for a frame with so many COLUMNS of WIDTH." (let ((sb-width (mdw-horizontal-window-overhead))) @@ -753,6 +759,68 @@ Pretend they don't exist. They might be on other display devices." (setq display-buffer-reuse-frames nil) +(defun mdw-last-window-in-frame-p (window) + "Return whether WINDOW is the last in its frame." + (catch 'done + (while window + (let ((next (window-next-sibling window))) + (while (and next (window-minibuffer-p next)) + (setq next (window-next-sibling next))) + (if next (throw 'done nil))) + (setq window (window-parent window))) + t)) + +(defun mdw-display-buffer-in-tolerable-window (buffer alist) + "Try finding a tolerable window in which to display BUFFER. +Begone, foul DWIMmerlaik! + +This is all totally subject to arbitrary change in the future, but the +emphasis is on predictability rather than crazy DWIMmery." + (let* ((selected (selected-window)) chosen + (full-height-p (window-full-height-p selected)) + (full-width-p (window-full-width-p selected))) + (cond + + ((and full-height-p full-width-p) + ;; We're basically the only window in the frame. If we want to get + ;; anywhere, we'll have to split the window. + + (let ((width (window-width selected)) + (preferred-width (mdw-preferred-column-width))) + (if (and (>= width (mdw-frame-width-for-columns 2 preferred-width)) + (mdw-frame-width-quantized-p width preferred-width)) + (setq chosen (split-window-right preferred-width)) + (setq chosen (split-window-below))) + (display-buffer-record-window 'window chosen buffer))) + + ((mdw-last-window-in-frame-p selected) + ;; This is the last window in the frame. I don't think I want to + ;; clobber the first window, so rebound and clobber the previous one + ;; instead. (This obviously has the same effect if there are only two + ;; windows, but seems more useful if there are three.) + + (setq chosen (previous-window selected 'never nil)) + (display-buffer-record-window 'reuse chosen buffer)) + + (t + ;; There's another window in front of us. Let's use that one. + (setq chosen (next-window selected 'never nil))) + (display-buffer-record-window 'reuse chosen buffer)) + + (if (eq chosen selected) + (error "Failed to select a different window!")) + + (when chosen + (with-selected-window chosen (switch-to-buffer buffer))) + chosen)) + +;; Hack the display actions so that they do something sensible. +(setq display-buffer-fallback-action + '((display-buffer--maybe-same-window + display-buffer-reuse-window + display-buffer-pop-up-window + mdw-display-buffer-in-tolerable-window))) + ;; Rename buffers along with files. (defvar mdw-inhibit-rename-buffer nil