all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Tassilo Horn <tsdh@gnu.org>
To: martin rudalics <rudalics@gmx.at>
Cc: 20189@debbugs.gnu.org
Subject: bug#20189: 25.0.50; Feature request: Alternative split-window-sensibly functions
Date: Tue, 24 Mar 2015 15:59:08 +0100	[thread overview]
Message-ID: <87384ubfwj.fsf@gnu.org> (raw)
In-Reply-To: <551166DE.9070007@gmx.at> (martin rudalics's message of "Tue, 24 Mar 2015 14:30:06 +0100")

martin rudalics <rudalics@gmx.at> writes:

>>>> With that and a maximized frame of size 269x82, I'd eventually end
>>>> up with three side-by-side windows each of size 86x82.
>>>
>>> Interesting.  What is your value of `window-combination-resize'?
>>
>> I didn't know that, so it has the default value nil.
>
> Then how comes you "eventually end up with three side-by-side windows
> each of size 86x82"?

No, I don't end up with that.  If I had the split function I imagined,
then I would end up with that configuration.  So that's the goal I want
to achieve but for which I have no solution.

> By default you should get one window with 135 columns and two windows
> with 67 columns, approximately.

Indeed, that's what I get with C-x 3 C-x 3 starting from a single window
of size 269x82 and the default value of `window-combination-resize' and
`window-combination-limit'.

With

  (setq window-combination-resize t
        window-combination-limit nil)

two consecutive C-x 3 starting from the big single window results in
three side-by-side *balanced* windows, each being 86x82 large.  That's
actually what I wanted.  However, I'd like that this splitting behavior
was the default for `display-buffer'.  But that fails because after the
first horizontal split, `window-splittable-p' says that both horizontal
windows aren't horizontally splittable anymore because they are narrower
than `split-width-threshold'.

>> Reading its docs I get the impression that I want that to be t
>> instead, and to have it effective, I'd also need to set
>> `window-combination-limit' to nil.
>>
>> But with
>>
>>    (setq window-combination-resize t
>>          window-combination-limit nil) ;; was window-size before
>>
>> and a single 269x82 window, I still get a horizontal split first
>> (forming a horizontal combination IIUC) and then a vertical split.
>
> Yes - these are unrelated.  `split-window-sensibly' controls the
> "split-direction".
>
> I share most of your concerns.  But I'm not sure though where to put
> a/the solution.

I've come up with a solution which seems to fit my preferences quite
nicely although it's probably quite hackish and ignores possible
contracts that might exist for dedicated windows, fixed-size windows,
side windows and what else there might be.

--8<---------------cut here---------------start------------->8---
(defun th/split-window-sensibly-prefer-horizontal-split (&optional window)
  "Like `split-window-sensibly' but prefer horizontal splits."
  (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 (eq window (frame-root-window (window-frame window)))
             (not (window-minibuffer-p window))
             ;; If WINDOW is the only window on its frame and is not the
             ;; minibuffer window, try to split it vertically disregarding
             ;; the value of `split-height-threshold'.
             (let ((split-height-threshold 0))
               (when (window-splittable-p window)
                 (with-selected-window window
                   (split-window-below))))))))

(defun th/split-window-sensibly (&optional window)
  (interactive)
  (let* ((root-tree (car (window-tree)))
         (new-window (when (listp root-tree)
                       (let ((dir (car root-tree))
                             (windows (cddr root-tree)))
                         (cond
                          ;; Split horizontally if we're horizontally split
                          ;; already and have enough space for another
                          ;; horizontal window after balancing.
                          ((and (null dir)
                                (cl-every #'windowp windows)
                                (> (apply #'+ (mapcar (lambda (w)
                                                        (- (window-width w)
                                                           (/ split-width-threshold 2)))
                                                      windows))
                                   (/ split-width-threshold 2)))
                           (split-window-right))
                          ;; Split vertically if we're vertically split already
                          ;; and have enough space for another vertical window.
                          ((and dir
                                (cl-every #'windowp windows)
                                (> (apply #'+ (mapcar (lambda (w)
                                                        (- (window-height w)
                                                           (/ split-height-threshold 2)))
                                                      windows))
                                   (/ split-height-threshold 2)))
                           (split-window-below))
                          ;; If we're already split either only horizontally or
                          ;; vertically, reuse the right-most/bottom window
                          ;; unless that's the one which should be split (which
                          ;; is usually the selected one).  In that case, reuse
                          ;; the LRU window.
                          ((cl-every #'windowp windows)
                           (if (eq window (car (last windows)))
                               (get-lru-window)
                             (car (last windows)))))))))
    (unless new-window
      ;; Ok, if we arrive here this means we've already destroyed our preferred
      ;; either-only-horizontal-or-only-vertical splits layout, so just let my
      ;; horizontal splitting favoring sensible split function do its job.  We
      ;; have to arrange windows manually anyhow to come back to
      (setq new-window (th/split-window-sensibly-prefer-horizontal-split window)))
    (balance-windows (window-parent new-window))
    new-window))

(setq split-window-preferred-function #'th/split-window-sensibly)
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo





  reply	other threads:[~2015-03-24 14:59 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-24  9:18 bug#20189: 25.0.50; Feature request: Alternative split-window-sensibly functions Tassilo Horn
2015-03-24 10:51 ` martin rudalics
2015-03-24 11:39   ` Tassilo Horn
2015-03-24 13:30     ` martin rudalics
2015-03-24 14:59       ` Tassilo Horn [this message]
2015-03-25  8:23         ` martin rudalics
2015-03-25  9:41           ` Tassilo Horn
2015-03-26 10:58             ` martin rudalics
2015-03-26 11:01             ` Tassilo Horn
2015-03-26 13:47               ` martin rudalics
2015-03-26 14:18                 ` Stefan Monnier
2015-03-26 14:31                   ` martin rudalics
2015-03-27 18:26                     ` Stefan Monnier
2015-03-26 15:15                 ` Tassilo Horn
2015-03-26 16:04                   ` martin rudalics
2015-03-24 17:05 ` Eli Zaretskii
2015-03-25  7:00   ` Tassilo Horn
2015-03-25  8:24     ` martin rudalics
2015-03-25 17:25     ` Eli Zaretskii
2015-03-25 19:33       ` Tassilo Horn
2015-03-25 19:38         ` Eli Zaretskii
2015-03-26  4:27           ` Tassilo Horn
2015-03-26 10:58             ` martin rudalics
2015-03-26 16:29             ` Eli Zaretskii
2015-03-25  8:23   ` martin rudalics

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

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

  git send-email \
    --in-reply-to=87384ubfwj.fsf@gnu.org \
    --to=tsdh@gnu.org \
    --cc=20189@debbugs.gnu.org \
    --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 external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.