From: Juri Linkov Date: Wed, 4 Dec 2019 22:56:54 +0000 (+0200) Subject: * lisp/tab-bar.el (switch-to-buffer-other-tab): Use display-buffer-in-tab. X-Git-Tag: emacs-27.0.90~439 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=67815c6bf2479eae5ad135782a1ce09a95734de8;p=emacs.git * lisp/tab-bar.el (switch-to-buffer-other-tab): Use display-buffer-in-tab. (tab-bar--tab): Use float-time instead of integer. This improves correct detection of recent tabs switched within 1 sec. (tab-bar--current-tab, tab-bar--current-tab-index) (tab-bar--tab-index, tab-bar--tab-index-by-name) (tab-bar--tab-index-recent): Add optional arg FRAME. (tab-bar-move-tab-to-frame): Add with-selected-frame for tab-bar-close-tab. (tab-bar--reusable-frames): New function. (tab-bar-get-buffer-tab): Add index to the found tab. (display-buffer-in-tab): Use `tab-name' entry instead of `name'. Add `reusable-frames' entry. (bug#38354) --- diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index d563d52d58d..22679e9832c 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -23000,7 +23000,7 @@ To open the group buffer in a new tab named @samp{Gnus}, use: @lisp (push '("\\`\\*Group\\*\\'" . (display-buffer-in-tab - (name . "Gnus"))) + (tab-name . "Gnus"))) display-buffer-alist) @end lisp @@ -23009,10 +23009,10 @@ To read every summary in a separate explicitly named tab, use: @lisp (push '("\\`\\*Summary .*\\*\\'" . (display-buffer-in-tab - (name . (lambda (buffer _alist) - (setq buffer (buffer-name buffer)) - (when (string-match "\\`\\*Summary \\(.*\\)\\*\\'" buffer) - (format "Group %s" (match-string 1 buffer))))))) + (tab-name . (lambda (buffer _alist) + (setq buffer (buffer-name buffer)) + (when (string-match "\\`\\*Summary \\(.*\\)\\*\\'" buffer) + (format "Group %s" (match-string 1 buffer))))))) display-buffer-alist) @end lisp diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 975b6d5d060..dc6d2d0b531 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -469,7 +469,7 @@ Return its existing value or a new value." (cdr (assq 'name tab)) (funcall tab-bar-tab-name-function))) (explicit-name . ,tab-explicit-name) - (time . ,(time-convert nil 'integer)) + (time . ,(float-time)) (ws . ,(window-state-get (frame-root-window (or frame (selected-frame))) 'writable)) (wc . ,(current-window-configuration)) @@ -479,11 +479,11 @@ Return its existing value or a new value." (wc-history-back . ,(gethash (or frame (selected-frame)) tab-bar-history-back)) (wc-history-forward . ,(gethash (or frame (selected-frame)) tab-bar-history-forward))))) -(defun tab-bar--current-tab (&optional tab) +(defun tab-bar--current-tab (&optional tab frame) ;; `tab` here is an argument meaning 'use tab as template'. This is ;; necessary when switching tabs, otherwise the destination tab ;; inherit the current tab's `explicit-name` parameter. - (let* ((tab (or tab (assq 'current-tab (frame-parameter nil 'tabs)))) + (let* ((tab (or tab (assq 'current-tab (frame-parameter frame 'tabs)))) (tab-explicit-name (cdr (assq 'explicit-name tab)))) `(current-tab (name . ,(if tab-explicit-name @@ -491,20 +491,20 @@ Return its existing value or a new value." (funcall tab-bar-tab-name-function))) (explicit-name . ,tab-explicit-name)))) -(defun tab-bar--current-tab-index (&optional tabs) - (seq-position (or tabs (funcall tab-bar-tabs-function)) +(defun tab-bar--current-tab-index (&optional tabs frame) + (seq-position (or tabs (funcall tab-bar-tabs-function frame)) 'current-tab (lambda (a b) (eq (car a) b)))) -(defun tab-bar--tab-index (tab &optional tabs) - (seq-position (or tabs (funcall tab-bar-tabs-function)) - tab)) +(defun tab-bar--tab-index (tab &optional tabs frame) + (seq-position (or tabs (funcall tab-bar-tabs-function frame)) + tab #'eq)) -(defun tab-bar--tab-index-by-name (name &optional tabs) - (seq-position (or tabs (funcall tab-bar-tabs-function)) +(defun tab-bar--tab-index-by-name (name &optional tabs frame) + (seq-position (or tabs (funcall tab-bar-tabs-function frame)) name (lambda (a b) (equal (cdr (assq 'name a)) b)))) -(defun tab-bar--tab-index-recent (nth &optional tabs) - (let* ((tabs (or tabs (funcall tab-bar-tabs-function))) +(defun tab-bar--tab-index-recent (nth &optional tabs frame) + (let* ((tabs (or tabs (funcall tab-bar-tabs-function frame))) (sorted-tabs (seq-sort-by (lambda (tab) (cdr (assq 'time tab))) #'> (seq-remove (lambda (tab) @@ -671,9 +671,10 @@ Interactively, ARG selects the ARGth different frame to move to." (tab-bar--tab from-frame) from-tab)) (nthcdr to-index to-tabs)) - (let ((tab-bar-mode t) ; avoid message about deleted tab - tab-bar-closed-tabs) - (tab-bar-close-tab from-index)) + (with-selected-frame from-frame + (let ((inhibit-message t) ; avoid message about deleted tab + tab-bar-closed-tabs) + (tab-bar-close-tab from-index))) (set-frame-parameter to-frame 'tabs to-tabs) (force-mode-line-update t)))) @@ -1276,7 +1277,7 @@ in the selected frame." (kill-buffer (current-buffer)) ;; Delete the current window configuration of tab list ;; without storing it in the undo list of closed tabs - (let ((tab-bar-mode t) ; avoid message about deleted tab + (let ((inhibit-message t) ; avoid message about deleted tab tab-bar-closed-tabs) (tab-bar-close-tab nil (1+ (tab-bar--tab-index to-tab)))))) @@ -1288,34 +1289,62 @@ in the selected frame." (tab-bar-list-select)) +(defun tab-bar--reusable-frames (all-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))))) + (defun display-buffer-in-tab (buffer alist) "Display BUFFER in a tab. ALIST is an association list of action symbols and values. See Info node `(elisp) Buffer Display Action Alists' for details of such alists. -If ALIST contains a `name' entry, it creates a new tab with that name and +If ALIST contains a `tab-name' entry, it creates a new tab with that name and displays BUFFER in a new tab. If a tab with this name already exists, it -switches to that tab before displaying BUFFER. The `name' entry can be +switches to that tab before displaying BUFFER. The `tab-name' entry can be a function, then it is called with two arguments: BUFFER and ALIST, and -should return the tab name. When a `name' entry is omitted, create +should return the tab name. When a `tab-name' entry is omitted, create a new tab without an explicit name. +If ALIST contains a `reusable-frames' entry, its value determines +which frames to search for a reusable tab: + nil -- the selected frame (actually the last non-minibuffer frame) + A frame -- just that frame + `visible' -- all visible frames + 0 -- all frames on the current terminal + t -- all frames. + This is an action function for buffer display, see Info node `(elisp) Buffer Display Action Functions'. It should be called only by `display-buffer' or a function directly or indirectly called by the latter." - (let ((name (cdr (assq 'name alist)))) - (when (functionp name) - (setq name (funcall name buffer alist))) - (if name - (let ((tab-index (tab-bar--tab-index-by-name name))) - (if tab-index - (tab-bar-select-tab (1+ tab-index)) - (let ((tab-bar-new-tab-choice t)) - (tab-bar-new-tab) - (tab-bar-rename-tab name)))) - (tab-bar-new-tab)))) + (let* ((tab-name (alist-get 'tab-name alist)) + (reusable-frames (alist-get 'reusable-frames alist)) + (reusable-tab (when reusable-frames + (tab-bar-get-buffer-tab buffer reusable-frames)))) + (if reusable-tab + (let* ((frame (alist-get 'frame reusable-tab)) + (index (alist-get 'index reusable-tab))) + (when frame + (select-frame-set-input-focus frame)) + (when index + (tab-bar-select-tab (1+ index))) + (when (get-buffer-window buffer frame) + (select-window (get-buffer-window buffer frame)))) + (when (functionp tab-name) + (setq tab-name (funcall tab-name buffer alist))) + (if tab-name + (let ((tab-index (tab-bar--tab-index-by-name tab-name))) + (if tab-index + (tab-bar-select-tab (1+ tab-index)) + (let ((tab-bar-new-tab-choice t)) + (tab-bar-new-tab) + (tab-bar-rename-tab tab-name)))) + (let ((tab-bar-new-tab-choice t)) + (tab-bar-new-tab)))))) (defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames) "Return a tab owning a window whose buffer is BUFFER-OR-NAME. @@ -1336,39 +1365,34 @@ selected frame and no others." (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) - (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 - ;; non-writable window-state - (memq buffer buffers) - ;; writable window-state - (member (buffer-name buffer) buffers)))) - (append tab `((frame . ,frame))))) - (funcall tab-bar-tabs-function frame))) - frames))))) + (seq-some + (lambda (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 + ;; non-writable window-state + (memq buffer buffers) + ;; writable window-state + (member (buffer-name buffer) buffers)))) + (append tab `((index . ,(tab-bar--tab-index tab nil frame)) + (frame . ,frame))))) + (funcall tab-bar-tabs-function frame))) + (tab-bar--reusable-frames all-frames))))) - (defun switch-to-buffer-other-tab (buffer-or-name &optional norecord) "Switch to buffer BUFFER-OR-NAME in another tab. Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab." (interactive (list (read-buffer-to-switch "Switch to buffer in other tab: "))) - (let ((tab-bar-new-tab-choice t)) - (tab-bar-new-tab)) - (delete-other-windows) - (switch-to-buffer buffer-or-name norecord)) + (display-buffer buffer-or-name '((display-buffer-in-tab + display-buffer-same-window) + (inhibit-same-window . nil)) + norecord)) (defun find-file-other-tab (filename &optional wildcards) "Edit file FILENAME, in another tab.