From: martin rudalics <rudalics@gmx.at>
To: Pranshu Sharma <pranshusharma366@gmail.com>
Cc: Juri Linkov <juri@linkov.net>, Eli Zaretskii <eliz@gnu.org>,
emacs-devel@gnu.org
Subject: Re: Add function to rotate/transpose all windows
Date: Thu, 24 Oct 2024 20:39:17 +0200 [thread overview]
Message-ID: <b4d15a09-76d6-4fc8-abdd-1276386626d4@gmx.at> (raw)
In-Reply-To: <87r085r2gl.fsf@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1905 bytes --]
> However, not on the one achived by:
> C-x 3
> C-x o
> C-x 2
> C-x 3
Yes, this one is a bit nasty.
> I did make some progress on this, but the problem was there was no way I know
> to achive this, which makes it a bit harder:
>
> |-------------| |-------------|
> | A | | A |
> |-------------| |-------------|
> | B | -> | B | |
> |-------------| |------| D |
> | C | | C | |
> |-------------| |-------------|
>
> I'm sure there is way to make it work without this, I'll probably come
> up with way in shower.
Maybe you should have done
|-------------| |-------------|
| A | | A |
|-------------| |-------------|
| | | -> | B | |
| B | D | |------| D |
| | | | C | |
|-------------| |-------------|
since you don't want to split parent windows.
I attach a file called window-rotate.el which handles the above
scenario. In contrast with a window tree it simply operates on the old
window structure of the frame directly which I store as an association
list. Note two aspects:
(1) It always tries to find a leftmost live window to start operating
on. I think you do the same but I've never been able to understand how.
(2) It binds 'window-combination-limit' to make a parent window within
something like the first combination you sketched above so this becomes
|-------------|
| A |
|-------------|
| ----------- |
|| B ||
||-----------||
|| C ||
| ----------- |
|-------------|
Half of the code is debugging code that is not commented. Note that the
code handles rotations only, rotates only the entire frame, does not set
sizes and probably misses other things. But it seems to work so please
test it and maybe try to use as much of it as possible.
martin
[-- Attachment #2: window-rotate.el --]
[-- Type: text/x-emacs-lisp, Size: 8543 bytes --]
;;; -*- lexical-binding:t -*-
;; Debugging code.
(defvar window-number 0)
(defvar old-window-alist nil)
(defvar old-window-list nil)
(defvar new-window-alist nil)
(defun old-window-alist ()
(setq old-window-list (window-list))
(setq old-window-alist nil)
(dolist (window old-window-list)
(setq old-window-alist
(cons
(cons window (window-parent window))
old-window-alist)))
(setq old-window-alist (nreverse old-window-alist)))
(defun new-window-alist ()
(setq new-window-alist nil)
(dolist (window old-window-list)
(setq new-window-alist
(cons
(cons window (window-parent window))
new-window-alist)))
(setq new-window-alist (nreverse new-window-alist)))
;; Two variables the code below binds lexically.
(defvar window-alist nil)
(defvar window-clockwise)
(defun window-first-window (window)
"Return topmost leftmost live descendant of WINDOW."
(let ((child (or (window-top-child window)
(window-left-child window))))
(if child
(window-first-window child)
window)))
(defun window-alist ()
"Return alist of all windows on selected frame."
(let (alist)
(walk-window-tree
(lambda (window)
(setq alist
(cons
(if (window-buffer window)
(list window
(cons 'buffer (window-buffer window))
(cons 'parent (window-parent window))
(cons 'next (window-next-sibling window))
(cons 'prev (window-prev-sibling window))
(cons 'width (window-pixel-width window))
(cons 'height (window-pixel-height window)))
(list window
(cons 'left (window-left-child window))
(cons 'top (window-top-child window))
(cons 'parent (window-parent window))
(cons 'next (window-next-sibling window))
(cons 'prev (window-prev-sibling window))
(cons 'first (window-first-window window))
(cons 'width (window-pixel-width window))
(cons 'height (window-pixel-height window))))
alist)))
nil t)
alist))
;; Accessor functions.
(defun window-alist-parent (window)
(cdr (assq 'parent (cdr (assq window window-alist)))))
(defun window-alist-buffer (window)
(cdr (assq 'buffer (cdr (assq window window-alist)))))
(defun window-alist-next (window)
(cdr (assq 'next (cdr (assq window window-alist)))))
(defun window-alist-prev (window)
(cdr (assq 'prev (cdr (assq window window-alist)))))
(defun window-alist-left (window)
(cdr (assq 'left (cdr (assq window window-alist)))))
(defun window-alist-top (window)
(cdr (assq 'top (cdr (assq window window-alist)))))
(defun window-alist-first (window)
(cdr (assq 'first (cdr (assq window window-alist)))))
(defun window-rotate-clockwise ()
"Rotate root window of selected frame clockwise."
(interactive)
(let ((window-clockwise t)
;; Construct 'window-alist' which also makes sure that no window
;; gets recycled by GC.
(window-alist (window-alist))
(window (frame-first-window)))
(setq window-number 0)
(old-window-alist)
;; Delete all windows but the frame's first window.
(delete-other-windows-internal window)
(with-current-buffer (get-buffer-create "*foo*")
(erase-buffer)
(pp window-alist (current-buffer))
(insert "\n"))
;; Now rotate starting with the frame's first window.
(window-rotate window nil)
(new-window-alist)
(with-current-buffer (get-buffer-create "*foo*")
(pp old-window-alist (current-buffer))
(insert "\n")
(pp new-window-alist (current-buffer)))))
(defun window-rotate-anti-clockwise ()
"Rotate root window of selected frame anti-clockwise."
(interactive)
(let (window-clockwise
;; Construct 'window-alist' which also makes sure that no window
;; gets recycled by GC.
(window-alist (window-alist))
(window (frame-first-window)))
(setq window-number 0)
(old-window-alist)
;; Delete all windows but the frame's first window.
(delete-other-windows-internal window)
(with-current-buffer (get-buffer-create "*foo*")
(erase-buffer)
(pp window-alist (current-buffer))
(insert "\n"))
;; Now rotate starting with the frame's first window.
(window-rotate window nil)
(new-window-alist)
(with-current-buffer (get-buffer-create "*foo*")
(pp old-window-alist (current-buffer))
(insert "\n")
(pp new-window-alist (current-buffer)))))
(defun window-rotate (window root)
"Rotate window subroutine.
WINDOW must be a leftmost bottommost child window such as produced by
`frame-first-window' or `window-first-window'. More precisely, WINDOW
must show a buffer and its previous sibling must be nil.
ROOT is either the root window to rotate or a parent window such that
WINDOW is its `frame-first-window'.
Traverse the window structure saved in `window-alist' starting with
WINDOW, continuing with its next siblings. If a sibling is a parent
window, recurse with WINDOW set to the window returned by
`window-first-window' for that sibling and ROOT set to sibling's parent.
After having traced all siblings continue with WINDOW's parent unless
that parent equals ROOT."
(let ((parent (window-alist-parent window))
next first side)
(when parent
;; Traverse WINDOW (which is always the first sibling) and its
;; next siblings.
(while (setq next (window-alist-next window))
;; Calculate SIDE argument for 'split-window' taking into
;; account 'window-clockwise' and whether WINDOW is in a
;; horizontal of vertical combination.
(setq side (if window-clockwise
(if (window-alist-left parent) 'below 'left)
(if (window-alist-left parent) 'above 'right)))
;; Save current window configuration in case of an error.
(let ((config (current-window-configuration)))
(if (window-alist-buffer next)
;; If the next sibling shows a buffer, split it with
;; WINDOW's old parent as new parent.
(condition-case var
(let* ((prev (window-alist-prev window))
;; Set 'window-combination-limit' to make sure
;; that a new parent is created when WINDOW's
;; previous sibling and WINDOW do not have the
;; same parent.
(window-combination-limit
(or (not prev)
(and (not (eq (window-alist-parent prev)
(window-alist-parent window)))
t))))
(with-current-buffer (get-buffer-create "*foo*")
(insert (format "1 .. w %s .. n %s .. p %s\n" window next parent)))
;; Split WINDOW with REFER set to a cons of WINDOW's
;; saved next sibling and WINDOW's saved parent.
(split-window window nil side nil (cons next parent)))
(error
(with-current-buffer (get-buffer-create "*foo*")
(pp window-alist (current-buffer))
(insert "\n")
(insert (format "1 .. w %s .. s %s .. r %s\n" window side (cons next parent)))
(insert (format "%s\n" var)))
(set-window-configuration config)))
;; If the next sibling is a parent window set FIRST to its
;; topmost leftmost live descendant.
(setq first (window-alist-first next))
(condition-case var
(let* ((prev (window-alist-prev window))
;; Set 'window-combination-limit' to make sure
;; that a new parent is created when WINDOW's
;; previous sibling and WINDOW do not have the
;; same parent.
(window-combination-limit
(or (not prev)
(and (not (eq (window-alist-parent prev)
(window-alist-parent window)))
t))))
(with-current-buffer (get-buffer-create "*foo*")
(insert (format "2 .. w %s .. f %s .. p %s\n" window first parent)))
;; Split WINDOW with REFER set to a cons of WINDOW's
;; first live descendant and WINDOW's saved parent.
(split-window window nil side nil (cons first parent)))
(error
(with-current-buffer (get-buffer-create "*foo*")
(pp window-alist (current-buffer))
(insert "\n")
(insert (format "2 .. w %s .. s %s .. r %s\n" window side (cons next parent)))
(insert (format "%s\n" var)))
(set-window-configuration config)))
;; Recurse starting with WINDOW's first live descendant.
;; The second argument PARENT should terminate the recursion
;; when going up again.
(window-rotate first parent)))
;; Continue with WINDOW's next sibling.
(setq window next))
;; Continue with WINDOW's parent unless we are at the ROOT of the
;; current recursion.
(unless (eq (window-alist-parent window) root)
(window-rotate (window-alist-parent window) root)))))
(global-set-key [(super p)] 'window-rotate-clockwise)
(global-set-key [(super q)] 'window-rotate-anti-clockwise)
next prev parent reply other threads:[~2024-10-24 18:39 UTC|newest]
Thread overview: 144+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-24 13:45 Add function to rotate/transpose all windows pranshu sharma
2024-09-24 13:53 ` Eli Zaretskii
2024-09-25 8:05 ` martin rudalics
2024-09-25 8:34 ` pranshu sharma
2024-09-25 9:31 ` martin rudalics
2024-09-25 10:50 ` pranshu sharma
2024-09-25 13:53 ` martin rudalics
2024-09-25 15:31 ` pranshu sharma
2024-09-26 14:10 ` martin rudalics
2024-09-26 14:22 ` Eli Zaretskii
2024-09-27 17:29 ` martin rudalics
2024-09-28 7:52 ` pranshu sharma
2024-09-28 9:26 ` martin rudalics
2024-09-28 10:53 ` pranshu sharma
2024-09-28 14:48 ` martin rudalics
2024-09-29 7:36 ` pranshu sharma
2024-09-29 8:40 ` martin rudalics
2024-09-29 9:23 ` pranshu sharma
2024-09-29 14:48 ` martin rudalics
2024-09-30 6:29 ` pranshu sharma
2024-09-30 8:57 ` martin rudalics
2024-10-01 9:17 ` pranshu sharma
2024-10-02 9:04 ` martin rudalics
2024-10-03 7:06 ` pranshu sharma
2024-10-03 8:17 ` martin rudalics
2024-10-03 10:09 ` pranshu sharma
2024-10-03 14:18 ` martin rudalics
2024-10-04 5:50 ` pranshu sharma
2024-10-04 8:08 ` martin rudalics
2024-10-04 15:10 ` pranshu sharma
2024-10-05 14:43 ` martin rudalics
2024-10-06 2:54 ` pranshu sharma
2024-10-06 15:02 ` martin rudalics
2024-10-06 15:52 ` pranshu sharma
2024-10-07 8:33 ` martin rudalics
2024-10-07 9:42 ` pranshu sharma
2024-10-03 15:12 ` Eli Zaretskii
2024-10-08 18:35 ` Juri Linkov
2024-10-09 6:59 ` pranshu sharma
2024-10-09 16:21 ` Juri Linkov
2024-10-10 11:49 ` pranshu sharma
2024-10-10 16:57 ` Juri Linkov
2024-10-13 5:43 ` pranshu sharma
2024-10-13 8:17 ` martin rudalics
2024-10-14 17:36 ` Juri Linkov
2024-10-15 8:34 ` pranshu sharma
2024-10-15 16:16 ` Juri Linkov
2024-10-18 14:52 ` pranshu sharma
2024-10-18 17:48 ` martin rudalics
2024-10-18 18:37 ` Eli Zaretskii
2024-10-19 1:45 ` pranshu sharma
2024-10-19 6:45 ` Eli Zaretskii
2024-10-19 18:19 ` Juri Linkov
2024-10-19 8:33 ` martin rudalics
2024-10-20 8:19 ` martin rudalics
2024-10-20 14:11 ` Pranshu Sharma
2024-10-20 17:37 ` martin rudalics
2024-10-21 5:54 ` Pranshu Sharma
2024-10-21 8:14 ` martin rudalics
2024-10-21 9:23 ` martin rudalics
2024-10-21 13:37 ` Pranshu Sharma
2024-10-22 18:12 ` martin rudalics
2024-10-24 14:38 ` Pranshu Sharma
2024-10-24 18:39 ` martin rudalics [this message]
2024-10-25 14:24 ` Pranshu Sharma
2024-10-25 17:09 ` martin rudalics
2024-10-26 9:14 ` Pranshu Sharma
2024-10-27 8:23 ` martin rudalics
2024-11-02 14:06 ` Pranshu Sharma
2024-11-05 18:01 ` martin rudalics
2024-11-08 9:23 ` Pranshu Sharma
2024-11-08 10:06 ` Pranshu Sharma
2024-11-08 15:52 ` martin rudalics
2024-11-09 2:14 ` Pranshu Sharma
2024-11-09 8:48 ` martin rudalics
2024-11-08 15:52 ` martin rudalics
2024-11-09 2:09 ` Pranshu Sharma
2024-11-09 8:48 ` martin rudalics
2024-11-09 10:55 ` Pranshu Sharma
2024-11-09 18:06 ` martin rudalics
2024-11-10 10:09 ` Pranshu Sharma
2024-11-10 16:36 ` martin rudalics
2024-11-11 14:47 ` Pranshu Sharma
2024-11-11 16:55 ` martin rudalics
2024-11-12 13:50 ` Pranshu Sharma
2024-11-12 17:46 ` martin rudalics
2024-11-16 13:36 ` Pranshu Sharma
2024-11-16 16:54 ` martin rudalics
2024-11-17 2:45 ` Pranshu Sharma
2024-11-17 10:22 ` martin rudalics
2024-11-17 15:03 ` Pranshu Sharma
2024-11-17 16:38 ` martin rudalics
2024-11-18 0:37 ` Pranshu Sharma
2024-11-18 8:55 ` martin rudalics
2024-11-19 9:34 ` Pranshu Sharma
2024-11-19 17:48 ` martin rudalics
2024-11-21 14:04 ` Pranshu Sharma
2024-11-21 17:54 ` martin rudalics
2024-11-24 13:53 ` Pranshu Sharma
2024-11-26 9:49 ` martin rudalics
2024-11-26 14:14 ` Pranshu Sharma
2024-11-27 8:29 ` Pranshu Sharma
2024-11-27 9:18 ` martin rudalics
2024-11-27 14:37 ` Pranshu Sharma
2024-11-27 17:42 ` martin rudalics
2024-11-28 2:43 ` Pranshu Sharma
2024-11-28 9:28 ` martin rudalics
2024-11-28 15:18 ` Pranshu Sharma
2024-11-30 10:07 ` martin rudalics
2024-11-30 17:41 ` Juri Linkov
2024-11-30 19:01 ` martin rudalics
2024-12-01 4:13 ` Pranshu Sharma
2024-12-03 7:30 ` Juri Linkov
2024-12-03 8:25 ` martin rudalics
2024-12-01 6:41 ` Pranshu Sharma
2024-12-01 17:20 ` martin rudalics
2024-12-02 8:06 ` Pranshu Sharma
2024-12-03 8:23 ` martin rudalics
2024-12-04 15:20 ` Pranshu Sharma
2024-12-04 17:56 ` martin rudalics
2024-12-04 19:12 ` Juri Linkov
2024-12-05 14:16 ` Pranshu Sharma
2024-12-05 17:48 ` Juri Linkov
2024-12-06 4:51 ` Pranshu Sharma
2024-12-06 7:29 ` Juri Linkov
2024-12-05 14:23 ` Pranshu Sharma
2024-12-05 15:17 ` Pranshu Sharma
2024-10-14 17:32 ` Juri Linkov
2024-09-28 7:58 ` pranshu sharma
2024-09-28 8:18 ` Eli Zaretskii
2024-09-28 9:40 ` martin rudalics
2024-09-28 11:35 ` Eli Zaretskii
2024-09-28 14:58 ` martin rudalics
2024-09-28 15:28 ` Eli Zaretskii
2024-10-07 8:33 ` martin rudalics
2024-09-28 13:22 ` pranshu sharma
2024-09-28 14:21 ` Eli Zaretskii
2024-09-28 14:49 ` martin rudalics
2024-09-27 10:06 ` pranshu sharma
2024-09-27 17:29 ` martin rudalics
2024-09-24 17:40 ` Petteri Hintsanen
2024-09-24 19:34 ` Charles Choi
2024-09-25 2:00 ` Emanuel Berg
2024-09-25 7:00 ` pranshu sharma
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b4d15a09-76d6-4fc8-abdd-1276386626d4@gmx.at \
--to=rudalics@gmx.at \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=juri@linkov.net \
--cc=pranshusharma366@gmail.com \
/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 public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).