Subject: bug#42149: Substring and flex completion ignore implicit trailing ‘any’

From: Dario Gjorgjevski <[email-masked]>
Date: Thu, 13 May 2021 17:41:54 +0200

Hi,

> Not sure if it's merged yet, but I don't think so.  I was waiting for
> Dario's comments on it, they never arrived, but I'm veryq confident that
> this fixes the issues reported here.

Sorry, I kind of forgot about this.  The bug itself was fixed by commit
d199a46, it is only the test that have not been merged yet.

The tests that fail are the ones related to
completions-first-difference, which, we agreed should be left as it is.
Therefore, those tests need to be changed.  (This also applies to the
scratch/bug-42149-funny-pcm-completion-scores branch.)

Here is a patch with the fixed tests: 

>From 215ac5b9c55670435b69fa92d6124d0c7bf9b5a3 Mon Sep 17 00:00:00 2001
From: Dario Gjorgjevski <[email-masked]>
Date: Thu, 13 May 2021 17:29:13 +0200
Subject: [PATCH] Add tests for bug#42149
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* test/lisp/minibuffer-tests.el (completion--pcm-score)
(completion--pcm-first-difference-pos): New helpers.
(completion-pcm-test-1, completion-pcm-test-2)
(completion-pcm-test-3, completion-pcm-test-4)
(completion-pcm-test-5, completion-pcm-test-6)
(completion-substring-test-1, completion-substring-test-2)
(completion-substring-test-3, completion-substring-test-4)
(completion-flex-test-1, completion-flex-test-2)
(completion-flex-test-3): New tests.

Co-authored-by: João Távora <[email-masked]>
---
 test/lisp/minibuffer-tests.el | 143 ++++++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)

diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 6ab5f57eff..c3ba8f9a92 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -188,5 +188,148 @@
                   '("some/alpha" "base/epsilon" "base/delta"))
                  `("epsilon" "delta" "beta" "alpha" "gamma"  . 5))))
 
+(defun completion--pcm-score (comp)
+  "Get `completion-score' from COMP."
+  (get-text-property 0 'completion-score comp))
+
+(defun completion--pcm-first-difference-pos (comp)
+  "Get `completions-first-difference' from COMP."
+  (cl-loop for pos = (next-single-property-change 0 'face comp)
+           then (next-single-property-change pos 'face comp)
+           while pos
+           when (eq (get-text-property pos 'face comp)
+                    'completions-first-difference)
+           return pos))
+
+(ert-deftest completion-pcm-test-1 ()
+  ;; Point is at end, this does not match anything
+  (should (null
+           (completion-pcm-all-completions
+            "foo" '("hello" "world" "barfoobar") nil 3))))
+
+(ert-deftest completion-pcm-test-2 ()
+  ;; Point is at beginning, this matches "barfoobar"
+  (should (equal
+           (car (completion-pcm-all-completions
+                 "foo" '("hello" "world" "barfoobar") nil 0))
+           "barfoobar")))
+
+(ert-deftest completion-pcm-test-3 ()
+  ;; Full match!
+  (should (eql
+           (completion--pcm-score
+            (car (completion-pcm-all-completions
+                  "R" '("R" "hello") nil 1)))
+           1.0)))
+
+(ert-deftest completion-pcm-test-4 ()
+  ;; One fourth of a match and no match due to point being at the end
+  (should (eql
+           (completion--pcm-score
+            (car (completion-pcm-all-completions
+                  "RO" '("RaOb") nil 1)))
+           (/ 1.0 4.0)))
+  (should (null
+           (completion-pcm-all-completions
+            "RO" '("RaOb") nil 2))))
+
+(ert-deftest completion-pcm-test-5 ()
+  ;; Since point is at the beginning, there is nothing that can really
+  ;; be typed anymore
+  (should (null
+           (completion--pcm-first-difference-pos
+            (car (completion-pcm-all-completions
+                  "f" '("few" "many") nil 0))))))
+
+(ert-deftest completion-pcm-test-6 ()
+  ;; Wildcards and delimiters work
+  (should (equal
+           (car (completion-pcm-all-completions
+                 "li-pac*" '("list-packages") nil 7))
+           "list-packages"))
+  (should (null
+           (car (completion-pcm-all-completions
+                 "li-pac*" '("do-not-list-packages") nil 7)))))
+
+(ert-deftest completion-substring-test-1 ()
+  ;; One third of a match!
+  (should (equal
+           (car (completion-substring-all-completions
+                 "foo" '("hello" "world" "barfoobar") nil 3))
+           "barfoobar"))
+  (should (eql
+           (completion--pcm-score
+            (car (completion-substring-all-completions
+                  "foo" '("hello" "world" "barfoobar") nil 3)))
+           (/ 1.0 3.0))))
+
+(ert-deftest completion-substring-test-2 ()
+  ;; Full match!
+  (should (eql
+           (completion--pcm-score
+            (car (completion-substring-all-completions
+                  "R" '("R" "hello") nil 1)))
+           1.0)))
+
+(ert-deftest completion-substring-test-3 ()
+  ;; Substring match
+  (should (equal
+           (car (completion-substring-all-completions
+                 "custgroup" '("customize-group") nil 4))
+           "customize-group"))
+  (should (null
+           (car (completion-substring-all-completions
+                 "custgroup" '("customize-group") nil 5)))))
+
+(ert-deftest completion-substring-test-4 ()
+  ;; `completions-first-difference' should be at the right place
+  (should (eql
+           (completion--pcm-first-difference-pos
+            (car (completion-substring-all-completions
+                  "jab" '("dabjobstabby" "many") nil 1)))
+           4))
+  (should (null
+           (completion--pcm-first-difference-pos
+            (car (completion-substring-all-completions
+                  "jab" '("dabjabstabby" "many") nil 1)))))
+  (should (equal
+           (completion--pcm-first-difference-pos
+            (car (completion-substring-all-completions
+                  "jab" '("dabjabstabby" "many") nil 3)))
+           6)))
+
+(ert-deftest completion-flex-test-1 ()
+  ;; Fuzzy match
+  (should (equal
+           (car (completion-flex-all-completions
+                 "foo" '("hello" "world" "fabrobazo") nil 3))
+           "fabrobazo")))
+
+(ert-deftest completion-flex-test-2 ()
+  ;; Full match!
+  (should (eql
+           (completion--pcm-score
+            (car (completion-flex-all-completions
+                  "R" '("R" "hello") nil 1)))
+           1.0)))
+
+(ert-deftest completion-flex-test-3 ()
+  ;; Another fuzzy match, but more of a "substring" one
+  (should (equal
+           (car (completion-flex-all-completions
+                 "custgroup" '("customize-group-other-window") nil 4))
+           "customize-group-other-window"))
+  ;; `completions-first-difference' should be at the right place
+  (should (equal
+           (completion--pcm-first-difference-pos
+            (car (completion-flex-all-completions
+                  "custgroup" '("customize-group-other-window") nil 4)))
+           4))
+  (should (equal
+           (completion--pcm-first-difference-pos
+            (car (completion-flex-all-completions
+                  "custgroup" '("customize-group-other-window") nil 9)))
+           15)))
+
 (provide 'minibuffer-tests)
 ;;; minibuffer-tests.el ends here
-- 
2.31.GIT

Once the tests are merged, I suppose the
scratch/bug-42149-funny-pcm-completion-scores branch can safely be
deleted.

Best regards,

-- 
Dario Gjorgjevski <[email-masked]>
Key fingerprint = F7C3 734D 2381 DAEB 4C6D  9CF7 744A 4F0B 4F1C 9371
$ gpg --keyserver   hkps://hkps.pool.sks-keyservers.net \
      --search-keys 744A4F0B4F1C9371