From 99750f9fdff60110e8289b2ba975b10df62462bf Mon Sep 17 00:00:00 2001 From: Phil Sainty Date: Mon, 29 Dec 2025 21:53:00 +1300 Subject: [PATCH] Improve documentation for tab-bar buffer display actions (bug#80092) * doc/lispref/windows.texi: Document the display actions `display-buffer-in-tab' and `display-buffer-in-new-tab' and the associated alist entries `tab-name' and `tab-group'. * lisp/tab-bar.el (display-buffer-in-tab): Restructure docstring for clarity. Describe the `reusable-frames' behaviour first (as if it finds a frame with a suitable tab then the `tab-name' entry is not used). (display-buffer-in-new-tab): Use consistent wording. * lisp/window.el (display-buffer--action-function-custom-type): Add the display actions as customize choices for user options. (display-buffer): Document the display actions and alist entries. --- doc/lispref/windows.texi | 81 ++++++++++++++++++++++++++++++++++++++++ lisp/tab-bar.el | 65 +++++++++++++++++++------------- lisp/window.el | 8 ++++ 3 files changed, 128 insertions(+), 26 deletions(-) diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index c659ec8edc8..dd0d925ed7e 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -3549,6 +3549,70 @@ the selected window is not used; thus if the selected frame has a single window, it is not used. @end defun +@defun display-buffer-in-new-tab buffer alist +This function tries to display @var{buffer} in a new tab. + +If @var{alist} contains a non-@code{nil} @code{tab-name} entry (which +may be a string or a function), the buffer is displayed in a new tab +with that name. If the @code{tab-name} entry is a function, it is +called with two arguments (@var{buffer} and @var{alist}), and should +return the tab name. + +If the @code{tab-name} entry is omitted or @code{nil}, a new tab is +created without an explicit name. + +If @var{alist} contains a non-@code{nil} @code{tab-group} entry, this +defines the tab group, overriding user option +@code{tab-bar-new-tab-group}. This entry may again be a string or a +function which is called in the same manner as @code{tab-name}. +@end defun + +@defun display-buffer-in-tab buffer alist +This function tries to display @var{buffer} in a new or existing tab. + +If @var{alist} contains a non-@code{nil} @code{reusable-frames} entry +then the frames indicated by its value are searched for an existing tab +which already displays the buffer. The possible values of +@code{reusable-frames} are: + +@itemize @bullet +@item @code{t} +means consider all existing frames. +@item @code{visible} +means consider all visible frames. +@item A frame +means consider that frame only. +@item Any other non-@code{nil} value +means consider the selected frame. +@item @code{nil} +means do not search any frames (equivalent to omitting the entry). Note +that this is different to the typical meaning of the value @code{nil} +for a @code{reusable-frames} entry in a buffer display action alist. +@end itemize + +If @var{alist} contains a non-@code{nil} @code{ignore-current-tab} +entry, then the current tab is skipped when searching for a reusable +tab. Otherwise the current tab is used by preference if it already +displays the buffer. + +If a window displaying the buffer is located in any reusable tab then +that tab and window are selected. + +If no such window is located, the buffer is displayed in a new or +existing tab based on the @var{alist} entry @code{tab-name} (which may +be a string or a function). If a tab with this name already exists then +that tab is selected, otherwise a new tab with that name is created. If +the @code{tab-name} entry is a function, it is called with two arguments +(@var{buffer} and @var{alist}), and should return the tab name. If the +@code{tab-name} entry is omitted or @code{nil}, a new tab is created +without an explicit name. + +If a new tab is created and @var{alist} contains a non-@code{nil} +@code{tab-group} entry, this defines the tab group, overriding user +option @code{tab-bar-new-tab-group}. This entry may again be a string +or a function which is called in the same manner as @code{tab-name}. +@end defun + @defun display-buffer-no-window buffer alist If @var{alist} has a non-@code{nil} @code{allow-no-window} entry, then this function does not display @var{buffer} and returns the symbol @@ -3661,6 +3725,10 @@ well. @code{display-buffer-in-previous-window} consults it when searching for a window that previously displayed the buffer on another frame. +Action function @code{display-buffer-in-tab} searches the tabs of the +frame(s) identified by this entry, and also interprets the value +@code{nil} differently. + @vindex inhibit-switch-frame@r{, a buffer display action alist entry} @item inhibit-switch-frame A non-@code{nil} value prevents another frame from being raised or @@ -3981,6 +4049,19 @@ List, @code{buffer-match-p}}. Thus, if a Lisp program uses a particular @var{symbol} as the category when calling @code{display-buffer}, users can customize how these buffers will be displayed by including such an entry in @code{display-buffer-alist}. + +@vindex tab-name@r{, a buffer display action alist entry} +@item tab-name +The value names the tab in which the buffer should be displayed. This +entry is used by @code{display-buffer-in-new-tab} and (conditionally) by +@code{display-buffer-in-tab}. + +@vindex tab-group@r{, a buffer display action alist entry} +@vindex tab-bar-new-tab-group@r{, override for buffer display actions} +@item tab-group +The value names the tab group to use when creating a new tab, overriding +user option @code{tab-bar-new-tab-group}. This entry is used by +@code{display-buffer-in-new-tab} and @code{display-buffer-in-tab}. @end table By convention, the entries @code{window-height}, @code{window-width} diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 680edae95f1..5c63de5e39f 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -2935,27 +2935,39 @@ 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 `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 `tab-name' entry can be -a function, in which case it is called with two arguments: BUFFER and ALIST, -and should return the tab name. When a `tab-name' entry is omitted, create -a new tab without an explicit name. +If ALIST contains a non-nil `reusable-frames' entry then the frames +indicated by its value are searched for an existing tab which already +displays BUFFER. The possible values of `reusable-frames' are: -The ALIST entry `tab-group' (string or function) defines the tab group. - -If ALIST contains a `reusable-frames' entry, its value determines -which frames to search for a reusable tab: - nil -- do not reuse any frames; - a frame -- just that frame; + t -- all existing frames; `visible' -- all visible frames; - 0 -- all frames on the current terminal; - t -- all frames; - other non-nil values -- use the selected frame. + A frame -- that frame only; + Any other non-nil value -- the selected frame; + nil -- do not search any frames (equivalent to omitting the entry). -If ALIST contains a non-nil `ignore-current-tab' entry, then the buffers -of the current tab are skipped when searching for a reusable tab. -Otherwise, prefer buffers of the current tab. +\(Note that the meaning of nil is different to the typical meaning of +nil for a `reusable-frames' entry in a buffer display action alist.) + +If ALIST contains a non-nil `ignore-current-tab' entry then skip the +current tab when searching for a reusable tab, otherwise prefer the +current tab if it already displays BUFFER. + +If a window displaying BUFFER is located in any reusable tab, select +that tab and window. + +If no such window is located, display BUFFER in a new or existing tab +based on the ALIST entry `tab-name' (string or function). If a tab with +this name already exists then select that tab, otherwise create a new +tab with this name. If `tab-name' is a function it is called with two +arguments (BUFFER and ALIST) and should return the tab name. If +`tab-name' is omitted or nil, create a new tab without an explicit name. + +If a new tab is created and ALIST contains a non-nil `tab-group' entry +\(string or function), this defines the tab group, overriding user +option `tab-bar-new-tab-group'. + +To create a new tab unconditionally, use `display-buffer-in-new-tab' +instead. This is an action function for buffer display, see Info node `(elisp) Buffer Display Action Functions'. It should be @@ -2994,16 +3006,17 @@ ALIST is an association list of action symbols and values. See Info node `(elisp) Buffer Display Action Alists' for details of such alists. -Like `display-buffer-in-tab', but always creates a new tab unconditionally, -without checking if a suitable tab already exists. +If ALIST contains a non-nil `tab-name' entry (string or function) then +display BUFFER in a new tab with this name. If `tab-name' is a function +it is called with two arguments (BUFFER and ALIST) and should return the +tab name. If `tab-name' is omitted or nil, create a new tab without an +explicit name. -If ALIST contains a `tab-name' entry, it creates a new tab with that name -and displays BUFFER in a new tab. The `tab-name' entry can be a function, -in which case it is called with two arguments: BUFFER and ALIST, and should -return the tab name. When a `tab-name' entry is omitted, create a new tab -without an explicit name. +If ALIST contains a non-nil `tab-group' entry (string or function), this +defines the tab group, overriding user option `tab-bar-new-tab-group'. -The ALIST entry `tab-group' (string or function) defines the tab group. +To check for a suitable existing tab to reuse before creating a new tab, +use `display-buffer-in-tab' instead. This is an action function for buffer display, see Info node `(elisp) Buffer Display Action Functions'. It should be diff --git a/lisp/window.el b/lisp/window.el index 6b08706b9ac..df404083b32 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -7999,6 +7999,8 @@ See the info node `(elisp)Dedicated Windows' for more details." (const display-buffer-use-least-recent-window) (const display-buffer-use-some-window) (const display-buffer-use-some-frame) + (const display-buffer-in-tab) + (const display-buffer-in-new-tab) (function :tag "Other function")) "Custom type for `display-buffer' action functions.") @@ -8147,6 +8149,8 @@ to an expression containing one of these \"action\" functions: `display-buffer-pop-up-frame' -- Show the buffer on a new frame. `display-buffer-in-child-frame' -- Show the buffer in a child frame. + `display-buffer-in-tab' -- Use an appropriate existing tab or a new tab. + `display-buffer-in-new-tab' -- Use a new tab. `display-buffer-no-window' -- Do not display the buffer and have `display-buffer' return nil immediately. @@ -8310,6 +8314,10 @@ Action alist entries are: `(category . symbol)' in its action argument, then you can match the displayed buffer by using the same category in the condition part of `display-buffer-alist' entries. + ‘tab-name’ -- If non-nil, specifies the name of the tab in which to + display the buffer; see `display-buffer-in-new-tab'. + \\+‘tab-group’ -- If non-nil, specifies the tab group to use when creating + a new tab; see ‘display-buffer-in-new-tab’. The entries `window-height', `window-width', `window-size' and `preserve-size' are applied only when the window used for