DarwinAwardWinner / ido-completing-read-plus

Fancy completion all over Emacs, not just for buffers and files.
GNU General Public License v3.0
241 stars 31 forks source link

Confusing behaviour with exact match #153

Closed patxoca closed 6 years ago

patxoca commented 6 years ago

In order to reproduce this behaviour with emacs -Q evaluate the following code (adjust directories as required):

(push "/home/aroda/.emacs.d/elpa/ido-completing-read+-4.9" load-path)
(push "/home/aroda/.emacs.d/elpa/s-1.12.0" load-path)
(push "/home/aroda/.emacs.d/elpa/memoize-1.1" load-path)

(require 'ido)
(ido-mode 1)

(require 'ido-completing-read+)
(ido-ubiquitous-mode 1)

Then type C-h i m e m a c s, the minibuffer displays:

Menu item: emacs{Emacs | Emacs MIME | Emacs GnuTLS | Emacs Lisp Intro | Emacs FAQ}

pressing the left key once selects Emacs MIME for a while and then displays:

Menu item: emacs{Emacs | Emacs MIME | Emacs GnuTLS | Emacs Lisp Intro | Emacs FAQ}

selecting Emacs (the exact match) again.

Pressing the left key twice selects Emacs GnuTLS for a while and then displays:

Menu item: emacs{Emacs | Emacs GnuTLS | Emacs Lisp Intro | Emacs FAQ  | Emacs MIME}

selecting Emacs again.

Pressing SPC discards Emacs and it works as expected (at least as I would expect) regarding to selection.

Not sure if this is the intended behaviour or a bug, but I find it a bit confusing.

DarwinAwardWinner commented 6 years ago

This sounds like a bug. I'll look into it when I get the chance.

DarwinAwardWinner commented 6 years ago

Ok, it turns out this is sort of a bug in ido, which is being surfaced by ido-cr+. You can easily demonstrate the bug like this. Evaluate the following form to initiate ido completion:

(ido-completing-read
 "Choose: "
 '("choice" "choice-A" "choice-B" "choice-C"))

First, type in "choice". This text exactly matches the first option, but also prefix-matches the rest of the options, which means you can cycle through all of them. Next, cycle to "choice-A" by pressing \<right>. Finally, use type M-: (ignore) RET, which is a no-op. However, after doing so, you will notice that the selected completion has reset back to "choice" instead of "choice-A".

This happens because ido normally executes a "re-scan" after every keystroke (i.e. after every command, using post-command-hook), unless that command sets ido-rescan to nil. When a re-scan happens, any exact matches are pulled to the front of the list. Commands like ido-next-match set ido-rescan to nil in order to suppress this behavior, which is what allows them to cycle away from an exact match without that match constantly being pulled back to the front. Effectively, the re-scan is opt-out, and obviously only internal ido functions know how to opt out of it. This is arguably a bug, but it's difficult to see how to fix it without a drastic rewrite of ido.

Anyway, the above reproduction doesn't even involve ido-cr+ at all, but the dynamic update features of ido-cr+ mean that ido updates the list of choices when idle, which can also trigger this bug without a keystroke. It's possible that this specific instance might be fixed simply by setting ido-rescan to nil after a dynamic update. I'll have to experiment.

patxoca commented 6 years ago

Thank you! Knowing that the problem is caused by exact matches makes it easily avoidable: just keep typing. I can live with that :smiley:

DarwinAwardWinner commented 6 years ago

In any case, I figured out how to fix this specific instance of the problem in version 4.10.