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))

Reply via email to