Subject: Re: bug#20189: 25.0.50; Feature request: Alternative split-window-sensibly functions

From: Tassilo Horn <[email-masked]>
Date: Wed, 25 Mar 2015 08:00:34 +0100

Eli Zaretskii <[email-masked]> writes:

Hi Eli,

>> The problem with `split-window-sensibly' on a wide screen is that it
>> prefers vertical splits.  The current emacs -Q behavior in a
>> maximized frame of size 269x82, the first split will be a vertical
>> one.  That's pretty useless because then you have two windows with
>> nearly 200 columns of free space right of the buffer contents
>> (assuming that usually most buffer contents are at most 80 columns
>> wide).
>
> 'split-window-sensibly' is documented to "split WINDOW in a way
> suitable for 'display-buffer'".  Are you talking about the same use
> case, i.e. are you talking about some command that invoked
> 'display-buffer'?  Or are you talking about some different use case?

Yes, I'm talking about display-buffer.  This is a test case:

--8<---------------cut here---------------start------------->8---
(defun test-display-buffer ()
  (interactive)
  (display-buffer (get-buffer-create "ONE"))
  (display-buffer (get-buffer-create "TWO")))
--8<---------------cut here---------------end--------------->8---

If your screen is as large that your emacs frame/window is taller than
`split-height-threshold' (80 lines), then the first split will be a
vertical one.  E.g., do emacs -Q, eval the above function in *scratch*,
and then M-x it.  You end up with 3 windows: one wide window on top
showing *scratch*, the lower half contains two side-by-side windows.

That's not too sensible when one assumes that most buffers are at most
80 columns wide but have many lines.  If the first split was a
horizontal split, you'd have more buffer contents on your screen.

> This is not clear from your description, since it lacks the context in
> which your needs are different.

The context is having a big enough screen where both a vertical and a
horizontal split would be possible initially.

> IMO, the rest of the discussion depends crucially upon the context,
> and in particular on the command that invoked 'display-buffer' (or
> maybe invoked 'split-window-sensibly' directly?).
>
> My understanding of the current logic is that 'display-buffer' is
> generally used for short-lived windows that are intended to be deleted
> a short time after the split.  Long-lived splits are supposed to be
> caused by "C-x 2" and "C-x 3", where the user determines how to split
> anyway.

I almost never split explicitly.  I just reuse the windows that are
there anyway no matter how they were brought into life.

Are explicitly created windows treated any differently than explicitly
created windows?

> If we are willing to produce long-lived splits automatically, then the
> 2 thresholds are IMO not enough for "sensible" behavior of any kind;
> what is missing is 2 more parameters that provide the desired (as
> opposed to minimal) height and width of a window.  These parameters
> are implicitly present in your description, but you never explicitly
> name them.

Yeah, exactly.  I personally defined them to be

  (/ split-{width,height}-threshold 2)

although I think the preferred height is usually "as high as possible"
or "exactly as high to fit the buffer contents".

>> It's exactly like `split-window-sensibly' except that the
>> horizontal/vertical clauses are reversed, i.e., it tries a horizontal
>> split before trying a vertical split.  That version suits my needs a
>> bit better.
>> 
>> However, it's still not exactly what I really want.  The problem is
>> that after the first horizontal split I end up with 2 side-by-side
>> windows where each one is 132 columns wide.  That's still much wider
>> as needed for most buffer contents but less than
>> `split-width-threshold', so the next splits will all be vertical ones
>> so that I'll eventually end up with four windows arranged in a 2x2
>> grid, each window having the size 132x40.
>
> You never say what are your values of the 2 thresholds, so it is hard
> to reason about your description.

Then assum they are the defaults.  Actually, `split-width-threshold' is
152 because most buffers I use are generally narrower than 80 chars, but
my examples were all run with emacs -Q.

>> (1) That version would prefer horizontal splits as above.
>> 
>> (2) I want either horizontal or vertical splitting but not both, i.e.,
>>     the layout should always be Nx1 or 1xN windows.
>> 
>> (3) A window may get split horizontally not if it's wider/taller than
>>     `split-width-threshold'/`split-height-threshold' but instead when
>>     its width/height *after* the split followed by `balance-windows'
>>     is larger than or equal to (/ split-{width,height}-threshold 2).
>> 
>> (4) The single-window exception of `split-height-threshold' still
>>     holds, so in frames with just one window a vertical split is
>>     performed even though that window is actually too small according
>>     to the rules above.
>
> Maybe I misunderstand, but doesn't (2) contradict (1)?

No.  (1) is meant for the initial split case, i.e., when there's just
one window.  If that's splittable both vertically and horizontally, I
prefer a horizontal split.

Thereafter, i.e., we already have 2 or more either side-by-side or
on-top-of-each-other windows, rule (2) says to stick to that layout.

> And why is (1) a good idea anyway?  Why not have a more optimal split,
> whereby (for example) the larger dimension is preferred?

IMO, a vertial split which produces windows which are much larger than
80 columns is useless to me because usually buffer contents are at most
80 columns wide so you have tons of empty space next to the contents.

Ok, there might be a situation where my single window contains a buffer
with very wide contents.  Let's say in that case, the optimal window
split function would determine that a vertical split is better.  With my
usage habits, I'd still say its wrong because chances are almost certain
that I'll switch buffers sooner or later, and the buffer being switched
to is most probably at most 80 columns wide again.

There might be some "dynamic" window adaption manager which computes an
optimal window configuration after every `set-window-buffer'.  But I'm
not sure if that is feasible and provides a good user experience.

> As for (3), such a criterion is IMO a good idea only if we actually
> balance the windows as part of the split.  Otherwise, you will have
> adverse effects when the window to be split is very narrow, but some
> of its peers are wide.

Yes, in my last mail I've hacked a split function which does exactly
that.

>> When I use a frame of size 80x82 instead, I'd end up with 2 vertical
>> windows
>
> And this is good because?...

Exactly because of the reason you state below.  The frame/window isn't
wide enough to have 2 side-by-side windows with at least 80 columns
each, so that's the case where I favor vertical over horizontal
splitting.

> FWIW, I'd prefer a 80x41 window to a 40x82 window, since 40 columns is
> way too few for editing a typical program or text buffer.  Or do you
> have a lot of buffers with very short lines?

No, exactly.  Do I use the wrong terminology?  When I say I end up with
2 vertical windows, I mean they are on top of each other thus have the
sizes 80x41 (or 80x40 because of the additional mode-line) each.

> It is also possible that in some cases the caller of
> split-window-sensibly could provide the requested dimensions in
> advance.

Possibly, but at least that's not possible with the current API.

Bye,
Tassilo