|
From: | Andy Schwartzmeyer |
Subject: | bug#42101: |
Date: | Sat, 27 Jun 2020 23:36:53 -0700 |
Okay, with some message style debugging I think I narrowed it down: (defun icomplete-force-complete-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) ;; 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) (progn (message (if completion-all-sorted-completions (message "completions t") (message "completions nil"))) (message (if minibuffer-default "default t" "default nil")) (message "FORCING") (minibuffer-force-complete-and-exit)) ;; Otherwise take the faster route... (minibuffer-complete-and-exit))) With fido-mode, the final test in the or clause, namely 'completion-all-sorted-completions’, is t, whereas in icomplete-mode it is nil. This is causing the first cached completion to be taken (i.e. the ‘completion-styles-alist’ which probably shouldn’t be the first completion anyway). Moreover, it means that this function’s existence is being overriden: it’s never shortcutting to 'minibuffer-complete-and-exit’ for fido-mode users. Now to find out two more things: 1. Why is the completion list not bubbling minibuffer-default to the top? (I’m using helpful-variable, but this also happens with describe-variable, and I’ve noticed it with other functions that will use a default from point.) 2. Why is 'completion-all-sorted-completions’ always t when using fido-mode? At least for #1: In this bit of code the minibuffer-default is compared with equal and with string-prefix-p: (defun icomplete--sorted-completions () (or completion-all-sorted-completions (cl-loop with beg = (icomplete--field-beg) with end = (icomplete--field-end) with all = (completion-all-sorted-completions beg end) 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) (equal minibuffer-default comp)) ,(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. `(,(lambda (comp) (string= "./" comp))))) thereis (cl-loop for l on all while (consp (cdr l)) for comp = (cadr l) when (funcall fn comp) do (setf (cdr l) (cddr l)) and return (completion--cache-all-sorted-completions beg end (cons comp all))) finally return all))) I’m not sure how to get it to do so, but when there are candidates satisfying both ‘equals’ and ‘string-prefix-p’, we need to get this to prefer the former over the latter. Cheers, Andy |
[Prev in Thread] | Current Thread | [Next in Thread] |