From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.bugs Subject: bug#38354: 27.0.50; Implement display action display-buffer-in-tab Date: Mon, 02 Dec 2019 00:29:35 +0200 Organization: LINKOV.NET Message-ID: <87lfrvk7cg.fsf@mail.linkov.net> References: <87imna2nsi.fsf@mail.linkov.net> <8736ea5kcz.fsf@mail.linkov.net> <7979be54-2a01-2e97-d956-2500e7999e26@gmx.at> <87d0dd3yb7.fsf@mail.linkov.net> <87r21r389g.fsf@mail.linkov.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="262659"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (x86_64-pc-linux-gnu) Cc: 38354@debbugs.gnu.org To: martin rudalics Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sun Dec 01 23:50:30 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1ibY2u-0016CH-UW for geb-bug-gnu-emacs@m.gmane.org; Sun, 01 Dec 2019 23:50:29 +0100 Original-Received: from localhost ([::1]:56426 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ibY2t-0003Ae-Q1 for geb-bug-gnu-emacs@m.gmane.org; Sun, 01 Dec 2019 17:50:27 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:33802) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ibXzm-0000xS-8B for bug-gnu-emacs@gnu.org; Sun, 01 Dec 2019 17:47:21 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ibXzd-0005EP-3m for bug-gnu-emacs@gnu.org; Sun, 01 Dec 2019 17:47:09 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:59110) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ibXza-0005CW-6g for bug-gnu-emacs@gnu.org; Sun, 01 Dec 2019 17:47:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ibXza-00021h-53 for bug-gnu-emacs@gnu.org; Sun, 01 Dec 2019 17:47:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Juri Linkov Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 01 Dec 2019 22:47:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 38354 X-GNU-PR-Package: emacs Original-Received: via spool by 38354-submit@debbugs.gnu.org id=B38354.15752403747707 (code B ref 38354); Sun, 01 Dec 2019 22:47:02 +0000 Original-Received: (at 38354) by debbugs.gnu.org; 1 Dec 2019 22:46:14 +0000 Original-Received: from localhost ([127.0.0.1]:36846 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ibXyn-00020E-Uf for submit@debbugs.gnu.org; Sun, 01 Dec 2019 17:46:14 -0500 Original-Received: from beige.elm.relay.mailchannels.net ([23.83.212.16]:2690) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ibXyl-000202-7W for 38354@debbugs.gnu.org; Sun, 01 Dec 2019 17:46:12 -0500 X-Sender-Id: dreamhost|x-authsender|jurta@jurta.org Original-Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id E824E501673; Sun, 1 Dec 2019 22:46:09 +0000 (UTC) Original-Received: from pdx1-sub0-mail-a71.g.dreamhost.com (100-96-14-7.trex.outbound.svc.cluster.local [100.96.14.7]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 7E7DA5011F2; Sun, 1 Dec 2019 22:46:09 +0000 (UTC) X-Sender-Id: dreamhost|x-authsender|jurta@jurta.org Original-Received: from pdx1-sub0-mail-a71.g.dreamhost.com ([TEMPUNAVAIL]. [64.90.62.162]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384) by 0.0.0.0:2500 (trex/5.18.5); Sun, 01 Dec 2019 22:46:09 +0000 X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|jurta@jurta.org X-MailChannels-Auth-Id: dreamhost X-Trade-Snatch: 0ebf381914d89c1e_1575240369763_1246949943 X-MC-Loop-Signature: 1575240369763:2016216471 X-MC-Ingress-Time: 1575240369763 Original-Received: from pdx1-sub0-mail-a71.g.dreamhost.com (localhost [127.0.0.1]) by pdx1-sub0-mail-a71.g.dreamhost.com (Postfix) with ESMTP id 065659689E; Sun, 1 Dec 2019 14:46:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=linkov.net; h=from:to:cc :subject:references:date:in-reply-to:message-id:mime-version :content-type; s=linkov.net; bh=A92JfO+IY2tofySNms1/B/R2WAU=; b= QXSRXvx0tLte+fzTqksLVHgR9ehe6+CJWp7mgP4JGYJzek5SCAIJxvVylXapGSJq uWEWlLkkYk5Ubtt6Rqb9OkYLZPBCQdjsetwHCYI+YsGI1AlOEDbr5E2wkaYzYEEk S9iU7mS8/L9qbUWYZe7DQvIFy4ltSklPh3NqOvY3fNs= Original-Received: from mail.jurta.org (m91-129-96-42.cust.tele2.ee [91.129.96.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: jurta@jurta.org) by pdx1-sub0-mail-a71.g.dreamhost.com (Postfix) with ESMTPSA id 8BB46968BF; Sun, 1 Dec 2019 14:46:01 -0800 (PST) X-DH-BACKEND: pdx1-sub0-mail-a71 In-Reply-To: (martin rudalics's message of "Fri, 29 Nov 2019 10:24:29 +0100") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:172739 Archived-At: --=-=-= Content-Type: text/plain >>>> (tab-bar-buffer-visible-in-tabs-p buffer) >>> >>> But this may also return non-nil when the buffer is invisible, that is >>> not shown in any window. We already have the "visible frames" >>> notation, including the non-obscured frames connotation, so I'd rather >>> not use the term visible in the context of tabs. >> >> Maybe like having the terms "visible frame" and "iconified frame", >> we should use the terms "current tab" and "inactive tabs". > > IIUC, during one and the same session any tab is frame-local, can be > shown only on one and the same frame. Deleting a frame kills its tabs > too, due to our implementation of window configurations. Right? Right. > If so, then we should decide whether we always want to stick to that > limitation or, eventually allow moving tabs between frames, probably > using window states for that purpose. And we have to decide whether > such moving of a tab would mean making a completely self-reliant copy > of it or keep properties of it shared among frames. And eventually we > should decide whether tabs could become first-class citizens - have a > life of their own without being attached to any frame. There are two separate cases to consider: 1. Moving an inactive tab to another frame. In this case we need to use its window-state, not window-configuration, i.e. just delete the window-configuration from tab data, then it could be moved to another frame without problems. 2. Moving the current tab to another frame. Here we need to save window-configuration of another frame to its inactive tab, then clone the original frame to another frame. Do you know if such a function already exists that duplicates all frame parameters with frame-root window-state to another frame? An additional question to consider is how to interactively select an another frame: by frame name, or using other-frame with a numeric prefix argument? > Once we have decided on what to do here, we can try finding an > appropriate nomenclature. That is, for each tab we can then either > find a function called 'tab-frame' (to return its one and only frame) > or 'tab-frame-list' (to return a possibly empty list of all frames > that currently have that tab in their tab-bar). For each frame, we > should use 'frame-tab(s)-list' for returning all tabs in their > tab-bar, 'frame-selected|current|active-tab' for returning the tab > currently shown on that frame. Maybe we could use a fitting > ALL-FRAMES arguments to return all tabs in tab-bars of all visible, > visible or iconified, ... frames with a function called 'tab(s)-list' > or the like. I think a tab should know nothing about the frame where it belongs, otherwise it would complicate the matter (e.g. saving to the desktop). The code that operates on tabs should follow the data hierarchy starting from frames then accessing tabs from each frame, i.e. we should never have a dangling tab from which to ask where is its frame. But code that returns the tab could add a parameter frame to the returned tab like in the patch below. >>> Wouldn't something like 'tab-bar-buffer-present-in-tabs-p' or >>> 'tab-bar-buffer-in-tabs-p' be more intuitive? >> >> Instead of suffix '-p' that assumes the function returns a boolean value, >> better to return the found tab with the function name 'tab-bar-buffer-in-tab'. > > Sure. You just have to decide here and now on the arguments of that > function: Which tabs to search for the buffer? A better function is implemented below: tab-bar-get-buffer-tab takes the function name, arguments and docstring from get-buffer-window. >>>>> 'display-buffer-reuse-window' together with 'reusable-frames' should >>>>> have all the ingredients for this. What is missing? >>>> >>>> Than we need to add 'reusable-tabs'? >>> >>> Why? If a target tab (a tab with the name specified by ALIST) exists >>> on any frame specified by 'reusable-frames', reuse it. Otherwise make >>> a new frame with the target tab as its only entry. >> >> I don't understand. Should ALIST look like this? >> >> (push '("test1" . >> ((display-buffer-reuse-window display-buffer-in-tab) >> (reusable-frames . visible) >> (name . "Tab1"))) >> display-buffer-alist) > > What would be the downside of it? The 'reusable-frames' would specify > the list of frames to investigate - the other dimension you mentioned > above. We need an alist entry that will tell display-buffer-reuse-window to search in tabs. Maybe just the presence of the 'use-tabs' param will tell display-buffer-reuse-window to search in tabs like: (push '("test1" . (display-buffer-reuse-window (reusable-frames . visible) (use-tabs . t))) display-buffer-alist) > BTW: In the manual you write: > > By default, a new tab starts with the current buffer that was current > before calling the command that adds a new tab. > > That's confusing, at least. Maybe this is better? By default, a new tab starts with the buffer that was current before calling the command that adds a new tab. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=tab-bar-get-buffer-tab.patch diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 5eb332884c..af993637a6 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -1284,6 +1284,44 @@ display-buffer-in-tab (tab-bar-rename-tab name)))) (tab-bar-new-tab)))) +(defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames) + "Return a tab currently displaying BUFFER-OR-NAME, or nil if none. +BUFFER-OR-NAME may be a buffer or a buffer name and defaults to +the current buffer. + +The optional argument ALL-FRAMES specifies the frames to consider: + +- t means consider all tabs on all existing frames. + +- `visible' means consider all tabs on all visible frames. + +- A frame means consider all tabs on that frame only. + +Any other value of ALL-FRAMES means consider all tabs on the +selected frame and no others." + (let ((buffer (if buffer-or-name + (get-buffer buffer-or-name) + (current-buffer)))) + (when (bufferp buffer) + (let ((frames (cond + ((eq all-frames t) (frame-list)) + ((eq all-frames 'visible) (visible-frame-list)) + ((framep all-frames) (list all-frames)) + (t (list (selected-frame)))))) + (seq-some (lambda (frame) + (with-selected-frame frame + (seq-some (lambda (tab) + (when (if (eq (car tab) 'current-tab) + (get-buffer-window buffer frame) + (let* ((state (cdr (assq 'ws tab))) + (buffers (when state + (window-state-buffers state)))) + (or (memq buffer buffers) + (member (buffer-name buffer) buffers)))) + (append tab `((frame . ,frame))))) + (funcall tab-bar-tabs-function)))) + frames))))) + (defun switch-to-buffer-other-tab (buffer-or-name &optional norecord) "Switch to buffer BUFFER-OR-NAME in another tab. --=-=-=--