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: Tue, 01 Oct 2024 19:17:01 +1000 Message-ID: <878qv8kws2.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> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="36076"; 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 Tue Oct 01 16:53:36 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 1sveFr-0009Cr-V8 for ged-emacs-devel@m.gmane-mx.org; Tue, 01 Oct 2024 16:53:36 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sveDE-000271-2K; Tue, 01 Oct 2024 10:50:52 -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 1sveAQ-0003L4-Of for emacs-devel@gnu.org; Tue, 01 Oct 2024 10:47:58 -0400 Original-Received: from mail-oa1-x2a.google.com ([2001:4860:4864:20::2a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sveAO-0004b2-Kp; Tue, 01 Oct 2024 10:47:58 -0400 Original-Received: by mail-oa1-x2a.google.com with SMTP id 586e51a60fabf-2877d7ae3e5so261570fac.3; Tue, 01 Oct 2024 07:47:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727794074; x=1728398874; 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=8cYoJSv3fxWv/T3NKSQaLgwYf8kQD/sJX+Q1DW6x9a8=; b=QVTXT6JFt2CAFhpdevV/LqjnZGE40M01u2J8XYQnmHHgSlpp4dOfEnTmckBKEAf85I fXnkOrNBrEojq3NoX+VQZ5faL1vubgNNIuLqWOj3m/GuwdwrdahJVf+DuxGtze6KZqbz 0Sw54pvMbkNbl7Vq00fSgonrd51dXrx7tV0zLqPx0qLLxIgfPh4iwkB2MxKzCtPbLEad RS7THD5sev8CdWeB+j38EmmnzSeCkt8dggcYG/gigaTni4RhQQQdaMjw15whray3PkXm gq6/TDqB1a0Hl7U+bdN9UZG6wwx/99Bw27Vx0IVUmDg3y7w3CEIODNATXstkm0thV9a0 J2nA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727794074; x=1728398874; 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=8cYoJSv3fxWv/T3NKSQaLgwYf8kQD/sJX+Q1DW6x9a8=; b=jQT1Z/9LuNBS7cCir75vYLM9zCS09itCDWwlxTE+1sjVw8I9Uy9CUqMLW9Rx7cXVY0 0KDD3TJAARCGRAkctSHYjW5UPgW12+R6kFufmw01DkpmSH0+nATAyaQLjwztnSpqCSHf QG/JT9H8LmTo4G7NhRT2nj3c2tTvzJjoYKoknvI52ToKLCz2F9a3rqbGixENjtKhx3SI 7ZTlwuPPCFGgScp/ZhzvE7xuCceydzGn6O1beIaSBpQAFwJoyWF0Ttg328nUrD3sHQjX NEJhtGSQshC5nL2+hbbB8DnhBP293d3L5Ukgzb9RTKM5eURDOkuMnPV4+a6SkEqKBNcu x9Jw== X-Forwarded-Encrypted: i=1; AJvYcCVCvfJXjyxzWKkCWSGyzXOautVCQtpI/+M/XFb4jIKRXkFlaQCZqu0xDNN9p3bRGX06w+ar93l3YhEaQQ==@gnu.org X-Gm-Message-State: AOJu0YxEbFrrfyIeamwFFzwucJ0exbb6js5NyUd4e+mF5djT2SJ80PS5 8f4RYI8SFmXVc4e52Q/3OCiAFdCFQ2Jcyf8aR/vWNmThLHtNR987xpiOrQ== X-Google-Smtp-Source: AGHT+IGbNYjoJmvw7/EAFFR6yRlHyK/7VJMiaWO4uxbwB6h5duhNecJNkKz38q3YB/sKzSfX6ckQPw== X-Received: by 2002:a17:902:e5cd:b0:20b:968e:2585 with SMTP id d9443c01a7336-20b968e285emr68828985ad.6.1727774226019; Tue, 01 Oct 2024 02:17:06 -0700 (PDT) Original-Received: from pebl ([2001:8003:7816:8300:7c58:853b:c371:cc01]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-20b37d5eda4sm66335205ad.48.2024.10.01.02.17.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Oct 2024 02:17:05 -0700 (PDT) In-Reply-To: <0d879e95-c37e-416d-b439-daa6384c4f30@gmx.at> (martin rudalics's message of "Mon, 30 Sep 2024 10:57:57 +0200") Received-SPF: pass client-ip=2001:4860:4864:20::2a; envelope-from=pranshusharma366@gmail.com; helo=mail-oa1-x2a.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: Tue, 01 Oct 2024 10:50:15 -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:324226 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 > > Lines should not exceed 80 characters and you probably want to use > 'cons' instead of 'list' here. > Done > > I think you should rename all these into something like > 'rotate-windows-anticlockwise' and 'transpose-windows' (we are already > using plurals in 'transpose-lines' and 'transpose-chars'). And we do > not rotate the entire frame - the minibuffer window stays in place, for > example. So I would try to say > > (defun rotate-windows-anticlockwise (&optional frame window) > "Rotate windows of FRAME anticlockwise by 90 degrees. > FRAME must be a live frame and defaults to the selected frame. By > default rotate the root window of FRAME (or its main window if it > differs from the root window). If WINDOW is non-nil ..." > > Which means that we need the additional features: > > (1) Rotate windows on any live frame. > > (2) Run the function on 'window-main-window' of FRAME unless WINDOW is > defined and never rotate a side window. Rotating side windows would > cause completely undefined behavior because their slots are expected to > never change. Hence, if WINDOW is specified and is a side window, say > that you cannot rotate side windows. > > (3) "subtree of selected window" is an undefined concept. You should > say something like "to transpose all windows in the same combination as > WINDOW" instead. But note that with a slightly more complex layout, no > average user will know what that combination is (think of C-x 2 C-x 3 > C-x o C-x o C-x 3). We could eventually try to flash all windows that > would be affected by the change but that would be non-trivial. > Done, I just said all 'windows of' instead. Also instead of seperate window and frame args, I just added added one window-or-frame arg. > I'd call this something like 'transpose-windows--rearrange' so you can > change its behavior whenever you want. > Yes, good idea > Is fwin not the same as what 'frame-first-window' returns? If not, > please telly why in a comment. It was, I just found out the function exists, thx > Please tell in a comment why you flatten win-tree her. > >> (flatten-list win-tree)) >> (toggle-window-split win-tree fwin conf norm-size) >> (select-window fwin)))) >> >> (defun toggle-window-split (subtree cwin conf norm-size) > > Should become window--... and have its arguments described. I just did as subroutine style, same as something like `window--atom-check-1'. > Here I'd write > > (let ((refer (seq-some > (lambda (x) > (and (windowp x) x)) > (flatten-list win)))) > (toggle-window-split > win (split-window cwin split-size split-type t refer) > conf norm-size)) > > but I won't argue about styles. Although this would be cleaner, but it means the instance of refer would be stored in memory unnecessarily while the old toggle-window-split would be going recursivly. > Whenever using things like cdddr, caaddr or caddr, please say in a > comment what these are supposed to be. You have condensed the original > version of your code considerably so please think about people who > eventually want to understand what the code does. > Yeah I did that, after all, I found out while doing this orignally how hard the code in in trasnpose-frame.el was to read. Well even without the comments(which I added now), the code is more readable now thanks you adding refer argument to split-window. --------------------------------------------- (defun window--subtree-with-size (window &optional next) "Like `window--subtree' but each window is replaced with the list: (WINDOW (PIXEL-HEIGHT . PIXEL-WIDTH)), and window-edges is replaced with the cons cell: (PIXEL-HEIGHT . PIXEL-WIDTH)." (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--subtree-with-size (window-top-child window) t)))) ((window-left-child window) (cons nil (cons (cons (window-pixel-height window) (window-pixel-width window)) (window--subtree-with-size (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 90 degrees anticlockwise. See `rotate-windows-clockwise' for more." (interactive `(,(and prefix-arg (window-parent (selected-window))))) (let ((window (if (windowp frame-or-window) frame-or-window (frame-root-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 from the root window of the frame, otherwise rotate from FRAME-OR-WINDOW." (interactive `(,(and prefix-arg (window-parent (selected-window))))) (let ((window (if (windowp frame-or-window) frame-or-window (frame-root-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. 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." (interactive `(,(and prefix-arg (window-parent (selected-window))))) (let ((window (if (windowp frame-or-window) frame-or-window (frame-root-window frame-or-window)))) (transpose-windows--rearrange window '(below . left) t))) (defun flip-windows-vertically (&optional frame-or-window) "Vertically flip windows of FRAME-OR-WINDOW. See `flip-windows-horizontally' for more." (interactive `(,(and prefix-arg (window-parent (selected-window))))) (let ((window (if (windowp frame-or-window) frame-or-window (frame-root-window frame-or-window)))) (transpose-windows--rearrange window '(above . right) t))) (defun transpose-windows (&optional frame-or-window) "Transpose windows of FRAME-OR-WINDOW. Windows are rearanged such that where an horizontal split was used, an vertical one is 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 from the root window of the frame, otherwise transpose from FRAME-OR-WINDOW." (interactive `(,(and prefix-arg (window-parent (selected-window))))) (let ((window (if (windowp frame-or-window) frame-or-window (frame-root-window frame-or-window)))) (transpose-windows--rearrange window '(right . below) nil))) (defun transpose-windows--rearrange (frame-or-window conf norm-size) "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. When is NORM-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." (let ((rwin (if (framep frame-or-window) (frame-root-window frame-root-window) frame-or-window))) (if (or (not rwin) (zerop (window-child-count rwin))) (message "Not enough windows") (let* ((fwin (frame-first-window rwin)) (selwin (frame-selected-window frame-or-window)) (win-tree (car (window--subtree-with-size rwin)))) ;; 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))) (transpose-windows--rearrange-1 win-tree fwin conf norm-size) ;; Go back to previously selected window. (select-window selwin))))) (defun transpose-windows--rearrange-1 (subtree cwin conf norm-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 norm-size size (round (* flen (/ size ilen)))))) (split-type (funcall (if (car subtree) 'car 'cdr) conf))) (if (listp win) ;; `win' is a window subtree. (transpose-windows--rearrange-1 win (split-window cwin split-size split-type t (seq-some (lambda (x) (and (windowp x) x)) (flatten-list win))) conf norm-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)) (transpose-windows--rearrange-1 (caddr subtree) cwin conf norm-size))))