diff options
-rw-r--r-- | doc/emacs/frames.texi | 6 | ||||
-rw-r--r-- | lisp/tab-bar.el | 91 |
2 files changed, 65 insertions, 32 deletions
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index f6c2d239132..3a98df7de9d 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -1302,9 +1302,9 @@ variable @code{tab-bar-tab-name-function}. @end table @vindex tab-bar-new-tab-choice - By default, a new tab starts with the current buffer that was -current before calling the command that adds a new tab. To start a -new tab with other buffers, customize the variable + By default, a new tab starts with the buffer that was +current before calling the command that adds a new tab. +To start a new tab with other buffers, customize the variable @code{tab-bar-new-tab-choice}. The following commands are used to delete and operate on tabs: diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index a36be13e37b..975b6d5d060 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -243,7 +243,7 @@ keyboard commands `tab-list', `tab-new', `tab-close', `tab-next', etc." If t, start a new tab with the current buffer, i.e. the buffer that was current before calling the command that adds a new tab (this is the same what `make-frame' does by default). -If the value is a string, use it as a buffer name switch to a buffer +If the value is a string, use it as a buffer name to switch to if such buffer exists, or switch to a buffer visiting the file or directory that the string specifies. If the value is a function, call it with no arguments and switch to the buffer that it returns. @@ -348,17 +348,19 @@ Also add the number of windows in the window configuration." (defvar tab-bar-tabs-function #'tab-bar-tabs "Function to get a list of tabs to display in the tab bar. -This function should return a list of alists with parameters +This function should have one optional argument FRAME, +defaulting to the selected frame when nil. +It should return a list of alists with parameters that include at least the element (name . TAB-NAME). For example, \\='((tab (name . \"Tab 1\")) (current-tab (name . \"Tab 2\"))) By default, use function `tab-bar-tabs'.") -(defun tab-bar-tabs () +(defun tab-bar-tabs (&optional frame) "Return a list of tabs belonging to the selected frame. Ensure the frame parameter `tabs' is pre-populated. Update the current tab name when it exists. Return its existing value or a new value." - (let ((tabs (frame-parameter nil 'tabs))) + (let ((tabs (frame-parameter frame 'tabs))) (if tabs (let* ((current-tab (assq 'current-tab tabs)) (current-tab-name (assq 'name current-tab)) @@ -370,7 +372,7 @@ Return its existing value or a new value." (funcall tab-bar-tab-name-function)))) ;; Create default tabs (setq tabs (list (tab-bar--current-tab))) - (set-frame-parameter nil 'tabs tabs)) + (set-frame-parameter frame 'tabs tabs)) tabs)) @@ -457,11 +459,11 @@ Return its existing value or a new value." (push '(tabs . frameset-filter-tabs) frameset-filter-alist) -(defun tab-bar--tab () - (let* ((tab (assq 'current-tab (frame-parameter nil 'tabs))) +(defun tab-bar--tab (&optional frame) + (let* ((tab (assq 'current-tab (frame-parameter frame 'tabs))) (tab-explicit-name (cdr (assq 'explicit-name tab))) - (bl (seq-filter #'buffer-live-p (frame-parameter nil 'buffer-list))) - (bbl (seq-filter #'buffer-live-p (frame-parameter nil 'buried-buffer-list)))) + (bl (seq-filter #'buffer-live-p (frame-parameter frame 'buffer-list))) + (bbl (seq-filter #'buffer-live-p (frame-parameter frame 'buried-buffer-list)))) `(tab (name . ,(if tab-explicit-name (cdr (assq 'name tab)) @@ -469,13 +471,13 @@ Return its existing value or a new value." (explicit-name . ,tab-explicit-name) (time . ,(time-convert nil 'integer)) (ws . ,(window-state-get - (frame-root-window (selected-frame)) 'writable)) + (frame-root-window (or frame (selected-frame))) 'writable)) (wc . ,(current-window-configuration)) (wc-point . ,(point-marker)) (wc-bl . ,bl) (wc-bbl . ,bbl) - (wc-history-back . ,(gethash (selected-frame) tab-bar-history-back)) - (wc-history-forward . ,(gethash (selected-frame) tab-bar-history-forward))))) + (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) ;; `tab` here is an argument meaning 'use tab as template'. This is @@ -645,6 +647,36 @@ If a negative ARG, move the current tab ARG positions to the left." (to-index (mod (+ from-index arg) (length tabs)))) (tab-bar-move-tab-to (1+ to-index) (1+ from-index)))) +(defun tab-bar-move-tab-to-frame (arg &optional from-frame from-index to-frame to-index) + "Move tab from FROM-INDEX position to new position at TO-INDEX. +FROM-INDEX defaults to the current tab index. +FROM-INDEX and TO-INDEX count from 1. +FROM-FRAME specifies the source frame and defaults to the selected frame. +TO-FRAME specifies the target frame and defaults the next frame. +Interactively, ARG selects the ARGth different frame to move to." + (interactive "P") + (unless from-frame + (setq from-frame (selected-frame))) + (unless to-frame + (dotimes (_ (prefix-numeric-value arg)) + (setq to-frame (next-frame to-frame)))) + (unless (eq from-frame to-frame) + (let* ((from-tabs (funcall tab-bar-tabs-function from-frame)) + (from-index (or from-index (1+ (tab-bar--current-tab-index from-tabs)))) + (from-tab (nth (1- from-index) from-tabs)) + (to-tabs (funcall tab-bar-tabs-function to-frame)) + (to-index (max 0 (min (1- (or to-index 1)) (1- (length to-tabs)))))) + (cl-pushnew (assq-delete-all + 'wc (if (eq (car from-tab) 'current-tab) + (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)) + (set-frame-parameter to-frame 'tabs to-tabs) + (force-mode-line-update t)))) + (defcustom tab-bar-new-tab-to 'right "Defines where to create a new tab. @@ -1286,7 +1318,7 @@ indirectly called by the latter." (tab-bar-new-tab)))) (defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames) - "Return a tab whose window contains BUFFER-OR-NAME, or nil if none. + "Return a tab owning a window whose buffer is BUFFER-OR-NAME. BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the current buffer. @@ -1309,22 +1341,23 @@ selected frame and no others." ((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 - ;; non-writable window-state - (memq buffer buffers) - ;; writable window-state - (member (buffer-name buffer) buffers)))) - (append tab `((frame . ,frame))))) - (funcall tab-bar-tabs-function)))) - 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 `((frame . ,frame))))) + (funcall tab-bar-tabs-function frame))) + frames))))) (defun switch-to-buffer-other-tab (buffer-or-name &optional norecord) |