branch: externals/hotfuzz
commit 05330fc7208c654631e7484c3c7c441716901237
Author: Axel Forsman <[email protected]>
Commit: Axel Forsman <[email protected]>

    Test filtering with long search string
---
 hotfuzz-module.c |  1 -
 hotfuzz.el       | 42 +++++++++++++++++++-----------------------
 test/tests.el    | 20 +++++++++++++++++++-
 3 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/hotfuzz-module.c b/hotfuzz-module.c
index b84417c1e7..a8c8b1e4c0 100644
--- a/hotfuzz-module.c
+++ b/hotfuzz-module.c
@@ -44,7 +44,6 @@ static uint64_t tolower8(uint64_t x) {
        return x | is_upper >> 2;
 }
 
-
 static void strtolower(struct EmacsStr *s) {
        // Complicated in order to optimize out the calls to tolower_utf8
        // on AMD64 System V with GCC 11.3.0.
diff --git a/hotfuzz.el b/hotfuzz.el
index 720c2809a2..a82bbefa50 100644
--- a/hotfuzz.el
+++ b/hotfuzz.el
@@ -34,12 +34,10 @@
   "The number of top-ranking completions that should be highlighted.
 Large values will decrease performance. Only applies when using the
 Emacs `completion-styles' interface."
-  :group 'hotfuzz
   :type 'integer)
 
 (declare-function hotfuzz--filter-c "hotfuzz-module")
-;; If the dynamic module is available: Load it
-(require 'hotfuzz-module nil t)
+(require 'hotfuzz-module nil t) ; Load dynamic module if it is available
 
 ;; Since we pre-allocate the vectors the common optimization where
 ;; symmetricity w.r.t. to insertions/deletions means it suffices to
@@ -119,15 +117,14 @@ HAYSTACK has to be a match according to `hotfuzz-filter'."
   (let ((n (length haystack)) (m (length needle))
         (c hotfuzz--c) (d hotfuzz--d)
         (case-fold-search completion-ignore-case))
-    (if (or (> n hotfuzz--max-haystack-len) (> m hotfuzz--max-needle-len))
-        haystack ; Bail out if is too long
+    (unless (or (> n hotfuzz--max-haystack-len) (> m hotfuzz--max-needle-len))
       (fillarray c 10000)
       (fillarray d 10000)
       (hotfuzz--calc-bonus haystack)
       (cl-loop
        with rows = (cl-loop
                     with nc and nd
-                    for i below n and pc = c then nc and pd = d then nd with 
res = nil do
+                    for i below n and pc = c then nc and pd = d then nd with 
res do
                     (setq nc (make-vector m 0) nd (make-vector m 0))
                     (hotfuzz--match-row haystack needle i nc nd pc pd)
                     (push `(,nc . ,nd) res)
@@ -140,15 +137,15 @@ HAYSTACK has to be a match according to `hotfuzz-filter'."
                   (and (> i 0) (< (aref (cdar rows) j) (aref d j))))))
        (pop rows)
        (cl-decf i)
-       (add-face-text-property i (1+ i) 'completions-common-part nil haystack)
-       finally return haystack))))
+       (add-face-text-property i (1+ i) 'completions-common-part nil 
haystack))))
+  haystack)
 
 ;;;###autoload
-(cl-defun hotfuzz-filter (string candidates)
+(defun hotfuzz-filter (string candidates)
   "Filter CANDIDATES that match STRING and sort by the match costs.
 CANDIDATES should be a list of strings."
   (cond
-   ((not (<= 1 (length string) hotfuzz--max-needle-len)) candidates)
+   ((string= string "") candidates)
    ((featurep 'hotfuzz-module)
     (hotfuzz--filter-c string candidates completion-ignore-case))
    ((let ((re (concat
@@ -157,17 +154,19 @@ CANDIDATES should be a list of strings."
                 (lambda (ch) (format "[^%c]*%s" ch (regexp-quote 
(char-to-string ch))))
                 string "")))
           (case-fold-search completion-ignore-case))
-      (mapcar
-       #'car
-       (cl-sort (cl-loop for x in candidates if (string-match-p re x)
-                         collect (cons x (hotfuzz--cost string x)))
-                #'< :key #'cdr))))))
+      (if (> (length string) hotfuzz--max-needle-len)
+          (cl-loop for x in candidates if (string-match-p re x) collect x)
+        (cl-loop
+         for x in candidates if (string-match-p re x)
+         collect (cons x (hotfuzz--cost string x)) into xs
+         finally return (mapcar #'car (cl-sort xs #'< :key #'cdr))))))))
 
 ;;; Completion style implementation
 
 ;;;###autoload
 (defun hotfuzz-all-completions (string table pred point)
-  "Implementation of `completion-all-completions' that uses hotfuzz.
+  "Get hotfuzz-completions of STRING in TABLE.
+See `completion-all-completions' for the semantics of PRED and POINT.
 This function prematurely sorts the completions; mutating the returned
 list before passing it to `display-sort-function' or
 `cycle-sort-function' will lead to inaccuracies."
@@ -179,7 +178,7 @@ list before passing it to `display-sort-function' or
          (completion-regexp-list nil)
          (all (hotfuzz-filter
                needle
-               (if (and (listp table) (not (consp (car-safe table)))
+               (if (and (listp table) (not (consp (car table)))
                         (not (functionp table)) (not pred))
                    table
                  (all-completions prefix table pred)))))
@@ -190,12 +189,11 @@ list before passing it to `display-sort-function' or
         (cl-loop
          repeat hotfuzz-max-highlighted-completions and for x in-ref all do
          (setf x (hotfuzz-highlight needle (copy-sequence x))))
-        (unless (> hotfuzz-max-highlighted-completions 0)
+        (when (zerop hotfuzz-max-highlighted-completions)
           (setcar all (copy-sequence (car all))))
         (put-text-property 0 1 'completion-sorted t (car all)))
       (if (string= prefix "") all (nconc all (length prefix))))))
 
-;; ;;;###autoload
 (defun hotfuzz--adjust-metadata (metadata)
   "Adjust completion METADATA for hotfuzz sorting."
   (let ((existing-dsf (completion-metadata-get metadata 
'display-sort-function))
@@ -211,7 +209,7 @@ list before passing it to `display-sort-function' or
       `(metadata
         (display-sort-function . ,(compose-sort-fn (or existing-dsf 
#'identity)))
         (cycle-sort-function . ,(compose-sort-fn (or existing-csf #'identity)))
-        ,@(cdr metadata)))))
+        . ,@(cdr metadata)))))
 
 ;;;###autoload
 (progn
@@ -238,7 +236,6 @@ list before passing it to `display-sort-function' or
 ;;;###autoload
 (define-minor-mode hotfuzz-selectrum-mode
   "Minor mode that enables hotfuzz in Selectrum menus."
-  :group 'hotfuzz
   :global t
   (if hotfuzz-selectrum-mode
       (setq hotfuzz--prev-selectrum-functions
@@ -249,7 +246,7 @@ list before passing it to `display-sort-function' or
             selectrum-refine-candidates-function #'hotfuzz-filter
             selectrum-highlight-candidates-function #'hotfuzz--highlight-all)
     (cl-flet ((restore
-               (sym old our &aux (standard (car-safe (get sym 
'standard-value))))
+               (sym old our &aux (standard (car (get sym 'standard-value))))
                (cond ((not (eq (symbol-value sym) our)))
                      (old (set sym old))
                      (standard (set sym (eval standard t)))
@@ -283,7 +280,6 @@ Contrary to what the name might suggest, this mode does not
 automatically enable Hotfuzz. You still have to choose when it gets
 used by customizing e.g. `completion-styles'."
   :global t
-  :group 'hotfuzz
   (if hotfuzz-vertico-mode
       (advice-add #'vertico--all-completions :around 
#'hotfuzz--vertico--all-completions-advice)
     (advice-remove #'vertico--all-completions 
#'hotfuzz--vertico--all-completions-advice)))
diff --git a/test/tests.el b/test/tests.el
index def5817e15..4b86e741a2 100644
--- a/test/tests.el
+++ b/test/tests.el
@@ -59,6 +59,14 @@
     (should (equal (hotfuzz-filter "x" (list (make-string 4096 ?y) b a "x"))
                    (list "x" b a)))))
 
+(ert-deftest filter-long-needle-test ()
+  (let* ((needle (make-string (1+ hotfuzz--max-needle-len) ?x))
+         (a (concat needle "y")))
+    ;; With a too long search string candidates should only be
+    ;; filtered but not sorted.
+    (should (equal (hotfuzz-filter needle (list a "y" needle))
+                   (list a needle)))))
+
 (ert-deftest all-completions-test ()
   (let* ((completion-styles '(hotfuzz))
          (s "fb")
@@ -90,6 +98,16 @@
        6) ; Point as in "/usr/s|/man"
       '("share/" . 5)))))
 
+;;; Selectrum integration
+
+(ert-deftest hotfuzz-selectrum-mode-toggle-test ()
+  (hotfuzz-selectrum-mode)
+  (hotfuzz-selectrum-mode -1)
+  ;; Have to unbind variables when disabling for them to be set to
+  ;; their standard values when Selectrum is loaded.
+  (should-not (or (boundp 'selectrum-refine-candidates-function)
+                  (boundp 'selectrum-highlight-candidates-function))))
+
 ;;; Vertico integration
 
 (ert-deftest vertico--all-completions-advice-test ()
@@ -104,4 +122,4 @@
       (cl-destructuring-bind (xs . hl) (f "x" '("x") nil 1)
         ;; Highlighting should not yet have been applied
         (should (equal-including-properties xs '(#("x" 0 1 (completion-sorted 
t)))))
-        (should-not (null hl))))))
+        (should (functionp hl))))))

Reply via email to