;;; +window.el --- Fixes for Emacs's window.el -*- lexical-binding: t; -*- ;;; Commentary: ;; Do I want to propose this change in the Emacs ML? ;;; Code: (require 'window) ;;; Split windows based on `window-total-width', not `window-width' ;; I have to just redefine these functions because the check is really deep in ;; there. (defun window-splittable-p (window &optional horizontal) "Return non-nil if `split-window-sensibly' may split WINDOW. Optional argument HORIZONTAL nil or omitted means check whether `split-window-sensibly' may split WINDOW vertically. HORIZONTAL non-nil means check whether WINDOW may be split horizontally. WINDOW may be split vertically when the following conditions hold: - `window-size-fixed' is either nil or equals `width' for the buffer of WINDOW. - `split-height-threshold' is an integer and WINDOW is at least as high as `split-height-threshold'. - When WINDOW is split evenly, the emanating windows are at least `window-min-height' lines tall and can accommodate at least one line plus - if WINDOW has one - a mode line. WINDOW may be split horizontally when the following conditions hold: - `window-size-fixed' is either nil or equals `height' for the buffer of WINDOW. - `split-width-threshold' is an integer and WINDOW is at least as wide as `split-width-threshold'. - When WINDOW is split evenly, the emanating windows are at least `window-min-width' or two (whichever is larger) columns wide." (when (and (window-live-p window) (not (window-parameter window 'window-side))) (with-current-buffer (window-buffer window) (if horizontal ;; A window can be split horizontally when its width is not ;; fixed, it is at least `split-width-threshold' columns wide ;; and at least twice as wide as `window-min-width' and 2 (the ;; latter value is hardcoded). (and (memq window-size-fixed '(nil height)) ;; Testing `window-full-width-p' here hardly makes any ;; sense nowadays. This can be done more intuitively by ;; setting up `split-width-threshold' appropriately. (numberp split-width-threshold) (>= (window-total-width window) (max split-width-threshold (* 2 (max window-min-width 2))))) ;; A window can be split vertically when its height is not ;; fixed, it is at least `split-height-threshold' lines high, ;; and it is at least twice as high as `window-min-height' and 2 ;; if it has a mode line or 1. (and (memq window-size-fixed '(nil width)) (numberp split-height-threshold) (>= (window-height window) (max split-height-threshold (* 2 (max window-min-height (if mode-line-format 2 1)))))))))) (defun split-window-sensibly (&optional window) "Split WINDOW in a way suitable for `display-buffer'. WINDOW defaults to the currently selected window. If `split-height-threshold' specifies an integer, WINDOW is at least `split-height-threshold' lines tall and can be split vertically, split WINDOW into two windows one above the other and return the lower window. Otherwise, if `split-width-threshold' specifies an integer, WINDOW is at least `split-width-threshold' columns wide and can be split horizontally, split WINDOW into two windows side by side and return the window on the right. If this can't be done either and WINDOW is the only window on its frame, try to split WINDOW vertically disregarding any value specified by `split-height-threshold'. If that succeeds, return the lower window. Return nil otherwise. By default `display-buffer' routines call this function to split the largest or least recently used window. To change the default customize the option `split-window-preferred-function'. You can enforce this function to not split WINDOW horizontally, by setting (or binding) the variable `split-width-threshold' to nil. If, in addition, you set `split-height-threshold' to zero, chances increase that this function does split WINDOW vertically. In order to not split WINDOW vertically, set (or bind) the variable `split-height-threshold' to nil. Additionally, you can set `split-width-threshold' to zero to make a horizontal split more likely to occur. Have a look at the function `window-splittable-p' if you want to know how `split-window-sensibly' determines whether WINDOW can be split." (let ((window (or window (selected-window)))) (or (and (window-splittable-p window) ;; Split window vertically. (with-selected-window window (split-window-below))) (and (window-splittable-p window t) ;; Split window horizontally. (with-selected-window window (split-window-right))) (and ;; If WINDOW is the only usable window on its frame (it is ;; the only one or, not being the only one, all the other ;; ones are dedicated) and is not the minibuffer window, try ;; to split it vertically disregarding the value of ;; `split-height-threshold'. (let ((frame (window-frame window))) (or (eq window (frame-root-window frame)) (catch 'done (walk-window-tree (lambda (w) (unless (or (eq w window) (window-dedicated-p w)) (throw 'done nil))) frame nil 'nomini) t))) (not (window-minibuffer-p window)) (let ((split-height-threshold 0)) (when (window-splittable-p window) (with-selected-window window (split-window-below)))))))) (provide '+window) ;;; +window.el ends here