From: "Nicolas Desprès" <nicolas.despres@gmail.com>
To: emacs-devel@gnu.org
Subject: Prefer to split along the longest edge
Date: Sat, 14 Dec 2024 11:05:30 +0100 [thread overview]
Message-ID: <CAPqtr1KBPhZSLPcJEvx1UW36hLesmzvduvHekNaat=MeVw+h1Q@mail.gmail.com> (raw)
[-- 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
next reply other threads:[~2024-12-14 10:05 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-14 10:05 Nicolas Desprès [this message]
2024-12-14 11:30 ` Prefer to split along the longest edge 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
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='CAPqtr1KBPhZSLPcJEvx1UW36hLesmzvduvHekNaat=MeVw+h1Q@mail.gmail.com' \
--to=nicolas.despres@gmail.com \
--cc=emacs-devel@gnu.org \
/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).