]> code.delx.au - gnu-emacs-elpa/blobdiff - company.el
Improve duplicates removal
[gnu-emacs-elpa] / company.el
index cac3ca26041c627ebd7e74437f8bcfc6ce5deaf8..41291891aa0a55e3e1019553df5a72f07759bbfd 100644 (file)
@@ -449,9 +449,11 @@ even if the back-end uses the asynchronous calling convention."
 (put 'company-backends 'safe-local-variable 'company-safe-backends-p)
 
 (defcustom company-transformers nil
-  "Functions to change the list of candidates received from backends,
-after sorting and removal of duplicates (if appropriate).
-Each function gets called with the return value of the previous one."
+  "Functions to change the list of candidates received from backends.
+
+Each function gets called with the return value of the previous one.
+The first one gets passed the list of candidates, already sorted and
+without duplicates."
   :type '(choice
           (const :tag "None" nil)
           (const :tag "Sort by occurrence" (company-sort-by-occurrence))
@@ -1055,13 +1057,6 @@ can retrieve meta-data for them."
                                               (symbol-name backend))))
           (setq company-lighter (format " company-<%s>" name)))))))
 
-(defun company-apply-predicate (candidates predicate)
-  (let (new)
-    (dolist (c candidates)
-      (when (funcall predicate c)
-        (push c new)))
-    (nreverse new)))
-
 (defun company-update-candidates (candidates)
   (setq company-candidates-length (length candidates))
   (if (> company-selection 0)
@@ -1107,10 +1102,12 @@ can retrieve meta-data for them."
                 (cl-return t)))))
         (progn
           ;; No cache match, call the backend.
-          (setq candidates (company--fetch-candidates prefix))
-          ;; Save in cache (without the predicate applied).
+          (setq candidates (company--preprocess-candidates
+                            (company--fetch-candidates prefix)))
+          ;; Save in cache.
           (push (cons prefix candidates) company-candidates-cache)))
-    (setq candidates (company--process-candidates candidates))
+    ;; Only now apply the predicate and transformers.
+    (setq candidates (company--postprocess-candidates candidates))
     (when candidates
       (if (or (cdr candidates)
               (not (eq t (compare-strings (car candidates) nil nil
@@ -1139,7 +1136,9 @@ can retrieve meta-data for them."
                ;; or the fetcher called us back right away.
                (setq res candidates)
              (setq company-backend backend
-                   company-candidates-cache (list (cons prefix candidates)))
+                   company-candidates-cache
+                   (list (cons prefix
+                               (company--preprocess-candidates candidates))))
              (company-idle-begin buf win tick pt)))))
       ;; FIXME: Relying on the fact that the callers
       ;; will interpret nil as "do nothing" is shaky.
@@ -1147,33 +1146,40 @@ can retrieve meta-data for them."
       (or res
           (progn (setq res 'done) nil)))))
 
-(defun company--process-candidates (candidates)
-  (when company-candidates-predicate
-    (setq candidates
-          (company-apply-predicate candidates
-                                   company-candidates-predicate)))
+(defun company--preprocess-candidates (candidates)
   (unless (company-call-backend 'sorted)
-    (setq candidates (sort (copy-sequence candidates) 'string<)))
+    (setq candidates (sort candidates 'string<)))
   (when (company-call-backend 'duplicates)
     (company--strip-duplicates candidates))
+  candidates)
+
+(defun company--postprocess-candidates (candidates)
+  (when (or company-candidates-predicate company-transformers)
+    (setq candidates (copy-sequence candidates)))
+  (when company-candidates-predicate
+    (setq candidates (cl-delete-if-not company-candidates-predicate candidates)))
   (company--transform-candidates candidates))
 
 (defun company--strip-duplicates (candidates)
-  (let ((c2 candidates))
+  (let ((c2 candidates)
+        (annos 'unk))
     (while c2
       (setcdr c2
-              (let ((str (car c2))
-                    (anno 'unk))
-                (pop c2)
+              (let ((str (pop c2)))
                 (while (let ((str2 (car c2)))
                          (if (not (equal str str2))
-                             nil
-                           (when (eq anno 'unk)
-                             (setq anno (company-call-backend
-                                         'annotation str)))
-                           (equal anno
-                                  (company-call-backend
-                                   'annotation str2))))
+                             (progn
+                               (setq annos 'unk)
+                               nil)
+                           (when (eq annos 'unk)
+                             (setq annos (list (company-call-backend
+                                                'annotation str))))
+                           (let ((anno2 (company-call-backend
+                                         'annotation str2)))
+                             (if (member anno2 annos)
+                                 t
+                               (push anno2 annos)
+                               nil))))
                   (pop c2))
                 c2)))))
 
@@ -1595,10 +1601,10 @@ from the rest of the back-ends in the group, if any, will be left at the end."
     (company--search-update-string ss)))
 
 (defun company--search-update-predicate (&optional ss)
-  (or ss (setq ss company-search-string))
   (let* ((company-candidates-predicate
-          (when company-search-filtering
-            (lambda (candidate) (string-match ss candidate))))
+          (and (not (string= ss ""))
+               company-search-filtering
+               (lambda (candidate) (string-match ss candidate))))
          (cc (company-calculate-candidates company-prefix)))
     (unless cc (error "No match"))
     (company-update-candidates cc)))
@@ -1617,7 +1623,7 @@ from the rest of the back-ends in the group, if any, will be left at the end."
 
 (defun company--search-assert-input ()
   (company--search-assert-enabled)
-  (unless (cl-plusp (length company-search-string))
+  (when (string= company-search-string "")
     (error "Empty search string")))
 
 (defun company-search-repeat-forward ()
@@ -1668,7 +1674,8 @@ from the rest of the back-ends in the group, if any, will be left at the end."
 (defun company-search-delete-char ()
   (interactive)
   (company--search-assert-enabled)
-  (when (cl-plusp (length company-search-string))
+  (if (string= company-search-string "")
+      (ding)
     (let ((ss (substring company-search-string 0 -1)))
       (when company-search-filtering
         (company--search-update-predicate ss))
@@ -2182,7 +2189,7 @@ If SHOW-VERSION is non-nil, show the version in the echo area."
                              mouse-face company-tooltip-mouse)
                            line))
     (when selected
-      (if (and (cl-plusp (length company-search-string))
+      (if (and (not (string= company-search-string ""))
                (string-match (regexp-quote company-search-string) value
                              (length company-prefix)))
           (let ((beg (+ margin (match-beginning 0)))