[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Add function to rotate/transpose all windows
From: |
martin rudalics |
Subject: |
Re: Add function to rotate/transpose all windows |
Date: |
Sun, 27 Oct 2024 09:23:27 +0100 |
User-agent: |
Mozilla Thunderbird |
> Look in window--transpose
I see it now. You should not bind 'window-combination-limit' there.
Always bind it around a single 'split-window' call only. If you bind it
for all 'split-window' operations run by transposing, you get a binary
window tree which is certainly not what a user wants.
When with emacs -Q I set 'debug-on-error' t, do C-x 2 C-x 2 and then
call 'rotate-windows-clockwise' twice I get
Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
-(916.0 nil)
(if (eq o-split split-type) (- fflen o-size) fflen)
(let* ((split-type (funcall (if (car subtree) 'car 'cdr) conf)) (flen (if (eq
o-split split-type) (- fflen o-size) fflen)) (deepest-window (seq-reduce #'(lambda
(parent-win arg0) (progn (ignore ...) (let* ... ...))) (let ((ls (mapcar ...
...))) (seq-mapn 'cons (mapcar 'car ls) (cons nil (mapcar ... ls)))) cwin)))
(progn (let ((upper-bound (- (length subtree) 3)) (counter 0)) (while (<
counter upper-bound) (let ((_ counter)) (setq deepest-window (window-parent
deepest-window))) (setq counter (1+ counter)))) deepest-window))
(let ((ilen x0) (fflen x1)) (let* ((split-type (funcall (if (car subtree) 'car
'cdr) conf)) (flen (if (eq o-split split-type) (- fflen o-size) fflen))
(deepest-window (seq-reduce #'(lambda (parent-win arg0) (progn ... ...)) (let ((ls
...)) (seq-mapn 'cons (mapcar ... ls) (cons nil ...))) cwin))) (progn (let
((upper-bound (- (length subtree) 3)) (counter 0)) (while (< counter
upper-bound) (let ((_ counter)) (setq deepest-window (window-parent
deepest-window))) (setq counter (1+ counter)))) deepest-window)))
(let* ((x0 (car-safe val)) (x1 (cdr-safe val))) (let ((ilen x0) (fflen x1))
(let* ((split-type (funcall (if (car subtree) 'car 'cdr) conf)) (flen (if (eq
o-split split-type) (- fflen o-size) fflen)) (deepest-window (seq-reduce #'(lambda
... ...) (let (...) (seq-mapn ... ... ...)) cwin))) (progn (let ((upper-bound (-
... 3)) (counter 0)) (while (< counter upper-bound) (let (...) (setq
deepest-window ...)) (setq counter (1+ counter)))) deepest-window))))
(progn (ignore (consp val)) (let* ((x0 (car-safe val)) (x1 (cdr-safe val))) (let
((ilen x0) (fflen x1)) (let* ((split-type (funcall (if ... ... ...) conf)) (flen
(if (eq o-split split-type) (- fflen o-size) fflen)) (deepest-window (seq-reduce
#'... (let ... ...) cwin))) (progn (let ((upper-bound ...) (counter 0)) (while
(< counter upper-bound) (let ... ...) (setq counter ...))) deepest-window)))))
(let* ((val (if (car subtree) (cons (float (car (car ...))) (float
(window-pixel-width cwin))) (cons (float (cdr (car ...))) (float
(window-pixel-height cwin)))))) (progn (ignore (consp val)) (let* ((x0
(car-safe val)) (x1 (cdr-safe val))) (let ((ilen x0) (fflen x1)) (let*
((split-type (funcall ... conf)) (flen (if ... ... fflen)) (deepest-window
(seq-reduce ... ... cwin))) (progn (let (... ...) (while ... ... ...))
deepest-window))))))
window--transpose-1((nil (916 . 1248) (#<window 7 on *scratch*> (916 . 843)) (#<window 8>
(916 . 405))) #<window 7 on *scratch*> (left . below) nil #<window 7 on *scratch*> nil
below)
(if (and (not size) o-size) (window--transpose-1 win parent-win conf
do-not-convert-size fwin o-size o-split) (window--transpose-1 win parent-win
conf do-not-convert-size fwin split-size split-type))
(if (listp win) (if (and (not size) o-size) (window--transpose-1 win
parent-win conf do-not-convert-size fwin o-size o-split) (window--transpose-1
win parent-win conf do-not-convert-size fwin split-size split-type)) (if (and
(not size) o-size) (split-window parent-win o-size o-split t win) (split-window
parent-win split-size split-type t win)))
(let ((split-size (and size (if do-not-convert-size size (round (* flen (/
size ilen))))))) (if (listp win) (if (and (not size) o-size)
(window--transpose-1 win parent-win conf do-not-convert-size fwin o-size
o-split) (window--transpose-1 win parent-win conf do-not-convert-size fwin
split-size split-type)) (if (and (not size) o-size) (split-window parent-win
o-size o-split t win) (split-window parent-win split-size split-type t win))))
(if (eq fwin win) parent-win (let ((split-size (and size (if
do-not-convert-size size (round (* flen ...)))))) (if (listp win) (if (and (not
size) o-size) (window--transpose-1 win parent-win conf do-not-convert-size fwin
o-size o-split) (window--transpose-1 win parent-win conf do-not-convert-size
fwin split-size split-type)) (if (and (not size) o-size) (split-window
parent-win o-size o-split t win) (split-window parent-win split-size split-type
t win)))))
(let ((win x2) (size x3)) (if (eq fwin win) parent-win (let ((split-size (and
size (if do-not-convert-size size (round ...))))) (if (listp win) (if (and (not
size) o-size) (window--transpose-1 win parent-win conf do-not-convert-size fwin
o-size o-split) (window--transpose-1 win parent-win conf do-not-convert-size
fwin split-size split-type)) (if (and (not size) o-size) (split-window
parent-win o-size o-split t win) (split-window parent-win split-size split-type
t win))))))
(let* ((x2 (car-safe arg0)) (x3 (cdr-safe arg0))) (let ((win x2) (size x3))
(if (eq fwin win) parent-win (let ((split-size (and size (if
do-not-convert-size size ...)))) (if (listp win) (if (and (not size) o-size)
(window--transpose-1 win parent-win conf do-not-convert-size fwin o-size
o-split) (window--transpose-1 win parent-win conf do-not-convert-size fwin
split-size split-type)) (if (and (not size) o-size) (split-window parent-win
o-size o-split t win) (split-window parent-win split-size split-type t
win)))))))
(progn (ignore (consp arg0)) (let* ((x2 (car-safe arg0)) (x3 (cdr-safe
arg0))) (let ((win x2) (size x3)) (if (eq fwin win) parent-win (let
((split-size (and size ...))) (if (listp win) (if (and ... o-size)
(window--transpose-1 win parent-win conf do-not-convert-size fwin o-size
o-split) (window--transpose-1 win parent-win conf do-not-convert-size fwin
split-size split-type)) (if (and ... o-size) (split-window parent-win o-size
o-split t win) (split-window parent-win split-size split-type t win))))))))
#f(lambda (parent-win arg0) [(flen 916.0) (split-type below) (ilen 1680.0) (o-split nil) (o-size nil)
(fwin #<window 7 on *scratch*>) (do-not-convert-size nil) (conf (left . below))] (progn (ignore
(consp arg0)) (let* ((x2 (car-safe arg0)) (x3 (cdr-safe arg0))) (let ((win x2) (size x3)) (if (eq fwin
win) parent-win (let ((split-size (and size (if do-not-convert-size size (round (* flen (/ size
ilen))))))) (if (listp win) (if (and (not size) o-size) (window--transpose-1 win parent-win conf
do-not-convert-size fwin o-size o-split) (window--transpose-1 win parent-win conf do-not-convert-size
fwin split-size split-type)) (if (and (not size) o-size) (split-window parent-win o-size o-split t win)
(split-window parent-win split-size split-type t win)))))))))(#<window 7 on *scratch*> ((nil (916
. 1248) (#<window 7 on *scratch*> (916 . 843)) (#<window 8> (916 . 405)))))
#f(compiled-function (elt) #<bytecode 0x1f3b072de5930c3f>)(((nil (916 . 1248)
(#<window 7 on *scratch*> (916 . 843)) (#<window 8> (916 . 405)))))
mapc(#f(compiled-function (elt) #<bytecode 0x1f3b072de5930c3f>) (((nil (916 . 1248)
(#<window 7 on *scratch*> (916 . 843)) (#<window 8> (916 . 405)))) (#<window 3> .
1248)))
seq-do(#f(compiled-function (elt) #<bytecode 0x1f3b072de5930c3f>) (((nil (916 . 1248)
(#<window 7 on *scratch*> (916 . 843)) (#<window 8> (916 . 405)))) (#<window 3> .
1248)))
seq-reduce(#f(lambda (parent-win arg0) [(flen 916.0) (split-type below) (ilen 1680.0) (o-split nil) (o-size
nil) (fwin #<window 7 on *scratch*>) (do-not-convert-size nil) (conf (left . below))] (progn (ignore
(consp arg0)) (let* ((x2 (car-safe arg0)) (x3 (cdr-safe arg0))) (let ((win x2) (size x3)) (if (eq fwin win)
parent-win (let (...) (if ... ... ...))))))) (((nil (916 . 1248) (#<window 7 on *scratch*> (916 . 843))
(#<window 8> (916 . 405)))) (#<window 3> . 1248)) #<window 7 on *scratch*>)
(let* ((split-type (funcall (if (car subtree) 'car 'cdr) conf)) (flen (if (eq
o-split split-type) (- fflen o-size) fflen)) (deepest-window (seq-reduce #'(lambda
(parent-win arg0) (progn (ignore ...) (let* ... ...))) (let ((ls (mapcar ...
...))) (seq-mapn 'cons (mapcar 'car ls) (cons nil (mapcar ... ls)))) cwin)))
(progn (let ((upper-bound (- (length subtree) 3)) (counter 0)) (while (<
counter upper-bound) (let ((_ counter)) (setq deepest-window (window-parent
deepest-window))) (setq counter (1+ counter)))) deepest-window))
(let ((ilen x0) (fflen x1)) (let* ((split-type (funcall (if (car subtree) 'car
'cdr) conf)) (flen (if (eq o-split split-type) (- fflen o-size) fflen))
(deepest-window (seq-reduce #'(lambda (parent-win arg0) (progn ... ...)) (let ((ls
...)) (seq-mapn 'cons (mapcar ... ls) (cons nil ...))) cwin))) (progn (let
((upper-bound (- (length subtree) 3)) (counter 0)) (while (< counter
upper-bound) (let ((_ counter)) (setq deepest-window (window-parent
deepest-window))) (setq counter (1+ counter)))) deepest-window)))
(let* ((x0 (car-safe val)) (x1 (cdr-safe val))) (let ((ilen x0) (fflen x1))
(let* ((split-type (funcall (if (car subtree) 'car 'cdr) conf)) (flen (if (eq
o-split split-type) (- fflen o-size) fflen)) (deepest-window (seq-reduce #'(lambda
... ...) (let (...) (seq-mapn ... ... ...)) cwin))) (progn (let ((upper-bound (-
... 3)) (counter 0)) (while (< counter upper-bound) (let (...) (setq
deepest-window ...)) (setq counter (1+ counter)))) deepest-window))))
(progn (ignore (consp val)) (let* ((x0 (car-safe val)) (x1 (cdr-safe val))) (let
((ilen x0) (fflen x1)) (let* ((split-type (funcall (if ... ... ...) conf)) (flen
(if (eq o-split split-type) (- fflen o-size) fflen)) (deepest-window (seq-reduce
#'... (let ... ...) cwin))) (progn (let ((upper-bound ...) (counter 0)) (while
(< counter upper-bound) (let ... ...) (setq counter ...))) deepest-window)))))
(let* ((val (if (car subtree) (cons (float (car (car ...))) (float
(window-pixel-width cwin))) (cons (float (cdr (car ...))) (float
(window-pixel-height cwin)))))) (progn (ignore (consp val)) (let* ((x0
(car-safe val)) (x1 (cdr-safe val))) (let ((ilen x0) (fflen x1)) (let*
((split-type (funcall ... conf)) (flen (if ... ... fflen)) (deepest-window
(seq-reduce ... ... cwin))) (progn (let (... ...) (while ... ... ...))
deepest-window))))))
window--transpose-1((nil (916 . 1680) (nil (916 . 1248) (#<window 7 on *scratch*> (916 . 843))
(#<window 8> (916 . 405))) (#<window 3> (916 . 432))) #<window 7 on *scratch*> (left .
below) nil #<window 7 on *scratch*> nil)
(let* ((frame (window-frame window)) (fwin window) (selwin
(frame-selected-window window)) (window-combination-limit t) (win-tree (car
(window-tree-pixel-sizes window)))) (while (not (window-live-p fwin)) (setq
fwin (window-child fwin))) (delete-other-windows-internal fwin)
(window--transpose-1 win-tree fwin conf do-not-convert-size fwin nil)
(set-frame-selected-window frame selwin))
(if (or (not window) (window-live-p window)) (message "No windows to
transpose") (let* ((frame (window-frame window)) (fwin window) (selwin
(frame-selected-window window)) (window-combination-limit t) (win-tree (car
(window-tree-pixel-sizes window)))) (while (not (window-live-p fwin)) (setq fwin
(window-child fwin))) (delete-other-windows-internal fwin) (window--transpose-1 win-tree
fwin conf do-not-convert-size fwin nil) (set-frame-selected-window frame selwin)))
window--transpose(#<window 6> (left . below) nil)
(let ((window (cond (subtree (window-parent)) ((windowp frame-or-window) frame-or-window) (t
(window-main-window frame-or-window))))) (old-window-alist) (window--transpose window '(left .
below) nil) (new-window-alist) (save-current-buffer (set-buffer (get-buffer-create
"*foo*")) (pp old-window-alist (current-buffer)) (insert "\n") (pp
new-window-alist (current-buffer))))
rotate-windows-clockwise(nil)
funcall-interactively(rotate-windows-clockwise nil)
call-interactively(rotate-windows-clockwise nil nil)
command-execute(rotate-windows-clockwise)
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.
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.
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?
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.
Preserving the identity of internal windows on the other hand is
important to keep their combination limits and any parameters stored
for them. Even here, it's much easier to reuse the old parent windows
instead of saving all these properties before deleting windows and
trying to find the identity of the parent windows that substituted the
old ones and store the appropriate properties in the new windows.
martin
- Re: Add function to rotate/transpose all windows, (continued)
- Re: Add function to rotate/transpose all windows, Pranshu Sharma, 2024/10/21
- Re: Add function to rotate/transpose all windows, martin rudalics, 2024/10/22
- Re: Add function to rotate/transpose all windows, Pranshu Sharma, 2024/10/24
- Re: Add function to rotate/transpose all windows, martin rudalics, 2024/10/24
- Re: Add function to rotate/transpose all windows, Pranshu Sharma, 2024/10/25
- Re: Add function to rotate/transpose all windows, martin rudalics, 2024/10/25
- Re: Add function to rotate/transpose all windows, Pranshu Sharma, 2024/10/26
- Re: Add function to rotate/transpose all windows,
martin rudalics <=
- Re: Add function to rotate/transpose all windows, Juri Linkov, 2024/10/14
Re: Add function to rotate/transpose all windows, martin rudalics, 2024/10/07