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, 28 Nov 2024 00:37:06 +1000 Message-ID: <87bjy03fql.fsf@gmail.com> References: <87setpdv21.fsf@gmail.com> <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> <878qt8spp2.fsf@gmail.com> <0ce35c7a-8b28-4905-a6ab-caf50f2fc750@gmx.at> <87mshl2i6h.fsf@gmail.com> <9b460366-f34e-48f6-a680-e7fa5bc7f598@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="34576"; 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 Wed Nov 27 16:30: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 1tGJzz-0008nm-C3 for ged-emacs-devel@m.gmane-mx.org; Wed, 27 Nov 2024 16:30:39 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tGJzR-0000Vz-7F; Wed, 27 Nov 2024 10:30:05 -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 1tGJAJ-000225-IR for emacs-devel@gnu.org; Wed, 27 Nov 2024 09:37:15 -0500 Original-Received: from mail-pf1-x42e.google.com ([2607:f8b0:4864:20::42e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tGJAH-0005eS-O6; Wed, 27 Nov 2024 09:37:15 -0500 Original-Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-7250c199602so3063045b3a.1; Wed, 27 Nov 2024 06:37:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1732718231; x=1733323031; 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=0792pvwsUf18oIszToracAT3h/1rbYK1fc59nTYNkHU=; b=GvpOeeOy2bHo44xvhQjitFkvROgqA+Ehg6+xdHtESLJTP0zt6bnmJDJTvKrN9xsTEv neDcyh7rEdsSljMaVLI/HLJ8opH7P/Af9rqrH/Brxrb6iVvbqzhg7x7j90G8WMBfN6rX BXRlheQAZPu3jXFynFn1qTCZdvBawWPMxGZXixZbpIWOD+ePASRIKSCR94nN47MOU8k/ qWnfa066LXG8nYhDuDSEmoo/Qi965M5pQTW9gBbu1jlnaPIEtbrxoix38SOfK4mIEdw4 8JBTtrEApB+xoAi7PTKThMo4BCDC6egOWQu5OO0i3wzoQGpvJyGKaoEe1Kj6+RlQ3Rpn v8AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732718231; x=1733323031; 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=0792pvwsUf18oIszToracAT3h/1rbYK1fc59nTYNkHU=; b=YPfLMYl58K43U3kwD6NJ610p/llgVvzd1Oz8s+hc++EtTHEFlgrg/OEq1LSsCIMHGX CNrVc0bpgoEtlnskzMYVeR3wiLTfncP9y42dnuKYRliOFOGkIU70CCiwMGEwj27bPoNh HaaSbHWqdpDCTRgxHOv7b+rtYEp+SD23DkEDHZM+FKVMUcXHTnM/IIjnx0Fyo8xheTG0 8TH8aUDjQ8Au3jTSErPfA08J4yN5KoDIM830jeksrnps90hFZ23EUza0wO73Ozlr/5Z/ X6V/IPxHt8Dy2zB5MGBhXYbKOEzNj/36p98Uq1Ug0xEosDcKwZemPz04Nv+t707N8ETI 4sJQ== X-Forwarded-Encrypted: i=1; AJvYcCUerMsLO44TadLSpySuvI2s/g2RTyTp31mtR6fCR/Hs6JBheKS+2Hk3Op/cgddNkgdbIDT2@gnu.org, AJvYcCVXM+aRCNSlR6Djsv/vXRYZs9vhCACvtoTX4fibVHVI2BiMvHF+xW7K5YT+JtxxrYHlMk16nBLPhktvcRg=@gnu.org X-Gm-Message-State: AOJu0Yw+usBTUBCqz8LXgPQTx440a/Kk/0roelqUWRIb8tRPl3ZRuNq8 yXawqDRKRge1UqmeiftzYuTmqAB3+rARMO74PvZ2V2Ptf1zwZxO4D3JdDDuk X-Gm-Gg: ASbGncsLs74tcKIMFQtQSFYNuRFIvyC/sg5jDZu4fc1SRq1vwwgdlPJ3KcmJc2Lt5BP KX9Effqsy3ngXA5cQ3LoHgq6dgG5VqKdlNsMDWaIxWMkFph8q1uJ3+Bnkh7j+TfMg7sJq80dVmJ 6cvK0Jd9fUtgp5ZfQObnnE/5a4EivTEd6NEEk5SM4bS71kfEx92Za78svrk8EfD7ezQ5S47YAQA IjRSp3qstjipqT54OKVZDDkrxSlgDw/2aCJNAEA7BQ/9PzCEjPB X-Google-Smtp-Source: AGHT+IF4+ydJgvYHNLOGXzKZv3FNLuVrQ2YUpdlouHmbdRmKgK1FNflvXNU87Fa53o+XSlJ/VeVHIA== X-Received: by 2002:a05:6a00:189c:b0:71e:5d1d:1aaf with SMTP id d2e1a72fcca58-7253015ec8cmr4660059b3a.23.1732718231155; Wed, 27 Nov 2024 06:37:11 -0800 (PST) Original-Received: from pebl ([2001:8003:7816:8300:b326:c686:57a:64ef]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7fbcc3de0ecsm10665147a12.57.2024.11.27.06.37.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Nov 2024 06:37:10 -0800 (PST) In-Reply-To: <9b460366-f34e-48f6-a680-e7fa5bc7f598@gmx.at> (martin rudalics's message of "Wed, 27 Nov 2024 10:18:47 +0100") Received-SPF: pass client-ip=2607:f8b0:4864:20::42e; envelope-from=pranshusharma366@gmail.com; helo=mail-pf1-x42e.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: Wed, 27 Nov 2024 10:29:54 -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:325779 Archived-At: --=-=-= Content-Type: text/plain martin rudalics writes: >> As of rn, compiling emacs bug outs for leim for some reason, so I can't >> compile with the improvemnt, but I got it to work. > > What is the bug? It was when byte comping emacs/lisp/leim/leim-list.el, so I just removed the whole thing along with the quail library. Then after than it was another thing where it would just spam me with 'temacs' warnings, and then segmentation fault. >> One thing you do in the code is check if parent of prev is equal to >> current window, which is my mind must be true cuz is it isn't, then it >> would go thoruhg another level of nesting. > > That's possible. I told you that my code is likely over-engineered. > > Your last version reuses all parent windows as expected so we should be > done in principle. Finally! Thanks for your patiance, it feels like we are getting somewhere again after the spliting parent window saga. > > Could you try using 'window-normal-size' as I did in window-rotate.el? > It should be able to preserve initial sizes better than using the real > sizes as you do. The only clue here is that the normal size of a window > is always relative to the size of its parent and not to that of the root > window. Ok, I did that, and it now works fine. I made progress with atom windows and fixed size windows. It just gives message if you have any of those and do-not-convert-size is non-nil (as in transpose and rotate window), but the strucuture preservign thing works in flip functions. I know it's theoreticly possible to do atom-windows when size is converted, but it's a nightmare iiuc. Also what do you want to happen with dedicated-windows in cycle-windows command? Technically it'll work fine, but it's unitutve as the user gets the expression buffers have changed but window remains the same, evo tho only windows have changed. So in atom windows, there is a bug where they do not remain atomic after the functino is called, although the strucutre and proportions are preserved,. I have prepared an gourmet bug experiance for you. Just insert the test in any buffer, and go C-x C-e at end. I don't think it'll work if you do M-:. Use the updated window-transpose.el. --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=test.el Content-Transfer-Encoding: quoted-printable Content-Description: The bug (progn (delete-other-windows) (switch-to-buffer "humptydumpty") (split-window nil nil t) (other-window 1) (split-window) (split-window nil nil t) (split-window) (split-window nil nil t) (other-window 3) (switch-to-buffer "bigbuf") (y-or-n-p "Note that the window on buffer bigbuf is selected") (y-or-n-p "Checkpoint: seting window parent of bigbuf window to atom wind= ow") (window-make-atom (window-parent)) (y-or-n-p (concat "Note that the selected window is: " (prin1-to-string (selected-window)) "\n And the (window-parameter (selected-window) 'window-atom) is:" (if (window-parameter (selected-window) 'window-atom) "t" "nil") "\n and parent window is " (prin1-to-string (window-parent)))) (insert (concat "window:"(prin1-to-string (selected-window)) "\n" "window-atom:" (if (window-parameter (selected-window) 'window-atom) "= t" "nil") "\n" "window parent:"(prin1-to-string (window-parent)) "\n")) (y-or-n-p "Note how after the splt happens, the stgrucure of atom window = will remain unchanged") (call-interactively 'flip-windows-vertically) (sit-for 1) (y-or-n-p (concat "Now the selected window is: " (prin1-to-string (selected-window)) "\n And the (window-parameter (selected-window) 'window-atom) is:" (if (window-parameter (selected-window) 'window-atom) "t" "nil") "\n and parent window is " (prin1-to-string (window-parent))))) --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=window-transpose.el Content-Transfer-Encoding: quoted-printable Content-Description: new window-transpose.el ;;; -*- 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-normal-size window nil) (window-normal-size window t)) (window-tree-pixel-sizes (window-top-child window) t)))) ((window-left-child window) (cons (cons nil window) (cons (cons (window-normal-size window nil) (window-normal-size window t)) (window-tree-pixel-sizes (window-left-child window) t)))) (t (list window (cons (window-normal-size window nil) (window-normal-size window t))))) 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 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))) ;; TODO: dedicated windows =F0=9F=98=84 (defun cycle-windows (&optional subtree frame-or-window) "This cycles windows basiclly so that for all windows, each window becomes it's `other-window'. +-----+ +-----+ | A | | C | |-----| -> |-----| |B | C| | A| B| +-----+ +-----+ " (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))))) ;; All child windows need to be recursively deleted. (delete-other-windows-internal fwin window) (delete-dups atom-windows) (window--transpose-1 new-win-tree fwin '(below . right) t nil) (set-frame-selected-window frame selwin) (other-window -1))))) (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))) (win-list (seq-filter 'window-live-p (flatten-list win-tree))) (atom-windows (remq nil (mapcar 'window-atom-root win-list)))) (if (and (not (eq (car atom-windows) window)) (or do-not-convert-size (and (not atom-windows) (not (seq-some 'window-fixed-size-p win-list))))) (progn (when atom-windows (delete-dups atom-windows)) (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 atom-windo= ws) ;; Go back to previously selected window. (set-frame-selected-window frame selwin)) (message "This does not work with fixed size or atom windows."))))) (defun window--transpose-1 (subtree cwin conf do-not-convert-size atom-wind= ows) "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. (let ((n-set t) (flen (if (funcall (if do-not-convert-size 'not 'identity) (caar subtree)) (float (window-pixel-width cwin)) (float (window-pixel-height cwin))))) (mapc (pcase-lambda (`(,win . ,size)) (prog1 (let ((split-size (- (* flen size))) (split-type (funcall (if (caar subtree) 'car 'cdr) conf))) (if (listp win) ;; `win' is a window subtree. (let* ((d-win win) (is-atom (memq (cdar d-win) atom-windows)) (_ (while (listp (caaddr d-win)) (setq d-win (caddr d-win))))) (window--transpose-1 win (let ((window-combination-limit n-set) (new-win (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)) new-win) (if is-atom '(nil . t) conf) do-not-convert-size atom-windows)) ;; `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)) (let ((is-atom (memq (cdar (caddr subtree)) atom-windows))) (window--transpose-1 (caddr subtree) cwin (if is-atom '(nil . t) conf) do-not-convert-size atom-windows))))) (define-key global-map (kbd "C-x w t") 'transpose-windows) (define-key global-map (kbd "C-x w c") 'cycle-windows) (pp (window-tree-pixel-sizes (window-parent))) --=-=-=--