No more right side window

This commit is contained in:
Joe Frikker
2026-09-04 14:36:52 -04:00
parent 3682c1ad10
commit 9e9d2bbfcc
+71 -58
View File
@@ -1062,30 +1062,58 @@ content to be.
(setq child (window-next-sibling child))) (setq child (window-next-sibling child)))
(reverse result))) (reverse result)))
(defun jf/enforce-right-side-heights (win) (defun jf/window-main-root (&optional frame)
(let ((slot-heights '((-1 . 20))) "Return FRAME's main (non-side) window or window subtree."
(parent (window-parent win))) (let* ((root (frame-root-window (or frame (selected-frame))))
(when parent (children (jf/window-children root)))
(let ((children (jf/window-children parent))) (if (seq-some (lambda (w) (window-parameter w 'window-side)) children)
(when (> (length children) 1) (seq-find (lambda (w) (not (window-parameter w 'window-side))) children)
(cl-loop for child in children root)))
for slot = (window-parameter child 'window-slot)
for height = (alist-get slot slot-heights)
when height do (progn (window-resize child (- height (window-height child)))
(window-preserve-size child nil t))))))))
(defun jf/enforce-right-side-width (win) (defun jf/window-leaves (window)
"Resize side window WIN so its frame keeps 120 columns for the rest of the frame." "Return the live leaf windows in WINDOW's subtree."
(let ((width (max 1 (- (frame-width (window-frame win)) 120)))) (if (window-live-p window)
(window-resize win (- width (window-width win)) t))) (list window)
(mapcan #'jf/window-leaves (jf/window-children window))))
(defun jf/enforce-right-side-widths (frame) (defun jf/topright-window (windows)
"Re-apply `jf/enforce-right-side-width' to all of FRAME's right-side windows." "Return whichever of WINDOWS sits furthest up, then furthest right."
(dolist (win (window-list frame 'nomini)) (car (sort (copy-sequence windows)
(when (eq (window-parameter win 'window-side) 'right) (lambda (a b)
(jf/enforce-right-side-width win)))) (let ((top-a (nth 1 (window-edges a)))
(top-b (nth 1 (window-edges b))))
(if (= top-a top-b)
(> (nth 0 (window-edges a)) (nth 0 (window-edges b)))
(< top-a top-b)))))))
(add-hook 'window-size-change-functions #'jf/enforce-right-side-widths) (defun jf/display-buffer-right (buffer alist)
"Display BUFFER on the right of the main editing area.
Applies three rules, based on the shape of the frame's non-side windows:
1. One window -> split it and show BUFFER in the new right window.
2. Two windows side-by-side -> show BUFFER in the right one. If the
right window is selected, swap the two windows first (keeping
focus on the buffer that was active) so BUFFER doesn't evict it.
3. Any other layout -> show BUFFER in the upper-rightmost window."
(let ((main (jf/window-main-root)))
(cond
((window-live-p main)
(let* ((new (split-window main nil 'right))
(width (max 1 (- (frame-width) 120)))
(delta (window-resizable new (- width (window-width new)) t)))
(window-resize new delta t)
(window--display-buffer buffer new 'window alist)))
((and (window-left-child main)
(= (length (jf/window-children main)) 2)
(seq-every-p #'window-live-p (jf/window-children main)))
(let* ((left (window-left-child main))
(right (window-next-sibling left)))
(when (eq (selected-window) right)
(window-swap-states left right)
(select-window left))
(window--display-buffer buffer right 'reuse alist)))
(t
(window--display-buffer buffer (jf/topright-window (jf/window-leaves main)) 'reuse alist)))))
;; (require 'perspective) ;; (require 'perspective)
;; (setopt persp-mode-prefix-key (kbd "C-x t")) ;; (setopt persp-mode-prefix-key (kbd "C-x t"))
@@ -1142,8 +1170,8 @@ content to be.
(defvar jf/fullscreen-popup--param 'jf/fullscreen-saved-configuration (defvar jf/fullscreen-popup--param 'jf/fullscreen-saved-configuration
"Key used to stash the window configuration a fullscreen popup replaced. "Key used to stash the window configuration a fullscreen popup replaced.
Stored per-tab when `tab-bar-mode' is active, otherwise as a plain frame Stored per-tab when `tab-bar-mode' is active, otherwise as a plain frame
parameter; see `jf/tab-or-frame-parameter'.") parameter; see `jf/tab-or-frame-parameter'.")
(defvar-local jf/fullscreen-popup-p nil (defvar-local jf/fullscreen-popup-p nil
"Non-nil in a buffer currently being displayed as a fullscreen popup.") "Non-nil in a buffer currently being displayed as a fullscreen popup.")
@@ -1156,10 +1184,10 @@ parameter; see `jf/tab-or-frame-parameter'.")
(defun jf/tab-or-frame-parameter (parameter &optional frame) (defun jf/tab-or-frame-parameter (parameter &optional frame)
"Like `frame-parameter', but scoped to FRAME's selected tab when tabs are in use. "Like `frame-parameter', but scoped to FRAME's selected tab when tabs are in use.
A plain frame parameter is shared by every tab on that frame, which is wrong A plain frame parameter is shared by every tab on that frame, which is wrong
for state like `jf/fullscreen-popup--param': switching tabs swaps in an for state like `jf/fullscreen-popup--param': switching tabs swaps in an
entirely different window layout, so \"the layout to restore\" has to travel entirely different window layout, so \"the layout to restore\" has to travel
with the tab, not the frame." with the tab, not the frame."
(if-let ((tab (jf/current-tab-cell frame))) (if-let ((tab (jf/current-tab-cell frame)))
(alist-get parameter tab) (alist-get parameter tab)
(frame-parameter frame parameter))) (frame-parameter frame parameter)))
@@ -1176,12 +1204,12 @@ with the tab, not the frame."
(defun jf/display-buffer-fullscreen (buffer alist) (defun jf/display-buffer-fullscreen (buffer alist)
"Display BUFFER, deleting other windows, saving the prior layout. "Display BUFFER, deleting other windows, saving the prior layout.
Intended for use in `display-buffer-alist' for popups (e.g. Magit Intended for use in `display-buffer-alist' for popups (e.g. Magit
status/log) that should take over the frame while displayed, but status/log) that should take over the frame while displayed, but
restore the previous window configuration once closed via either restore the previous window configuration once closed via either
`q' or `popper-toggle' -- both end up calling `quit-window', which `q' or `popper-toggle' -- both end up calling `quit-window', which
is where the restore actually happens; see is where the restore actually happens; see
`jf/quit-window-restore-fullscreen'." `jf/quit-window-restore-fullscreen'."
(unless (jf/tab-or-frame-parameter jf/fullscreen-popup--param) (unless (jf/tab-or-frame-parameter jf/fullscreen-popup--param)
(jf/set-tab-or-frame-parameter jf/fullscreen-popup--param (jf/set-tab-or-frame-parameter jf/fullscreen-popup--param
(current-window-configuration))) (current-window-configuration)))
@@ -1198,13 +1226,13 @@ is where the restore actually happens; see
(defun jf/quit-window-restore-fullscreen (orig-fn &optional kill window) (defun jf/quit-window-restore-fullscreen (orig-fn &optional kill window)
"Restore the saved window configuration after quitting a fullscreen popup. "Restore the saved window configuration after quitting a fullscreen popup.
Advice around `quit-window' so both `q' (which Magit and other Advice around `quit-window' so both `q' (which Magit and other
special-mode buffers bind to buffer-quitting commands that call special-mode buffers bind to buffer-quitting commands that call
`quit-window') and Popper's close/toggle commands (which also call `quit-window') and Popper's close/toggle commands (which also call
`quit-window' directly) trigger the restore. Only restores once the `quit-window' directly) trigger the restore. Only restores once the
last fullscreen popup on the tab (or frame, without `tab-bar-mode') last fullscreen popup on the tab (or frame, without `tab-bar-mode')
has closed, so opening one fullscreen popup from within another has closed, so opening one fullscreen popup from within another
falls back to the outer one first." falls back to the outer one first."
(let* ((window (or window (selected-window))) (let* ((window (or window (selected-window)))
(was-fullscreen (buffer-local-value 'jf/fullscreen-popup-p (was-fullscreen (buffer-local-value 'jf/fullscreen-popup-p
(window-buffer window))) (window-buffer window)))
@@ -1253,25 +1281,10 @@ falls back to the outer one first."
"new-pullreq" "new-pullreq"
"\\*claude:.*" "\\*claude:.*"
"\\*Man .*" "\\*Man .*"
"\\*List .*") "\\*List .*"
(display-buffer-in-side-window) "\\*Embark Actions\\*"
(side . right)
(slot . 0)
(window-width . jf/enforce-right-side-width)
(window-height . jf/enforce-right-side-heights)
(preserve-size . (nil . nil))
(window-parameters (no-delete-other-windows . t)
(no-other-window . t)))
((or "\\*Embark Actions\\*"
"\\*eldoc\\*") "\\*eldoc\\*")
(display-buffer-in-side-window) (jf/display-buffer-right))))
(side . right)
(slot . -1)
(window-width . jf/enforce-right-side-width)
(window-height . jf/enforce-right-side-heights)
(preserve-size . (nil . t))
(window-parameters (no-delete-other-windows . t)
(no-other-window . t)))))
(setopt window-persistent-parameters (setopt window-persistent-parameters
(cl-list* '(no-delete-other-windows . writable) (cl-list* '(no-delete-other-windows . writable)