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: Sun, 03 Nov 2024 00:06:15 +1000
User-agent: Gnus/5.13 (Gnus v5.13)

martin rudalics <rudalics@gmx.at> writes:

> I have no idea whether it's related.  For me that backtrace is
> impossible to trace.  Please have a look.  Once it works, I'll try to
> come up with an example why what you do is wrong.

I totally understood it, then I saw it

> Note the following paragraph in the Elisp manual on
> 'window-combination-limit'.
>
>      If, as a consequence of this variable’s setting, ‘split-window’
>      makes a new parent window, it also calls
>      ‘set-window-combination-limit’ (see below) on the newly-created
>      internal window.  This affects how the window tree is rearranged
>      when the child windows are deleted (see below).
>
> So when you bind 'window-combination-limit' globally, deleting windows
> after transposing may behave differently from before transposing them.
>
> The correct approach is to save the value of 'window-combination-limit'
> for a parent window before splitting, split the window, and then restore
> the previous value of the parent.

I get what you meant, I made a new version of the program that fixes
this problem, but it doesn't work for too deep splits yet

> The problem, however, is also with finding the right parent window and
> I'm afraid your algorithm doesn't get that right yet.  IIUC when finding
> a next sibling as the new window in a split and that sibling is an
> internal window, you take that window's first live descendant - let's
> call it FIRST - and pass it to 'split-window' as REFER argument.
> Right?

This is the top-down way, where say you have the tree
(a (b (c d) e))
You go like
(a) -> (a (b)) -> (a (b c)) -> (a (b (c d)))...
the way this one works is bottom up, kind of like:
(a) -> (a (c d)) -> (a (b (c d)))...

But this is not the best representation for windows at all

> But 'split-window' has no idea of FIRST's former parent and, when it now
> needs a parent because of 'window-combination-limit' being non-nil, it
> will not reuse the previous parent of FIRST (some internal window down
> the old window tree) but simply make a new one.
>
> Note that if you had not set 'window-combination-limit', 'split-window'
> would have set the parent to the parent of the window to split, which is
> equally wrong as you probably noticed earlier.  So what you have to do
> here is to pass a cons as REFER to 'split-window' with the car set to
> FIRST and the cdr set to the parent of FIRST it had in the window tree
> _before_ you deleted the other windows.  This will instruct
> 'split-window' to reinstall that old parent in the window tree and
> things should work out as intended.
>
> Note in this context that preserving the identities of live windows
> across transpositions via the REFER argument is important to keep all
> those things like window positions, margins, scroll bars, fringes,
> overlays with a window property, dedicated status and parameters like
> 'no-other-window' or 'quit-restore' in place.  Without the REFER
> argument, you would have to painstakingly restore all these things
> manually for each new live window from the old one it substitutes.

I think I might have sent you code without refer argument, if that was
the case I was just working on code in a non patch applied emacs, so the
refer argument would work if you just ad `win'

The problem with my curent solution is that it does not account for
emacs split's properly, for example if you split the parent of a and b:

|--------|     |---------------|
| A | B  | ->  | A | B  |  C   |
|--------|     |---------------|

this means it squashes the proportions to match C, which eff's up the
inital split of A and B, which was designed to match the transpsoed from
the inital tree, messing up the current model where I don't pass down
the size information directly, rather pass the full width/height of the
current split(kind of like ilen), so it can be converted

If you didn't understand any of that, don't worry, I fully don't
understand also

Also sorry for late replies, I am kind of in weekend warrior mode on
this until wednesday, been focusing on trying to get my rap career
started

------------------------

(defun window--transpose-1 (subtree cwin conf do-not-convert-size fwin root
                                                                        
&optional fflen root-split-type)
  "Subroutine of `window--transpose'.
SUBTREE must be in the format of the result of
`window-tree-pixel-sizes'.  CWIN is the current window through which the
window splits are made.  The CONF and DO-NOT-CONVERT-SIZE arguments are
the same as the ones in `window--transpose'."
  ;; `ilen' is the max size a window could be of given the split type.
  ;; `flen' is max size the window could be converted to the opposite
  ;; of the given split type.
  (pcase-let* ((`(,ilen ,oflen)
                                (funcall (if (car subtree) 'identity 'reverse)
                                                 (mapcar 'float
                                                                 (flatten-list 
(cadr subtree)))))
                           (split-type (if (car subtree)
                                                           (car conf)
                                                         (cdr conf)))
                           (flen (or fflen oflen))
                           (nfsize ;; (and fflen (* oflen (/ ilen fflen)))
                                (if (eq split-type root-split-type)
                                        flen
                                  (* oflen (/ ilen flen)))))
        (cons
         (window-parent
          (cadr
           (seq-reduce
                (pcase-lambda (`(,count ,mwin ,lsize) `(,win . ,size))
                  ;; Better than (/ (* flen size) ilen) as (* flen size) can 
make
                  ;; really big numbers
                  (cons
                   (+ 1 count)
                   (let ((new-size (and size (if do-not-convert-size
                                                                                
 size
                                                                           
(round (* flen (/ size ilen)))))))
                         (if (eq fwin win)
                                 (list mwin (- lsize new-size))
                           (if (listp win)
                                   (let ((win-n-size
                                                  (window--transpose-1
                                                   win
                                                   mwin
                                                   conf
                                                   do-not-convert-size
                                                   fwin
                                                   nil
                                                   ;; nfsize
                                                   (if (eq split-type 
root-split-type)
                                                           oflen
                                                           nfsize)
                                                   (if (= count 0)
                                                           root-split-type
                                                         split-type))))
                                         (list (car win-n-size)
                                                   (- lsize new-size)))
                                 (if (eq count 0)
                                         (list (split-window mwin (- nfsize)
                                                                                
 root-split-type t win)
                                                   (- lsize new-size))
                                   (let ((window-combination-limit
                                                  (and (= count 1) (eq 
split-type root-split-type))))
                                         (list (split-window mwin (- lsize) 
split-type t win)
                                                   (- lsize new-size)))))))))
                (mapcar
                 (lambda (e)
                   (let ((window? (if (windowp (car e)) (car e) e)))
                         (cons window?
                                   ;; The respective size of the window.
                                   (if (car subtree)
                                           (car (cadr e))
                                         (cdr (cadr e))))))
                 (cddr subtree))
                ;; This is the starting point.
                (list 0 cwin ;; (if do-not-convert-size ilen flen)
                          (or flen nfsize)
                          ))))
         nfsize))
  )



reply via email to

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