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: Sun, 24 Nov 2024 23:53:45 +1000 Message-ID: <878qt8spp2.fsf@gmail.com> References: <87setpdv21.fsf@gmail.com> <87ses0r81d.fsf@gmail.com> <69658762-5fc7-4a9d-9262-528dfd9e93cd@gmx.at> <87wmhb2yew.fsf@gmail.com> <801bbd24-8f79-48a4-9615-f5ef21b2341e@gmx.at> <87ikstsu7f.fsf@gmail.com> <68dc98d6-42c0-431a-aefe-eecb02991764@gmx.at> <875xosy316.fsf@gmail.com> <87bjyfcncu.fsf@gmail.com> <87cyiuefxs.fsf@gmail.com> <878qthewbq.fsf@gmail.com> <8599bc67-b05d-4afc-8e6e-1ba64a30054e@gmx.at> <87frnp2x85.fsf@gmail.com> <823c7cca-63d4-4568-94bc-11f5949d6c5c@gmx.at> <87h683muss.fsf@gmail.com> <02432e6c-6ee2-4c68-9ebb-246f6be88918@gmx.at> <877c8wadke.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="4597"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: Juri Linkov , Eli Zaretskii , emacs-devel@gnu.org To: martin rudalics Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Nov 24 15:02:17 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 1tFDBn-0000zj-WE for ged-emacs-devel@m.gmane-mx.org; Sun, 24 Nov 2024 15:02:16 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tFDB3-0004iv-Pu; Sun, 24 Nov 2024 09:01:29 -0500 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 1tFD3k-00041W-9a for emacs-devel@gnu.org; Sun, 24 Nov 2024 08:53:56 -0500 Original-Received: from mail-pl1-x632.google.com ([2607:f8b0:4864:20::632]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tFD3g-0007fi-Rd; Sun, 24 Nov 2024 08:53:55 -0500 Original-Received: by mail-pl1-x632.google.com with SMTP id d9443c01a7336-21278f3d547so26502695ad.1; Sun, 24 Nov 2024 05:53:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1732456430; x=1733061230; 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=ogYdVtgqKFnX4EcaHOrJV9a7BsOYMzXiA/ay3BfS+r4=; b=WqGckHphQ2wyuET30tWX4y8HOHYFgdRpYhPRlOSgRqmMjba+hgj7QR7gM/Pw7LMxd0 Po1I+E3BAbO1oAjT5wjwYtHS1W9h5qMV0JtN9mdMoKWCkL/ZO6NXA1tprMGHO56xpfXB d7y4UsU5zFgioVtJh1I+lzrRxsDw8a7mtSo4KNEe41bIPvUJDmetreso9NsNaK9RRMxt LrDFZatozkj4TZWa5gjsRkWGGsxq2GO53Wc7ec2CqgdNNMkvNVyeK/4Ywkxe0eEorb4M a6mQE/zfJHk6kWnrSb154ovV4lLwp46yQ5v5KVzUkvFnjdZD3Wiz716O6Gnz83qSRMbm jbFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732456430; x=1733061230; 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=ogYdVtgqKFnX4EcaHOrJV9a7BsOYMzXiA/ay3BfS+r4=; b=fs3nKHBsrvyQQ6prbn3QOg+2awWdQ7CLOkwynnlGRUe52m5oV3T0Z6OJ8ZSRwO8o4m 6NafyQUaaEr6rwsZR10fCRk+0biRyVFWcAQ6pw2t6rjUAhExnViI/PZgGEMKDAUrAVMA iesJ1N5cSLkrY3ew8vicAYFD3A5VJZoQc3WykqT0MlerurwvWGb68wegC9R/iHclHo2K RCjZSFDnDPKvmJazrGI+6oWR3Xg0+ps1kqbUOSB3JZC0i0DZ6JzYG3XMuTjqQ9v4Rlti oU3CP8DDQF6emYCDAXjMYVfl9rYE/mLP7TxdwOzb71OrskjY8zW3xMkHf3ViLPqtAdJP lcKQ== X-Forwarded-Encrypted: i=1; AJvYcCVIaHO3hrCx1yWfuJAsw/zlW32OHOZL0m59gz24fTMX7lHVkORmGYcESmLzAuVJjyIiW2VETPoBk70PpX0=@gnu.org, AJvYcCWFPAkQSNmQ2Xj+3nV312mMq9yZ27rL9vM2ZmA3h/vmUtYMxeUEi3akzXm2/4YESmyL44od@gnu.org X-Gm-Message-State: AOJu0YzgY4QVh/eqxWn5q0TlgVhNg1GHYSHRw1uERsIpnMZE69Whet32 TQaxvWjJi+bEoAnvHphJ/X1y9LthsGOXIncvnEeFjfb+D899NIOK8IMN7/Hl X-Gm-Gg: ASbGncuMOiTWWvi0P8ou6KG59wnRg2aq+LD+T89G6GTxKmC/F5TcTYzw4cANBr93Vdq HdiYpA60jUtnVOd2+G/CgP8INgiWv5CnseWkICB1IBtC0nvniA6yaELFxiqiKcsNEfLImQfu4n/ K6BOBu4ZTXntTJnujNCi1rJMjyBkgSdUdmpB01Bs51S2k9FBCXNbEh/w5WSd1mIH0iNnyOS2I2e 0XbbSsbfz08o9irdLCBTXAx3Fz0MepqoropwTBM7a0ZWYroCjL4Qg== X-Google-Smtp-Source: AGHT+IFfQRbKzaSAe3p7DeTkDtzt1xhknOTT25Fs2i0tVsTYT4vjbl06nfx9hS8BqTXtZa3UigkWlQ== X-Received: by 2002:a17:902:cece:b0:212:46c2:632e with SMTP id d9443c01a7336-2129f760f7fmr125173975ad.15.1732456430120; Sun, 24 Nov 2024 05:53:50 -0800 (PST) Original-Received: from pebl ([2001:8003:7816:8300:c7df:6299:d3b2:6f0c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2129dbfa321sm46705995ad.139.2024.11.24.05.53.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 24 Nov 2024 05:53:49 -0800 (PST) In-Reply-To: (martin rudalics's message of "Thu, 21 Nov 2024 18:54:34 +0100") Received-SPF: pass client-ip=2607:f8b0:4864:20::632; envelope-from=pranshusharma366@gmail.com; helo=mail-pl1-x632.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: Sun, 24 Nov 2024 09:01:28 -0500 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:325664 Archived-At: --=-=-= Content-Type: text/plain martin rudalics writes: >> I don't fully understnad why this is happening. iiuc, the purpose of >> checking for previous split is to see if the (cons window parent) refer >> split has already happened, to avoid doing it again. Instead of doing >> this, I just use a vriable called `n-set' which determines if the >> parent >> window has already been split with the cons refer argument, so I don't >> belive this is neccasary. > > I think my code is over-engineered in this regard. Fact is that you > create a new parent window where you should use the existing one. I think your code was fine, my code just does same thing but instead of storing the name of the prev window, it just stores bool if it has previous window. >> Nice, can you send the whole diff. > > Attached. It's a bit more than that and comes without warranty. The > elisp manual has not been updated in this regard. Ok so I got the thing to work under the split you described and and a coupla other splits, and it works fine now. I'll have a look at getting things to work with the other diff, but iiuc I should only need combinations (or worst case scinario is window paremater to check if it is atom window, but iiuc this should be preventable as if it is, they I will iterate windows when still alive, and replace the windows with their `window-atom-root'). Also have a look at the cycle-window command, wdyt? Sorry for the late reply, the temprature where I live dropped to 20C (maybe this was the reason, but I've heard rumors that an overuse of M-x edebug-defun can causes sickness), and I got the headachy kind of ill. --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=window-transpose.el Content-Transfer-Encoding: quoted-printable ;;; -*- lexical-binding:t -*- (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 valid 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 (cons t window) (cons (cons (window-pixel-height window) (window-pixel-width window)) (window-tree-pixel-sizes (window-top-child window) t)))) ((window-left-child window) (cons (cons nil window) (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 subtree frame-or-window) "Rotate windows of FRAME-OR-WINDOW anticlockwise by 90 degrees. FRAME-OR-WINDOW must be a valid 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. If SUBTREE is non-nil, the function will act as if FRAME-OR-WINDOW is the parent window of the selected window." (interactive "P") (let ((window (cond (subtree (window-parent)) ((windowp frame-or-window) frame-or-window) (t (window-main-window frame-or-window))))) (window--transpose window '(right . above) nil))) (defun rotate-windows-clockwise (&optional subtree frame-or-window) "Rotate windows of FRAME-OR-WINDOW clockwise by 90 degrees. FRAME-OR-WINDOW must be a valid 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. If SUBTREE is non-nil, the function will act as if FRAME-OR-WINDOW is the parent window of the selected window." (interactive "P") (let ((window (cond (subtree (window-parent)) ((windowp frame-or-window) frame-or-window) (t (window-main-window frame-or-window))))) (window--transpose window '(left . below) nil))) (defun flip-windows-horizontally (&optional subtree 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 valid 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. If SUBTREE is non-nil, the function will act as if FRAME-OR-WINDOW is the parent window of the selected window." (interactive "P") (let ((window (cond (subtree (window-parent)) ((windowp frame-or-window) frame-or-window) (t (window-main-window frame-or-window))))) (window--transpose window '(below . left) t))) (defun flip-windows-vertically (&optional subtree 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 valid 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 "P") (let ((window (cond (subtree (window-parent)) ((windowp frame-or-window) frame-or-window) (t (window-main-window frame-or-window))))) (window--transpose window '(above . right) t))) (defun transpose-windows (&optional subtree 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 valid 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. If SUBTREE is non-nil, the function will act as if FRAME-OR-WINDOW is the parent window of the selected window." (interactive "P") (let ((window (cond (subtree (window-parent)) ((windowp frame-or-window) frame-or-window) (t (window-main-window frame-or-window))))) (window--transpose window '(right . below) nil))) (defun window--transpose (window conf do-not-convert-size) "Rearrange windows of 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 of `split-window' for a window that was previously vertically split. If 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." (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)) (win-tree (car (window-tree-pixel-sizes window)))) (while (not (window-live-p fwin)) (setq fwin (window-child fwin))) ;; All child windows need to be recursively deleted. (delete-other-windows-internal fwin window) (window--transpose-1 win-tree fwin conf do-not-convert-size) ;; Go back to previously selected window. (set-frame-selected-window frame selwin)))) (defun deepmap(fun ls) (if (consp ls) (cons (if (consp (car ls)) (deepmap fun (car ls)) (funcall fun (car ls))) (deepmap fun (cdr ls))) (funcall fun ls))) (defun cycle-windows (&optional subtree frame-or-window) (interactive "P") (let ((window (cond (subtree (window-parent)) ((windowp frame-or-window) frame-or-window) (t (window-main-window frame-or-window))))) (if (or (not window) (window-live-p window)) (message "No windows to transpose") (let* ((frame (window-frame window)) (selwin (frame-selected-window window)) (win-tree (car (window-tree-pixel-sizes window))) (winls (seq-filter 'window-live-p (flatten-list win-tree))) (rotated-ls (append (last winls) winls)) (fwin (car (last winls))) (new-win-tree (deepmap (lambda (x) (if (window-live-p x) (pop rotated-ls) x)) win-tree))) ;; All child windows need to be recursively deleted. (delete-other-windows-internal fwin window) (window--transpose-1 new-win-tree fwin '(below . right) t) (set-frame-selected-window frame selwin) (other-window -1))))) (defun window--transpose-1 (subtree cwin conf do-not-convert-size) "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 . ,flen) (if (caar subtree) (cons (float (car (cadr subtree))) (float (window-pixel-width cwin))) (cons (float (cdr (cadr subtree))) (float (window-pixel-height cwin))))) (n-set t)) (mapc (pcase-lambda (`(,win . ,size)) (prog1 (let ((split-size (- (if do-not-convert-size size (round (* flen (/ size ilen)))))) (split-type (funcall (if (caar subtree) 'car 'cdr) conf))) (if (listp win) ;; `win' is a window subtree. (let* ((d-win win) (_ (while (listp (caaddr d-win)) (setq d-win (caddr d-win)))) (window-combination-limit n-set)) (window--transpose-1 win (prog1 (split-window cwin split-size split-type t (if window-combination-limit (cons (caaddr d-win) (cdar subtree)) (caaddr d-win))) (when window-combination-limit (set-window-combination-limit (cdar subtree) nil))) conf do-not-convert-size)) ;; `win' is a window. (split-window cwin split-size split-type t (if n-set (cons win (cdar subtree)) win)))) (setq n-set nil))) (mapcar (lambda (e) (let ((window? (if (windowp (car e)) (car e) e))) (cons window? ;; The respective size of the window. (if (caar subtree) (car (cadr e)) (cdr (cadr e)))))) ;; By using cdddr, we ignore 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)))) (define-key global-map (kbd "C-x w t") 'transpose-windows) (define-key global-map (kbd "C-x w c") 'cycle-windows) (pp (car (window-tree-pixel-sizes (window-parent)))) --=-=-=--