aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2019-12-22 12:52:17 +0100
committerJoão Távora2019-12-22 12:52:32 +0100
commit2fa8fd18dfb0dc673ea82491de952a45b84c6667 (patch)
tree68c535e615edbaacc97a08b32e2859036a4af003
parentba042176d8931cdf9441b3b4919ec74b75019494 (diff)
downloademacs-2fa8fd18dfb0dc673ea82491de952a45b84c6667.tar.gz
emacs-2fa8fd18dfb0dc673ea82491de952a45b84c6667.zip
Improve sorting of flex completion style with non-nil minibuffer-default
This affects the behaviour of flex completion when there is a default completion and the user hasn't entered any input pattern to flex-match against. It is most visible when icomplete-mode or fido-mode are being used in conjunctio. When using M-x man, for instance, the default completion is picked from text around point. Say it is "emacs" (for Emacs's man page). It will not match the intended completion, "emacs(1)", exactly. If the user hasn't yet given any input to the completion prompt, that completion should bubble to top so that icomplete-force-complete-and-exit will select it, but it didn't. This new approach uses 'string-prefix-p' instead of 'equal' to find the default to bubble to the top. This strategy could eventually be improved, most naturally by flex-matching the default string to all the candidates and picking the highest scoring one. Additionally, the new strategy only considers minibuffer-default if there is no input in the minibuffer, which seems sensible and produces a small but noticeable speedup. * lisp/minibuffer.el (completion--flex-adjust-metadata): Reformulate sorting strategy.
-rw-r--r--lisp/minibuffer.el38
1 files changed, 27 insertions, 11 deletions
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5dc753ffd5c..96931162cc1 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3585,17 +3585,33 @@ that is non-nil."
3585 (cl-flet ((compose-flex-sort-fn 3585 (cl-flet ((compose-flex-sort-fn
3586 (existing-sort-fn) ; wish `cl-flet' had proper indentation... 3586 (existing-sort-fn) ; wish `cl-flet' had proper indentation...
3587 (lambda (completions) 3587 (lambda (completions)
3588 (let ((res 3588 (let* ((by-score
3589 (if existing-sort-fn 3589 (sort
3590 (funcall existing-sort-fn completions) 3590 (if existing-sort-fn
3591 completions))) 3591 (funcall existing-sort-fn completions)
3592 (sort 3592 completions)
3593 res 3593 (lambda (c1 c2)
3594 (lambda (c1 c2) 3594 (let ((s1 (get-text-property 0 'completion-score c1))
3595 (or (equal c1 minibuffer-default) 3595 (s2 (get-text-property 0 'completion-score c2)))
3596 (let ((s1 (get-text-property 0 'completion-score c1)) 3596 (> (or s1 0) (or s2 0))))))
3597 (s2 (get-text-property 0 'completion-score c2))) 3597 (promoted-default
3598 (> (or s1 0) (or s2 0)))))))))) 3598 (and minibuffer-default
3599 (and (window-minibuffer-p)
3600 (= (point-max)
3601 (minibuffer-prompt-end)))
3602 ;; If we have an empty pattern and a
3603 ;; non-nil default we probably want to
3604 ;; make sure that default is bubbled to
3605 ;; the top even if it doesn't match the
3606 ;; completion perfectly (like in M-x man
3607 ;; case)
3608 (cl-loop
3609 for l on by-score
3610 for comp = (cadr l)
3611 when (string-prefix-p minibuffer-default comp)
3612 do (setf (cdr l) (cddr l))
3613 and return (cons comp by-score)))))
3614 (or promoted-default by-score)))))
3599 `(metadata 3615 `(metadata
3600 (display-sort-function 3616 (display-sort-function
3601 . ,(compose-flex-sort-fn 3617 . ,(compose-flex-sort-fn