Subject: Re: bug#4219: 23.1; case insensitive + partial completions

From: Stefan Monnier <[email-masked]>
Date: Sun, 13 Sep 2009 23:35:12 -0400

>>>>> "Eli" == Eli Barzilay <[email-masked]> writes:

> Start with a default Emacs, and
>   (setq read-file-name-completion-ignore-case t)
>   (setq completion-styles '(partial-completion))

> Now go to a directory that has two files called

>   INSTALL
>   install-sh

> Hit `C-x C-f ins TAB' -- it will be completed to "insTALL".

I think the patch below will help out.  You may still get such
inconsistent results in different parts of a completion (e.g. completing
"fo-ba" against "FOO-BAR" and "foo-bar" may return "FOO-bar"), but at
least the above case should be handled better.

        Stefan

--- minibuffer.el.~1.83.~	2009-09-02 20:35:02.000000000 -0400
+++ minibuffer.el	2009-09-13 23:31:10.000000000 -0400
@@ -1670,28 +1670,32 @@
           (unless (string-match re str)
             (error "Internal error: %s doesn't match %s" str re))
           (let ((chopped ())
-                (i 1))
-            (while (match-beginning i)
-              (push (match-string i str) chopped)
+                (last 0)
+                (i 1)
+                next)
+            (while (setq next (match-end i))
+              (push (substring str last next) chopped)
+              (setq last next)
               (setq i (1+ i)))
             ;; Add the text corresponding to the implicit trailing `any'.
-            (push (substring str (match-end 0)) chopped)
+            (push (substring str last) chopped)
             (push (nreverse chopped) ccs))))
 
       ;; Then for each of those non-constant elements, extract the
       ;; commonality between them.
-      (let ((res ()))
-        ;; Make the implicit `any' explicit.  We could make it explicit
+      (let ((res ())
+            (fixed ""))
+        ;; Make the implicit trailing `any' explicit.  We could make it explicit
         ;; everywhere, but it would slow down regexp-matching a little bit.
         (dolist (elem (append pattern '(any)))
           (if (stringp elem)
-              (push elem res)
+              (setq fixed (concat fixed elem))
             (let ((comps ()))
               (dolist (cc (prog1 ccs (setq ccs nil)))
                 (push (car cc) comps)
                 (push (cdr cc) ccs))
-              (let* ((prefix (try-completion "" comps))
-                     (unique (or (and (eq prefix t) (setq prefix ""))
+              (let* ((prefix (try-completion fixed comps))
+                     (unique (or (and (eq prefix t) (setq prefix fixed))
                                  (eq t (try-completion prefix comps)))))
                 (unless (equal prefix "") (push prefix res))
                 ;; If there's only one completion, `elem' is not useful
@@ -1700,7 +1704,8 @@
                 ;; `any' into a `star' because the surrounding context has
                 ;; changed such that string->pattern wouldn't add an `any'
                 ;; here any more.
-                (unless unique (push elem res))))))
+                (unless unique (push elem res))
+                (setq fixed "")))))
         ;; We return it in reverse order.
         res)))))