GNU bug report logs - #68547
[PATCH] ; Fix 'mode-line-format-right-align' with ElDoc

Previous Next

Package: emacs;

Reported by: Eshel Yaron <me <at> eshelyaron.com>

Date: Wed, 17 Jan 2024 19:45:02 UTC

Severity: minor

Tags: patch

Full log


View this message in rfc822 format

From: Stefan Kangas <stefankangas <at> gmail.com>
To: João Távora <joaotavora <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Eshel Yaron <me <at> eshelyaron.com>, 68547 <at> debbugs.gnu.org
Subject: bug#68547: [PATCH] ; Fix 'mode-line-format-right-align' with ElDoc
Date: Wed, 5 Mar 2025 19:31:01 -0800
João Távora <joaotavora <at> gmail.com> writes:

> On Sat, Jan 20, 2024 at 3:33 PM Eshel Yaron <me <at> eshelyaron.com> wrote:
>
>> Then I tried the following (somewhat pathological) use case:
>>
>> 0. Setup: (keymap-global-set "C-x w a" #'windmove-swap-states-left)
>> 1. Open two buffers in two windows side by side.
>> 2. Say `M-: (car `, to show info in the mode line of the left window.
>> 3. Without quitting the minibuffer, use `C-x o` to switch to the right
>>    window, followed by `C-x w a` to switch the buffers in the left and
>>    right windows.
>> 4. Return to the minibuffer and type `nil) RET` or something like that
>>    to exit the minibuffer.
>> 5. The `mode-line-format` of the left buffer is becomes nil, i.e. no mode line.
>>
>> Shuffling `mode-line-format` around is really tricky :(
>
> Indeed.  Your case is pathological, but not particularly hard to
> trigger.  Given the consequences are somewhat dire (vanished mode-line)
> , it should most definitely be handled.
>
> Try this version, please.  Only difference is it uses a setq-local
> for eldoc--saved-mlf instead of a setq.
>
> Please give it as much testing as you can.
>
> João

Was this installed?  If not, should it be?

> diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
> index 912a7357ca7..1ba4e6a006f 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-local eldoc--saved-mlf (or eldoc--saved-mlf mode-line-format))
> +        (when format-string
> +          (setq-local
> +           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")




This bug report was last modified 157 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.