From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: pranshu sharma Newsgroups: gmane.emacs.devel Subject: Re: Add function to rotate/transpose all windows Date: Thu, 03 Oct 2024 17:06:31 +1000 Message-ID: <87ed4xvf60.fsf@gmail.com> References: <87setpdv21.fsf@gmail.com> <86zfnxcg57.fsf@gnu.org> <877cb09ln4.fsf@gmail.com> <9005cccc-7545-4257-b2c0-885a13d3bde2@gmx.at> <86o74aa41b.fsf@gnu.org> <3d4546ac-70d9-4865-b42d-0dc50cb0f3a7@gmx.at> <878qvcgqpu.fsf@gmail.com> <0138d382-8e63-4b53-8c2c-fece826a7d0a@gmx.at> <87plooaw1w.fsf@gmail.com> <87v7yeykr0.fsf@gmail.com> <19ca7821-e034-4ae5-9ff6-570243329d74@gmx.at> <87r09224pe.fsf@gmail.com> <87ikudk62k.fsf@gmail.com> <0d879e95-c37e-416d-b439-daa6384c4f30@gmx.at> <878qv8kws2.fsf@gmail.com> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="16368"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: Eli Zaretskii , emacs-devel@gnu.org To: martin rudalics Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Oct 03 11:52:15 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1swIVK-00043r-3Z for ged-emacs-devel@m.gmane-mx.org; Thu, 03 Oct 2024 11:52:14 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1swGRk-0005OO-Ox; Thu, 03 Oct 2024 03:40:33 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1swFv7-0008H7-Mi for emacs-devel@gnu.org; Thu, 03 Oct 2024 03:06:41 -0400 Original-Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1swFv5-0004j8-1s; Thu, 03 Oct 2024 03:06:41 -0400 Original-Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-20b90ab6c19so6426615ad.0; Thu, 03 Oct 2024 00:06:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727939196; x=1728543996; darn=gnu.org; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=bxTNzM01Y2ylec1s3IFe9PMqs6n97Zqd4GUFOQ77YH4=; b=QRBWdRMvxlBegeyuXR6vA9tE0YcReSYaeAnhUcZ76gtWVPKp3QFlYu7eOiTbk1zjQt KpRAKzBD0RwVbY/ix0S1/qcUpyJA6TVw8JL31tvHGBCdDK+2blFQhtDwMK9rMJemFFDx XYzp+ZlFKvRCjAIbFISZ6BXWA1pkAvCVxVvMExcYrjN61Qso6HI3nb+V51If+ipGX/hW L5O/GYr0a+AvpD7gmtwMQ8sUHFDd7/fxeVLDqLE5H+tI5HnXS1uV1KxxPlvHOY2ikPle +AyIFh5EA0qS5VYLXsUu9EHj1Jv0eCm513sJgejWmz+ZARriKRZ0sv4wYsmIkldwl/pJ /ISQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727939196; x=1728543996; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=bxTNzM01Y2ylec1s3IFe9PMqs6n97Zqd4GUFOQ77YH4=; b=mCuIU+gU9CrJ3sehVn3eZamRQiq9DRj0pQJdphe0CHElsx1dKfTgH5LTEIhvzOacrU K94ga2E+J3IbnZWabyqfADjmy6c/zgZYGTiIxjxYxQ8sRq9ibXjxr9HLoFx4FKZlBcjl i4eRLiAngjBmKNyYLOpws5xClAE7UGJDAAB2NjZPJ3ddixqV8bA1s1tEYhyZ9NX7ri/4 xJqz2PerL0XCsD3hiWrV1OSz6/94nl8Cc1AM2RC4R2nD3fcAP8AlwSCtJlLelHWXIDVm LwzXGuSJ72j7KtVO+RAN+zmoKfQBWjT7O9u8W12sQl1gbdFxfNMgtnMejOqCn9D0/XY9 Gg6g== X-Forwarded-Encrypted: i=1; AJvYcCWqJUFot88NM1QS/p++k2ID0Uk4ly3gl7OYaf4uRkXHiteOYbO00s/W8bPrOA2AQ6c0Myclukkj17fLsw==@gnu.org X-Gm-Message-State: AOJu0Yx1zYSILCbvTShdyEiOpBXkXzc0iz/6mvoW5xveHhPmhm9GWuJl 1ty9YlLCp3B7Tdd1nziUAgM0Lk9KL+ROYIGIYNfbRKonD3atjMXYc/ckfQ== X-Google-Smtp-Source: AGHT+IFLsbt+YE16KGG47mOW3cLzjeIiqdWad0CKF2whoKJHTT0t4oUHWOx391jqcmjqybT4bfkU7g== X-Received: by 2002:a17:902:e88f:b0:20b:c258:2a74 with SMTP id d9443c01a7336-20bc5a3d3cemr75942915ad.29.1727939195960; Thu, 03 Oct 2024 00:06:35 -0700 (PDT) Original-Received: from pebl ([2001:8003:7816:8300:576a:9079:833f:796b]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7e9dcb5da39sm103985a12.93.2024.10.03.00.06.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Oct 2024 00:06:35 -0700 (PDT) In-Reply-To: (martin rudalics's message of "Wed, 2 Oct 2024 11:04:28 +0200") Received-SPF: pass client-ip=2607:f8b0:4864:20::62f; envelope-from=pranshusharma366@gmail.com; helo=mail-pl1-x62f.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 03 Oct 2024 03:40:09 -0400 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:324271 Archived-At: martin rudalics 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))))