emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Add function to rotate/transpose all windows


From: Pranshu Sharma
Subject: Re: Add function to rotate/transpose all windows
Date: Mon, 21 Oct 2024 15:54:19 +1000
User-agent: Gnus/5.13 (Gnus v5.13)

martin rudalics <rudalics@gmx.at> writes:

>> Or do you mean it automaticlly makes the window-parameters the same?, as
>> in I won't have to modify anything?
>
> It should work automatically in the sense that the parent windows get
> reused too.  But it doesn't work reliably for a couple of reasons:

I compiled an it works

> With emacs -Q do
>
> (let ((window (split-window)))
>   (set-window-buffer window (get-buffer-create "*foo*"))
>   (setq window (split-window nil nil t))
>   (set-window-buffer window "*Messages*"))
>
> so you have an arrangement with *scratch* and *Messages* at the top and
> *foo* at the bottom.  Now rotate windows clockwise with the *Messages*
> window selected.  Here this first deletes the remaining windows and
> starts with *scratch* as the root window's buffer.  Now the very first
> you ask is to split the *scratch* window with REFER set to the *foo*
> window.
>
> This is a bad idea because *foo* is _not_ *scratch*'s sibling in the
> initial configuration - *Messages* is.  It can break my approach which
> reuses the old parent of REFER which, however, is _not_ the old parent
> of the *scratch* window.  In the next call to 'split-window' you again
> ask to split the *scratch* window but set REFER to the *Messages* window.
> All goes miraculously well.

Ohh, I finally get what you mean.

I thought that for each layout, there is only one possible window tree
that will match it.

> Repeat the call.  Now *foo* with REFER *scratch* reuses the parent of
> *scratch*.  Next *scratch* with REFER *Messages* reuses the parent of
> *Messages*.  Probably due to the fact in which order you earlier deleted
> windows, this changes the parent windows from (the car of each cons is
> the buffer window the cdr the parent window)
>
> ((#<window 9 on *Messages*> . #<window 8>)
>  (#<window 7 on *foo*> . #<window 6>)
>  (#<window 3 on *scratch*> . #<window 8>))
>
> before the call to
>
> ((#<window 9 on *Messages*> . #<window 6>)
>  (#<window 7 on *foo*> . #<window 8>)
>  (#<window 3 on *scratch*> . #<window 6>))
>
> after the call. So the parent windows were interchanged.  Looks like a
> minor annoyance.  But with a more complex layout things fail.  Try with
>
> (let ((window (split-window)))
>   (set-window-buffer window (get-buffer-create "*foo1*"))
>   (setq window (split-window nil nil t))
>   (set-window-buffer window (get-buffer-create "*foo2*"))
>   (setq window (split-window window))
>   (set-window-buffer window (get-buffer-create "*foo3*")))
>
> and repeat the scenario.  Here, in the second call, when it tries to
> split the window on *foo3* with REFER set to the window of *foo2*,
> 'split-window' finds out that the parent of *foo2* has been already
> reused and allocates a new parent window.
>
> I think you have to change two things:
>
> (1) Instead of
>
>       ;; All child windows need to be recursively deleted.
>       (mapc (lambda (win)
>             (when (and (windowp win)
>                        (not (eq win fwin)))
>               (delete-window win)))
>           ;; We know for sure that first 2 in the list are not
>           ;; windows.
>           (cddr (flatten-list win-tree)))
>
> use
>
>       (delete-other-windows fwin)
>
> Your strategy of deleting windows piecemeal destroys the original window
> structure in a quite chaotic way.

The problem is that it will fail when only acting upon a partial subtree.

> (2) Whenever you split a leaf window (like *scratch* in the first
> scenario), make sure that REFER gets always set to the window's
> 'window-next-sibling' (*Messages* in the first scenario) and never to
> some window further up or down in the hierarchy (like *foo* in the first
> scenario).  Which means that in the first scenario you have two possible
> strategies:
>
> - Split *scratch* first with REFER *Messages* and then its parent with
>   REFER *foo*.
>
> - Split *foo* first with REFER *scratch* and then *scratch* with REFER
>   *Messages*.

I see what you mean here, I knew I should done something like this from
the start when I had to flatten the window subtree.

Seems like this will require a rewrite of the windows--transpose-1
(Yay!), but it should be doable, I have an idea of what I could do.

btw, is there a major perfomance/memory footprint of the patches you are
adding



reply via email to

[Prev in Thread] Current Thread [Next in Thread]