branch: externals/ivy commit a0b2150dbe1872050b1886a94d167f1deacc5a61 Author: Basil L. Contovounesios <ba...@contovou.net> Commit: Basil L. Contovounesios <ba...@contovou.net>
Prefer base-size over ivy-completion-common-length The latter is very problematic: it is specific to a single candidate, does not necessarily correspond to the string being completed, complicates bounds calculations, relies on only partially documented presentation details rather than the usual API, etc. When completion-all-completions returns a base-size (which in practice seems to be most if not all the time), it corresponds more closely to the substring that is being completed and will be replaced. This should address most of the remaining issues in reports #1361, #1755, #2643, #2879, #3051, #3056, and https://bugs.gnu.org/76440. * ivy.el (ivy-completion-common-length): Discourage use. (ivy-completion-in-region): When completion-all-completions returns a base-size, prefer that over the completions-first-difference face to determine the completion boundaries and initial-input. Fixes #1755. Fixes #2643. Fixes #2879. Closes #3051. Fixes #3056. --- ivy.el | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/ivy.el b/ivy.el index fe3f58a6ca..5f8e608ace 100644 --- a/ivy.el +++ b/ivy.el @@ -2665,7 +2665,9 @@ That is, return the largest index into STR at which either the If no such index is found, return the length of STR. Typically the completion-matching parts of STR have previously been -propertized by `completion-all-completions'." +propertized by `completion-all-completions', but then the base-size +returned by that function should be preferred over +`ivy-completion-common-length'." (let* ((char-property-alias-alist '((face font-lock-face))) (cmn (length str)) (i cmn)) @@ -2690,15 +2692,16 @@ See `completion-in-region' for further information." (md (completion-metadata str collection predicate)) (try (completion-try-completion str collection predicate reg md)) (comps (completion-all-completions str collection predicate reg md)) + (last (last comps)) + (base-size (cdr last)) (ivy--minibuffer-table collection) (ivy--minibuffer-pred predicate)) + (when last (setcdr last ())) (cond ((null comps) (message "No matches") nil) - ((progn - (nconc comps nil) - (and (null (cdr comps)) - (string= str (car comps)))) + ((and (null (cdr comps)) + (string= str (car comps))) (message "Sole match") t) (t @@ -2709,15 +2712,20 @@ See `completion-in-region' for further information." ;; of fixing `ivy-completion-common-length') for backward ;; compatibility, since it's a potentially public function. (cmn (if (= cmn (length (car comps))) 0 cmn)) - (initial (cond ((= cmn 0) + (initial (cond (base-size (substring str base-size)) + ;; The remaining clauses should hopefully never + ;; be taken, since they rely on + ;; `ivy-completion-common-length'. + ((= cmn 0) "") ((>= cmn reg) (setq cmn reg) str) (t - (substring str (- cmn)))))) - (delete-region (- end cmn) end) - (setq ivy-completion-beg (- end cmn)) + (substring str (- cmn))))) + (base-pos (if base-size (+ start base-size) (- end cmn)))) + (delete-region base-pos end) + (setq ivy-completion-beg base-pos) (setq ivy-completion-end ivy-completion-beg) (if (null (cdr comps)) (let ((ivy--minibuffer-try try))