Subject: Re: bug#68547: [PATCH] ; Fix 'mode-line-format-right-align' with ElDoc

From: João Távora <[email-masked]>
Date: Sat, 20 Jan 2024 13:55:21 +0000

On Sat, Jan 20, 2024 at 12:01 PM João Távora <[email-masked]> wrote:
> Thanks.  I pushed it.  I'm going to look at this function though,
> since I don't I love the logic of destroying any old buffer's
> mode-line-format and not restoring after the minibuffer is
> exited.

While we're on the subject, can you give this patch a try Eshel?

diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 912a7357ca7..78ce7ecd123 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -182,7 +182,7 @@ eldoc-current-idle-delay
   "Idle time delay currently in use by timer.
 This is used to determine if `eldoc-idle-delay' is changed by the user.")

-(defvar eldoc-message-function #'eldoc-minibuffer-message
+(defvar eldoc-message-function #'eldoc--minibuffer-message
   "The function used by `eldoc--message' to display messages.
 It should receive the same arguments as `message'.")

@@ -292,43 +292,42 @@ eldoc-schedule-timer
          (setq eldoc-current-idle-delay eldoc-idle-delay)
          (timer-set-idle-time eldoc-timer eldoc-idle-delay t))))

-(defvar eldoc-mode-line-string nil)
-(put 'eldoc-mode-line-string 'risky-local-variable t)
-
-(defun eldoc-minibuffer-message (format-string &rest args)
+(defvar eldoc--saved-mlf nil
+  "Saved `mode-line-format' used in `eldoc--minibuffer-message'.")
+(defun eldoc--minibuffer-message (format-string &rest args)
   "Display message specified by FORMAT-STRING and ARGS on the
mode-line as needed.
 This function displays the message produced by formatting ARGS
 with FORMAT-STRING on the mode line when the current buffer is a minibuffer.
 Otherwise, it displays the message like `message' would."
-  (if (or (bound-and-true-p edebug-mode) (minibufferp))
-      (progn
-        (add-hook 'post-command-hook #'eldoc-minibuffer--cleanup)
- (with-current-buffer
-     (window-buffer
-      (or (window-in-direction 'above (minibuffer-window))
- (minibuffer-selected-window)
- (get-largest-window)))
-          (when (and mode-line-format
-                     (not (and (listp mode-line-format)
-                               (assq 'eldoc-mode-line-string
mode-line-format))))
-     (setq mode-line-format
-                  (funcall
-                   (if (listp mode-line-format) #'append #'list)
-                   (list "" '(eldoc-mode-line-string
-       (" " eldoc-mode-line-string " ")))
-                   mode-line-format)))
-          (setq eldoc-mode-line-string
-                (when (stringp format-string)
-                  (apply #'format-message format-string args)))
-          (force-mode-line-update)))
-    (apply #'message format-string args)))
-
-(defun eldoc-minibuffer--cleanup ()
-  (unless (or (bound-and-true-p edebug-mode) (minibufferp))
-    (setq eldoc-mode-line-string nil
-          ;; https://debbugs.gnu.org/16920
-          eldoc-last-message nil)
-    (remove-hook 'post-command-hook #'eldoc-minibuffer--cleanup)))
+  (cond ((bound-and-true-p edebug-mode)
+         (eldoc--message-in-mode-line 'edebug-mode-hook format-string args))
+        ((minibufferp)
+         (eldoc--message-in-mode-line 'minibuffer-exit-hook
format-string args))
+        (t
+         (apply #'message format-string args))))
+
+(defun eldoc--message-in-mode-line (hook format-string args)
+  (with-current-buffer
+      (window-buffer
+       (or (window-in-direction 'above (minibuffer-window))
+           (minibuffer-selected-window)
+           (get-largest-window)))
+    (let ((buf (current-buffer)))
+      (cl-labels ((cleanup ()
+                    (with-current-buffer buf
+                      (remove-hook hook #'cleanup)
+                      (setq mode-line-format eldoc--saved-mlf
+                            eldoc--saved-mlf nil))))
+        (add-hook hook #'cleanup)
+        (setq eldoc--saved-mlf (or eldoc--saved-mlf mode-line-format))
+        (when format-string
+          (setq
+           mode-line-format
+           (funcall (if (listp eldoc--saved-mlf) #'cons #'list)
+                    (and format-string
+                         (apply #'format-message format-string args))
+                    eldoc--saved-mlf)))
+        (force-mode-line-update)))))

 (make-obsolete
  'eldoc-message "use `eldoc-documentation-functions' instead." "eldoc-1.1.0")

-- 
João Távora