Subject: bug#71883: [PATCH] Fix tab-bar-auto-width with customized tab-bar-tab-face-function

From: Joseph Turner <[email-masked]>
Date: Tue, 02 Jul 2024 09:25:10 -0700

Juri Linkov <[email-masked]> writes:

>> The function tab-bar-auto-width determines which tabs to automatically
>> resize based on the face applied to each tab's text.  If the face is one
>> of tab-bar-auto-width-faces, then the tab gets resized.  However, if
>> either tab-bar-tab-face-function or tab-bar-tab-group-face-function is
>> set to a function which does not apply one of tab-bar-auto-width-faces,
>> then the tabs which have a different face are not auto resized.
>>
>> A real-world example of this issue is in activities.el:
>>
>> https://github.com/alphapapa/activities.el/issues/76
>
> Thanks for the request.
>
> Maybe activities.el could add its face to tab-bar-auto-width-faces?

Unfortunately, this isn't possible.  activities.el sets
tab-bar-tab-face-function to

(defun activities-tabs--tab-bar-tab-face-function (tab)
  "Return a face for TAB.
If TAB represents an activity, face `activities-tabs' is added as
inherited."
  ;; TODO: Propose a tab-bar equivalent of `tab-line-tab-face-functions'.
  (let ((face (funcall activities-tabs-tab-bar-tab-face-function-original tab)))
    (if (activities-tabs--tab-parameter 'activity tab)
        `(:inherit (activities-tabs ,face))
      face)))

so there's no face symbol to match against.

> If not, then what about allowing tab-bar-auto-width-faces to have
> the value t that means that all tabs should be resized regardless of
> what faces they have.

Would you be willing to send a patch with this idea?

>> In the proposed patch, instead of checking each tab's face, we check
>> that the symbol at the start of each tab keymap matches
>>
>> (rx bos (or "current-tab" "tab-" "group-"))
>
>> -(defvar tab-bar-auto-width-faces
>> -  '( tab-bar-tab tab-bar-tab-inactive
>> -     tab-bar-tab-ungrouped
>> -     tab-bar-tab-group-inactive)
>> -  "Resize tabs only with these faces.")
>
> Sorry, we can't remove the existing variable to not break user
> configs.

You're right.

>> @@ -1250,8 +1244,8 @@ tab-bar-auto-width
>> -        (if (memq (get-text-property 0 'face (nth 2 item))
>> -                  tab-bar-auto-width-faces)
>> +        (if (string-match-p "\\`\\(?:current-tab\\|\\(?:group\\|tab\\)-\\)"
>> +                            (symbol-name (nth 0 item)))
>
> Matching the symbol name with the hard-coded regexp doesn't look right.
> Maybe better to add a new variable that contains a predicate function?
> When it returns t then resize.

What would be passed to the predicate function?

Thanks for the review!

Joseph