Subject: bug#77715: [PATCH] Add ring-bell functions for mode line and header line.

From: Elijah Gabe Pérez <[email-masked]>
Date: Sun, 27 Apr 2025 12:12:58 -0600

I don't know if there still interest on this,
I'm sending here a fixed and updated version of this patch.

This is ready to merge into master (unless there is something else).

>From 8941df9a32bdadef37a665f9665aafd5805dc255 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?El=C3=ADas=20Gabriel=20P=C3=A9rez?= <[email-masked]>
Date: Thu, 10 Apr 2025 11:38:21 -0600
Subject: [PATCH] New ring-bell functions for flash faces.  (bug#77715)

New functions for flash any face or echo area once whether
`ring-bell-function' is called.
* lisp/faces.el (flash-face): New face.
* lisp/simple.el (flash-line-duration, flash-face-faces): New
user options.
(flash-face-bell-function, flash-echo-area-bell-function): New
functions.
---
 etc/NEWS       | 24 ++++++++++++++++++++++++
 lisp/faces.el  | 11 +++++++++++
 lisp/simple.el | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index ade5abc43fc..8fb56c341f5 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -429,6 +429,11 @@ on the header lines are now these two: the selected window uses
 
 ** In 'customize-face', the "Font family" attribute now supports completion.
 
+** New face 'flash-face'.
+This face is used for flash a face briefly.
+Mainly used for 'flash-echo-area-bell-function' and
+'flash-face-bell-function'.
+
 ** 'process-adaptive-read-buffering' is now nil by default.
 Setting this variable to a non-nil value reduces performance and leads
 to wrong results in some cases.  We believe that it is no longer useful;
@@ -1919,6 +1924,25 @@ change their face if the current line exceeds the 'fill-column'.  The
 new face 'display-fill-column-indicator-warning-face' is used to
 highlight the fill-column indicators.  By default this is disabled.
 
+---
+*** New function 'flash-face-bell-function'.
+This function when called will flash a face briefly.
+Intended to be used in 'ring-bell-function'.
+
+---
+*** New function 'flash-echo-area-bell-function'.
+This function when called will flash current echo area briefly.
+Intended to be used in 'ring-bell-function'.
+
+---
+*** New user option 'flash-face-duration'.
+This option controls flash duration for 'flash-face-bell-function' and
+'flash-echo-area-bell-function'.
+
+---
+*** New user option 'flash-face-faces'.
+This option tells 'flash-face-bell-function' which faces should flash.
+
 ---
 ** Flymake
 
diff --git a/lisp/faces.el b/lisp/faces.el
index dbc0a2e04f6..b749627254c 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -2825,6 +2825,17 @@ header-line-inactive
   :group 'mode-line-faces
   :group 'basic-faces)
 
+(defface flash-face
+  '((((class color) (min-colors 88))
+     :background "red3" :foreground "white")
+    (((class color grayscale) (min-colors 88))
+     :background "grey10" :foreground "white")
+    (t
+     :inherit error :inverse-video t))
+  "Basic face used for flash a face briefly."
+  :version "31.1"
+  :group 'basic-faces)
+
 (defface vertical-border
   '((((type tty)) :inherit mode-line-inactive))
   "Face used for vertical window dividers on ttys."
diff --git a/lisp/simple.el b/lisp/simple.el
index ee09a6f1b19..5aa3027ada2 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -9389,6 +9389,50 @@ auto-save-mode
   (and (< buffer-saved-size 0)
        (setq buffer-saved-size 0)))
 
+(declare-function face-remap-remove-relative "face-remap" (cookie))
+
+(defcustom flash-face-duration 0.05
+  "Time (in seconds) used for flash face duration."
+  :type 'float
+  :version "31.1")
+
+(defcustom flash-face-faces
+  '(mode-line-active)
+  "A list of faces which `flash-face-bell-function' will flash them."
+  :type '(repeat face)
+  :version "31.1")
+
+(defun flash-face-bell-function ()
+  "Flash a face or faces as ring a bell.
+Intended to be used in `ring-bell-function'."
+  (when-let* (flash-face-duration ; Ensure time is non-nil
+              (cookies (mapcar (lambda (f) (face-remap-add-relative f 'flash-face))
+                               flash-face-faces)))
+    (unwind-protect
+        (sit-for flash-face-duration)
+      (mapc #'face-remap-remove-relative cookies))))
+
+(defun flash-echo-area-bell-function ()
+  "Flash echo area as ring a bell.
+Intended to be used in `ring-bell-function'."
+  ;; like `with-temp-message' but suppress message log for not flood
+  ;; messages buffer
+  (unless (minibufferp) ; Avoid conflicts if cursor is in minibuffer
+    (let ((with-temp-message
+              (propertize " " 'display `(space :align-to right) 'face
+                          'flash-face))
+          (current-message))
+      (unwind-protect
+          (progn
+            (when with-temp-message
+              (setq current-message (current-message))
+              (let (message-log-max)
+                (message "%s" with-temp-message)))
+            (sit-for flash-face-duration))
+        (and with-temp-message
+             (if current-message (message "%s" current-message)
+               (message nil)))))))
+
 (defgroup paren-blinking nil
   "Blinking matching of parens and expressions."
   :prefix "blink-matching-"
-- 
2.49.0

-- 
                                          - E.G via GNU Emacs and Org.