Subject: Re: bug#48841: fido-mode is slower than ido-mode with similar settings

From: Dmitry Gutov <[email-masked]>
Date: Thu, 17 Jun 2021 05:23:53 +0300

On 14.06.2021 03:16, João Távora wrote:
>> Perhaps predicate it on the value of icomplete-hide-common-prefix instead?
>>
>> fido-mode sets it to nil, and this way we retain a better level of
>> abstraction, and better backward compatibility for vanilla
>> icomplete-mode users.
> This is a good idea, the level of abstraction.  But what is this
> "common prefix" anyway?  Is it the the same as the "determ"
> thing,  or the "[mplete...] dance" as I called it earlier.  Shouldn't
> fido-mode then_hide_  it?
> 
> I'm confused, but if you're not, go ahead and make that more
> abstract change instead of relying on fido-mode.

So... it's a bit more complex than that. The 'most' value computes the 
biggest "fuzzy" match (taking into account completion styles) and bases 
the resulting display of the "single match" on that.

Before your patch the output could look like:

   starfshe|(...t-file-process-shell-command) [Matched]

with the patch it's much less informative:

   starfshe| [Matched]

...so it has value, whether the variable I mentioned above is t or nil.

It seems there are two ways to proceed from here:

- Just alter the printing logic in the "single match" case to print the 
match text in full is it's not equal to the input string. I haven't 
puzzled out the logic doing that yet.

- Try to keep the current behavior while avoiding the duplicate work.

About the latter option: the result of that most-try stuff is only 
useful when there is only one match, right? But that work is performed 
unconditionally.

Unless I'm missing something and the value does see some use in the 
multiple-matches situations, the patch below both keeps the current 
behavior and gives the same performance improvement:

diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 08b4ef2030..fc88e2a3e0 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -859,13 +859,14 @@ icomplete-completions
                 (base-size (prog1 (cdr last)
                              (if last (setcdr last nil))))
                 (most-try
-                (if (and base-size (> base-size 0))
+                (unless (cdr comps)
+                  (if (and base-size (> base-size 0))
+                      (completion-try-completion
+                       name candidates predicate (length name) md)
+                    ;; If the `comps' are 0-based, the result should be
+                    ;; the same with `comps'.
                      (completion-try-completion
-                     name candidates predicate (length name) md)
-                  ;; If the `comps' are 0-based, the result should be
-                  ;; the same with `comps'.
-                  (completion-try-completion
-                   name comps nil (length name) md)))
+                     name comps nil (length name) md))))
                 (most (if (consp most-try) (car most-try)
                         (if most-try (car comps) "")))
                 ;; Compare name and most, so we can determine if name is