GNU bug report logs -
#79420
30.2; icomplete-vertical-mode flashes horizontal minibuffer prompt before expanding
Previous Next
Full log
Message #8 received at 79420 <at> debbugs.gnu.org (full text, mbox):
> Date: Wed, 10 Sep 2025 11:48:18 +0200
> From: Chris Roberts via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>
> 1. emacs -Q
> 2. Evaluate the following:
>
> (setq icomplete-show-matches-on-no-input t)
> (icomplete-vertical-mode +1)
>
> 3. M-x
>
> Looking at the minibuffer, you will see the text "M-x" flash
> momentarily, before the minibuffer window expands vertically. This can
> be made more apparent by setting `icomplete-compute-delay' to a higher
> value (0.15 by default.)
>
> This is caused by the call to `sit-for' inside of the
> `icomplete-exhibit' function. The wait obviously causes the issue,
> because the function pauses the setup, including all of the necessary
> vertical code, and waits for `icomplete-compute-delay' seconds. But
> even if we set `icomplete-compute-delay' to 0, the prompt will still
> flash, because redisplay is triggered. In other words, the only way to
> call `sit-for' that doesn't cause an issue is:
>
> (sit-for x t)
>
> where x <= 0.
>
> Following are my thoughts on how to fix this.
>
> The piece of code from `icomplete-exhibit' that we are interested in is
> the following:
>
> (and (or icomplete-show-matches-on-no-input
> (not (equal (icomplete--field-string)
> icomplete--initial-input)))
> (or
> ;; Don't bother with delay after certain number of chars:
> (> (- (point) (icomplete--field-beg))
> icomplete-max-delay-chars)
> ;; Don't delay if the completions are known.
> completion-all-sorted-completions
> ;; Don't delay if alternatives number is small enough:
> (and (sequencep (icomplete--completion-table))
> (< (length (icomplete--completion-table))
> icomplete-delay-completions-threshold))
> ;; Delay - give some grace time for next keystroke, before
> ;; embarking on computing completions:
> (sit-for icomplete-compute-delay)))
>
> We see that `sit-for' will only execute if all the preceding forms
> return nil (since it's inside `and'). We also see that setting
> `icomplete-delay-completions-threshold' to a high value, like maybe
> `most-positive-fixnum' should help us avoid the call to `sit-for' in
> most situations. Except it doesn't, because
> `(icomplete--completion-table)' does not return `sequencep'! This can
> be verified by overriding the function via advice, and capturing the
> value returned by `icomplete--completion-table':
>
> ;; Don't delay if alternatives number is small enough:
> (progn ;; Important that we return nil to avoid exiting early
> (setq reimu (icomplete--completion-table))
> nil)
> (and (sequencep (icomplete--completion-table))
> (< (length (icomplete--completion-table))
> icomplete-delay-completions-threshold))
>
> Repeat the reproduction steps including this advice, press C-g after
> M-x, and finally C-x C-e `(sequencep reimu)' in the buffer (it's
> important that we don't do something that reads from the minibuffer,
> to not change the value), and you will get nil. In fact, `(type-of
> reimu)' shows that it's a compiled function.
>
> After debugging `icomplete--completion-table', I verified that this
> compiled function is in fact the value of the
> minibuffer-completion-table at the time. I believe this might be
> another bug, because the docstring of `minibuffer-completion-table'
> says:
>
> "Alist or obarray used for completion in the minibuffer."
>
> But it's evidently neither alist nor obarray (I assume, since
> `(sequencep obarray)' returns t).
>
> Thus, my ideas of fixing the original problem with the flashing prompt
> are following, from easiest to hardest:
>
> 1. Add a check for `icomplete-compute-delay)' <= 0, before the call to
> `sit-for', like so:
>
> ;; Don't delay if the wait is <= 0, to avoid redisplay
> ;; and prompt flashing in vertical mode.
> (<= icomplete-compute-delay 0)
> ;; Delay - give some grace time for next keystroke, before
> ;; embarking on computing completions:
> (sit-for icomplete-compute-delay)))
>
> 2. Force `sit-for' to never redisplay. This could also be
> conditionalized on `ido-vertical-mode' variable, to not affect the
> existing code. I think this is a tricky option, because this line is
> really ancient (at least 30 years old) and changing it might have
> unintended consequences, perhaps?
>
> 3. Fix the presumed bug with minibuffer-completion-table and adjust the
> `sequencep' check in `icomplete-exhibit' to compare with
> `icomplete-delay-completions-threshold' correctly.
>
> And finally, as mentioned earlier, this line of code is ancient. Maybe
> some deliberation is in order on whether it's actually still needed
> nowadays?
Thanks.
João, any comments or suggestions?
This bug report was last modified today.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.