unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: pranshu sharma <pranshusharma366@gmail.com>
To: martin rudalics <rudalics@gmx.at>
Cc: Eli Zaretskii <eliz@gnu.org>,  emacs-devel@gnu.org
Subject: Re: Add function to rotate/transpose all windows
Date: Thu, 03 Oct 2024 17:06:31 +1000	[thread overview]
Message-ID: <87ed4xvf60.fsf@gmail.com> (raw)
In-Reply-To: <ba31e779-1f30-41f8-8bf3-8a9390df7210@gmx.at> (martin rudalics's message of "Wed, 2 Oct 2024 11:04:28 +0200")

martin rudalics <rudalics@gmx.at> writes:

>>> Alternatively, we could give 'window-tree' an optional PIXELWISE
>>> argument so it returns the pixel edges of windows.
>>
>> You decide
>
> Better not - the fact that 'window-tree' does not report the edges of
> live windows constitutes bad design.  Let's not support it.  Rather
> let's make it a normal function called 'window-tree-pixel-sizes'.  I
> would write its doc string as
>
>   (defun window-tree-pixel-sizes (window &optional next)
>     "Return pixel sizes of all windows rooted at WINDOW.
>   The return value is a list where each window is represented either by a
>   triple whose first element is either t for an internal window that is a
>   horizontal combination, nil for an internal window that is a vertical
>   combination, or the window itself for a live window.  The second element
>   is a cons of the pixel height and pixel width of the window.  The third
>   element is specified for internal windows only and recursively lists
>   that window's child windows using the same triple structure."
>
> but you would have to check whether it really does what I wrote.

yes this does exactly that, thanks

>> (defun rotate-windows-anticlockwise (&optional frame-or-window)
>>   "Rotate windows of FRAME-OR-WINDOW 90 degrees anticlockwise.
>> See `rotate-windows-clockwise' for more."
>
> I think it's better to write out the full doc-string here first and
> in a final sentence say
>
>   See `rotate-windows-clockwise' for how to rotate windows in the
>   opposite direction.

k

>
>> (defun flip-windows-horizontally (&optional frame-or-window)
>>   "Horizontally flip windows of FRAME-OR-WINDOW.
>> FRAME-OR-WINDOW must be a live frame or window and defaults to the
>> selected frame. If FRAME-OR-WINDOW is a frame, flip from the root
>> window of the frame, otherwise flip from FRAME-OR-WINDOW."
>
> Here you should probably first say what "flip" means.  It's obvious when
> you have a frame with two side-by-side live windows.  It's already less
> obvious with three side-by-side windows and even less so with more
> complex layouts.

I explained it just using the metaphor of a reflection

>> (defun transpose-windows--rearrange (frame-or-window conf norm-size)
>
> I'd call this just 'window--transpose'.

done

>
>> "Rearrange windows of FRAME-OR-WINDOW recursively.
>> CONF should be a cons cell: (HORIZONTAL-SPLIT . VERTICAL-SPLIT) where
>> horizontal split is called when splitting a window that was previously
>> horizontally split, and VERTICAL-SPLIT for a window that was previously
>> vertically split.
>
> CONF is confusing.  Why is it a cons cell in the first place?  Wouldn't
> a simple boolean - t for horizontal and nil for vertical - suffice?  If
> not, please explain why.

You can also have below split and abvoe split, not just nil and t

>
>> When is NORM-SIZE non-nil, the size argument of the
>
> I think it's just the pixel size and not the normal size, right?  Also
> you should write it as "When NORM-SIZE is non-nil ..."

It's a bolean that states if or not the height or width should be
converted to width or height respecitlcly. I changed the name.

> Note that 'frame-first-window' returns the first live window on its
> frame.  What if you want to flip some child windows only?

I didnt read docstring properly when I rewrote function, mb, played
cardi b bit too loud.  I kind of assumed since it accepts
frame-or-window it would return first child.  But fixed that now.

>> 	(select-window selwin)))))
>
> should become (set-frame-selected-window selwin) for the case that you
> rotate windows on a non-selected frame.

Thanks, I was looking for this function

>
>> (defun transpose-windows--rearrange-1 (subtree cwin conf norm-size)
>
> And this I'd call 'window--transpose-1'
>
> Again please describe all arguments in the doc-string.

I already explained the arguments in transpose-windows--rearrange.  As
far as I can tell most other -1 postfix don't explain their arguments eg
window--resize-reset-1.

btw, what are the plans for the keybindings? imo they should be added
top level in C-x w map, as there are lots of spots avaiable, and there
are only 5 total new functions.


(defun window-tree-pixel-sizes (window &optional next)
  "Return pixel sizes of all windows rooted at WINDOW.
The return value is a list where each window is represented either by a
triple whose first element is either t for an internal window that is a
horizontal combination, nil for an internal window that is a vertical
combination, or the window itself for a live window.  The second element
is a cons of the pixel height and pixel width of the window.  The third
element is specified for internal windows only and recursively lists
that window's child windows using the same triple structure."
  (let (list)
    (while window
      (setq list
	    (cons
	     (cond
	      ((window-top-child window)
	       (cons t (cons (cons (window-pixel-height window)
				   (window-pixel-width window))
			     (window-tree-pixel-sizes
			      (window-top-child window) t))))
	      ((window-left-child window)
	       (cons nil (cons (cons (window-pixel-height window)
				     (window-pixel-width window))
			       (window-tree-pixel-sizes
				(window-left-child window) t))))
	      (t (list window (cons (window-pixel-height window)
				    (window-pixel-width window)))))
	     list))
      (setq window (when next (window-next-sibling window))))
    (nreverse list)))

(defun rotate-windows-anticlockwise (&optional frame-or-window)
  "Rotate windows of FRAME-OR-WINDOW anti-clockwise by 90 degrees.
FRAME-OR-WINDOW must be a live frame or window and defaults to the
selected frame.  If FRAME-OR-WINDOW is a frame, rotate the main window
of the frame, otherwise rotate FRAME-OR-WINDOW.  See
`rotate-windows-clockwise' for how to rotate windows in the opposite
direction"
  (interactive `(,(and current-prefix-arg (window-parent))))
  (let ((window (if (windowp frame-or-window)
		    frame-or-window
		  (window-main-window frame-or-window))))
    (transpose-windows--rearrange window '(right . above) nil)))

(defun rotate-windows-clockwise (&optional frame-or-window)
  "Rotate windows of FRAME-OR-WINDOW clockwise by 90 degrees.
FRAME-OR-WINDOW must be a live frame or window and defaults to the
selected frame.  If FRAME-OR-WINDOW is a frame, rotate the main window
of the frame, otherwise rotate FRAME-OR-WINDOW.  See
`rotate-windows-anticlockwise' for how to rotate windows in the opposite
direction"
  (interactive `(,(and current-prefix-arg (window-parent))))
  (let ((window (if (windowp frame-or-window)
		    frame-or-window
		  (window-main-window frame-or-window))))
    (transpose-windows--rearrange window '(left . below) nil)))

(defun flip-windows-horizontally (&optional frame-or-window)
  "Horizontally flip windows of FRAME-OR-WINDOW.  When the windows are
flipped horzontally, the window layout is made to it's reflection from
the side edge.  FRAME-OR-WINDOW must be a live frame or window and
defaults to the selected frame. If FRAME-OR-WINDOW is a frame, flip from
the main window of the frame, otherwise flip from FRAME-OR-WINDOW.  See
`flip-windows-vertically' for how to flip windows vertically."
  (interactive `(,(and current-prefix-arg (window-parent))))
  (let ((window (if (windowp frame-or-window)
		    frame-or-window
		  (window-main-window frame-or-window))))
    (transpose-windows--rearrange window '(below . left) t)))


(defun flip-windows-vertically (&optional frame-or-window)
  "Horizontally flip windows of FRAME-OR-WINDOW.  When the windows are
flipped vertically, the window layout is made to it's reflection from
the top edge.  FRAME-OR-WINDOW must be a live frame or window and
defaults to the selected frame. If FRAME-OR-WINDOW is a frame, flip from
the main window of the frame, otherwise flip from FRAME-OR-WINDOW.  See
`flip-windows-horizontally' for how to flip windows horizontally."
  (interactive `(,(and current-prefix-arg (window-parent))))
  (let ((window (if (windowp frame-or-window)
		    frame-or-window
		  (window-main-window frame-or-window))))
    (transpose-windows--rearrange window '(above . right) t)))

(defun transpose-windows (&optional frame-or-window)
  "Transpose windows of FRAME-OR-WINDOW.
Rearrange windows such that where a horizontal split was used a vertical
one is used instead, and vice versa.  FRAME-OR-WINDOW must be a live
frame or window and defaults to the selected frame.  If FRAME-OR-WINDOW
is a frame, transpose the main window of the frame, otherwise
transpose FRAME-OR-WINDOW."
  (interactive `(,(and current-prefix-arg (window-parent (selected-window)))))
  (let ((window (if (windowp frame-or-window)
		    frame-or-window
		  (window-main-window frame-or-window))))
    (transpose-windows--rearrange window '(right . below) nil)))


(defun transpose-windows--rearrange (frame-or-window conf do-not-convert-size)
  "Rearrange windows of FRAME-OR-WINDOW recursively.
CONF should be a cons cell: (HORIZONTAL-SPLIT . VERTICAL-SPLIT) where
HORIZONTAL-SPLIT will be used as the third argument of `split-window'
when splitting a window that was previously horizontally split, and
VERTICAL-SPLIT as third argument `split-window' for a window that was
previously vertically split.  When is DO-NOT-CONVERT-SIZE non-nil, the
size argument of the window-split is converted from vertical to
horizontal or vice versa, with the same proportion of the total split."
  (pcase-let ((`(,rwin . ,frame)
	       (if (framep frame-or-window)
		   (cons (window-main-window frame-or-window) frame-or-window)
		 (cons frame-or-window (window-frame frame-or-window)))))
    (if (or (not rwin)
	    (zerop (window-child-count rwin)))
	(message "No windows to transpose")
      (let* ((fwin rwin)
	     (selwin (frame-selected-window frame-or-window))
	     (win-tree (car (window-tree-pixel-sizes rwin))))
	(while (not (window-live-p fwin))
	  (setq fwin (window-child fwin)))
	;; 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)))
	(window--transpose-1 win-tree fwin conf do-not-convert-size)
	;; Go back to previously selected window.
	(set-frame-selected-window frame selwin)))))

(defun window--transpose-1 (subtree cwin conf do-not-convert-size)
  "Subroutine of `transpose-windows--rearrange'."
  ;; `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 . ,flen) (if (car subtree)
				    (cons (float (car (cadr subtree)))
					  (float (window-pixel-width cwin)))
				  (cons (float (cdr (cadr subtree)))
					(float (window-pixel-height cwin))))))
    (mapc
     (pcase-lambda (`(,win . ,size))
       (let ((split-size (- (if do-not-convert-size
				size
			      (round (* flen  (/ size ilen))))))
	     (split-type
	      (funcall (if (car subtree) 'car 'cdr) conf)))
	 (if (listp win)
	     ;; `win' is a window subtree.
	     (window--transpose-1 win (split-window cwin
						    split-size
						    split-type
						    t
						    (seq-some
						     (lambda (x)
						       (and (windowp x) x))
						     (flatten-list win)))
				  conf do-not-convert-size)
	   ;; `win' is a window.
	   (split-window cwin split-size
			 split-type t
			 win))))
     (mapcar
      (lambda (e)
	(let ((window? (if (windowp (car e)) (car e) e)))
	  (cons window?
		;; The relevent size of the window.
		(if (car subtree)
		    (car (cadr e))
		  (cdr (cadr e))))))
      ;; By using cdddr, we ignore over window split type, sizes and
      ;; the first window (it's implicitly created).
      (nreverse (cdddr subtree))))
    ;; (caaddr subtree) is the first window.
    (unless (windowp (caaddr subtree))
      (window--transpose-1 (caddr subtree) cwin conf do-not-convert-size))))



  reply	other threads:[~2024-10-03  7:06 UTC|newest]

Thread overview: 66+ 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 [this message]
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-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=87ed4xvf60.fsf@gmail.com \
    --to=pranshusharma366@gmail.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@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 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).