Commit 67815c6b authored by Juri Linkov's avatar Juri Linkov

* 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)
parent 5b45c269
Pipeline #4242 failed with stage
in 90 minutes and 3 seconds
...@@ -23000,7 +23000,7 @@ To open the group buffer in a new tab named @samp{Gnus}, use: ...@@ -23000,7 +23000,7 @@ To open the group buffer in a new tab named @samp{Gnus}, use:
@lisp @lisp
(push '("\\`\\*Group\\*\\'" . (push '("\\`\\*Group\\*\\'" .
(display-buffer-in-tab (display-buffer-in-tab
(name . "Gnus"))) (tab-name . "Gnus")))
display-buffer-alist) display-buffer-alist)
@end lisp @end lisp
...@@ -23009,10 +23009,10 @@ To read every summary in a separate explicitly named tab, use: ...@@ -23009,10 +23009,10 @@ To read every summary in a separate explicitly named tab, use:
@lisp @lisp
(push '("\\`\\*Summary .*\\*\\'" . (push '("\\`\\*Summary .*\\*\\'" .
(display-buffer-in-tab (display-buffer-in-tab
(name . (lambda (buffer _alist) (tab-name . (lambda (buffer _alist)
(setq buffer (buffer-name buffer)) (setq buffer (buffer-name buffer))
(when (string-match "\\`\\*Summary \\(.*\\)\\*\\'" buffer) (when (string-match "\\`\\*Summary \\(.*\\)\\*\\'" buffer)
(format "Group %s" (match-string 1 buffer))))))) (format "Group %s" (match-string 1 buffer)))))))
display-buffer-alist) display-buffer-alist)
@end lisp @end lisp
...@@ -469,7 +469,7 @@ Return its existing value or a new value." ...@@ -469,7 +469,7 @@ Return its existing value or a new value."
(cdr (assq 'name tab)) (cdr (assq 'name tab))
(funcall tab-bar-tab-name-function))) (funcall tab-bar-tab-name-function)))
(explicit-name . ,tab-explicit-name) (explicit-name . ,tab-explicit-name)
(time . ,(time-convert nil 'integer)) (time . ,(float-time))
(ws . ,(window-state-get (ws . ,(window-state-get
(frame-root-window (or frame (selected-frame))) 'writable)) (frame-root-window (or frame (selected-frame))) 'writable))
(wc . ,(current-window-configuration)) (wc . ,(current-window-configuration))
...@@ -479,11 +479,11 @@ Return its existing value or a new value." ...@@ -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-back . ,(gethash (or frame (selected-frame)) tab-bar-history-back))
(wc-history-forward . ,(gethash (or frame (selected-frame)) tab-bar-history-forward))))) (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 ;; `tab` here is an argument meaning 'use tab as template'. This is
;; necessary when switching tabs, otherwise the destination tab ;; necessary when switching tabs, otherwise the destination tab
;; inherit the current tab's `explicit-name` parameter. ;; 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)))) (tab-explicit-name (cdr (assq 'explicit-name tab))))
`(current-tab `(current-tab
(name . ,(if tab-explicit-name (name . ,(if tab-explicit-name
...@@ -491,20 +491,20 @@ Return its existing value or a new value." ...@@ -491,20 +491,20 @@ Return its existing value or a new value."
(funcall tab-bar-tab-name-function))) (funcall tab-bar-tab-name-function)))
(explicit-name . ,tab-explicit-name)))) (explicit-name . ,tab-explicit-name))))
(defun tab-bar--current-tab-index (&optional tabs) (defun tab-bar--current-tab-index (&optional tabs frame)
(seq-position (or tabs (funcall tab-bar-tabs-function)) (seq-position (or tabs (funcall tab-bar-tabs-function frame))
'current-tab (lambda (a b) (eq (car a) b)))) 'current-tab (lambda (a b) (eq (car a) b))))
(defun tab-bar--tab-index (tab &optional tabs) (defun tab-bar--tab-index (tab &optional tabs frame)
(seq-position (or tabs (funcall tab-bar-tabs-function)) (seq-position (or tabs (funcall tab-bar-tabs-function frame))
tab)) tab #'eq))
(defun tab-bar--tab-index-by-name (name &optional tabs) (defun tab-bar--tab-index-by-name (name &optional tabs frame)
(seq-position (or tabs (funcall tab-bar-tabs-function)) (seq-position (or tabs (funcall tab-bar-tabs-function frame))
name (lambda (a b) (equal (cdr (assq 'name a)) b)))) name (lambda (a b) (equal (cdr (assq 'name a)) b))))
(defun tab-bar--tab-index-recent (nth &optional tabs) (defun tab-bar--tab-index-recent (nth &optional tabs frame)
(let* ((tabs (or tabs (funcall tab-bar-tabs-function))) (let* ((tabs (or tabs (funcall tab-bar-tabs-function frame)))
(sorted-tabs (sorted-tabs
(seq-sort-by (lambda (tab) (cdr (assq 'time tab))) #'> (seq-sort-by (lambda (tab) (cdr (assq 'time tab))) #'>
(seq-remove (lambda (tab) (seq-remove (lambda (tab)
...@@ -671,9 +671,10 @@ Interactively, ARG selects the ARGth different frame to move to." ...@@ -671,9 +671,10 @@ Interactively, ARG selects the ARGth different frame to move to."
(tab-bar--tab from-frame) (tab-bar--tab from-frame)
from-tab)) from-tab))
(nthcdr to-index to-tabs)) (nthcdr to-index to-tabs))
(let ((tab-bar-mode t) ; avoid message about deleted tab (with-selected-frame from-frame
tab-bar-closed-tabs) (let ((inhibit-message t) ; avoid message about deleted tab
(tab-bar-close-tab from-index)) tab-bar-closed-tabs)
(tab-bar-close-tab from-index)))
(set-frame-parameter to-frame 'tabs to-tabs) (set-frame-parameter to-frame 'tabs to-tabs)
(force-mode-line-update t)))) (force-mode-line-update t))))
...@@ -1276,7 +1277,7 @@ in the selected frame." ...@@ -1276,7 +1277,7 @@ in the selected frame."
(kill-buffer (current-buffer)) (kill-buffer (current-buffer))
;; Delete the current window configuration of tab list ;; Delete the current window configuration of tab list
;; without storing it in the undo list of closed tabs ;; 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-closed-tabs)
(tab-bar-close-tab nil (1+ (tab-bar--tab-index to-tab)))))) (tab-bar-close-tab nil (1+ (tab-bar--tab-index to-tab))))))
...@@ -1288,34 +1289,62 @@ in the selected frame." ...@@ -1288,34 +1289,62 @@ in the selected frame."
(tab-bar-list-select)) (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) (defun display-buffer-in-tab (buffer alist)
"Display BUFFER in a tab. "Display BUFFER in a tab.
ALIST is an association list of action symbols and values. See ALIST is an association list of action symbols and values. See
Info node `(elisp) Buffer Display Action Alists' for details of Info node `(elisp) Buffer Display Action Alists' for details of
such alists. 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 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 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. 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 This is an action function for buffer display, see Info
node `(elisp) Buffer Display Action Functions'. It should be node `(elisp) Buffer Display Action Functions'. It should be
called only by `display-buffer' or a function directly or called only by `display-buffer' or a function directly or
indirectly called by the latter." indirectly called by the latter."
(let ((name (cdr (assq 'name alist)))) (let* ((tab-name (alist-get 'tab-name alist))
(when (functionp name) (reusable-frames (alist-get 'reusable-frames alist))
(setq name (funcall name buffer alist))) (reusable-tab (when reusable-frames
(if name (tab-bar-get-buffer-tab buffer reusable-frames))))
(let ((tab-index (tab-bar--tab-index-by-name name))) (if reusable-tab
(if tab-index (let* ((frame (alist-get 'frame reusable-tab))
(tab-bar-select-tab (1+ tab-index)) (index (alist-get 'index reusable-tab)))
(let ((tab-bar-new-tab-choice t)) (when frame
(tab-bar-new-tab) (select-frame-set-input-focus frame))
(tab-bar-rename-tab name)))) (when index
(tab-bar-new-tab)))) (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) (defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames)
"Return a tab owning a window whose buffer is BUFFER-OR-NAME. "Return a tab owning a window whose buffer is BUFFER-OR-NAME.
...@@ -1336,39 +1365,34 @@ selected frame and no others." ...@@ -1336,39 +1365,34 @@ selected frame and no others."
(get-buffer buffer-or-name) (get-buffer buffer-or-name)
(current-buffer)))) (current-buffer))))
(when (bufferp buffer) (when (bufferp buffer)
(let ((frames (cond (seq-some
((eq all-frames t) (frame-list)) (lambda (frame)
((eq all-frames 'visible) (visible-frame-list)) (seq-some
((framep all-frames) (list all-frames)) (lambda (tab)
(t (list (selected-frame)))))) (when (if (eq (car tab) 'current-tab)
(seq-some (get-buffer-window buffer frame)
(lambda (frame) (let* ((state (cdr (assq 'ws tab)))
(seq-some (buffers (when state
(lambda (tab) (window-state-buffers state))))
(when (if (eq (car tab) 'current-tab) (or
(get-buffer-window buffer frame) ;; non-writable window-state
(let* ((state (cdr (assq 'ws tab))) (memq buffer buffers)
(buffers (when state ;; writable window-state
(window-state-buffers state)))) (member (buffer-name buffer) buffers))))
(or (append tab `((index . ,(tab-bar--tab-index tab nil frame))
;; non-writable window-state (frame . ,frame)))))
(memq buffer buffers) (funcall tab-bar-tabs-function frame)))
;; writable window-state (tab-bar--reusable-frames all-frames)))))
(member (buffer-name buffer) buffers))))
(append tab `((frame . ,frame)))))
(funcall tab-bar-tabs-function frame)))
frames)))))
(defun switch-to-buffer-other-tab (buffer-or-name &optional norecord) (defun switch-to-buffer-other-tab (buffer-or-name &optional norecord)
"Switch to buffer BUFFER-OR-NAME in another tab. "Switch to buffer BUFFER-OR-NAME in another tab.
Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab." Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab."
(interactive (interactive
(list (read-buffer-to-switch "Switch to buffer in other tab: "))) (list (read-buffer-to-switch "Switch to buffer in other tab: ")))
(let ((tab-bar-new-tab-choice t)) (display-buffer buffer-or-name '((display-buffer-in-tab
(tab-bar-new-tab)) display-buffer-same-window)
(delete-other-windows) (inhibit-same-window . nil))
(switch-to-buffer buffer-or-name norecord)) norecord))
(defun find-file-other-tab (filename &optional wildcards) (defun find-file-other-tab (filename &optional wildcards)
"Edit file FILENAME, in another tab. "Edit file FILENAME, in another tab.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment