From: João Távora Date: Mon, 7 Sep 2020 09:52:46 +0000 (+0100) Subject: Better explain behaviour of icomplete--sorted-completions X-Git-Tag: emacs-28.0.90~6202 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=c8472cc69d4bce7f53c9a62966245a4de3d99fbd;p=emacs.git Better explain behaviour of icomplete--sorted-completions * lisp/icomplete.el (icomplete--sorted-completions): Overhaul comment --- diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 47d78a0bc82..38115ab2c86 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -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