Subject: bug#40774: Error messages shouldn't be hidden when the user is idle

From: Juri Linkov <[email-masked]>
Date: Wed, 08 Dec 2021 21:21:22 +0200

>> > I can't find it on Github, and this is understandable - it's a new variable
>> > with quite limited usefulness.  I hoped that even if someone used it,
>> > mentioning it in the Incompatible Lisp Changes of NEWS would be sufficient
>> > as in case of all other incompatible changes.
>>
>> OK; then I'm OK with changing the semantics in Emacs 29 (and noting this
>> in the NEWS in Emacs 28), but perhaps Eli has an opinion here.  Eli?
>
> This is a long discussion, and I chimed in at least twice.  What
> exactly is the proposal for which you want my opinion?  Is there some
> patch I could study, perhaps?

The updated patch is here:

diff --git a/etc/NEWS b/etc/NEWS
index 55e3216e41..8a92a0dcaa 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -718,6 +718,11 @@ Emacs buffers, like indentation and the like.  The new ert function
 
 * Incompatible Lisp Changes in Emacs 29.1
 
+---
+** The return value of 'clear-message-function' is not ignored anymore.
+If the function returns t, then the message is not cleared,
+with the assumption that the function cleared it itself.
+
 ** User option 'mail-source-ignore-errors' is now obsolete.
 The whole mechanism for prompting users to continue in case of
 mail-source errors has been removed, so this option is no longer
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 28bd1df59a..d8db8898f1 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -864,7 +945,11 @@ clear-minibuffer-message
       (setq minibuffer-message-timer nil))
     (when (overlayp minibuffer-message-overlay)
       (delete-overlay minibuffer-message-overlay)
-      (setq minibuffer-message-overlay nil))))
+      (setq minibuffer-message-overlay nil)))
+
+  ;; Return nil telling the caller that the message
+  ;; should be also handled by the caller.
+  nil)
 
 (setq clear-message-function 'clear-minibuffer-message)
 
diff --git a/src/xdisp.c b/src/xdisp.c
index 0ff6286af7..c79168b1be 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12521,18 +12521,23 @@ set_message_1 (void *a1, Lisp_Object string)
 void
 clear_message (bool current_p, bool last_displayed_p)
 {
+  Lisp_Object preserve = Qnil;
+
   if (current_p)
     {
-      echo_area_buffer[0] = Qnil;
-      message_cleared_p = true;
-
       if (FUNCTIONP (Vclear_message_function))
         {
           ptrdiff_t count = SPECPDL_INDEX ();
           specbind (Qinhibit_quit, Qt);
-          safe_call (1, Vclear_message_function);
+          preserve = safe_call (1, Vclear_message_function);
           unbind_to (count, Qnil);
         }
+
+      if (!EQ (preserve, Qt))
+        {
+          echo_area_buffer[0] = Qnil;
+          message_cleared_p = true;
+        }
     }
 
   if (last_displayed_p)
@@ -36232,9 +36237,13 @@ syms_of_xdisp (void)
   DEFVAR_LISP ("clear-message-function", Vclear_message_function,
 	       doc: /* If non-nil, function to clear echo-area messages.
 Usually this function is called when the next input event arrives.
-The function is called without arguments.  It is expected to clear the
-message displayed by its counterpart function specified by
-`set-message-function'.  */);
+It is expected to clear the message displayed by its counterpart
+function specified by `set-message-function'.
+The function is called without arguments.
+If this function returns a non-t value, the message is cleared
+from the echo area as usual.  If this function returns t,
+this means that the message was already handled, and the original
+message text will not be cleared from the echo area.  */);
   Vclear_message_function = Qnil;
 
   DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
--