(defvar prot-window-window-sizes '( :max-height (lambda () (floor (frame-height) 3)) :min-height 10 :max-width (lambda () (floor (frame-width) 4)) :min-width 20) "Property list of maximum and minimum window sizes. The property keys are `:max-height', `:min-height', `:max-width', and `:min-width'. They all accept a value of either a number (integer or floating point) or a function.") (defun prot-window--get-window-size (key) "Extract the value of KEY from `prot-window-window-sizes'." (when-let ((value (plist-get prot-window-window-sizes key))) (cond ((functionp value) (funcall value)) ((numberp value) value) (t (error "The value of `%s' is neither a number nor a function" key))))) (defun prot-window-select-fit-size (window) "Select WINDOW and resize it. The resize pertains to the maximum and minimum values for height and width, per `prot-window-window-sizes'. Use this as the `body-function' in a `display-buffer-alist' entry." (select-window window) (fit-window-to-buffer window (prot-window--get-window-size :max-height) (prot-window--get-window-size :min-height) (prot-window--get-window-size :max-width) (prot-window--get-window-size :min-width)) ;; If we did not use `display-buffer-below-selected', then we must ;; be in a lateral window, which has more space. Then we do not ;; want to dedicate the window to this buffer, because we will be ;; running out of space. (when (or (window-in-direction 'above) (window-in-direction 'below)) (set-window-dedicated-p window t))) (defun prot-window--get-display-buffer-below-or-pop () "Return list of functions for `prot-window-display-buffer-below-or-pop'." (list #'display-buffer-reuse-mode-window (if (or (prot-common-window-small-p) (prot-common-three-or-more-windows-p)) #'display-buffer-below-selected #'display-buffer-pop-up-window))) (defun prot-window-display-buffer-below-or-pop (&rest args) "Display buffer below current window or pop a new window. The criterion for choosing to display the buffer below the current one is a non-nil return value for `prot-common-window-small-p'. Apply ARGS expected by the underlying `display-buffer' functions. This as the action function in a `display-buffer-alist' entry." (let ((functions (prot-window--get-display-buffer-below-or-pop))) (catch 'success (dolist (fn functions) (when (apply fn args) (throw 'success fn)))))) (provide 'bard-window)