unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [PATCH] tab-line-alternate-colors
@ 2020-12-13  6:04 Adam Porter
  2020-12-13  6:17 ` Adam Porter
  2020-12-13  8:45 ` Juri Linkov
  0 siblings, 2 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-13  6:04 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 278 bytes --]

Hi,

This patch adds a new option and face which makes inactive tab-line tabs display in alternating colors, which makes them easier to distinguish between.  Assuming that the idea is acceptable, please let me know if any further changes to the patch are required.

Thanks,
Adam

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 3505 bytes --]

From d1bebe1441f728b6da6bd44bc2a78a943594dafe Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] New option `tab-line-alternate-colors` and associated face

* lisp/tab-line.el:
(tab-line-alternate-colors): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-format-template): Use them.
---
 lisp/tab-line.el | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f14e..b8fcb737b9 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -35,6 +35,14 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-alternate-colors t
+  "Alternate background colors of inactive tabs.
+When non-nil, alternating tabs use the face
+`tab-line-tab-inactive-alternate'."
+  :type 'boolean
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +71,14 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  (let ((mode-line-bg (face-background 'mode-line nil t)))
+    `((t (:inherit tab-line-tab-inactive :background ,mode-line-bg))))
+  "Alternate face for inactive tab-line tabs.
+Used on alternating tabs when `tab-line-alternate-colors' is non-nil."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -403,6 +419,7 @@ tab-line-format-template
   (let* ((selected-buffer (window-buffer))
          (separator (or tab-line-separator (if window-system " " "|")))
          (hscroll (window-parameter nil 'tab-line-hscroll))
+         (tab-number 0)
          (strings
           (mapcar
            (lambda (tab)
@@ -412,7 +429,16 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (cond (selected-p
+                                 (if (eq (selected-window) (old-selected-window))
+                                     'tab-line-tab-current
+                                   'tab-line-tab))
+                                ((and tab-line-alternate-colors
+                                      (cl-evenp (cl-incf tab-number)))
+                                 'tab-line-tab-inactive-alternate)
+                                (t
+                                 'tab-line-tab-inactive))))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +451,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13  6:04 [PATCH] tab-line-alternate-colors Adam Porter
@ 2020-12-13  6:17 ` Adam Porter
  2020-12-13  8:45 ` Juri Linkov
  1 sibling, 0 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-13  6:17 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 140 bytes --]

It's probably necessary to require cl-lib since no cl- functions were
used in the file previously.  I've attached a new patch.

Thanks,
Adam

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: updated patch --]
[-- Type: text/x-diff, Size: 3639 bytes --]

From 93fb347ada44b34d8e656b33fdd62e3b786cf8a1 Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] New option `tab-line-alternate-colors` and associated face

* lisp/tab-line.el:
(tab-line-alternate-colors): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-format-template): Use them.
---
 lisp/tab-line.el | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f14e..9719a42da3 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,14 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-alternate-colors t
+  "Alternate background colors of inactive tabs.
+When non-nil, alternating tabs use the face
+`tab-line-tab-inactive-alternate'."
+  :type 'boolean
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +72,14 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  (let ((mode-line-bg (face-background 'mode-line nil t)))
+    `((t (:inherit tab-line-tab-inactive :background ,mode-line-bg))))
+  "Alternate face for inactive tab-line tabs.
+Used on alternating tabs when `tab-line-alternate-colors' is non-nil."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -403,6 +420,7 @@ tab-line-format-template
   (let* ((selected-buffer (window-buffer))
          (separator (or tab-line-separator (if window-system " " "|")))
          (hscroll (window-parameter nil 'tab-line-hscroll))
+         (tab-number 0)
          (strings
           (mapcar
            (lambda (tab)
@@ -412,7 +430,16 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (cond (selected-p
+                                 (if (eq (selected-window) (old-selected-window))
+                                     'tab-line-tab-current
+                                   'tab-line-tab))
+                                ((and tab-line-alternate-colors
+                                      (cl-evenp (cl-incf tab-number)))
+                                 'tab-line-tab-inactive-alternate)
+                                (t
+                                 'tab-line-tab-inactive))))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +452,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13  6:04 [PATCH] tab-line-alternate-colors Adam Porter
  2020-12-13  6:17 ` Adam Porter
@ 2020-12-13  8:45 ` Juri Linkov
  2020-12-13 10:06   ` Adam Porter
  1 sibling, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2020-12-13  8:45 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

> This patch adds a new option and face which makes inactive tab-line tabs
> display in alternating colors, which makes them easier to distinguish
> between.  Assuming that the idea is acceptable, please let me know if any
> further changes to the patch are required.

Thanks, it would be nice to support displaying tabs in alternating colors.
But there are endless possibilities for look and feel of tabs, so instead of
hard-coding only one of them for alternating colors, I suggest to add
a customizable function with a name like 'tab-line-tab-face' that with
a tab provided as its arg (and a list of tabs to be able to find
the ordinal number of the given tab) would return its face to use.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13  8:45 ` Juri Linkov
@ 2020-12-13 10:06   ` Adam Porter
  2020-12-13 11:13     ` Adam Porter
                       ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-13 10:06 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 630 bytes --]

Juri Linkov <juri@linkov.net> writes:

> Thanks, it would be nice to support displaying tabs in alternating
> colors.  But there are endless possibilities for look and feel of
> tabs, so instead of hard-coding only one of them for alternating
> colors, I suggest to add a customizable function with a name like
> 'tab-line-tab-face' that with a tab provided as its arg (and a list of
> tabs to be able to find the ordinal number of the given tab) would
> return its face to use.

Yes, that seems like a good idea.  Something like this?  I also added
another face for non-file-backed buffers, which helps distinguish them.

Thanks.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 4762 bytes --]

From aab7908e63589b989cc8d4efebfcc838d5b4c805 Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] New tab-line options, faces, and face function

* lisp/tab-line.el:
(tab-line-tab-face-function): New option.
(tab-line-alternate-colors): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-tab-special): New face.
(tab-line-tab-face-default): New function.
(tab-line-format-template): Use them.

Thanks to Juri Linkov for his feedback.
---
 lisp/tab-line.el | 72 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 66 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f14e..313899503c 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,22 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-alternate-colors t
+  "Alternate background colors of inactive tabs.
+When non-nil, alternating tabs use the face
+`tab-line-tab-inactive-alternate'."
+  :type 'boolean
+  :group 'tab-line
+  :version "28.1")
+
+(defcustom tab-line-tab-face-function #'tab-line-tab-face-default
+  "Function called to get a tab's face.
+The function is called with two arguments: the tab and a list of
+all tabs."
+  :type 'function
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +80,19 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  (let ((mode-line-bg (face-background 'mode-line nil t)))
+    `((t (:inherit tab-line-tab-inactive :background ,mode-line-bg))))
+  "Alternate face for inactive tab-line tabs.
+Used on alternating tabs when `tab-line-alternate-colors' is non-nil."
+  :version "28.1"
+  :group 'tab-line-faces)
+
+(defface tab-line-tab-special '((t (:slant italic)))
+  "Face for special (i.e. non-file-backed) tabs."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -412,7 +442,9 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (funcall tab-line-tab-face-function
+                                   tab tabs)))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +457,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
@@ -453,6 +481,38 @@ tab-line-format-template
                 tab-line-new-button)
        (list tab-line-new-button)))))
 
+(defun tab-line-tab-face-default (tab tabs)
+  "Return face for TAB in TABS.
+If TAB is selected, return `tab-line-tab-current' if the tab's
+window is also selected, otherwise `tab-line-tab'.
+
+Otherwise, if `tab-line-alternate-colors' is non-nil, return
+`tab-line-tab-inactive-alternate' for even-numbered tabs and
+`tab-line-tab-inactive' for odd-numbered ones.
+
+Otherwise, return `tab-line-tab-inactive'.
+
+If the tab's buffer is not file-backed, the returned face also
+inherits from `tab-line-tab-special'.
+
+For use as `tab-line-tab-face-function'."
+  (let* ((buffer-p (bufferp tab))
+	 (selected-p (if buffer-p
+			 (eq tab (window-buffer))
+		       (cdr (assq 'selected tab))))
+	 (face (cond (selected-p
+		      (if (eq (selected-window) (old-selected-window))
+			  'tab-line-tab-current
+			'tab-line-tab))
+		     ((and tab-line-alternate-colors
+			   (cl-evenp (cl-position tab tabs)))
+		      'tab-line-tab-inactive-alternate)
+		     (t
+		      'tab-line-tab-inactive))))
+    (if (and buffer-p (not (buffer-file-name tab)))
+	`((t (:inherit (tab-line-tab-special ,face))))
+      face)))
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13 10:06   ` Adam Porter
@ 2020-12-13 11:13     ` Adam Porter
  2020-12-13 15:21     ` Eli Zaretskii
  2020-12-13 21:25     ` Juri Linkov
  2 siblings, 0 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-13 11:13 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 825 bytes --]

> Yes, that seems like a good idea.  Something like this?  I also added
> another face for non-file-backed buffers, which helps distinguish
> them.

The attached patch fixes a bug with an anonymous face in the previous
patch.

By the way, it seems that, because the face `tab-line' inherits from the
face `variable-pitch', an anonymous face that inherits from
`tab-line-tab-special' (which defaults to italic slant in this patch) is
prevented from having italic slant applied.  If I set `tab-line' to not
inherit from `variable-pitch', the italic slant is inherited.
`variable-pitch' has not been customized, so it has no value for the
slant attribute, so it seems like it shouldn't interfere.  I don't know
if this is a bug in my code, in Emacs 28, or in the native-comp branch
that I'm using to develop this patch.

Thanks.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 4940 bytes --]

From dc4723fefa5d77eb28a6d2b67afdf5e5b8e696d7 Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] New tab-line options, faces, and face function

* lisp/tab-line.el:
(tab-line-tab-face-function): New option.
(tab-line-alternate-colors): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-tab-special): New face.
(tab-line-tab-face-default): New function.
(tab-line-format-template): Use them.

Thanks to Juri Linkov for his feedback.
---
 lisp/tab-line.el | 75 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 69 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f14e..640c568cc5 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,22 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-alternate-colors t
+  "Alternate background colors of inactive tabs.
+When non-nil, alternating tabs use the face
+`tab-line-tab-inactive-alternate'."
+  :type 'boolean
+  :group 'tab-line
+  :version "28.1")
+
+(defcustom tab-line-tab-face-function #'tab-line-tab-face-default
+  "Function called to get a tab's face.
+The function is called with two arguments: the tab and a list of
+all tabs."
+  :type 'function
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +80,19 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  (let ((mode-line-bg (face-background 'mode-line nil t)))
+    `((t (:inherit tab-line-tab-inactive :background ,mode-line-bg))))
+  "Alternate face for inactive tab-line tabs.
+Used on alternating tabs when `tab-line-alternate-colors' is non-nil."
+  :version "28.1"
+  :group 'tab-line-faces)
+
+(defface tab-line-tab-special '((t (:slant italic)))
+  "Face for special (i.e. non-file-backed) tabs."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -412,7 +442,9 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (funcall tab-line-tab-face-function
+                                   tab tabs)))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +457,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
@@ -453,6 +481,41 @@ tab-line-format-template
                 tab-line-new-button)
        (list tab-line-new-button)))))
 
+(defun tab-line-tab-face-default (tab tabs)
+  "Return face for TAB in TABS.
+If TAB is selected, return `tab-line-tab-current' if the tab's
+window is also selected, otherwise `tab-line-tab'.
+
+Otherwise, if `tab-line-alternate-colors' is non-nil, return
+`tab-line-tab-inactive-alternate' for even-numbered tabs and
+`tab-line-tab-inactive' for odd-numbered ones.
+
+Otherwise, return `tab-line-tab-inactive'.
+
+If the tab's buffer is not file-backed, the returned face also
+inherits from `tab-line-tab-special'.
+
+For use as `tab-line-tab-face-function'."
+  (let* ((buffer-p (bufferp tab))
+	 (selected-p (if buffer-p
+			 (eq tab (window-buffer))
+		       (cdr (assq 'selected tab))))
+	 (face (cond (selected-p
+		      (if (eq (selected-window) (old-selected-window))
+			  'tab-line-tab-current
+			'tab-line-tab))
+		     ((and tab-line-alternate-colors
+			   (cl-evenp (cl-position tab tabs)))
+		      'tab-line-tab-inactive-alternate)
+		     (t
+		      'tab-line-tab-inactive))))
+    (if (and buffer-p (not (buffer-file-name tab)))
+        ;; FIXME: The `tab-line' face's inheriting from
+        ;; `variable-pitch' seems to prevent inheriting from
+        ;; `tab-line-tab-special' applying italic slant.
+        `(:inherit (tab-line-tab-special ,face))
+      face)))
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13 10:06   ` Adam Porter
  2020-12-13 11:13     ` Adam Porter
@ 2020-12-13 15:21     ` Eli Zaretskii
  2020-12-14  2:17       ` Adam Porter
  2020-12-13 21:25     ` Juri Linkov
  2 siblings, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2020-12-13 15:21 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

> From: Adam Porter <adam@alphapapa.net>
> Date: Sun, 13 Dec 2020 04:06:36 -0600
> 
> +(defface tab-line-tab-inactive-alternate
> +  (let ((mode-line-bg (face-background 'mode-line nil t)))
> +    `((t (:inherit tab-line-tab-inactive :background ,mode-line-bg))))

Is this supposed to change the background when that of the mode line
changes, or is it supposed to keep the original one, recorded when
this defface is processed?

More generally, why use such an unusual definition of a face?

> +(defface tab-line-tab-special '((t (:slant italic)))

What will this do on terminals that don''t support italic?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13 10:06   ` Adam Porter
  2020-12-13 11:13     ` Adam Porter
  2020-12-13 15:21     ` Eli Zaretskii
@ 2020-12-13 21:25     ` Juri Linkov
  2020-12-14  4:33       ` Adam Porter
  2 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2020-12-13 21:25 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

>> Thanks, it would be nice to support displaying tabs in alternating
>> colors.  But there are endless possibilities for look and feel of
>> tabs, so instead of hard-coding only one of them for alternating
>> colors, I suggest to add a customizable function with a name like
>> 'tab-line-tab-face' that with a tab provided as its arg (and a list of
>> tabs to be able to find the ordinal number of the given tab) would
>> return its face to use.
>
> Yes, that seems like a good idea.  Something like this?  I also added
> another face for non-file-backed buffers, which helps distinguish them.

What if some users might want to display tabs with rainbow colors?
Then this too specific option tab-line-alternate-colors won't help.

What I suggest is that defcustom tab-line-tab-face-function could
provide a separate function choice, e.g. tab-line-tab-face-alternate,
so when customized to tab-line-tab-face-alternate, this function
could call the default function tab-line-tab-face-default,
and if the default function returns 'tab-line-tab-inactive',
then replace it with 'tab-line-tab-inactive-alternate'
depending on whether the tab is odd/even.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13 15:21     ` Eli Zaretskii
@ 2020-12-14  2:17       ` Adam Porter
  2020-12-14 15:34         ` Eli Zaretskii
  0 siblings, 1 reply; 25+ messages in thread
From: Adam Porter @ 2020-12-14  2:17 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> +(defface tab-line-tab-inactive-alternate
>> +  (let ((mode-line-bg (face-background 'mode-line nil t)))
>> +    `((t (:inherit tab-line-tab-inactive :background ,mode-line-bg))))
>
> Is this supposed to change the background when that of the mode line
> changes, or is it supposed to keep the original one, recorded when
> this defface is processed?

This is the default definition of the face, so it would not be updated
if the mode-line face changes (e.g. when a theme is loaded).  That's not
ideal, of course.

I know of two alternatives:

1.  Use an anonymous face computed at runtime (e.g. by calling
color-darken-name on the tab-line face's background color).  That would
seem wasteful, considering how often these functions are called.

2.  Define the face with a specific color.  That would work for the
default theme, but when other themes are loaded, the colors would
usually clash, and that would require themes to add support for the new
face.

> More generally, why use such an unusual definition of a face?

In the default theme, the mode-line face has a background color that's
slightly darker than the header-line face's (and therefore the tab-line
face's) background color, so it seems like a suitable color for
alternating tabs' background color.  For themes that follow the pattern
of the header-line and mode-line having different background colors, it
should work without requiring themes to support a new face.  So it
seemed preferable to hard-coding the default for the new face.

AFAIK there's no way to inherit only a certain attribute of a face,
other than using an anonymous face made at runtime.  If there were, it
would be simple to just inherit the mode-line face's background color.

>> +(defface tab-line-tab-special '((t (:slant italic)))
>
> What will this do on terminals that don''t support italic?

Nothing, I suppose.  :)  I don't often use Emacs in a terminal, so I'm
not as familiar with that issue.

I'll be glad to follow whatever guidance you may provide here.  Thanks.




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-13 21:25     ` Juri Linkov
@ 2020-12-14  4:33       ` Adam Porter
  2020-12-14  9:10         ` Juri Linkov
  2020-12-14  9:14         ` Adam Porter
  0 siblings, 2 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-14  4:33 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2092 bytes --]

Juri Linkov <juri@linkov.net> writes:

>>> Thanks, it would be nice to support displaying tabs in alternating
>>> colors.  But there are endless possibilities for look and feel of
>>> tabs, so instead of hard-coding only one of them for alternating
>>> colors, I suggest to add a customizable function with a name like
>>> 'tab-line-tab-face' that with a tab provided as its arg (and a list of
>>> tabs to be able to find the ordinal number of the given tab) would
>>> return its face to use.
>>
>> Yes, that seems like a good idea.  Something like this?  I also added
>> another face for non-file-backed buffers, which helps distinguish them.
>
> What if some users might want to display tabs with rainbow colors?
> Then this too specific option tab-line-alternate-colors won't help.
>
> What I suggest is that defcustom tab-line-tab-face-function could
> provide a separate function choice, e.g. tab-line-tab-face-alternate,
> so when customized to tab-line-tab-face-alternate, this function
> could call the default function tab-line-tab-face-default,
> and if the default function returns 'tab-line-tab-inactive',
> then replace it with 'tab-line-tab-inactive-alternate'
> depending on whether the tab is odd/even.

Okay, here's my next proposal: The tab-line-tab-face-default function
returns a face, and then a new option, tab-line-tab-face-modifiers, is a
list of functions, each of which is called with that face and returns
it, possibly modified.  This seems like a flexible mechanism which makes
it possible to modify the faces orthogonally according to arbitrary
criteria, and it can be used to add the alternating colors and
special-buffer faces when applicable (when so-configured by the user).
It could also be used to do a "rainbow" of faces, as you mentioned, etc.

To address Eli's feedback, in this patch I also defined the alternate
face to have a certain background color by default rather than
inheriting from mode-line.

However, the issue regarding italic slant on terminals remains; I'll be
glad to do whatever you or Eli suggest.

Thanks to you and Eli for your help.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 6013 bytes --]

From 74bea2f33da16d8d79c8e010435096ca00b4c646 Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] New tab-line options, faces, and functions

* lisp/tab-line.el:
(tab-line-tab-face-function): New option.
(tab-line-tab-face-modifiers): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-tab-special): New face.
(tab-line-tab-face-default): New function.
(tab-line-tab-face-inactive-alternating): New function.
(tab-line-tab-face-special): New function.
(tab-line-format-template): Use new face-default function.

With thanks to Juri Linkov and Eli Zaretskii for their guidance.
---
 lisp/tab-line.el | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 84 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f..278ff30 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,26 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-tab-face-function #'tab-line-tab-face-default
+  "Function called to get a tab's face.
+The function is called with two arguments: the tab and a list of
+all tabs."
+  :type '(choice (function-item :tag "Default" tab-line-tab-face-default)
+                 (function :tag "Custom function"))
+  :group 'tab-line
+  :version "28.1")
+
+(defcustom tab-line-tab-face-modifiers '(tab-line-tab-face-special)
+  "Functions called to modify tab faces.
+Each function is called with three arguments: the tab, a list of
+all tabs, and the face returned by the previously called
+modifier."
+  :type '(set (function-item tab-line-tab-face-special)
+              (function-item tab-line-tab-face-inactive-alternating)
+              (function :tag "Custom function"))
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +84,22 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  `((t (:inherit tab-line-tab-inactive :background "grey65")))
+  "Alternate face for inactive tab-line tabs.
+Applied to alternating tabs when option
+`tab-line-tab-face-modifiers' includes function
+`tab-line-tab-face-inactive-alternating'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
+(defface tab-line-tab-special '((t (:slant italic)))
+  "Face for special (i.e. non-file-backed) tabs.
+Applied when option `tab-line-tab-face-modifiers' includes
+function `tab-line-tab-face-special'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -412,7 +449,11 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (funcall tab-line-tab-face-function
+                                   tab tabs)))
+               (dolist (fn tab-line-tab-face-modifiers)
+                 (setf face (funcall fn tab tabs face)))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +466,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
@@ -453,6 +490,47 @@ tab-line-format-template
                 tab-line-new-button)
        (list tab-line-new-button)))))
 
+(defun tab-line-tab-face-default (tab _tabs)
+  "Return face for TAB.
+If TAB is selected, return `tab-line-tab-current' if the tab's
+window is also selected, otherwise `tab-line-tab'.  Otherwise,
+return `tab-line-tab-inactive'.  For use as
+`tab-line-tab-face-function'."
+  (let* ((buffer-p (bufferp tab))
+	 (selected-p (if buffer-p
+			 (eq tab (window-buffer))
+		       (cdr (assq 'selected tab)))))
+    (if selected-p
+	(if (eq (selected-window) (old-selected-window))
+	    'tab-line-tab-current
+	  'tab-line-tab)
+      'tab-line-tab-inactive)))
+
+(defun tab-line-tab-face-inactive-alternating (tab tabs face)
+  "Return FACE for TAB in TABS with alternation.
+When TAB is an inactive buffer and is even-numbered, make FACE
+inherit from `tab-line-tab-inactive-alternate'.  For use in
+`tab-line-tab-face-modifiers'."
+  (let* ((buffer-p (bufferp tab))
+	 (selected-p (if buffer-p
+			 (eq tab (window-buffer))
+		       (cdr (assq 'selected tab)))))
+    (when (and (not selected-p) (cl-evenp (cl-position tab tabs)))
+      (setf face `(:inherit (tab-line-tab-inactive-alternate ,face)))))
+  face)
+
+(defun tab-line-tab-face-special (tab _tabs face)
+  "Return FACE for TAB according to whether it's special.
+When TAB is a non-file-backed buffer, make FACE inherit from
+`tab-line-tab-special'.  For use in
+`tab-line-tab-face-modifiers'."
+  ;; FIXME: When the face `tab-line' inherits from the face
+  ;; `variable-pitch', the face `tab-line-tab-special' doesn't seem to
+  ;; apply properly (e.g. its :slant has no effect).
+  (when (and (bufferp tab) (not (buffer-file-name tab)))
+    (setf face `(:inherit (tab-line-tab-special ,face))))
+  face)
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14  4:33       ` Adam Porter
@ 2020-12-14  9:10         ` Juri Linkov
  2020-12-14 10:05           ` Adam Porter
  2020-12-14  9:14         ` Adam Porter
  1 sibling, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2020-12-14  9:10 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

> Okay, here's my next proposal: The tab-line-tab-face-default function
> returns a face, and then a new option, tab-line-tab-face-modifiers, is a
> list of functions, each of which is called with that face and returns
> it, possibly modified.

Thanks, tab-line-tab-face-modifiers is a good idea.  It's like hooks
used to post-process the result.  But the '-hooks' suffix is deprecated,
and the new standard is to end such variable names in '-functions'.
Then using the name tab-line-tab-face-functions will also avoid ambiguity
of the word 'modifiers' that is mostly applied to key modifiers -
there is already the option tab-bar-select-tab-modifiers.

Then tab-line-tab-face-functions will obsolete the need to have
an almost duplicate option tab-line-tab-face-function.  But then we have
two variants:

1. add tab-line-tab-face-default to tab-line-tab-face-functions by default.

2. remove tab-line-tab-face-default and leave its code in tab-line-format-template
   as before, with a supposition that it should be sufficient to customize
   tab-line-tab-face-functions to post-process its output face.

What variant would you prefer?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14  4:33       ` Adam Porter
  2020-12-14  9:10         ` Juri Linkov
@ 2020-12-14  9:14         ` Adam Porter
  2020-12-14 19:33           ` Juri Linkov
  1 sibling, 1 reply; 25+ messages in thread
From: Adam Porter @ 2020-12-14  9:14 UTC (permalink / raw)
  To: emacs-devel

By the way, your rainbow idea may have some merit.  Using the modifiers
implemented in that patch, I hacked this together using buffers' Bufler
workspace as the key for generating a unique color, and applied the same
color to the tab and the buffer's row in bufler-list:

https://i.imgur.com/gZZqC5u.png

Obviously it could use some polishing, but the colors do help show which
tab-line tabs are in which workspace.  (I also sorted the tabs by
workspace.)




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14  9:10         ` Juri Linkov
@ 2020-12-14 10:05           ` Adam Porter
  2020-12-14 19:37             ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Adam Porter @ 2020-12-14 10:05 UTC (permalink / raw)
  To: emacs-devel

Juri Linkov <juri@linkov.net> writes:

>> Okay, here's my next proposal: The tab-line-tab-face-default function
>> returns a face, and then a new option, tab-line-tab-face-modifiers, is a
>> list of functions, each of which is called with that face and returns
>> it, possibly modified.
>
> Thanks, tab-line-tab-face-modifiers is a good idea.  It's like hooks
> used to post-process the result.  But the '-hooks' suffix is deprecated,
> and the new standard is to end such variable names in '-functions'.
> Then using the name tab-line-tab-face-functions will also avoid ambiguity
> of the word 'modifiers' that is mostly applied to key modifiers -
> there is already the option tab-bar-select-tab-modifiers.

Sure, I'll change that in the next patch.

> Then tab-line-tab-face-functions will obsolete the need to have an
> almost duplicate option tab-line-tab-face-function.  But then we have
> two variants:
>
> 1. add tab-line-tab-face-default to tab-line-tab-face-functions by default.
>
> 2. remove tab-line-tab-face-default and leave its code in tab-line-format-template
>    as before, with a supposition that it should be sufficient to customize
>    tab-line-tab-face-functions to post-process its output face.
>
> What variant would you prefer?

Hmm, I'm not sure which is best.  #1 might be the cleanest in theory,
but it would seem to conflate the two types of functions: the initial
face-determining function and the face-modifying functions.  So that
variant would seem to require one of two approaches: a) require the
function tab-line-tab-face-default to be first in the list of functions
(which would be error-prone), or b) modify the function
tab-line-tab-face-default to work as a face-modifier so it could work
regardless of its position in the list (and it would need to be able to
start from a nil face, which might be awkward).

OTOH, #2 would minimize the diff from master and avoid the problems that
#1 would seem to present.

So I suppose I would choose variant #2, although I don't have a strong
preference, and I might be overlooking something that would make #1 a
better choice.

WDYT?  Thanks.




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14  2:17       ` Adam Porter
@ 2020-12-14 15:34         ` Eli Zaretskii
  2020-12-16  2:58           ` Adam Porter
  0 siblings, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2020-12-14 15:34 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

> From: Adam Porter <adam@alphapapa.net>
> Date: Sun, 13 Dec 2020 20:17:28 -0600
> 
> AFAIK there's no way to inherit only a certain attribute of a face,
> other than using an anonymous face made at runtime.  If there were, it
> would be simple to just inherit the mode-line face's background color.

I'm not sure I understand why would want to inherit just the
background color.  What's wrong with inheriting all the rest?

> >> +(defface tab-line-tab-special '((t (:slant italic)))
> >
> > What will this do on terminals that don''t support italic?
> 
> Nothing, I suppose.  :)  I don't often use Emacs in a terminal, so I'm
> not as familiar with that issue.
> 
> I'll be glad to follow whatever guidance you may provide here.  Thanks.

I guess if italics isn't supported, you could use bold or some
foreground color instead?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14  9:14         ` Adam Porter
@ 2020-12-14 19:33           ` Juri Linkov
  0 siblings, 0 replies; 25+ messages in thread
From: Juri Linkov @ 2020-12-14 19:33 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

> By the way, your rainbow idea may have some merit.  Using the modifiers
> implemented in that patch, I hacked this together using buffers' Bufler
> workspace as the key for generating a unique color, and applied the same
> color to the tab and the buffer's row in bufler-list:
>
> https://i.imgur.com/gZZqC5u.png
>
> Obviously it could use some polishing, but the colors do help show which
> tab-line tabs are in which workspace.  (I also sorted the tabs by
> workspace.)

Really nice color coding!



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14 10:05           ` Adam Porter
@ 2020-12-14 19:37             ` Juri Linkov
  2020-12-16  3:24               ` Adam Porter
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2020-12-14 19:37 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

>> 1. add tab-line-tab-face-default to tab-line-tab-face-functions by default.
>>
>> 2. remove tab-line-tab-face-default and leave its code in tab-line-format-template
>>    as before, with a supposition that it should be sufficient to customize
>>    tab-line-tab-face-functions to post-process its output face.
>>
>> What variant would you prefer?
>
> Hmm, I'm not sure which is best.  #1 might be the cleanest in theory,
> but it would seem to conflate the two types of functions: the initial
> face-determining function and the face-modifying functions.  So that
> variant would seem to require one of two approaches: a) require the
> function tab-line-tab-face-default to be first in the list of functions
> (which would be error-prone), or b) modify the function
> tab-line-tab-face-default to work as a face-modifier so it could work
> regardless of its position in the list (and it would need to be able to
> start from a nil face, which might be awkward).
>
> OTOH, #2 would minimize the diff from master and avoid the problems that
> #1 would seem to present.
>
> So I suppose I would choose variant #2, although I don't have a strong
> preference, and I might be overlooking something that would make #1 a
> better choice.
>
> WDYT?  Thanks.

The only drawback of #2 is that when the user wants to completely
override all default faces, then calculating the default faces
is unnecessary, but its performance overhead is negligible.

For more optimization we could try also to add more args to the
face-returning functions, such args as 'selected-p', but OTOH, maybe
'selected-p' is not needed in tab-line-tab-face-inactive-alternating,
because it can just check if the arg 'face' from the previous function is
not 'tab-line-tab-current'.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14 15:34         ` Eli Zaretskii
@ 2020-12-16  2:58           ` Adam Porter
  2020-12-16 15:41             ` Eli Zaretskii
  0 siblings, 1 reply; 25+ messages in thread
From: Adam Porter @ 2020-12-16  2:58 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> AFAIK there's no way to inherit only a certain attribute of a face,
>> other than using an anonymous face made at runtime.  If there were, it
>> would be simple to just inherit the mode-line face's background color.
>
> I'm not sure I understand why would want to inherit just the
> background color.  What's wrong with inheriting all the rest?

I would guess that the mode-line face could have other attributes that
we wouldn't want to interfere with the tab-line faces, e.g. size or
family.  The only reason I would want to inherit from mode-line is to
get the background color.

Since this doesn't seem advisable, I've changed the definition of the
tab-line-tab-special face to define the background color explicitly,
using one which is slightly darker than the tab-line face's default.

>> >> +(defface tab-line-tab-special '((t (:slant italic)))
>> >
>> > What will this do on terminals that don''t support italic?
>> 
>> Nothing, I suppose.  :)  I don't often use Emacs in a terminal, so I'm
>> not as familiar with that issue.
>> 
>> I'll be glad to follow whatever guidance you may provide here.  Thanks.
>
> I guess if italics isn't supported, you could use bold or some
> foreground color instead?

Sure.  I've changed the face definition to only use italic on terminals
that support it, and to default to bold otherwise.

These changes will be in the next patch version.  Thanks.




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-14 19:37             ` Juri Linkov
@ 2020-12-16  3:24               ` Adam Porter
  2020-12-16  3:55                 ` Adam Porter
  2020-12-16  9:03                 ` Juri Linkov
  0 siblings, 2 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-16  3:24 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1058 bytes --]

Juri Linkov <juri@linkov.net> writes:

> The only drawback of #2 is that when the user wants to completely
> override all default faces, then calculating the default faces
> is unnecessary, but its performance overhead is negligible.
>
> For more optimization we could try also to add more args to the
> face-returning functions, such args as 'selected-p', but OTOH, maybe
> 'selected-p' is not needed in tab-line-tab-face-inactive-alternating,
> because it can just check if the arg 'face' from the previous function is
> not 'tab-line-tab-current'.

Ok, I went with option 2, which moves the default-face code from the
-tab-face-default function back into the -format-template function.

Then I added buffer-p and selected-p arguments to the modifier functions
as optimizations.

This patch also includes changes for the face-related issues Eli
mentioned, and it renames the -modifiers option to -functions, as you
suggested.

Please let me know what other changes are required.  Also, if I should
write a NEWS entry, let me know and I'll add one.

Thanks.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 5580 bytes --]

From 9e28e65c5e0d97d2418f93cdbb593ac80b047285 Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] tab-line: New faces and functions

* lisp/tab-line.el:
(tab-line-tab-face-function): New option.
(tab-line-tab-face-functions): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-tab-special): New face.
(tab-line-tab-face-inactive-alternating): New function.
(tab-line-tab-face-special): New function.
(tab-line-format-template): Use new function.
---
 lisp/tab-line.el | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f..54611b7 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,26 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-tab-face-function #'tab-line-tab-face-default
+  "Function called to get a tab's face.
+The function is called with two arguments: the tab and a list of
+all tabs."
+  :type '(choice (function-item :tag "Default" tab-line-tab-face-default)
+                 (function :tag "Custom function"))
+  :group 'tab-line
+  :version "28.1")
+
+(defcustom tab-line-tab-face-functions '(tab-line-tab-face-special)
+  "Functions called to modify tab faces.
+Each function is called with five arguments: the tab, a list of
+all tabs, the face returned by the previously called modifier,
+whether the tab is a buffer, and whether the tab is selected."
+  :type '(repeat (choice (function-item tab-line-tab-face-special)
+                         (function-item tab-line-tab-face-inactive-alternating)
+                         (function :tag "Custom function")))
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +84,25 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  `((t (:inherit tab-line-tab-inactive :background "grey65")))
+  "Alternate face for inactive tab-line tabs.
+Applied to alternating tabs when option
+`tab-line-tab-face-functions' includes function
+`tab-line-tab-face-inactive-alternating'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
+(defface tab-line-tab-special
+  '((default (:weight bold))
+    (((supports :slant italic))
+     (:slant italic :weight normal)))
+  "Face for special (i.e. non-file-backed) tabs.
+Applied when option `tab-line-tab-face-functions' includes
+function `tab-line-tab-face-special'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -412,7 +452,14 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (if selected-p
+                              (if (eq (selected-window) (old-selected-window))
+                                  'tab-line-tab-current
+                                'tab-line-tab)
+                            'tab-line-tab-inactive)))
+               (dolist (fn tab-line-tab-face-functions)
+                 (setf face (funcall fn tab tabs face buffer-p selected-p)))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +472,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
@@ -453,6 +496,27 @@ tab-line-format-template
                 tab-line-new-button)
        (list tab-line-new-button)))))
 
+(defun tab-line-tab-face-inactive-alternating (tab tabs face _buffer-p selected-p)
+  "Return FACE for TAB in TABS with alternation.
+When TAB is an inactive buffer and is even-numbered, make FACE
+inherit from `tab-line-tab-inactive-alternate'.  For use in
+`tab-line-tab-face-functions'."
+  (when (and (not selected-p) (cl-evenp (cl-position tab tabs)))
+    (setf face `(:inherit (tab-line-tab-inactive-alternate ,face))))
+  face)
+
+(defun tab-line-tab-face-special (tab _tabs face buffer-p _selected-p)
+  "Return FACE for TAB according to whether it's special.
+When TAB is a non-file-backed buffer, make FACE inherit from
+`tab-line-tab-special'.  For use in
+`tab-line-tab-face-functions'."
+  ;; FIXME: When the face `tab-line' inherits from the face
+  ;; `variable-pitch', the face `tab-line-tab-special' doesn't seem to
+  ;; apply properly (e.g. its :slant has no effect).
+  (when (and buffer-p (not (buffer-file-name tab)))
+    (setf face `(:inherit (tab-line-tab-special ,face))))
+  face)
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-16  3:24               ` Adam Porter
@ 2020-12-16  3:55                 ` Adam Porter
  2020-12-16  9:03                 ` Juri Linkov
  1 sibling, 0 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-16  3:55 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 99 bytes --]

Of course, I should have removed the obsolete defcustom from that
patch.  Here's the corrected one.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 5224 bytes --]

From ee5c366e1c80cfbd196fa7f0072575970eaebe72 Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] tab-line: New faces and functions

* lisp/tab-line.el:
(tab-line-tab-face-function): New option.
(tab-line-tab-face-functions): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-tab-special): New face.
(tab-line-tab-face-inactive-alternating): New function.
(tab-line-tab-face-special): New function.
(tab-line-format-template): Use new function.
---
 lisp/tab-line.el | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 61 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f..6e77cf5 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,17 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-tab-face-functions '(tab-line-tab-face-special)
+  "Functions called to modify tab faces.
+Each function is called with five arguments: the tab, a list of
+all tabs, the face returned by the previously called modifier,
+whether the tab is a buffer, and whether the tab is selected."
+  :type '(repeat (choice (function-item tab-line-tab-face-special)
+                         (function-item tab-line-tab-face-inactive-alternating)
+                         (function :tag "Custom function")))
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +75,25 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  `((t (:inherit tab-line-tab-inactive :background "grey65")))
+  "Alternate face for inactive tab-line tabs.
+Applied to alternating tabs when option
+`tab-line-tab-face-functions' includes function
+`tab-line-tab-face-inactive-alternating'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
+(defface tab-line-tab-special
+  '((default (:weight bold))
+    (((supports :slant italic))
+     (:slant italic :weight normal)))
+  "Face for special (i.e. non-file-backed) tabs.
+Applied when option `tab-line-tab-face-functions' includes
+function `tab-line-tab-face-special'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -412,7 +443,14 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (if selected-p
+                              (if (eq (selected-window) (old-selected-window))
+                                  'tab-line-tab-current
+                                'tab-line-tab)
+                            'tab-line-tab-inactive)))
+               (dolist (fn tab-line-tab-face-functions)
+                 (setf face (funcall fn tab tabs face buffer-p selected-p)))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +463,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
@@ -453,6 +487,27 @@ tab-line-format-template
                 tab-line-new-button)
        (list tab-line-new-button)))))
 
+(defun tab-line-tab-face-inactive-alternating (tab tabs face _buffer-p selected-p)
+  "Return FACE for TAB in TABS with alternation.
+When TAB is an inactive buffer and is even-numbered, make FACE
+inherit from `tab-line-tab-inactive-alternate'.  For use in
+`tab-line-tab-face-functions'."
+  (when (and (not selected-p) (cl-evenp (cl-position tab tabs)))
+    (setf face `(:inherit (tab-line-tab-inactive-alternate ,face))))
+  face)
+
+(defun tab-line-tab-face-special (tab _tabs face buffer-p _selected-p)
+  "Return FACE for TAB according to whether it's special.
+When TAB is a non-file-backed buffer, make FACE inherit from
+`tab-line-tab-special'.  For use in
+`tab-line-tab-face-functions'."
+  ;; FIXME: When the face `tab-line' inherits from the face
+  ;; `variable-pitch', the face `tab-line-tab-special' doesn't seem to
+  ;; apply properly (e.g. its :slant has no effect).
+  (when (and buffer-p (not (buffer-file-name tab)))
+    (setf face `(:inherit (tab-line-tab-special ,face))))
+  face)
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-16  3:24               ` Adam Porter
  2020-12-16  3:55                 ` Adam Porter
@ 2020-12-16  9:03                 ` Juri Linkov
  2020-12-16 10:26                   ` Adam Porter
  1 sibling, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2020-12-16  9:03 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

> Ok, I went with option 2, which moves the default-face code from the
> -tab-face-default function back into the -format-template function.
>
> Then I added buffer-p and selected-p arguments to the modifier functions
> as optimizations.
>
> This patch also includes changes for the face-related issues Eli
> mentioned, and it renames the -modifiers option to -functions, as you
> suggested.
>
> Please let me know what other changes are required.  Also, if I should
> write a NEWS entry, let me know and I'll add one.

Thanks, everything looks right.  The only thing I'm unsure about is the
default value.  I don't know how important is to highlight the distinction
between file and non-file buffers.  But it's a matter of taste, so
I can't argue against or for a specific default value.  Ideally, the
default value should reflect preferences of the most users, but even the
conducted surveys don't help, as the discussion about the toolbar indicates.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-16  9:03                 ` Juri Linkov
@ 2020-12-16 10:26                   ` Adam Porter
  2020-12-16 20:46                     ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Adam Porter @ 2020-12-16 10:26 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1344 bytes --]

Juri Linkov <juri@linkov.net> writes:

> Thanks, everything looks right.  The only thing I'm unsure about is
> the default value.  I don't know how important is to highlight the
> distinction between file and non-file buffers.  But it's a matter of
> taste, so I can't argue against or for a specific default value.

I don't know how important it is, either.  :)  But I think it's very
helpful for distinguishing buffers, especially in the smaller text of
the tab-line.  It seems to me that it does no harm, and it seems more
useful than not, so it seems that it might as well be the default.

> Ideally, the default value should reflect preferences of the most
> users, but even the conducted surveys don't help, as the discussion
> about the toolbar indicates.

I don't think we should use design-by-committee for every option, even
if we could.  To a certain extent, users won't know what they want until
they try it (cf. Ford's famous saying about asking his customers what
they wanted).  I think we should set the most useful defaults, and users
can customize to their taste.

That's my opinion, anyway.  I'll adjust the patch according to whatever
you or Eli think is best.  Let me know.

By the way, the attached patch tidies up a couple of things, including
removing a FIXME that seems to be not a bug after all.

Thanks for your help.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 5095 bytes --]

From df2b42fa06651d93267954aa9af6fb3cff90fb0f Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] tab-line: New faces and functions

* lisp/tab-line.el:
(tab-line-tab-face-function): New option.
(tab-line-tab-face-functions): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-tab-special): New face.
(tab-line-tab-face-inactive-alternating): New function.
(tab-line-tab-face-special): New function.
(tab-line-format-template): Use new function.

Thanks to Juri Linkov and Eli Zaretskii for their guidance.
---
 lisp/tab-line.el | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 59 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f..c944471 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,18 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-tab-face-functions '(tab-line-tab-face-special)
+  "Functions called to modify tab faces.
+Each function is called with five arguments: the tab, a list of
+all tabs, the face returned by the previously called modifier,
+whether the tab is a buffer, and whether the tab is selected."
+  :type '(repeat
+          (choice (function-item tab-line-tab-face-special)
+                  (function-item tab-line-tab-face-inactive-alternating)
+                  (function :tag "Custom function")))
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +76,25 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  `((t (:inherit tab-line-tab-inactive :background "grey65")))
+  "Alternate face for inactive tab-line tabs.
+Applied to alternating tabs when option
+`tab-line-tab-face-functions' includes function
+`tab-line-tab-face-inactive-alternating'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
+(defface tab-line-tab-special
+  '((default (:weight bold))
+    (((supports :slant italic))
+     (:slant italic :weight normal)))
+  "Face for special (i.e. non-file-backed) tabs.
+Applied when option `tab-line-tab-face-functions' includes
+function `tab-line-tab-face-special'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -412,7 +444,14 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (if selected-p
+                              (if (eq (selected-window) (old-selected-window))
+                                  'tab-line-tab-current
+                                'tab-line-tab)
+                            'tab-line-tab-inactive)))
+               (dolist (fn tab-line-tab-face-functions)
+                 (setf face (funcall fn tab tabs face buffer-p selected-p)))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +464,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
@@ -453,6 +488,24 @@ tab-line-format-template
                 tab-line-new-button)
        (list tab-line-new-button)))))
 
+(defun tab-line-tab-face-inactive-alternating (tab tabs face _buffer-p selected-p)
+  "Return FACE for TAB in TABS with alternation.
+When TAB is an inactive buffer and is even-numbered, make FACE
+inherit from `tab-line-tab-inactive-alternate'.  For use in
+`tab-line-tab-face-functions'."
+  (when (and (not selected-p) (cl-evenp (cl-position tab tabs)))
+    (setf face `(:inherit (tab-line-tab-inactive-alternate ,face))))
+  face)
+
+(defun tab-line-tab-face-special (tab _tabs face buffer-p _selected-p)
+  "Return FACE for TAB according to whether it's special.
+When TAB is a non-file-backed buffer, make FACE inherit from
+`tab-line-tab-special'.  For use in
+`tab-line-tab-face-functions'."
+  (when (and buffer-p (not (buffer-file-name tab)))
+    (setf face `(:inherit (tab-line-tab-special ,face))))
+  face)
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-16  2:58           ` Adam Porter
@ 2020-12-16 15:41             ` Eli Zaretskii
  0 siblings, 0 replies; 25+ messages in thread
From: Eli Zaretskii @ 2020-12-16 15:41 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

> From: Adam Porter <adam@alphapapa.net>
> Date: Tue, 15 Dec 2020 20:58:35 -0600
> 
> > I'm not sure I understand why would want to inherit just the
> > background color.  What's wrong with inheriting all the rest?
> 
> I would guess that the mode-line face could have other attributes that
> we wouldn't want to interfere with the tab-line faces, e.g. size or
> family.  The only reason I would want to inherit from mode-line is to
> get the background color.

Then inherit from the face and override the attributes you don't want.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-16 10:26                   ` Adam Porter
@ 2020-12-16 20:46                     ` Juri Linkov
  2020-12-18  3:55                       ` Adam Porter
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2020-12-16 20:46 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

>> Thanks, everything looks right.  The only thing I'm unsure about is
>> the default value.  I don't know how important is to highlight the
>> distinction between file and non-file buffers.  But it's a matter of
>> taste, so I can't argue against or for a specific default value.
>
> I don't know how important it is, either.  :)  But I think it's very
> helpful for distinguishing buffers, especially in the smaller text of
> the tab-line.  It seems to me that it does no harm, and it seems more
> useful than not, so it seems that it might as well be the default.

The problem is that it's not self-evident to the users why some tabs
are displayed in italic, and other tabs are not.

But if no one opposed to this change, then etc/NEWS should explain
the difference of tab styles for the new default value.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-16 20:46                     ` Juri Linkov
@ 2020-12-18  3:55                       ` Adam Porter
  2020-12-23 21:07                         ` Juri Linkov
  0 siblings, 1 reply; 25+ messages in thread
From: Adam Porter @ 2020-12-18  3:55 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1147 bytes --]

Juri Linkov <juri@linkov.net> writes:

>>> Thanks, everything looks right.  The only thing I'm unsure about is
>>> the default value.  I don't know how important is to highlight the
>>> distinction between file and non-file buffers.  But it's a matter of
>>> taste, so I can't argue against or for a specific default value.
>>
>> I don't know how important it is, either.  :)  But I think it's very
>> helpful for distinguishing buffers, especially in the smaller text of
>> the tab-line.  It seems to me that it does no harm, and it seems more
>> useful than not, so it seems that it might as well be the default.
>
> The problem is that it's not self-evident to the users why some tabs
> are displayed in italic, and other tabs are not.

You're right, but I would say that many things in Emacs aren't
self-evident but are useful.  :)  Of course, I'll defer to your or the
other maintainers' judgment if this seems like a bad idea.

> But if no one opposed to this change, then etc/NEWS should explain
> the difference of tab styles for the new default value.

This new patch includes such a news entry.

Thanks for your guidance with this work.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 6079 bytes --]

From d92420dc655368dcac7eaa6742001bdd1b3f122c Mon Sep 17 00:00:00 2001
From: Adam Porter <adam@alphapapa.net>
Date: Sun, 13 Dec 2020 05:54:28 +0000
Subject: [PATCH] * lisp/tab-line.el: New options, faces, and functions

* lisp/tab-line.el:
(tab-line-tab-face-functions): New option.
(tab-line-tab-inactive-alternate): New face.
(tab-line-tab-special): New face.
(tab-line-tab-face-inactive-alternating): New function.
(tab-line-tab-face-special): New function.
(tab-line-format-template): Use them.

* etc/NEWS: Update.

With thanks to Juri Linkov and Eli Zaretskii for their guidance.
---
 etc/NEWS         | 12 +++++++++++
 lisp/tab-line.el | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 909473f..2233139 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -371,6 +371,18 @@ value of 'tab-bar-show'.
 If your mouse or trackpad supports it, you can now scroll tabs when
 the mouse pointer is in the tab line by scrolling left or right.
 
+---
+*** New tab-line faces and options
+The face 'tab-line-tab-special' is used for tabs whose buffers are
+special, i.e. not file-backed.  The face
+'tab-line-tab-inactive-alternate' is used to display inactive tabs
+with an alternating background color, making them easier to
+distinguish between, especially if the face 'tab-line-tab' is
+configured to not display with a box; this alternate face is only
+applied when the option 'tab-line-tab-face-functions' is
+so-configured.  That option may also be used to customize tab-line
+faces in other ways.
+
 ** New bindings in occur-mode, 'next-error-no-select' bound to 'n' and
 'previous-error-no-select' bound to 'p'.
 
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 46bf89f..c944471 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -27,6 +27,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
 
 \f
@@ -35,6 +36,18 @@ tab-line
   :group 'convenience
   :version "27.1")
 
+(defcustom tab-line-tab-face-functions '(tab-line-tab-face-special)
+  "Functions called to modify tab faces.
+Each function is called with five arguments: the tab, a list of
+all tabs, the face returned by the previously called modifier,
+whether the tab is a buffer, and whether the tab is selected."
+  :type '(repeat
+          (choice (function-item tab-line-tab-face-special)
+                  (function-item tab-line-tab-face-inactive-alternating)
+                  (function :tag "Custom function")))
+  :group 'tab-line
+  :version "28.1")
+
 (defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
   "Faces used in the tab line."
   :group 'tab-line
@@ -63,6 +76,25 @@ tab-line-tab-inactive
   :version "27.1"
   :group 'tab-line-faces)
 
+(defface tab-line-tab-inactive-alternate
+  `((t (:inherit tab-line-tab-inactive :background "grey65")))
+  "Alternate face for inactive tab-line tabs.
+Applied to alternating tabs when option
+`tab-line-tab-face-functions' includes function
+`tab-line-tab-face-inactive-alternating'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
+(defface tab-line-tab-special
+  '((default (:weight bold))
+    (((supports :slant italic))
+     (:slant italic :weight normal)))
+  "Face for special (i.e. non-file-backed) tabs.
+Applied when option `tab-line-tab-face-functions' includes
+function `tab-line-tab-face-special'."
+  :version "28.1"
+  :group 'tab-line-faces)
+
 (defface tab-line-tab-current
   '((default
       :inherit tab-line-tab)
@@ -412,7 +444,14 @@ tab-line-format-template
                                   (cdr (assq 'selected tab))))
                     (name (if buffer-p
                               (funcall tab-line-tab-name-function tab tabs)
-                            (cdr (assq 'name tab)))))
+                            (cdr (assq 'name tab))))
+                    (face (if selected-p
+                              (if (eq (selected-window) (old-selected-window))
+                                  'tab-line-tab-current
+                                'tab-line-tab)
+                            'tab-line-tab-inactive)))
+               (dolist (fn tab-line-tab-face-functions)
+                 (setf face (funcall fn tab tabs face buffer-p selected-p)))
                (concat
                 separator
                 (apply 'propertize
@@ -425,11 +464,7 @@ tab-line-format-template
                        `(
                          tab ,tab
                          ,@(if selected-p '(selected t))
-                         face ,(if selected-p
-                                   (if (eq (selected-window) (old-selected-window))
-                                       'tab-line-tab-current
-                                     'tab-line-tab)
-                                 'tab-line-tab-inactive)
+                         face ,face
                          mouse-face tab-line-highlight)))))
            tabs))
          (hscroll-data (tab-line-auto-hscroll strings hscroll)))
@@ -453,6 +488,24 @@ tab-line-format-template
                 tab-line-new-button)
        (list tab-line-new-button)))))
 
+(defun tab-line-tab-face-inactive-alternating (tab tabs face _buffer-p selected-p)
+  "Return FACE for TAB in TABS with alternation.
+When TAB is an inactive buffer and is even-numbered, make FACE
+inherit from `tab-line-tab-inactive-alternate'.  For use in
+`tab-line-tab-face-functions'."
+  (when (and (not selected-p) (cl-evenp (cl-position tab tabs)))
+    (setf face `(:inherit (tab-line-tab-inactive-alternate ,face))))
+  face)
+
+(defun tab-line-tab-face-special (tab _tabs face buffer-p _selected-p)
+  "Return FACE for TAB according to whether it's special.
+When TAB is a non-file-backed buffer, make FACE inherit from
+`tab-line-tab-special'.  For use in
+`tab-line-tab-face-functions'."
+  (when (and buffer-p (not (buffer-file-name tab)))
+    (setf face `(:inherit (tab-line-tab-special ,face))))
+  face)
+
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-18  3:55                       ` Adam Porter
@ 2020-12-23 21:07                         ` Juri Linkov
  2020-12-24 11:26                           ` Adam Porter
  0 siblings, 1 reply; 25+ messages in thread
From: Juri Linkov @ 2020-12-23 21:07 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

>> The problem is that it's not self-evident to the users why some tabs
>> are displayed in italic, and other tabs are not.
>
> You're right, but I would say that many things in Emacs aren't
> self-evident but are useful.  :)  Of course, I'll defer to your or the
> other maintainers' judgment if this seems like a bad idea.

I think this is a bad idea, unlike your other idea of
color coding by workspaces that was a great idea.

But since no one opposed this default value,
I pushed your patch as is.  Thanks for making it
easy to customize, so there is no problem :-)



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] tab-line-alternate-colors
  2020-12-23 21:07                         ` Juri Linkov
@ 2020-12-24 11:26                           ` Adam Porter
  0 siblings, 0 replies; 25+ messages in thread
From: Adam Porter @ 2020-12-24 11:26 UTC (permalink / raw)
  To: emacs-devel

Juri Linkov <juri@linkov.net> writes:

>>> The problem is that it's not self-evident to the users why some tabs
>>> are displayed in italic, and other tabs are not.
>>
>> You're right, but I would say that many things in Emacs aren't
>> self-evident but are useful.  :)  Of course, I'll defer to your or the
>> other maintainers' judgment if this seems like a bad idea.
>
> I think this is a bad idea, unlike your other idea of color coding by
> workspaces that was a great idea.
>
> But since no one opposed this default value, I pushed your patch as
> is.  Thanks for making it easy to customize, so there is no problem
> :-)

I would have been glad to remove that on your objection, but thank you
for your humility and helpfulness with this patch.  :)




^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2020-12-24 11:26 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-13  6:04 [PATCH] tab-line-alternate-colors Adam Porter
2020-12-13  6:17 ` Adam Porter
2020-12-13  8:45 ` Juri Linkov
2020-12-13 10:06   ` Adam Porter
2020-12-13 11:13     ` Adam Porter
2020-12-13 15:21     ` Eli Zaretskii
2020-12-14  2:17       ` Adam Porter
2020-12-14 15:34         ` Eli Zaretskii
2020-12-16  2:58           ` Adam Porter
2020-12-16 15:41             ` Eli Zaretskii
2020-12-13 21:25     ` Juri Linkov
2020-12-14  4:33       ` Adam Porter
2020-12-14  9:10         ` Juri Linkov
2020-12-14 10:05           ` Adam Porter
2020-12-14 19:37             ` Juri Linkov
2020-12-16  3:24               ` Adam Porter
2020-12-16  3:55                 ` Adam Porter
2020-12-16  9:03                 ` Juri Linkov
2020-12-16 10:26                   ` Adam Porter
2020-12-16 20:46                     ` Juri Linkov
2020-12-18  3:55                       ` Adam Porter
2020-12-23 21:07                         ` Juri Linkov
2020-12-24 11:26                           ` Adam Porter
2020-12-14  9:14         ` Adam Porter
2020-12-14 19:33           ` Juri Linkov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).