]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix icomplete-force-complete-and-exit for no-input situations
authorJoão Távora <joaotavora@gmail.com>
Thu, 31 Oct 2019 20:19:35 +0000 (20:19 +0000)
committerJoão Távora <joaotavora@gmail.com>
Sat, 2 Nov 2019 02:35:45 +0000 (02:35 +0000)
If there is no minibuffer input, but the user has already cycled some
pre-calculated completions, we should be calling
minibuffer-force-complete-and-exit instead of
minibuffer-complete-and-exit.  The former is guaranteed to be fast in
this situation and yields the desired "selected" completion, while the
latter will just give us the default, ignoring all the cycling of
icomplete-{forward|backward}-completions.

* lisp/icomplete.el (icomplete-force-complete-and-exit): Add
comments and fix for empty input but some completions calculated.

lisp/icomplete.el

index 89318ca4c7e97ff87c21c9b7740b7371b6147fdb..47e47f895f02e5942633e59a7446a87e53139df7 100644 (file)
@@ -152,13 +152,33 @@ icompletion is occurring."
   "Keymap used by `icomplete-mode' in the minibuffer.")
 
 (defun icomplete-force-complete-and-exit ()
-  "Complete the minibuffer and exit.
+  "Complete the minibuffer with the longest possible match and exit.
 Use the first of the matches if there are any displayed, and use
 the default otherwise."
   (interactive)
-  (if (or (and (not minibuffer-default) icomplete-show-matches-on-no-input)
-          (> (icomplete--field-end) (icomplete--field-beg)))
+  ;; This function is tricky.  The mandate is to "force", meaning we
+  ;; should take the first possible valid completion for the input.
+  ;; However, if there is no input and we can prove that that
+  ;; coincides with the default, it is much faster to just call
+  ;; `minibuffer-complete-and-exit'.  Otherwise, we have to call
+  ;; `minibuffer-force-complete-and-exit', which needs the full
+  ;; completion set and is potentially slow and blocking.  Do the
+  ;; latter if:
+  (if (or
+       ;; there's some input, meaning the default in off the table by
+       ;; definition; OR
+       (> (icomplete--field-end) (icomplete--field-beg))
+       ;; there's no input, but there's also no minibuffer default
+       ;; (and the user really wants to see completions on no input,
+       ;; meaning he expects a "force" to be at least attempted); OR
+       (and (not minibuffer-default)
+            icomplete-show-matches-on-no-input)
+       ;; there's no input but the full completion set has been
+       ;; calculated, This causes the first cached completion to
+       ;; be taken (i.e. the one that the user sees highlighted)
+       completion-all-sorted-completions)
       (minibuffer-force-complete-and-exit)
+    ;; Otherwise take the faster route...
     (minibuffer-complete-and-exit)))
 
 (defun icomplete-force-complete ()