In my experience this is a harder problem that one might think, because one's intuitive idea of what is sensible is not always easy to put in precise terms. I'll just describe what I've ended up with, but you may have to fiddle around.
First: the existing split-window-sensibly
function always prefers to end up with a horizontal stack of windows (which, rather confusingly, it calls a vertical "split", though the split is horizontal ...) over a side-by-side arrangement. It's easy enough to create a function which has the opposite preference, which is essentially just a copy of split-window-sensibly
with the preferences reversed:
(defun split-window-sensibly-prefer-horizontal (&optional window)
"Based on split-window-sensibly, but designed to prefer a horizontal split,
i.e. windows tiled side-by-side."
(interactive)
(let ((window (or window (selected-window))))
(or (and (window-splittable-p window t)
;; Split window horizontally
(with-selected-window window
(split-window-right)))
(and (window-splittable-p window)
;; Split window vertically
(with-selected-window window
(split-window-below)))
(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 horizontally disregarding the value of
;; `split-height-threshold'.
(let ((frame (window-frame window)))
(or
(eq window (frame-root-window frame))
(catch 'done
(walk-window-tree (lambda (w)
(unless (or (eq w window)
(window-dedicated-p w))
(throw 'done nil)))
frame)
t)))
(not (window-minibuffer-p window))
(let ((split-width-threshold 0))
(when (window-splittable-p window t)
(with-selected-window window
(split-window-right))))))))
So now we have two functions: the original which "prefers" a vertical stack, and the new one which "prefers" a horizontal stack.
Next we need a function which tends to prefer the one we'd rather use.
(defun split-window-really-sensibly (&optional window)
(let ((window (or window (selected-window))))
(if (> (window-total-width window) (* 2 (window-total-height window)))
(with-selected-window window (split-window-sensibly-prefer-horizontal window))
(with-selected-window window (split-window-sensibly window)))))
You need to fiddle around with the values here, but the basic idea is that we prefer a vertical arrangement whenever there is at least twice as much width as height. You might think you wanted it wherever the existing window is wider than it's tall, but in my experience that's not right, and lets you end up with windows which are far too skinny.
Finally, we also need to have some sane minimums. I set a split-height-threshold
of 4 (i.e. I don't want, unless it's unavoidable, to have less than 2 lines in a window) and a split-width-threshold
of 40 (i.e. I don't want, unless it's unavoidable, to have less than 20 characters across in a window) -- at least I think that's what these mean.
Then one just binds split-window-preferred-function
to split-window-really-sensibly
(setq
split-height-threshold 4
split-width-threshold 40
split-window-preferred-function 'split-window-really-sensibly)
Another idea (which you might prefer) would just be to substitute the "preference for side-by-side" arrangement, and set split-width-threshold
to 80: then you would get side-by-side windows whenever there was space for them, I think.
split-window-preferred-function
which can be set to use a custom function. Have a good look at the functionsplit-window-sensibly
and see if it can suit your needs by adjusting certain variables as you mentioned in your question, and also read the doc-string of that function ... if it cannot be made to suit your needs, then you can write another, or obtain help writing another function ...