From 666e2cd2546c7a9bda48f5857b032f97accac6fb Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sun, 10 Dec 2023 05:33:48 -0800 Subject: [PATCH 2/4] [5.7] Promote "normal" faces in erc-track * etc/ERC-NEWS: Add entry for new behavior involving the option `erc-track-faces-normal-list'. * lisp/erc/erc-button.el (erc-button-nick-default-face): New face to serve as default for `erc-button-nickname-face'. (erc-button-nickname-face): Change default value to `erc-button-nick-default-face'. * lisp/erc/erc-track.el (erc-track--old-nick-button-faces, erc-track--massage-nick-button-faces): New supporting variable and function to serve as Custom :set function for priority and "normal" face-list options. (erc-track-faces-priority-list, erc-track-faces-normal-list): Change values for `match' module faces to feature `erc-button-nick-default-face' instead of `erc-nick-default-face'. (erc-track-ignore-normal-contenders-p): New compatibility switch to access pre-5.6 behavior, in which faces in `erc-track-faces-normal-list' were only considered for promotion to the mode line if the current face occupying that pole position wasn't present. (erc-track-mode, erc-track-enable, erc-track-disable): Add FIXME comments regarding perceived futility of `erc-server-001-functions and likely unneeded hook removal. Run common buffer-local setup and teardown. (erc-track--normal-faces): New local variable, a snapshot of `erc-track-faces-normal-list'. (erc-track--setup): New function to stash `erc-track-faces-normal-list' on init. (erc-track-select-mode-line-face): Offer alternate explanation of certain particulars in doc string. (erc-track--gett): New helper function. (erc-track--select-mode-line-face): New function similar to its public namesake except that it considers other viable candidates among the "normal" alternatives. (erc-track-modified-channels): Only run face selection portion when faces are actually found. Use `erc-track--select-mode-line-face' instead of `erc-track-select-mode-line-face'. * test/lisp/erc/erc-track-tests.el (erc-track-select-mode-line-face): New test. (erc-track-tests--select-mode-line-face): New function. (erc-track--select-mode-line-face): New test. (Bug#67767) --- etc/ERC-NEWS | 39 ++++++ lisp/erc/erc-button.el | 8 +- lisp/erc/erc-track.el | 219 +++++++++++++++++++++++++++---- test/lisp/erc/erc-track-tests.el | 130 ++++++++++++++++++ 4 files changed, 373 insertions(+), 23 deletions(-) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 4642c742b0f..40e3d5d5638 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -170,6 +170,19 @@ options, like 'erc-command-indicator', have moved to the 'erc-goodies' library, although their Custom groups remain the same. Add 'command-indicator' to 'erc-modules' to get started. +** Option 'erc-track-faces-normal-list' slightly more influential. +This option has always been a source of confusion for users, mainly +because its influence rode heavily on the makeup of faces in a given +message. Historically, when a buffer's current mode-line face was a +member of this option's value, ERC would only swap it out for a fellow +"normal" if it was absent from message being processed. Beginning +with this release, ERC now looks to other ranked and (if necessary) +unranked "normals" instead of sustaining the same face between +messages. This was done to better honor the stated purpose of the +option, which is to provide consistent visual feedback when buffer +activity occurs. If you experience problems with this development, +see the compatibility flag 'erc-track-ignore-normal-contenders-p'. + ** 'erc-button-alist' and 'erc-nick-popup-alist' have evolved slightly. It's no secret that the 'buttons' module treats potential nicknames specially. This is perhaps most evident in its treatment of the @@ -184,6 +197,23 @@ s-expressions, which ERC will continue to honor. Although the default lineup remains functionally equivalent, its members have all been updated accordingly. +** 'erc-track-faces-priority-list' and 'erc-track-faces-normal-list' slimmed. +These options have been purged of certain 'button'-related face +combinations. Originally added in ERC 5.3, these combinations +described the effect of "buttonizing" atop faces added by the 'match' +module, like '(erc-nick-default-face erc-pal-face)'. However, since +at least Emacs 27, 'match' has run before 'button' in +'erc-insert-modify-hook', meaning such permutations aren't possible. + +More importantly, users who've customized either of these options +should update them with the new default value of the option +'erc-button-nickname-face'. Like 'erc-nick-default-face', which it +replaces, the new 'erc-button-nick-default-face' is also a "real" +face. Its sole reason for existing is to make it easier for users and +modules to distinguish between basic buttonized faces and +'erc-nick-default-face', which is now reserved to mean the base +"speaker" face. + ** Option 'erc-query-on-unjoined-chan-privmsg' restored and renamed. This option was accidentally removed from the default client in ERC 5.5 and was thus prevented from influencing PRIVMSG routing. It's now @@ -306,6 +336,15 @@ from 't' to the more useful 'erc-prompt', although the property of the same name has been retained and now has a value of 'hidden' when disconnected. +*** Lists of faces in buttonized text are no longer nested. +Previously, when "buttonizing" a new region, ERC would combine faces +by blindly consing the new onto the existing. In theory, this kept a +nice record of all modifications to a given region. However, it also +complicated life for other modules wanting to analyze and operate on +these regions. Beginning with this release, ERC now merges combined +faces together when creating buttons, although the odd nested list may +still crop up here and there. + *** Members of insert- and send-related hooks have been reordered. As anyone reading this is no doubt aware, both built-in and third-party modules rely on certain hooks for adjusting incoming and diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el index e1c10be53f6..f10d7a2fce7 100644 --- a/lisp/erc/erc-button.el +++ b/lisp/erc/erc-button.el @@ -70,6 +70,11 @@ erc-button "ERC button face." :group 'erc-faces) +(defface erc-button-nick-default-face '((t :inherit erc-nick-default-face)) + "Default face for a buttonized nickname." + :package-version '(ERC . "5.7") ; FIXME sync on release + :group 'erc-faces) + (defcustom erc-button-face 'erc-button "Face used for highlighting buttons in ERC buffers. @@ -78,8 +83,9 @@ erc-button-face :type 'face :group 'erc-faces) -(defcustom erc-button-nickname-face 'erc-nick-default-face +(defcustom erc-button-nickname-face 'erc-button-nick-default-face "Face used for ERC nickname buttons." + :package-version '(ERC . "5.7") ; FIXME sync on release :type 'face :group 'erc-faces) diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index a36b781e04d..478eabaa961 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el @@ -161,23 +161,39 @@ erc-track-use-faces \(e.g. `erc-pal-face' is used if a pal sent a message to that channel.)" :type 'boolean) +;; Historically, `erc-track-faces-priority-list' had members +;; describing the effect of buttonizing atop faces from `match', e.g., +;; (erc-nick-default-face erc-pal-face). However, since at least +;; Emacs 27, `match' has done its damage after `button' in +;; `erc-insert-modify-hook', meaning such permutations cannot exist. +(defvar erc-track--old-nick-button-faces + '((erc-nick-default-face erc-default-face)) + "List of obsolete nick button faces.") + +(defun erc-track--massage-nick-button-faces (val) + "Update members of face list VAL to have the default nick button face. +In ERC 5.7, it changed from `erc-current-nick-face' to +`erc-button-nick-default-face'." + (mapcar (lambda (f) + (if (and (eq (car-safe f) 'erc-nick-default-face) + (member f erc-track--old-nick-button-faces)) + (cons 'erc-button-nick-default-face (cdr f)) + f)) + val)) + (defcustom erc-track-faces-priority-list '(erc-error-face - (erc-nick-default-face erc-current-nick-face) erc-current-nick-face erc-keyword-face - (erc-nick-default-face erc-pal-face) erc-pal-face erc-nick-msg-face erc-direct-msg-face (erc-button erc-default-face) - (erc-nick-default-face erc-dangerous-host-face) erc-dangerous-host-face erc-nick-default-face - (erc-nick-default-face erc-default-face) + (erc-button-nick-default-face erc-default-face) erc-default-face erc-action-face - (erc-nick-default-face erc-fool-face) erc-fool-face erc-notice-face erc-input-face @@ -188,6 +204,9 @@ erc-track-faces-priority-list Note that ERC prioritizes certain faces reserved for critical messages regardless of this option's value." + :package-version '(ERC . "5.7") ; FIXME sync on release + :set (lambda (sym val) + (set-default sym (erc-track--massage-nick-button-faces val))) :type (erc--with-dependent-type-match (repeat (choice face (repeat :tag "Combination" face))) erc-button)) @@ -209,10 +228,9 @@ erc-track-priority-faces-only (defcustom erc-track-faces-normal-list '((erc-button erc-default-face) - (erc-nick-default-face erc-dangerous-host-face) erc-dangerous-host-face erc-nick-default-face - (erc-nick-default-face erc-default-face) + (erc-button-nick-default-face erc-default-face) erc-default-face erc-action-face) "A list of faces considered to be part of normal conversations. @@ -224,10 +242,26 @@ erc-track-faces-normal-list message. This gives a rough indication that active conversations are occurring in these channels. +Note that ERC makes a copy of this option when initializing the +module. To see your changes reflected mid-session, cycle +\\[erc-track-mode]. + The effect may be disabled by setting this variable to nil." + :package-version '(ERC . "5.7") ; FIXME sync on release + :set (lambda (sym val) + (set-default sym (erc-track--massage-nick-button-faces val))) :type '(repeat (choice face (repeat :tag "Combination" face)))) +(defvar erc-track-ignore-normal-contenders-p nil + "Compatibility flag to promote only exclusively new \"normal\" faces. +When non-nil, revert to pre-5.6 behavior in which a current +mode-line face that both outranks and is absent from the current +message is eligible for replacement with a fellow face from +`erc-track-faces-normal-list' that does appear in the message. +By extension, when enabled, never replace the current, reigning +mode-line face if it's present in the current message.") + (defcustom erc-track-position-in-mode-line 'before-modes "Where to show modified channel information in the mode-line. @@ -518,6 +552,9 @@ track (progn (add-hook 'window-configuration-change-hook #'erc-user-is-active) (add-hook 'erc-send-completed-hook #'erc-user-is-active) + ;; FIXME find out why this uses `erc-server-001-functions'. + ;; `erc-user-is-active' runs when `erc-server-connected' is + ;; non-nil. But this hook usually only runs when it's nil. (add-hook 'erc-server-001-functions #'erc-user-is-active)) (erc-track-add-to-mode-line erc-track-position-in-mode-line) (erc-update-mode-line) @@ -528,6 +565,8 @@ track ;; enable the tracking keybindings (add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe) (erc-track-minor-mode-maybe)) + (add-hook 'erc-mode-hook #'erc-track--setup) + (unless erc--updating-modules-p (erc-buffer-do #'erc-track--setup)) (add-hook 'erc-networks--copy-server-buffer-functions #'erc-track--replace-killed-buffer)) ;; Disable: @@ -539,6 +578,7 @@ track #'erc-user-is-active) (remove-hook 'erc-send-completed-hook #'erc-user-is-active) (remove-hook 'erc-server-001-functions #'erc-user-is-active) + ;; FIXME remove this if unused. (remove-hook 'erc-timer-hook #'erc-user-is-active)) (remove-hook 'window-configuration-change-hook #'erc-window-configuration-change) @@ -548,9 +588,12 @@ track (remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe) (when erc-track-minor-mode (erc-track-minor-mode -1))) + (remove-hook 'erc-mode-hook #'erc-track--setup) + (erc-buffer-do #'erc-track--setup) (remove-hook 'erc-networks--copy-server-buffer-functions #'erc-track--replace-killed-buffer))) +;; FIXME move this above the module definition. (defcustom erc-track-when-inactive nil "Enable channel tracking even for visible buffers, if you are inactive." :type 'boolean @@ -562,6 +605,52 @@ erc-track-when-inactive (erc-track-enable)) (set sym val)))) +(defvar-local erc-track--normal-faces nil + "Local copy of `erc-track-faces-normal-list' as a hash table.") + +(defun erc-track--setup () + "Initialize a buffer for use with the `track' module. +If this is a server buffer or `erc-track-faces-normal-list' is +locally bound, create a new `erc-track--normal-faces' for the +current buffer. Otherwise, set the local value to the server +buffer's." + (if erc-track-mode + (let ((existing (erc-with-server-buffer erc-track--normal-faces)) + (localp (and erc--target + (local-variable-p 'erc-track-faces-normal-list))) + warnp table) + (unless (or erc--target (not (or (bound-and-true-p erc-button-mode) + (memq 'button erc-modules)))) + (dolist (opt '(erc-track-faces-normal-list + erc-track-faces-priority-list)) + (when (seq-some + (lambda (f) + (and (eq (car-safe f) 'erc-nick-default-face) + (member f erc-track--old-nick-button-faces))) + (symbol-value opt)) + (push opt warnp) + (set opt (erc-track--massage-nick-button-faces + (symbol-value opt))))) + (when warnp + (erc--warn-once-before-connect 'erc-track-mode + (if (cdr warnp) "Options " "Option ") + (mapconcat (lambda (o) (format "`%S'" o)) warnp " and ") + (if (cdr warnp) " contain" " contains") + " obsolete list-style faces intended to match buttonized" + " nicknames. To silence this warning, please update members" + " with `%S' at their head, like %S, by converting them to %S." + " ERC has done this for you for this session." + 'erc-nick-default-face '(erc-nick-default-face foo) + '(erc-button-nick-default-face foo)))) + (when (or (null existing) localp) + (setq table (map-into (mapcar (lambda (f) (cons f f)) + erc-track-faces-normal-list) + '(hash-table :test equal :weakness value)))) + (setq erc-track--normal-faces (or table existing)) + (unless (or localp existing) + (erc-with-server-buffer (setq erc-track--normal-faces table)))) + (kill-local-variable 'erc-track--normal-faces))) + ;;; Visibility (defvar erc-buffer-activity nil @@ -766,7 +855,12 @@ erc-track-select-mode-line-face face, if a member of `erc-track-faces-normal-list', to be replaced with another with lower priority face from NEW-FACES, if that face with highest priority in NEW-FACES is also a member of -`erc-track-faces-normal-list'." +`erc-track-faces-normal-list'. + +To put it another way, when CUR-FACE outranks all NEW-FACES and +doesn't appear among them, it's eligible to be replaced with a +fellow \"normal\" from NEW-FACES. But if it does appear among +them, it can't be replaced." (let ((choice (catch 'face (dolist (candidate erc-track-faces-priority-list) (when (or (equal candidate cur-face) @@ -785,6 +879,51 @@ erc-track-select-mode-line-face choice)) choice)))) +(define-inline erc-track--gett (table-or-function key) + "Look up KEY via TABLE-OR-FUNCTION." + (inline-quote + (if (functionp ,table-or-function) + (funcall ,table-or-function ,key) + (gethash ,key ,table-or-function)))) + +(defun erc-track--select-mode-line-face (cur-face new-faces ranks normals) + "Return CUR-FACE or a replacement for displaying in the mode-line, or nil. +Expect RANKS to be a list of faces and both NORMALS and the car +of NEW-FACES to be hash tables mapping faces to non-nil values. +Assume the latter's makeup and that of RANKS to resemble +`erc-track-face-normal-list' and `erc-track-faces-priority-list'. +If NEW-FACES has a cdr, expect it to be its car's contents +ordered from most recently seen (later in the buffer) to +earliest. In general, act like `erc-track-select-mode-line-face' +except reconsider NEW-FACES when CUR-FACE outranks all its +members. That is, choose the highest RANKS among NEW-FACES not +equal to CUR-FACE. Failing that, choose the first face in +NORMALS to appear anywhere in NEW-FACES, but only if NEW-FACES +has a cdr. If NORMALS is a function, call it with the name of a +face to query membership." + (cl-check-type erc-track-ignore-normal-contenders-p null) + (cl-check-type new-faces cons) + (when-let ((choice (catch 'face + (dolist (candidate ranks) + (when (or (equal candidate cur-face) + (gethash candidate (car new-faces))) + (throw 'face candidate)))))) + (when-let (((equal choice cur-face)) + ((erc-track--gett normals choice)) + (contender (catch 'face + (progn + (dolist (candidate ranks) + (when (and (not (equal candidate choice)) + (gethash candidate (car new-faces)) + (erc-track--gett normals candidate)) + (throw 'face candidate))) + (dolist (f (cdr new-faces)) + (when (and (not (equal f choice)) + (erc-track--gett normals f)) + (throw 'face f))))))) + (setq choice contender)) + choice)) + (defvar erc-track--skipped-msgs '(datestamp) "Values of `erc-msg' text prop to ignore.") @@ -819,31 +958,43 @@ erc-track-modified-channels ;; (in the car), change its face attribute (in the cddr) if ;; necessary. See `erc-modified-channels-alist' for the ;; exact data structure used. - (let ((faces (erc-faces-in (buffer-string))) - (erc-track-faces-priority-list - `(,@erc-track--attn-faces ,@erc-track-faces-priority-list))) - (unless (and - (or (eq erc-track-priority-faces-only 'all) - (member this-channel erc-track-priority-faces-only)) - (not (catch 'found - (dolist (f faces) - (when (member f erc-track-faces-priority-list) - (throw 'found t)))))) + (when-let + ((faces (if erc-track-ignore-normal-contenders-p + (erc-faces-in (buffer-string)) + (erc-track--get-faces-in-current-message))) + (normals erc-track--normal-faces) + (erc-track-faces-priority-list + `(,@erc-track--attn-faces ,@erc-track-faces-priority-list)) + (ranks erc-track-faces-priority-list) + ((not (and + (or (eq erc-track-priority-faces-only 'all) + (member this-channel erc-track-priority-faces-only)) + (not (catch 'found + (dolist (f ranks) + (when (gethash f (or (car-safe faces) faces)) + (throw 'found t))))))))) + (progn ; FIXME remove `progn' on next major edit (if (not (assq (current-buffer) erc-modified-channels-alist)) ;; Add buffer, faces and counts (setq erc-modified-channels-alist (cons (cons (current-buffer) (cons - 1 (erc-track-select-mode-line-face - nil faces))) + 1 (if erc-track-ignore-normal-contenders-p + (erc-track-select-mode-line-face + nil faces) + (erc-track--select-mode-line-face + nil faces ranks normals)))) erc-modified-channels-alist)) ;; Else modify the face for the buffer, if necessary. (when faces (let* ((cell (assq (current-buffer) erc-modified-channels-alist)) (old-face (cddr cell)) - (new-face (erc-track-select-mode-line-face - old-face faces))) + (new-face (if erc-track-ignore-normal-contenders-p + (erc-track-select-mode-line-face + old-face faces) + (erc-track--select-mode-line-face + old-face faces ranks normals)))) (setcdr cell (cons (1+ (cadr cell)) new-face))))) ;; And display it (erc-modified-channels-display))) @@ -872,6 +1023,30 @@ erc-faces-in (push cur faces))) faces)) +(defvar erc-track--face-reject-function nil + "Function called with face in current buffer to massage or reject.") + +(defun erc-track--get-faces-in-current-message () + "Collect all faces in the narrowed buffer. +Return a cons of a hash table and a list ordered from most +recently seen to earliest seen." + (let ((i (text-property-not-all (point-min) (point-max) 'font-lock-face nil)) + (seen (make-hash-table :test #'equal)) + ;; + (rfaces ()) + (faces (make-hash-table :test #'equal))) + (while-let ((i) + (cur (get-text-property i 'face))) + (unless (gethash cur seen) + (puthash cur t seen) + (when erc-track--face-reject-function + (setq cur (funcall erc-track--face-reject-function cur))) + (when cur + (push cur rfaces) + (puthash cur t faces))) + (setq i (next-single-property-change i 'font-lock-face))) + (cons faces rfaces))) + ;;; Buffer switching (defvar erc-track-last-non-erc-buffer nil diff --git a/test/lisp/erc/erc-track-tests.el b/test/lisp/erc/erc-track-tests.el index ab8d708b721..4477727be8a 100644 --- a/test/lisp/erc/erc-track-tests.el +++ b/test/lisp/erc/erc-track-tests.el @@ -120,4 +120,134 @@ erc-track--erc-faces-in (should (erc-faces-in str0)) (should (erc-faces-in str1)) )) +;; This simulates an alternating bold/non-bold [#c] in the mode-line, +;; i.e., an `erc-modified-channels-alist' that vacillates between +;; +;; ((# 42 . erc-default-face)) +;; +;; and +;; +;; ((# 42 erc-nick-default-face erc-default-face)) +;; +;; This is a fairly typical scenario where consecutive messages +;; feature speaker and addressee button highlighting and otherwise +;; plain message bodies. This mapping of phony to real faces +;; describes the picture in 5.6: +;; +;; `1': (erc-button erc-default-face) ; URL +;; `2': (erc-nick-default-face erc-default-face) ; mention +;; `3': erc-default-face ; body +;; `_': (erc-nick-default-face erc-nick-default-face) ; speaker +;; +;; The `_' represents a commonly occurring face (a ) that's +;; not present in either option's default (standard) value. It's a +;; no-op from the POV of `erc-track-select-mode-line-face'. + +(ert-deftest erc-track-select-mode-line-face () + + ;; Observed (see key above). + (let ((erc-track-faces-priority-list '(1 2 3)) + (erc-track-faces-normal-list '(1 2 3))) + + (should (equal 2 (erc-track-select-mode-line-face 3 '(2 _ 3)))) + (should (equal 2 (erc-track-select-mode-line-face 2 '(2 _ 3)))) + (should (equal 3 (erc-track-select-mode-line-face 2 '(_ 3)))) + (should (equal 2 (erc-track-select-mode-line-face 3 '(2 3)))) + (should (equal 3 (erc-track-select-mode-line-face 2 '(3)))) + + (should (equal 1 (erc-track-select-mode-line-face 1 '(2 1 3)))) + (should (equal 1 (erc-track-select-mode-line-face 1 '(1 3)))) + (should (equal 1 (erc-track-select-mode-line-face 1 '(1 3 2)))) + (should (equal 1 (erc-track-select-mode-line-face 1 '(3 1))))) + + ;; When the current face outranks all new faces and doesn't appear + ;; among them, it's eligible to be replaced with a fellow "normal" + ;; from those new faces. But if it does appear among them, it's + ;; never replaced. + (let ((erc-track-faces-priority-list '(a b)) + (erc-track-faces-normal-list '(a b))) + + (should (equal 'a (erc-track-select-mode-line-face 'a '(b a)))) + (should (equal 'a (erc-track-select-mode-line-face 'a '(a b)))) + (should (equal 'a (erc-track-select-mode-line-face 'b '(b a)))) + (should (equal 'a (erc-track-select-mode-line-face 'b '(a b)))) + + (should (equal 'a (erc-track-select-mode-line-face 'b '(a)))) + (should (equal 'b (erc-track-select-mode-line-face 'a '(b))))) + + ;; The ordering of the "normal" list doesn't matter. + (let ((erc-track-faces-priority-list '(a b)) + (erc-track-faces-normal-list '(b a))) + + (should (equal 'a (erc-track-select-mode-line-face 'a '(b a)))) + (should (equal 'a (erc-track-select-mode-line-face 'a '(a b)))) + (should (equal 'a (erc-track-select-mode-line-face 'b '(b a)))) + (should (equal 'a (erc-track-select-mode-line-face 'b '(a b)))))) + +(defun erc-track-tests--select-mode-line-face (ranked normals cases) + (setq normals (map-into (mapcar (lambda (f) (cons f t)) normals) + '(hash-table :test equal))) + (pcase-dolist (`(,want ,cur-face ,new-faces) cases) + + (ert-info ((format "Observed: {cur: %S, new: %S, want: %S}" + cur-face new-faces want)) + (setq new-faces (cons (map-into + (mapcar (lambda (f) (cons f t)) new-faces) + '(hash-table :test equal)) + (reverse new-faces))) + (should (equal want (funcall #'erc-track--select-mode-line-face + cur-face new-faces ranked normals)))))) + +;; The main difference between these variants is that with the above, +;; when given alternating lines like +;; +;; CUR NEW CHOICE +;; text (mention $speaker text) => mention +;; mention ($speaker text) => text +;; +;; we see the effect of alternating faces in the indicator. But when +;; given consecutive lines with a similar composition, like +;; +;; text (mention $speaker text) => mention +;; text (mention $speaker text) => mention +;; +;; we lose the effect. With the variant below, we get +;; +;; text (mention $speaker text) => mention +;; text (mention $speaker text) => text +;; + +(ert-deftest erc-track--select-mode-line-face () + (should-not erc-track-ignore-normal-contenders-p) + + ;; These are the same test cases from the previous test. The syntax + ;; is (expected cur-face new-faces). + (erc-track-tests--select-mode-line-face + '(1 2 3) '(1 2 3) + '((2 3 (2 _ 3)) + (3 2 (2 _ 3)) + (3 2 (_ 3)) + (2 3 (2 3)) + (3 2 (3)) + (2 1 (2 1 3)) + (3 1 (1 3)) + (2 1 (1 3 2)) + (3 1 (3 1)))) + + (erc-track-tests--select-mode-line-face + '(a b) '(a b) + '((b a (b a)) + (b a (a b)) + (a b (b a)) + (a b (a b)) + (a b (a)) + (b a (b)))) + + (erc-track-tests--select-mode-line-face + '(a b) '(b a) + '((b a (b a)) + (b a (a b)) + (a b (b a)) + (a b (a b))))) + ;;; erc-track-tests.el ends here -- 2.42.0