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

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

[elpa] externals/vertico e2c91a6 1/2: Add vertico-sort-function and vert


From: ELPA Syncer
Subject: [elpa] externals/vertico e2c91a6 1/2: Add vertico-sort-function and vertico-sort-override-function
Date: Sun, 11 Jul 2021 10:57:15 -0400 (EDT)

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

    Add vertico-sort-function and vertico-sort-override-function
    
    These variables can be configured as follows:
    
    * nil/identity
    * vertico-sort-recency-length-alpha (default)
    * vertico-sort-recency-alpha
    * vertico-sort-length-alpha
    * vertico-sort-alpha
---
 README.org                  |   2 +-
 extensions/vertico-flat.el  |   2 +-
 extensions/vertico-quick.el |   4 +-
 vertico.el                  | 105 +++++++++++++++++++++++++++-----------------
 4 files changed, 68 insertions(+), 45 deletions(-)

diff --git a/README.org b/README.org
index f93c53e..2f16bd5 100644
--- a/README.org
+++ b/README.org
@@ -27,7 +27,7 @@
   - Prompt shows the current candidate index and the total number of candidates
   - The current candidate is inserted with =TAB= and selected with =RET=
   - Non-existing candidates can be entered by moving the point to the prompt 
line
-  - Sorting by history position, string length and alphabetically
+  - Configurable sorting by recency (history position), length and 
alphabetically
   - Long candidates with newlines are formatted to take up less space
   - Deferred completion style highlighting for performance
   - Support for annotations (~annotation-function~ and ~affixation-function~)
diff --git a/extensions/vertico-flat.el b/extensions/vertico-flat.el
index f167b18..afa702b 100644
--- a/extensions/vertico-flat.el
+++ b/extensions/vertico-flat.el
@@ -68,7 +68,7 @@
          (result))
     (while (and candidates (> width 0) (> count 0))
       (let ((cand (car candidates)))
-        (setq cand (car (funcall vertico--highlight (list cand))))
+        (setq cand (car (funcall vertico--highlight-function (list cand))))
         (when (string-match-p "\n" cand)
           (setq cand (vertico--truncate-multiline cand width)))
         (setq cand (string-trim
diff --git a/extensions/vertico-quick.el b/extensions/vertico-quick.el
index 6da93e3..dd3033f 100644
--- a/extensions/vertico-quick.el
+++ b/extensions/vertico-quick.el
@@ -77,7 +77,7 @@
                    (let ((first (elt vertico-quick2 (mod (/ (- idx fst) len) 
snd)))
                          (second (elt (concat vertico-quick1 vertico-quick2) 
(mod (- idx fst) len))))
                      (push (cons first t) vertico-quick--list)
-                     (push (cons (+ first (lsh second 16)) index) 
vertico-quick--list)
+                     (push (cons (+ first (ash second 16)) index) 
vertico-quick--list)
                      (cond
                       ((eq first vertico-quick--first)
                        (concat " " (propertize (char-to-string second) 'face 
'vertico-quick1)))
@@ -112,7 +112,7 @@
       (let ((vertico-quick--first key)
             (vertico-quick--list))
         (vertico--exhibit))
-      (setq key (+ key (lsh (read-key) 16))))
+      (setq key (+ key (ash (read-key) 16))))
     (when-let (idx (alist-get key vertico-quick--list))
       (setq vertico--index idx))))
 
diff --git a/vertico.el b/vertico.el
index 9e2ec08..21496e8 100644
--- a/vertico.el
+++ b/vertico.el
@@ -73,6 +73,14 @@ See `resize-mini-windows' for documentation."
   "Replacements for multiline strings."
   :type '(cons string string))
 
+(defcustom vertico-sort-override-function nil
+  "Sorting function override, which takes precedence over the 
`display-sort-function'."
+  :type '(choice (const nil) function))
+
+(defcustom vertico-sort-function #'vertico-sort-recency-length-alpha
+  "Default sorting function, which is used if no `display-sort-function' is 
specified."
+  :type '(choice (const nil) function))
+
 (defgroup vertico-faces nil
   "Faces used by Vertico."
   :group 'vertico
@@ -110,7 +118,7 @@ See `resize-mini-windows' for documentation."
     map)
   "Vertico minibuffer keymap derived from `minibuffer-local-map'.")
 
-(defvar-local vertico--highlight #'identity
+(defvar-local vertico--highlight-function #'identity
   "Deferred candidate highlighting function.")
 
 (defvar-local vertico--history-hash nil
@@ -155,12 +163,6 @@ See `resize-mini-windows' for documentation."
 (defvar-local vertico--default-missing nil
   "Default candidate is missing from candidates list.")
 
-(defun vertico--sort-predicate (x y)
-  "Sorting predicate which compares X and Y."
-  (or (< (length x) (length y))
-      (and (= (length x) (length y))
-           (string< x y))))
-
 (defun vertico--update-history-hash (base)
   "Update history hash, given current BASE prefix string."
   (unless (and vertico--history-hash (equal vertico--history-base base))
@@ -187,33 +189,51 @@ See `resize-mini-windows' for documentation."
       (setq vertico--history-hash hash
             vertico--history-base base))))
 
-(defun vertico--sort (candidates)
-  "Sort CANDIDATES by history, length and alphabetically."
-  ;; 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--length-string< (x y)
+  "Sorting predicate which compares X and Y first by length then by `string<'."
+  (or (< (length x) (length y))
+      (and (= (length x) (length y))
+           (string< x y))))
+
+(defmacro vertico--define-sort (fun recency bsize bindex bpred pred)
+  "Generate optimized sort FUN.
+The function is configured by RECENCY, BSIZE, BINDEX, BPRED and PRED."
+  `(defun ,fun (candidates)
+     (let* ((buckets (make-vector ,bsize nil))
+            (recent-candidates))
+       ,@(if recency
+             `((dolist (cand candidates)
+                 (if-let (idx (gethash cand vertico--history-hash))
+                     (push (cons idx cand) recent-candidates)
+                   (let ((idx (min ,(1- bsize) ,bindex)))
+                     (aset buckets idx (cons cand (aref buckets idx))))))
+               ;; Sort recent candidates
+               (setq recent-candidates (sort recent-candidates 
#'car-less-than-car))
+               (let ((cand recent-candidates))
+                 (while cand
+                   (setcar cand (cdar cand))
+                   (pop cand))))
+          `((dolist (cand candidates)
+              (let ((idx (min ,(1- bsize) ,bindex)))
+                (aset buckets idx (cons cand (aref buckets idx)))))))
+       (nconc
+        ;; Sorted recent candidates
+        recent-candidates
+        ;; Sort bucket candidates
+        (mapcan
+         (lambda (bucket) (sort bucket #',bpred))
+         (nbutlast (append buckets nil)))
+        ;; Last bucket needs special treatment
+        (sort (aref buckets ,(1- bsize)) #',pred)))))
+
+(vertico--define-sort vertico-sort-recency-length-alpha
+  'recency 32 (length cand) string< vertico--length-string<)
+(vertico--define-sort vertico-sort-recency-alpha
+  'recency 32 (if (eq cand "") 0 (/ (aref cand 0) 4)) string< string<)
+(vertico--define-sort vertico-sort-length-alpha
+  nil 32 (length cand) string< vertico--length-string<)
+(vertico--define-sort vertico-sort-alpha
+  nil 32 (if (eq cand "") 0 (/ (aref cand 0) 4)) string< string<)
 
 (defun vertico--affixate (metadata candidates)
   "Annotate CANDIDATES with annotation function specified by METADATA."
@@ -298,10 +318,13 @@ See `resize-mini-windows' for documentation."
                             (and completion-ignored-extensions
                                  (concat "\\|" (regexp-opt 
completion-ignored-extensions) "\\'")))))
         (setq all (cl-delete-if (lambda (x) (string-match-p ignore x)) all))))
-    (setq all (if-let (sort (completion-metadata-get metadata 
'display-sort-function))
-                  (funcall sort all)
-                (vertico--update-history-hash (substring content 0 base))
-                (vertico--sort all)))
+    ;; Sort using the `display-sort-function' or the Vertico sort functions
+    (when-let (sort (or (and (not vertico-sort-override-function)
+                             (completion-metadata-get metadata 
'display-sort-function))
+                        vertico-sort-override-function vertico-sort-function))
+      (unless (eq sort #'identity)
+        (vertico--update-history-hash (substring content 0 base))
+        (setq all (funcall sort 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)))
@@ -382,7 +405,7 @@ See `resize-mini-windows' for documentation."
            vertico--index index
            vertico--base base
            vertico--total total
-           vertico--highlight hl
+           vertico--highlight-function hl
            vertico--groups groups
            vertico--all-groups all-groups
            vertico--candidates candidates
@@ -445,7 +468,7 @@ See `resize-mini-windows' for documentation."
            (candidates
             (thread-last (seq-subseq vertico--candidates start
                                      (min (+ start vertico-count) 
vertico--total))
-              (funcall vertico--highlight)
+              (funcall vertico--highlight-function)
               (vertico--affixate metadata))))
       (dolist (cand candidates)
         (when-let (new-title (and group-format (funcall group-fun (car cand) 
nil)))
@@ -685,7 +708,7 @@ When the prefix argument is 0, the group order is reset."
           ;; code is already marked with a FIXME. Should this be reported as a 
bug?
           (vertico--remove-face 0 (length cand) 'completions-common-part cand)
           (concat (substring content 0 vertico--base)
-                  (if hl (car (funcall vertico--highlight (list cand))) cand)))
+                  (if hl (car (funcall vertico--highlight-function (list 
cand))) cand)))
       content)))
 
 (defun vertico--setup ()



reply via email to

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