diff --git a/etc/NEWS b/etc/NEWS index b790c7e318c..462098a0238 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -427,6 +427,11 @@ This user option controls where 'tab-line-mode' should not be enabled in a buffer. The value must be a condition which is passed to 'buffer-match-p'. +--- +*** New user option 'tab-line-close-modified-button-show'. +With this user option, if non-nil (the default), the tab close button +will change its appearance whether the tab buffer has been modified. + ** Project --- diff --git a/etc/images/tabs/README b/etc/images/tabs/README index c3bab00d56c..2a68577951f 100644 --- a/etc/images/tabs/README +++ b/etc/images/tabs/README @@ -4,5 +4,9 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES Files: close.xpm new.xpm left-arrow.xpm right-arrow.xpm Author: Juri Linkov + +Files: close-modified.xpm +Author: Elías Gabriel Pérez + Copyright (C) 2019-2025 Free Software Foundation, Inc. License: GNU General Public License version 3 or later (see COPYING) diff --git a/etc/images/tabs/close-modified.xpm b/etc/images/tabs/close-modified.xpm new file mode 100644 index 00000000000..44b45d49011 --- /dev/null +++ b/etc/images/tabs/close-modified.xpm @@ -0,0 +1,16 @@ +/* XPM */ +static char *dummy[]={ +"9 9 4 1", +". c None", +"b c #000000", +"a c #808080", +"# c #bfbfbf", +"..#####..", +".#######.", +"###aaa###", +"##abbba##", +"##abbba##", +"##abbba##", +"###aaa###", +".#######.", +"..#####.."}; diff --git a/lisp/tab-line.el b/lisp/tab-line.el index 5ed32ef2ed9..5e33064b5b1 100644 --- a/lisp/tab-line.el +++ b/lisp/tab-line.el @@ -251,6 +251,36 @@ If nil, don't show it at all." 'help-echo "Click to close tab") "Button for closing the clicked tab.") +(defcustom tab-line-close-modified-button-show t + "If non-nil, the close button appearance will change when its buffer is modified." + :type 'boolean + :initialize 'custom-initialize-default + :set (lambda (sym val) + (set-default sym val) + (force-mode-line-update t)) + :group 'tab-line + :version "31.1") + +(define-icon tab-line-close-modified nil + `((image "symbols/dot_medium_16.svg" "tabs/close-modified.xpm" + :face shadow + :height (1 . em) + :margin (2 . 0) + :ascent center) + (symbol ,(concat " " [#x2022])) ; bullet + (text " *")) + "Icon for closing the clicked tab when tab is modified." + :version "31.1" + :help-echo "Click to close tab") + +(defvar tab-line-close-modified-button + (propertize (icon-string 'tab-line-close-modified) + 'rear-nonsticky nil + 'keymap tab-line-tab-close-map + 'mouse-face 'tab-line-close-highlight + 'help-echo "Click to close tab") + "Button for closing the clicked tab when tab is modified.") + (define-icon tab-line-left nil `((image "symbols/chevron_left_16.svg" "tabs/left-arrow.xpm" :face shadow @@ -387,6 +417,12 @@ Used only for `tab-line-tabs-mode-buffers' and `tab-line-tabs-buffer-groups'.") (derived-mode-p mode))) (funcall tab-line-tabs-buffer-list-function))))) +(defun tab-line-tab-modified-p (tab buffer-p) + "Return t if TAB is modified." + (let ((buffer (if buffer-p tab (cdr (assq 'buffer tab))))) + (when (and buffer (buffer-file-name buffer) (buffer-modified-p buffer)) + t))) + (defcustom tab-line-tabs-buffer-group-function #'tab-line-tabs-buffer-group-by-mode "Function to add a buffer to the appropriate group of tabs. @@ -619,7 +655,10 @@ using `tab-line-cache-key-function'." (not (eq tab-line-close-button-show (if selected-p 'non-selected 'selected))) - tab-line-close-button) + (if (and tab-line-close-modified-button-show + (tab-line-tab-modified-p tab buffer-p)) + tab-line-close-modified-button + tab-line-close-button)) ""))) (setq close (copy-sequence close)) ;; Don't overwrite the icon face @@ -687,9 +726,8 @@ When TAB is a non-file-visiting buffer, make FACE inherit from When TAB is a modified, file-backed buffer, make FACE inherit from `tab-line-tab-modified'. For use in `tab-line-tab-face-functions'." - (let ((buffer (if buffer-p tab (cdr (assq 'buffer tab))))) - (when (and buffer (buffer-file-name buffer) (buffer-modified-p buffer)) - (setf face `(:inherit (tab-line-tab-modified ,face))))) + (when (tab-line-tab-modified-p tab buffer-p) + (setf face `(:inherit (tab-line-tab-modified ,face)))) face) (defun tab-line-tab-face-group (tab _tabs face _buffer-p _selected-p)