emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/vertico b7d55f0 1/2: vertico--sort: Use bucket sort as


From: Protesilaos Stavrou
Subject: [elpa] externals/vertico b7d55f0 1/2: vertico--sort: Use bucket sort as suggested by Stefan Monnier
Date: Tue, 20 Apr 2021 01:21:36 -0400 (EDT)

branch: externals/vertico
commit b7d55f096fc9e07b91b368fda7f865abbb148a39
Author: Daniel Mendler <mail@daniel-mendler.de>
Commit: Daniel Mendler <mail@daniel-mendler.de>

    vertico--sort: Use bucket sort as suggested by Stefan Monnier
    
    Drop the threshold
---
 vertico.el | 58 +++++++++++++++++++++++++++++++---------------------------
 1 file changed, 31 insertions(+), 27 deletions(-)

diff --git a/vertico.el b/vertico.el
index e8aaac7..7fc2262 100644
--- a/vertico.el
+++ b/vertico.el
@@ -44,10 +44,6 @@
   :group 'convenience
   :prefix "vertico-")
 
-(defcustom vertico-sort-threshold 20000
-  "Candidates will only be sorted if there are fewer than this threshold."
-  :type 'integer)
-
 (defcustom vertico-count-format (cons "%-6s " "%s/%s")
   "Format string used for the candidate count."
   :type '(choice (const nil) (cons string string)))
@@ -140,9 +136,9 @@
 
 (defun vertico--sort-predicate (x y)
   "Sorting predicate which compares X and Y."
-  (or (< (cdr x) (cdr y))
-      (and (= (cdr x) (cdr y))
-           (string< (car x) (car y)))))
+  (or (< (length x) (length y))
+      (and (= (length x) (length y))
+           (string< x y))))
 
 (defun vertico--sort (input candidates)
   "Sort CANDIDATES by history, length and alphabetically, given current INPUT."
@@ -186,22 +182,31 @@
         (unless (gethash elem vertico--history-hash)
           (puthash elem index vertico--history-hash))
         (setq index (1+ index))))))
-  ;; Decorate each candidate with (index<<13) + length. This way we sort first 
by index and then by
-  ;; length. We assume that the candidates are shorter than 2**13 characters 
and that the history is
-  ;; shorter than 2**16 entries.
-  (let ((cand candidates))
-    (while cand
-      (setcar cand (cons (car cand)
-                         (+ (lsh (gethash (car cand) vertico--history-hash 
#xFFFF) 13)
-                            (length (car cand)))))
-      (pop cand)))
-  (setq candidates (sort candidates #'vertico--sort-predicate))
-  ;; Drop decoration from the candidates
-  (let ((cand candidates))
-    (while cand
-      (setcar cand (caar cand))
-      (pop cand)))
-  candidates)
+  ;; Separate history candidates from candidates first.
+  ;; Move the remaining candidates into buckets according to length.
+  (let* ((max-bucket 40)
+         (buckets (make-vector (1+ max-bucket) nil))
+         (hcands))
+    (dolist (cand candidates)
+      (if-let (idx (gethash cand vertico--history-hash))
+          (push (cons idx cand) hcands)
+        (let ((idx (min max-bucket (length cand))))
+          (aset buckets idx (cons cand (aref buckets idx))))))
+    ;; Sort history candidates
+    (setq hcands (sort hcands #'car-less-than-car))
+    (let ((cand hcands))
+      (while cand
+        (setcar cand (cdar cand))
+        (pop cand)))
+    (nconc
+     ;; Sorted History candidates
+     hcands
+     ;; Sort bucket candidates
+     (mapcan
+      (lambda (bucket) (sort bucket #'string<))
+      (nbutlast (append buckets nil)))
+     ;; Last bucket needs special treatment
+     (sort (aref buckets max-bucket) #'vertico--sort-predicate))))
 
 (defun vertico--annotate (metadata candidates)
   "Annotate CANDIDATES with annotation function specified by METADATA."
@@ -271,10 +276,9 @@
          (base (or (when-let (z (last all)) (prog1 (cdr z) (setcdr z nil))) 0))
          (def (or (car-safe minibuffer-default) minibuffer-default))
          (total (length all)))
-    (when (<= total vertico-sort-threshold)
-      (setq all (if-let (sort (completion-metadata-get metadata 
'display-sort-function))
-                    (funcall sort all)
-                  (vertico--sort content all))))
+    (setq all (if-let (sort (completion-metadata-get metadata 
'display-sort-function))
+                  (funcall sort all)
+                (vertico--sort content all)))
     ;; Move special candidates: "field" appears at the top, before "field/", 
before default value
     (when (stringp def)
       (setq all (vertico--move-to-front def all)))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]