Package: emacs;
Reported by: Eshel Yaron <me <at> eshelyaron.com>
Date: Wed, 17 Jan 2024 19:45:02 UTC
Severity: minor
Tags: patch
Message #47 received at 68547 <at> debbugs.gnu.org (full text, mbox):
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: Re: 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")
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.