GNU bug report logs - #79420
30.2; icomplete-vertical-mode flashes horizontal minibuffer prompt before expanding

Previous Next

Package: emacs;

Reported by: Chris Roberts <frayedultrasonicaligator <at> disroot.org>

Date: Wed, 10 Sep 2025 10:52:01 UTC

Severity: normal

Found in version 30.2

To reply to this bug, email your comments to 79420 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#79420; Package emacs. (Wed, 10 Sep 2025 10:52:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Chris Roberts <frayedultrasonicaligator <at> disroot.org>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Wed, 10 Sep 2025 10:52:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Chris Roberts <frayedultrasonicaligator <at> disroot.org>
To: bug-gnu-emacs <at> gnu.org
Subject: 30.2; icomplete-vertical-mode flashes horizontal minibuffer prompt
 before expanding
Date: Wed, 10 Sep 2025 11:48:18 +0200
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?

-----------------------------------------------------------------------

In GNU Emacs 30.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.33,
 cairo version 1.16.0) of 2025-09-10 built on cdr
Windowing system distributor 'The X.Org Foundation', version
11.0.12101004
System Description: Linux Mint 21.2

Configured using:
 'configure --with-cairo --with-x-toolkit=gtk3'

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG LCMS2
LIBSELINUX LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG SECCOMP SOUND
SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINPUT2 XPM
GTK3 ZLIB




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79420; Package emacs. (Sat, 13 Sep 2025 10:02:02 GMT) Full text and rfc822 format available.

Message #8 received at 79420 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Chris Roberts <frayedultrasonicaligator <at> disroot.org>,
 João Távora <joaotavora <at> gmail.com>
Cc: 79420 <at> debbugs.gnu.org
Subject: Re: bug#79420: 30.2;
 icomplete-vertical-mode flashes horizontal minibuffer prompt before
 expanding
Date: Sat, 13 Sep 2025 13:01:04 +0300
> 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?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79420; Package emacs. (Sat, 27 Sep 2025 08:55:02 GMT) Full text and rfc822 format available.

Message #11 received at 79420 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: joaotavora <at> gmail.com
Cc: frayedultrasonicaligator <at> disroot.org, 79420 <at> debbugs.gnu.org
Subject: Re: bug#79420: 30.2;
 icomplete-vertical-mode flashes horizontal minibuffer prompt before
 expanding
Date: Sat, 27 Sep 2025 11:53:48 +0300
Ping!  João, could you please chime in?

> Cc: 79420 <at> debbugs.gnu.org
> Date: Sat, 13 Sep 2025 13:01:04 +0300
> From: Eli Zaretskii <eliz <at> gnu.org>
> 
> > 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?
> 
> 
> 
> 




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79420; Package emacs. (Sat, 27 Sep 2025 12:09:02 GMT) Full text and rfc822 format available.

Message #14 received at 79420 <at> debbugs.gnu.org (full text, mbox):

From: João Távora <joaotavora <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: frayedultrasonicaligator <at> disroot.org, 79420 <at> debbugs.gnu.org
Subject: Re: bug#79420: 30.2; icomplete-vertical-mode flashes horizontal
 minibuffer prompt before expanding
Date: Sat, 27 Sep 2025 13:08:07 +0100
[Message part 1 (text/plain, inline)]
I think the line of code in question, or at least the idea behind it, is
"ancient" indeed, and it precedes my work on icomplete. I think I do recall
trying to tweak it and giving up. Please see Stefan... I think he wrote
this code. Nothing against changing it if it makes things better and
doesn't break stuff.

João

On Sat, Sep 27, 2025, 09:53 Eli Zaretskii <eliz <at> gnu.org> wrote:

> Ping!  João, could you please chime in?
>
> > Cc: 79420 <at> debbugs.gnu.org
> > Date: Sat, 13 Sep 2025 13:01:04 +0300
> > From: Eli Zaretskii <eliz <at> gnu.org>
> >
> > > 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?
> >
> >
> >
> >
>
[Message part 2 (text/html, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79420; Package emacs. (Sat, 27 Sep 2025 12:22:08 GMT) Full text and rfc822 format available.

Message #17 received at 79420 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: João Távora <joaotavora <at> gmail.com>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: frayedultrasonicaligator <at> disroot.org, 79420 <at> debbugs.gnu.org
Subject: Re: bug#79420: 30.2; icomplete-vertical-mode flashes horizontal
 minibuffer prompt before expanding
Date: Sat, 27 Sep 2025 15:21:11 +0300
> From: João Távora <joaotavora <at> gmail.com>
> Date: Sat, 27 Sep 2025 13:08:07 +0100
> Cc: frayedultrasonicaligator <at> disroot.org, 79420 <at> debbugs.gnu.org
> 
> I think the line of code in question, or at least the idea behind it, is "ancient" indeed, and it precedes my work
> on icomplete. I think I do recall trying to tweak it and giving up. Please see Stefan... I think he wrote this
> code. Nothing against changing it if it makes things better and doesn't break stuff.
> 
> João

Stefan, any suggestions or comments?

> On Sat, Sep 27, 2025, 09:53 Eli Zaretskii <eliz <at> gnu.org> wrote:
> 
>  Ping!  João, could you please chime in?
> 
>  > Cc: 79420 <at> debbugs.gnu.org
>  > Date: Sat, 13 Sep 2025 13:01:04 +0300
>  > From: Eli Zaretskii <eliz <at> gnu.org>
>  > 
>  > > 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?
>  > 
>  > 
>  > 
>  > 




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79420; Package emacs. (Sat, 27 Sep 2025 23:20:02 GMT) Full text and rfc822 format available.

Message #20 received at 79420 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Chris Roberts <frayedultrasonicaligator <at> disroot.org>
Cc: 79420 <at> debbugs.gnu.org,
 João Távora <joaotavora <at> gmail.com>
Subject: Re: bug#79420: 30.2; icomplete-vertical-mode flashes horizontal
 minibuffer prompt before expanding
Date: Sat, 27 Sep 2025 19:19:24 -0400
> 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:

`icomplete-vertical-mode` is "special" here because the user expects
that when (it's in use) the minibuffer input is followed by N lines
(possibly empty) of completions.
E.g. if `icomplete-vertical-mode` were changed to list the completions
*above* rather than below, then the problem would disappear (because
the `M-x` wouldn't move when adding the N lines above it).

So I think we need to change `icomplete--vertical-minibuffer-setup` so
it inserts those N empty lines right away (tho maybe we should do it
only if `icomplete-show-matches-on-no-input` is non-nil, I don't know).
IIUC the code that inserts the lines is in `icomplete--render-vertical`
but I tried adding a call to (icomplete--render-vertical '("") nil) at
the end of `icomplete--vertical-minibuffer-setup` and failed miserably.
Understanding that code is above my current pay grade, so I hope João
can come to the rescue.


        Stefan





This bug report was last modified 39 days ago.

Previous Next


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