unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Prefer to split along the longest edge
@ 2024-12-14 10:05 Nicolas Desprès
  2024-12-14 11:30 ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Desprès @ 2024-12-14 10:05 UTC (permalink / raw)
  To: emacs-devel


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

Hi,

I have been enjoying using Emacs since more than 20 years now.  So,
thank you all guys for this impressive work.

It is the first time I send a patch to this list.  I am not a very
fluent lisp coder so please do apologies if the style is not very
good and feel free to tell me how to improve it.

Currently, `split-window-sensibly' prefers to split vertically,
disregarding the shape of the frame.  This is a good default when
Emacs is taller than wider.  However, when Emacs is in fullscreen
(landscape screen layout), splitting vertically is generally not the
thing to do because there is plenty of space on the right.

Typical scenario: Emacs is in fullscreen; one buffer is open in a window
covering the entire frame.  Another buffer is opened in a second
window (C-x 4 f). In this case, the split should generally be horizontal.
The attached patch changes `split-window-sensibly' to just try
spliting the longest edge first. It works well when implemented in my
init.el
and installed by setting `split-window-preferred-function'.

However, when the same logic is implemented by directly modifying
`split-window-sensibly' in window.el, it does not work for one very specific
case: when the frame is 80x30 and C-x 4 f is pressed, the window is not
split and the buffer is opened in another frame. The problem seems to
come from the last eval expression at the bottom of `split-window-sensibly',
but I failed to find a solution. I though better elisp coder than me will
find a
solution quickly that's why I am posting here.

Apart from that, I have been using this alternate approach for a couple of
weeks now, and it works well, that's why I am submitting it for inclusion
in Emacs.

I have tested on 8d94a9ec613470b7e8e4ee0e86b643f34f8a724c with emacs built
with --with-imagemagick --with-native-compilation=yes
--with-compress-install --with-mailutils --with-gnutls --with-tree-sitter
--with-xwidgets --disable-gc-mark-trace --no-create --no-recursion on macOS
15.2.

Best regards,
Nico

-- 
Nicolas Desprès

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

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

From 8d94a9ec613470b7e8e4ee0e86b643f34f8a724c Mon Sep 17 00:00:00 2001
From: Nicolas Despres <nicolas.despres@gmail.com>
Date: Fri, 13 Dec 2024 19:58:13 +0100
Subject: [PATCH] Split along the longest edge by default.

Currently, `split-window-sensibly' prefer to split vertically
disregarding the actual shape of the frame.  This is a good default when
Emacs is taller than wider.  However, when Emacs is in fullscreen
(landscape screen layout) splitting vertically is generally not the
things to do because there is plenty more space on the right.

Typical scenario: Emacs is in fullscreen, one buffer is open in window
covering the entire frame.  Another buffer is opened in a second
window (C-x 4 f). In this case, the split should happen horizontally.

I have tested this approach since a couple of weeks now and it works well
if `split-height-threshold' and `split-width-threshold' are set
properly.

* lisp/window.el (split-window-sensibly): Always prefer the longest edge
instead of blindly splitting vertically, unless width is less than 80 columns.

A part from that, the patch carefully preserves the current split logic.
---
 lisp/window.el | 68 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/lisp/window.el b/lisp/window.el
index e9d57652ec6..58ca6c8679d 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -7347,20 +7347,30 @@ window-splittable-p
 		      (* 2 (max window-min-height
 				(if mode-line-format 2 1))))))))))
 
+(defun window--try-split-window-vertically (window)
+  "Helper function for `split-window-sensibly'"
+  (when (window-splittable-p window)
+    (with-selected-window window
+      (split-window-below))))
+
+(defun window--try-split-window-horizontally (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.
+WINDOW defaults to the currently selected window.  First, try to split
+along the longest edge of the window.  If the threshold
+(`split-height-threshold' respectively `split-width-threshold')
+specifies an integer, WINDOW is at least that threshold lines tall
+(resp. wide) and can be split (vertically respectively horizontally).
+If that fails, try to split along the shortest edge.  If this can't be
+done either and WINDOW is the only window on its frame, try to split
+WINDOW along the longest edge disregarding any value specified by
+`split-height-threshold' respectively `split-width-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
@@ -7379,21 +7389,27 @@ split-window-sensibly
 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)))
+  (let ((window (or window (selected-window)))
+        (first-split nil)
+        (second-split nil)
+        (first-threshold-variable nil))
+    ;; Choose preferred splitting edge.
+    (if (and (> (frame-width) (frame-height)) (> (frame-width) 80))
+        (setq first-split 'window--try-split-window-horizontally
+              second-split 'window--try-split-window-vertically
+              first-threshold-variable 'split-width-threshold)
+      (setq first-split 'window--try-split-window-vertically
+            second-split 'window--try-split-window-horizontally
+            first-threshold-variable 'split-height-threshold))
+    (or (funcall first-split window)
+	(funcall second-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
          ;; ones are dedicated) and is not the minibuffer window, try
-         ;; to split it vertically disregarding the value of
-         ;; `split-height-threshold'.
+         ;; to split it along the longest edge disregarding the value of
+         ;; the matching threshold (`split-height-threshold'
+         ;; or `split-width-threshold').
          (let ((frame (window-frame window)))
            (or
             (eq window (frame-root-window frame))
@@ -7405,10 +7421,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))))))))
+	 (eval `(let ((,first-threshold-variable 0))
+                  (funcall first-split window)))))))
 
 (defun window--try-to-split-window (window &optional alist)
   "Try to split WINDOW.
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2024-12-14 17:36 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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

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).