From: Nicolas Despres Date: Sat, 21 Dec 2024 11:45:12 +0000 (+0100) Subject: Prioritize split along the longest edge by default. X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=a409a5316d0b8acc257029fcba08ed4568af14bf;p=emacs.git Prioritize split along the longest edge by default. Currently, `split-window-sensibly' prefers to try to split vertically first, disregarding the actual shape of the frame or the user preferences. This is a good default when Emacs is taller than wider. However, when Emacs is in full-screen (landscape screen layout), trying to split vertically may not be what the user expected, since there is plenty of space available on the right. Typical scenario: Emacs is in landscape layout, one buffer is open in a window covering the entire frame. Another buffer is opened in a second window (C-x 4 f). Both splits are feasible but users may prefer the horizontal one. This patch preserves the behavior of the `split-height-threshold' and `split-width-threshold' variables. Splitting continues not to be permitted if the edge length is below the threshold. * lisp/window.el (split-window-sensibly): First tried split direction follows user preferences. * etc/NEWS: Add an entry for new variable `split-window-preferred-direction'. * doc/emacs/windows.texi: Document new variable. (cherry picked from commit 77ff0df588b6691db38be810210225e84d15eca3) --- diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi index 0abb3fbdc75..94296a9ae7d 100644 --- a/doc/emacs/windows.texi +++ b/doc/emacs/windows.texi @@ -511,6 +511,7 @@ selected frame, and display the buffer in that new window. @vindex split-height-threshold @vindex split-width-threshold +@vindex split-window-preferred-direction The split can be either vertical or horizontal, depending on the variables @code{split-height-threshold} and @code{split-width-threshold}. These variables should have integer @@ -519,7 +520,9 @@ window's height, the split puts the new window below. Otherwise, if @code{split-width-threshold} is smaller than the window's width, the split puts the new window on the right. If neither condition holds, Emacs tries to split so that the new window is below---but only if the -window was not split before (to avoid excessive splitting). +window was not split before (to avoid excessive splitting). Whether +Emacs tries first to split vertically or horizontally, is +determined by the value of @code{split-window-preferred-direction}. @item Otherwise, display the buffer in a window previously showing it. diff --git a/lisp/window.el b/lisp/window.el index 53e0ddf5e84..b3081b0aec5 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -7342,20 +7342,64 @@ hold: (* 2 (max window-min-height (if mode-line-format 2 1)))))))))) +(defcustom split-window-preferred-direction 'vertical + "The first direction tried when Emacs needs to split a window. +This variable controls in which order `split-window-sensibly' will try to +split the window. That order specially matters when both dimensions of +the frame are long enough to be split according to +`split-width-threshold' and `split-height-threshold'. If this is set to +`vertical' (the default), `split-window-sensibly' tries to split +vertically first and then horizontally. If set to `horizontal' it does +the opposite. If set to `longest', the first direction tried +depends on the frame shape: in landscape orientation it will be like +`horizontal', but in portrait it will be like `vertical'. Basically, +the longest of the two dimension is split first. + +If both `split-width-threshold' and `split-height-threshold' cannot be +satisfied, it will fallback to split vertically. + +See `split-window-preferred-function' for more control of the splitting +strategy." + :type '(radio + (const :tag "Try to split vertically first" + vertical) + (const :tag "Try to split horizontally first" + horizontal) + (const :tag "Try to split along the longest edge first" + longest)) + :version "31.1" + :group 'windows) + +(defun window--try-vertical-split (window) + "Helper function for `split-window-sensibly'" + (when (window-splittable-p window) + (with-selected-window window + (split-window-below)))) + +(defun window--try-horizontal-split (window) + "Helper function for `split-window-sensibly'" + (when (window-splittable-p window t) + (with-selected-window window + (split-window-right)))) + (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. +The variable `split-window-preferred-direction' prescribes an order of +directions in which Emacs should try to split WINDOW. If that order +mandates starting with a vertical split, and `split-height-threshold' +specifies an integer that is at least as large a WINDOW's height, split +WINDOW into two windows one below the other and return the lower one. +If that order mandates starting with a horizontal split, and +`split-width-threshold' specifies an integer that is at least as large +as WINDOW's width, split WINDOW into two windows side by side and return +the one on the right. + +In either case, if the first attempt to split WINDOW fails, try to split +the window in the other direction in the same manner as described above. +If that attempt fails too, and WINDOW is the only window on its frame, +try splitting WINDOW into two windows, one below the other, disregarding +the value of `split-height-threshold' and return the window on the +bottom. By default `display-buffer' routines call this function to split the largest or least recently used window. To change the default @@ -7375,14 +7419,14 @@ 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))) + (or (if (or + (eql split-window-preferred-direction 'horizontal) + (and (eql split-window-preferred-direction 'longest) + (> (frame-width) (frame-height)))) + (or (window--try-horizontal-split window) + (window--try-vertical-split window)) + (or (window--try-vertical-split window) + (window--try-horizontal-split window))) (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 @@ -7400,10 +7444,8 @@ split." 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)))))))) + (let ((split-height-threshold 0)) + (window--try-vertical-split window)))))) (defun window--try-to-split-window (window &optional alist) "Try to split WINDOW.