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: Sat, 19 Oct 2024 00:52:27 +1000 Message-ID: <87frotqx90.fsf@gmail.com> References: <87setpdv21.fsf@gmail.com> <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> <87ed4xvf60.fsf@gmail.com> <861q0qfnhr.fsf@mail.linkov.net> <878quxdant.fsf@gmail.com> <86zfndi6wh.fsf@mail.linkov.net> <87zfncuqhu.fsf@gmail.com> <86v7y00w68.fsf@mail.linkov.net> <87y12smubh.fsf@gmail.com> <96ea5140-9043-4c1b-97f3-4c534296355e@gmx.at> 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="9190"; 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 Fri Oct 18 17:01:39 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 1t1oTw-0002A0-Be for ged-emacs-devel@m.gmane-mx.org; Fri, 18 Oct 2024 17:01:36 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t1oTR-0006oD-Nv; Fri, 18 Oct 2024 11:01:05 -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 1t1oLF-0003Nx-Ne for emacs-devel@gnu.org; Fri, 18 Oct 2024 10:52:37 -0400 Original-Received: from mail-pl1-x636.google.com ([2607:f8b0:4864:20::636]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t1oLE-0003S7-3G; Fri, 18 Oct 2024 10:52:37 -0400 Original-Received: by mail-pl1-x636.google.com with SMTP id d9443c01a7336-208cf673b8dso22763325ad.3; Fri, 18 Oct 2024 07:52:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1729263153; x=1729867953; 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=3jc0a4w0BxDkKvyzO8badwq9wBrXhCG77he66HEFpf0=; b=b3fC+qfXR5Pnn0Gvnfl/JB7uro7+00NOEuBmDqRCVMUhzCNPLtW49REeoqOGxKwnCJ lfr8dCyPxwj7Gp/XBN/1Lp/l8X5A7rLn6EPKGIawykZ6OFRn7ermAd84rEDXUkg7MI2h frNDWag40qBQIjxkbA7cJpMOBMybxesfuHkUMnV1z4icyt8HQC8/2I+KeaY/PAcy6VFm JKx96yXhDlWypSCWORdWJyBuMpfuBuzWjGSMXCNpnD6z7qZ/WKsN56ETPmGQT3pF9u2+ tIZdfLySLdX7zO4DRrlQDU9eAeTeRIALjJ0AK/O7k1Gj4fACukT0vPbFyuFXe2etmhQw i2IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729263153; x=1729867953; 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=3jc0a4w0BxDkKvyzO8badwq9wBrXhCG77he66HEFpf0=; b=QNRH9lrrw9HBw7kh4ZXJc5tSl4oZv+J7b/BShIHivzRAS9CpE+UDEJB0DiwIv1OKhN goVIi7Bbq2iBr2CpUpFV4QIa71i4S8uvWHgpDkJWxpHihCjuzyi4MdKWbzlSxBHy/cGu Mdp5CgKAPqftIWNRQ3GpZA9+UvPrgMKxAHFEtrk9Rdk0PNqtwhfQmZqITdUKcxQ1x3S3 /PBSuv9qax79brd2v4paKJY8u+uQJu6kEWIhfDDf46VJnVNsRLioFNy7bL6WqjxWVg94 uJCerJ89Fjq+nJV4PlRaXIZRsMxTeXSGF+EaED3Huklz1Yd/xJxIvhdwnyFDWdQyIJ1x zavA== X-Forwarded-Encrypted: i=1; AJvYcCWdhoibG0XBcAlxPRKEyQobOXTO9tX8A2fL+HY7cb9BO3PU/6G0gHeF6d3WtptyYhVt2ekM@gnu.org, AJvYcCXlQmdtDvCQdF2X5tEkUTkSFYX+4YXPy6pjoKDUI4KKlb83BlZh+0CPEHa5UUbv7qpv2QDK+FbDW1cGxDc=@gnu.org X-Gm-Message-State: AOJu0YxIdOQOaL1kf9O3OCgZIqy8lvZK5GssM7x6haXdC9YpcpW2RBAP O3kzTqI9gQxhE/WjQjQV1bIN80PMO6YS/h3rJL92grqJ7nmanJKJNjo7FxrX X-Google-Smtp-Source: AGHT+IFd8ib/Mkj1WKhlyU9s3KjLLzPCTQ+5o5ZKL1ZlT5wAqruBHQMvOOj83HkMWWv4tC7xydOLTA== X-Received: by 2002:a17:902:e845:b0:20b:ab4b:544a with SMTP id d9443c01a7336-20e5a8ee9e6mr36021195ad.43.1729263153130; Fri, 18 Oct 2024 07:52:33 -0700 (PDT) Original-Received: from pebl ([2001:8003:7816:8300:535b:f6c2:90a7:552b]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-20e5a71eae8sm13459795ad.45.2024.10.18.07.52.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Oct 2024 07:52:32 -0700 (PDT) In-Reply-To: <96ea5140-9043-4c1b-97f3-4c534296355e@gmx.at> (martin rudalics's message of "Sun, 13 Oct 2024 10:17:58 +0200") Received-SPF: pass client-ip=2607:f8b0:4864:20::636; envelope-from=pranshusharma366@gmail.com; helo=mail-pl1-x636.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: Fri, 18 Oct 2024 11:01:03 -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:324658 Archived-At: --=-=-= Content-Type: text/plain martin rudalics writes: >> Btw Martin, did you have look at the code for these functions, and think >> it is ready? I am still waiting on assign@gnu.org(I sent them signed >> form) but then we can add it. > > Yes. Also people might still want to comment on my latest patch to > 'split-window'. > Ok, so today I made major changes to the interactive side of the functions(new file attached), mostly because the function would error if you call iti with prefix arg, and the press C-x z, as it would use the last used argument of frame-or-window which is now dead. The problem was that C-x z sends with same arguments, so using code in the (interactive (HERE)) would be repeated, which means same argument would be used in `repeat'. I added subtree speicfic options to the docstring(before they were not there), and made changes to window--transpose. However it is weird if you C-u M-x transpose-windows C-x z multiple times, you get weired result since the parent window changes, nothing I can do about that, just how windows work. Also I'm finally done with the bureaucracy, I got the copyright assignment done. I'm ready to send final patch now, do you want it to be added to window.el or new file? --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=window-transpose.el Content-Transfer-Encoding: quoted-printable Content-Description: new file (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 subtree frame-or-window) "Rotate windows of FRAME-OR-WINDOW anticlockwise 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. 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 (if current-prefix-arg (window-parent) (if (windowp frame-or-window) frame-or-window (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 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. 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 (if current-prefix-arg (window-parent) (if (windowp frame-or-window) frame-or-window (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 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. 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 ((windows (if current-prefix-arg (window-parent) (if (windowp frame-or-window) frame-or-window (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 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 "P") (let ((window (if subtree (window-parent) (if (windowp frame-or-window) frame-or-window (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 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. 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 (if subtree (window-parent) (if (windowp frame-or-window) frame-or-window (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. (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 `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 (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 respective size of the window. (if (car 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)))) --=-=-=--