unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: "Nicolas Desprès" <nicolas.despres@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: martin rudalics <rudalics@gmx.at>,
	rpluim@gmail.com, juri@linkov.net, emacs-devel@gnu.org
Subject: Re: Prefer to split along the longest edge
Date: Thu, 19 Dec 2024 17:20:03 +0100	[thread overview]
Message-ID: <CAPqtr1+Z=wm4bL6k7Mq3h2QHjG10bB8T9io4rP-gN7jGWB4=0Q@mail.gmail.com> (raw)
In-Reply-To: <86h670koyu.fsf@gnu.org>


[-- Attachment #1.1: Type: text/plain, Size: 167 bytes --]

Hi,

Thank you all for your feedback.  My first attempt was to try to stick to
the original explanation.

Attached, the new version of the patch.

Best regards,
-Nico

[-- Attachment #1.2: Type: text/html, Size: 676 bytes --]

[-- Attachment #2: 0001-Prioritize-split-along-the-longest-edge-by-default.patch --]
[-- Type: application/octet-stream, Size: 8661 bytes --]

From 23c660e5b05dec7dedcc5d2e1ce9cad8fbc82452 Mon Sep 17 00:00:00 2001
From: Nicolas Despres <nicolas.despres@gmail.com>
Date: Thu, 19 Dec 2024 16:52:37 +0100
Subject: [PATCH] Prioritize split along the longest edge by default.

Currently, `split-window-sensibly' prefer 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 split 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 continue 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.
---
 doc/emacs/windows.texi |  5 ++-
 etc/NEWS               |  8 ++++
 lisp/window.el         | 90 +++++++++++++++++++++++++++++++-----------
 3 files changed, 78 insertions(+), 25 deletions(-)

diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi
index 69f24ec192f..1885e5a7f2e 100644
--- a/doc/emacs/windows.texi
+++ b/doc/emacs/windows.texi
@@ -511,6 +511,7 @@ Window Choice
 
 @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 Choice
 @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 frist 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/etc/NEWS b/etc/NEWS
index c5396b4774c..5d4948fbfe3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -165,6 +165,14 @@ It has been obsolete since Emacs 30.1.  Use '(category . comint)' instead.
 Another user option 'display-tex-shell-buffer-action' has been removed too
 for which you can use '(category . tex-shell)'.
 
++++
+*** New user option 'split-window-preferred-direction'.
+Users can now choose in which direction Emacs tries to split first:
+vertical or horizontal.  With this new setting, when the frame is in
+landscape shape for instance, Emacs could split horizontally before to
+split vertically.  The default setting preserves Emacs historical
+behavior to try to split vertically first.
+
 ** Frames
 
 +++
diff --git a/lisp/window.el b/lisp/window.el
index e9d57652ec6..c7139bee893 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -7347,20 +7347,64 @@ window-splittable-p
 		      (* 2 (max window-min-height
 				(if mode-line-format 2 1))))))))))
 
+(defcustom split-window-preferred-direction 'vertical
+  "The first direction tried when Emacs need to split a window.
+This variable control in which order `split-window-sensibly' will try to
+split the window.  That order specially matters when both dimension 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', it the first direction tried will
+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 on 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 to start 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 to start 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 attempts fail 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
@@ -7380,14 +7424,14 @@ split-window-sensibly
 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
@@ -7405,10 +7449,8 @@ split-window-sensibly
                                 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.
-- 
2.47.1


  reply	other threads:[~2024-12-19 16:20 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-14 10:05 Prefer to split along the longest edge Nicolas Desprès
2024-12-14 11:30 ` Eli Zaretskii
2024-12-14 11:45   ` Nicolas Desprès
2024-12-14 12:34     ` Eli Zaretskii
2024-12-14 14:06       ` Nicolas Desprès
2024-12-14 14:55         ` Eli Zaretskii
2024-12-14 15:41           ` Nicolas Desprès
2024-12-14 17:16   ` martin rudalics
2024-12-14 17:33     ` Eli Zaretskii
2024-12-14 17:36     ` Eli Zaretskii
2024-12-14 18:35 ` Juri Linkov
2024-12-14 20:10   ` Nicolas Desprès
2024-12-15  7:34     ` Juri Linkov
2024-12-15  9:29       ` Nicolas Desprès
2024-12-16  7:55         ` Juri Linkov
2024-12-16 11:56           ` Nicolas Desprès
2024-12-16 17:14             ` Eli Zaretskii
2024-12-16 17:44               ` Juri Linkov
2024-12-16 19:07                 ` Eli Zaretskii
2024-12-16 19:14                   ` Juri Linkov
2024-12-16 19:53                     ` Eli Zaretskii
2024-12-17  6:12                       ` Nicolas Desprès
2024-12-17  7:40                         ` Juri Linkov
2024-12-17  8:35                           ` Nicolas Desprès
2024-12-17  9:02                             ` martin rudalics
2024-12-17  9:09                               ` Nicolas Desprès
2024-12-17 13:34                               ` Eli Zaretskii
2024-12-18 10:05                                 ` martin rudalics
2024-12-18 14:12                                   ` Eli Zaretskii
2024-12-18 16:24                                     ` martin rudalics
2024-12-18 16:55                                       ` Eli Zaretskii
2024-12-18 17:41                                         ` martin rudalics
2024-12-18 18:41                                           ` Eli Zaretskii
2024-12-18 19:13                                             ` martin rudalics
2024-12-19  7:06                                           ` Juri Linkov
2024-12-18 17:25                                       ` Juri Linkov
2024-12-17  6:06               ` Nicolas Desprès
2024-12-17 12:52                 ` Eli Zaretskii
2024-12-17 12:59                 ` Eli Zaretskii
2024-12-17 13:12                   ` Robert Pluim
2024-12-18 21:08                     ` Nicolas Desprès
2024-12-19  6:39                       ` Eli Zaretskii
2024-12-19  8:52                         ` martin rudalics
2024-12-19  9:21                           ` Eli Zaretskii
2024-12-19 16:20                             ` Nicolas Desprès [this message]
2024-12-20  9:03                               ` martin rudalics
2024-12-20 14:43                                 ` Nicolas Desprès
2024-12-20 15:05                                   ` Robert Pluim
2024-12-20 20:25                                     ` Stephen Berman
2024-12-16 17:32             ` Juri Linkov
2024-12-17  9:01               ` martin rudalics
2024-12-17 13:32                 ` Eli Zaretskii
2024-12-17  1:51             ` Liu Hui
2024-12-17  7:43               ` Juri Linkov
2024-12-17  8:27                 ` Nicolas Desprès
2024-12-17  8:26               ` Nicolas Desprès
2024-12-16 17:15           ` [External] : " Drew Adams
2024-12-17  8:39             ` Nicolas Desprès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAPqtr1+Z=wm4bL6k7Mq3h2QHjG10bB8T9io4rP-gN7jGWB4=0Q@mail.gmail.com' \
    --to=nicolas.despres@gmail.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=juri@linkov.net \
    --cc=rpluim@gmail.com \
    --cc=rudalics@gmx.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).