]> git.eshelyaron.com Git - emacs.git/commitdiff
Better explain behaviour of icomplete--sorted-completions
authorJoão Távora <joaotavora@gmail.com>
Mon, 7 Sep 2020 09:52:46 +0000 (10:52 +0100)
committerJoão Távora <joaotavora@gmail.com>
Mon, 7 Sep 2020 09:53:01 +0000 (10:53 +0100)
* lisp/icomplete.el (icomplete--sorted-completions): Overhaul comment

lisp/icomplete.el

index 47d78a0bc82882864fd4b71cac2092601dc82afc..38115ab2c86e6da57fafae379ac8ff968d63197f 100644 (file)
@@ -469,33 +469,70 @@ Usually run by inclusion in `minibuffer-setup-hook'."
        with beg = (icomplete--field-beg)
        with end = (icomplete--field-end)
        with all = (completion-all-sorted-completions beg end)
-       ;; First, establish the "bubble up" predicates.
+       ;; Icomplete mode re-sorts candidates, bubbling the default to
+       ;; top if it's found somewhere down the list.  This loop's
+       ;; iteration variable, `fn' iterates through these "bubble up
+       ;; predicates" which may vary depending on specific
+       ;; `completing-read' invocations, described below:
        for fn in (cond ((and minibuffer-default
                              (stringp minibuffer-default) ; bug#38992
                              (= (icomplete--field-end) (icomplete--field-beg)))
-                        ;; When we have a non-nil string default and
-                        ;; no input whatsoever: we want to make sure
-                        ;; that default is bubbled to the top so that
-                        ;; `icomplete-force-complete-and-exit' will
-                        ;; select it (do that even if the match
-                        ;; doesn't match the completion perfectly.
-                        `(,(lambda (comp)
+                        ;; Here, we have a non-nil string default and
+                        ;; no input whatsoever.  We want to make sure
+                        ;; that the default is bubbled to the top so
+                        ;; that `icomplete-force-complete-and-exit'
+                        ;; will select it.  We want to do that even if
+                        ;; the match doesn't match the completion
+                        ;; perfectly.
+                        ;;
+                        `(;; The first predicate ensures that:
+                          ;;
+                          ;; (completing-read "thing? " '("foo" "bar")
+                          ;;                  nil nil nil nil "bar")
+                          ;;
+                          ;; Has "bar" at the top, so RET will select
+                          ;; it, as desired.
+                          ,(lambda (comp)
                              (equal minibuffer-default comp))
+                          ;; Why do we need this second predicate?
+                          ;; Because that'll make things like M-x man
+                          ;; RET RET, when invoked with point on the
+                          ;; "bar" word, behave correctly.  There, the
+                          ;; default doesn't quite match any
+                          ;; candidate. So:
+                          ;;
+                          ;; (completing-read "Man entry? " '("foo(1)" "bar(1)")
+                          ;;                  nil nil nil nil "bar")
+                          ;;
+                          ;; Will place "bar(1)" on top, and RET will
+                          ;; select it -- again, as desired.
+                          ;;
+                          ;; FIXME: it's arguable that this second
+                          ;; behaviour should be a property of the
+                          ;; completion table and not the completion
+                          ;; frontend such as we have done
+                          ;; here. However, it seems generically
+                          ;; useful for a very broad spectrum of
+                          ;; cases.
                           ,(lambda (comp)
                              (string-prefix-p minibuffer-default comp))))
                        ((and fido-mode
                              (not minibuffer-default)
                              (eq (icomplete--category) 'file))
-                        ;; `fido-mode' has some extra file-sorting
-                        ;; semantics even if there isn't a default,
-                        ;; which is to bubble "./" to the top if it
-                        ;; exists.  This makes M-x dired RET RET go to
-                        ;; the directory of current file, which is
-                        ;; what vanilla Emacs and `ido-mode' both do.
+                        ;; When there isn't a default, `fido-mode'
+                        ;; specifically also has some extra
+                        ;; file-sorting semantics inherited from Ido.
+                        ;; Those make the directory "./" bubble to the
+                        ;; top (if it exists).  This makes M-x dired
+                        ;; RET RET go to the directory of current
+                        ;; file, which is non-Icomplete vanilla Emacs
+                        ;; and `ido-mode' both do.
                         `(,(lambda (comp)
                              (string= "./" comp)))))
-       ;; Now, look for a completion matching one of those predicates
-       ;; to bubble up (unless that completion is already on top).
+       ;; After we have setup the predicates, look for a completion
+       ;; matching one of them and bubble up it, destructively on
+       ;; `completion-all-sorted-completions' (unless that completion
+       ;; happens to be already on top).
        thereis (or
                 (and (funcall fn (car all)) all)
                 (cl-loop