From 76938e1789ecf447507199b6f1b7c0d4f7924ea3 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Mon, 28 Aug 2023 19:57:16 +0300 Subject: [PATCH] * lisp/tab-bar.el: Add tab-bar-tab-name-format-functions (bug#65554) (tab-bar-tab-name-format-truncated) (tab-bar-tab-name-format-hints) (tab-bar-tab-name-format-close-button) (tab-bar-tab-name-format-face): New functions. (tab-bar-tab-name-format-functions): New defcustom. (tab-bar-tab-name-format-default): Rewrite to use 'tab-bar-tab-name-format-functions'. --- etc/NEWS | 6 +++++ lisp/tab-bar.el | 70 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 9d356240f9c..0c9275f1e10 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -146,6 +146,12 @@ Anything following the symbol 'mode-line-format-right-align' in right-aligned to is controlled by the new user option 'mode-line-right-align-edge'. +** Tab Bars and Tab Lines + +*** New user option 'tab-bar-tab-name-format-functions'. +It can be used to add, remove and reorder functions that change +the appearance of every tab on the tab bar. + * Editing Changes in Emacs 30.1 diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 9a59e480f06..6b286598a14 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -782,6 +782,31 @@ Return its existing value or a new value." (set-frame-parameter frame 'tabs tabs)) +(defun tab-bar-tab-name-format-truncated (name _tab _i) + "Truncate the tab name. +The maximal length is specified by `tab-bar-tab-name-truncated-max'. +Append ellipsis `tab-bar-tab-name-ellipsis' at the end." + (if (< (length name) tab-bar-tab-name-truncated-max) + name + (truncate-string-to-width + name tab-bar-tab-name-truncated-max nil nil + tab-bar-tab-name-ellipsis))) + +(defun tab-bar-tab-name-format-hints (name _tab i) + "Show absolute numbers on tabs in the tab bar before the tab name. +It has effect when `tab-bar-tab-hints' is non-nil." + (if tab-bar-tab-hints (concat (format "%d " i) name) name)) + +(defun tab-bar-tab-name-format-close-button (name tab _i) + "Show the tab close button. +The variable `tab-bar-close-button-show' defines when to show it." + (if (and tab-bar-close-button-show + (not (eq tab-bar-close-button-show + (if (eq (car tab) 'current-tab) 'non-selected 'selected))) + tab-bar-close-button) + (concat name tab-bar-close-button) + name)) + (defcustom tab-bar-tab-face-function #'tab-bar-tab-face-default "Function to define a tab face. Function gets one argument: a tab." @@ -792,6 +817,38 @@ Function gets one argument: a tab." (defun tab-bar-tab-face-default (tab) (if (eq (car tab) 'current-tab) 'tab-bar-tab 'tab-bar-tab-inactive)) +(defun tab-bar-tab-name-format-face (name tab _i) + "Apply the face to the tab name. +It uses the function `tab-bar-tab-face-function'." + (add-face-text-property + 0 (length name) (funcall tab-bar-tab-face-function tab) t name) + name) + +(defcustom tab-bar-tab-name-format-functions + '(tab-bar-tab-name-format-hints + tab-bar-tab-name-format-close-button + tab-bar-tab-name-format-face) + "Functions called to modify the tab name. +Each function is called with three arguments: the name returned +by the previously called modifier, the tab and its number. +It should return the formatted tab name to display in the tab bar." + :type '(repeat + (choice (function-item tab-bar-tab-name-format-truncated) + (function-item tab-bar-tab-name-format-hints) + (function-item tab-bar-tab-name-format-close-button) + (function-item tab-bar-tab-name-format-face) + (function :tag "Custom function"))) + :group 'tab-bar + :version "30.1") + +(defun tab-bar-tab-name-format-default (tab i) + (let ((name (copy-sequence (alist-get 'name tab)))) + (run-hook-wrapped 'tab-bar-tab-name-format-functions + (lambda (fun) + (setq name (funcall fun name tab i)) + nil)) + name)) + (defcustom tab-bar-tab-name-format-function #'tab-bar-tab-name-format-default "Function to format a tab name. Function gets two arguments, the tab and its number, and should return @@ -804,19 +861,6 @@ the formatted tab name to display in the tab bar." :group 'tab-bar :version "28.1") -(defun tab-bar-tab-name-format-default (tab i) - (let* ((current-p (eq (car tab) 'current-tab)) - (name (concat (if tab-bar-tab-hints (format "%d " i) "") - (alist-get 'name tab) - (or (and tab-bar-close-button-show - (not (eq tab-bar-close-button-show - (if current-p 'non-selected 'selected))) - tab-bar-close-button) - "")))) - (add-face-text-property - 0 (length name) (funcall tab-bar-tab-face-function tab) t name) - name)) - (defcustom tab-bar-format '(tab-bar-format-history tab-bar-format-tabs tab-bar-separator -- 2.39.2