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
View this message in rfc822 format
From: Chris Roberts <frayedultrasonicaligator <at> disroot.org> To: 79420 <at> debbugs.gnu.org Subject: bug#79420: 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
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.