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

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

[elpa] externals/vertico a962a8b 2/3: Implement deferred highlighting fo


From: Protesilaos Stavrou
Subject: [elpa] externals/vertico a962a8b 2/3: Implement deferred highlighting for all completion styles
Date: Sun, 11 Apr 2021 09:17:39 -0400 (EDT)

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

    Implement deferred highlighting for all completion styles
    
    Every completion style needs a small bit of special code. Fortunately
    `completion-hilit-commonality` and `completion-pcm--hilit-commonality` are
    shared by multiple styles.
---
 vertico.el | 81 ++++++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 47 insertions(+), 34 deletions(-)

diff --git a/vertico.el b/vertico.el
index 7e7c247..310fea7 100644
--- a/vertico.el
+++ b/vertico.el
@@ -36,6 +36,7 @@
 
 (require 'seq)
 (eval-when-compile
+  (require 'cl-lib)
   (require 'subr-x))
 
 (defgroup vertico nil
@@ -105,6 +106,9 @@
     map)
   "Minibuffer keymap.")
 
+(defvar-local vertico--highlight #'identity
+  "Deferred candidate highlighting function.")
+
 (defvar-local vertico--history-hash nil
   "History hash table.")
 
@@ -211,21 +215,6 @@
         (mapcar (lambda (cand) (list cand (or (funcall ann cand) ""))) 
candidates)
       candidates)))
 
-(defvar orderless-skip-highlighting)
-(defun vertico--highlight (input metadata candidates)
-  "Highlight CANDIDATES with INPUT using the completion style specified by 
METADATA."
-  (let* ((orderless-skip-highlighting)
-         (highlighted (nconc
-                       (completion-all-completions input
-                                                   candidates
-                                                   nil
-                                                   (length input)
-                                                   metadata)
-                       nil)))
-    ;; Check if everything went alright, all the candidates should still be 
present.
-    (if (= (length highlighted) (length candidates))
-        highlighted candidates)))
-
 (defun vertico--move-to-front (elem list)
   "Move ELEM to front of LIST."
   (if-let (found (member elem list))
@@ -242,20 +231,44 @@
         (lambda (x) (and (not (string-match-p ignore x)) (funcall pred x)))
       (lambda (x) (not (string-match-p ignore x))))))
 
+(declare-function orderless-highlight-matches "ext:orderless")
+(defun vertico--all-completions (&rest args)
+  "Compute all completions for ARGS with deferred highlighting."
+  (cl-letf* ((orig-pcm (symbol-function #'completion-pcm--hilit-commonality))
+             (orig-flex (symbol-function #'completion-flex-all-completions))
+             ((symbol-function #'completion-flex-all-completions)
+              (lambda (&rest args)
+                ;; Unfortunately for flex we have to undo the deferred 
highlighting, since flex uses
+                ;; the completion-score for sorting, which is applied during 
highlighting.
+                (cl-letf (((symbol-function 
#'completion-pcm--hilit-commonality) orig-pcm))
+                  (apply orig-flex args))))
+             ;; Defer the following highlighting functions
+             (hl #'identity)
+             ((symbol-function #'completion-hilit-commonality)
+              (lambda (cands prefix &optional base)
+                (setq hl (lambda (x) (nconc (completion-hilit-commonality x 
prefix base) nil)))
+                (and cands (nconc cands base))))
+             ((symbol-function #'completion-pcm--hilit-commonality)
+              (lambda (pattern cands)
+                (setq hl (lambda (x) (completion-pcm--hilit-commonality 
pattern x)))
+                cands))
+             ((symbol-function #'orderless-highlight-matches)
+              (lambda (pattern cands)
+                (setq hl (lambda (x) (orderless-highlight-matches pattern x)))
+                cands)))
+    (cons (apply #'completion-all-completions args) hl)))
+
 (defun vertico--recompute-candidates (pt content bounds metadata)
   "Recompute candidates given PT, CONTENT, BOUNDS and METADATA."
   (let* ((field (substring content (car bounds) (+ pt (cdr bounds))))
-         (all (completion-all-completions
-               content
-               minibuffer-completion-table
-               (if minibuffer-completing-file-name
-                   (vertico--file-predicate)
-                 minibuffer-completion-predicate)
-               pt metadata))
-         (base (if-let (last (last all))
-                   (prog1 (cdr last)
-                     (setcdr last nil))
-                 0))
+         (all-hl (vertico--all-completions content
+                                           minibuffer-completion-table
+                                           (if minibuffer-completing-file-name
+                                               (vertico--file-predicate)
+                                             minibuffer-completion-predicate)
+                                           pt metadata))
+         (all (car all-hl))
+         (base (if-let (last (last all)) (prog1 (cdr last) (setcdr last nil)) 
0))
          (def (or (car-safe minibuffer-default) minibuffer-default))
          (total (length all)))
     (when (<= total vertico-sort-threshold)
@@ -270,14 +283,14 @@
     (setq all (vertico--move-to-front field all))
     (when-let (group (completion-metadata-get metadata 'x-group-function))
       (setq all (mapcan #'cdr (funcall group all))))
-    (list base total all)))
+    (list base total all (cdr all-hl))))
 
 (defun vertico--update-candidates (pt content bounds metadata)
   "Preprocess candidates given PT, CONTENT, BOUNDS and METADATA."
   (pcase (let ((while-no-input-ignore-events '(selection-request)))
            (while-no-input (vertico--recompute-candidates pt content bounds 
metadata)))
     ('nil (abort-recursive-edit))
-    (`(,base ,total ,candidates)
+    (`(,base ,total ,candidates ,hl)
      (unless (and vertico--keep (< vertico--index 0))
        (if-let* ((old (and candidates
                            vertico--keep
@@ -298,6 +311,7 @@
      (setq vertico--input (cons content pt)
            vertico--base base
            vertico--total total
+           vertico--highlight hl
            vertico--candidates candidates))))
 
 (defun vertico--flatten-string (prop str)
@@ -312,8 +326,8 @@
         (setq pos next)))
     (apply #'concat (nreverse chunks))))
 
-(defun vertico--format-candidates (content bounds metadata)
-  "Format current candidates with CONTENT string, BOUNDS and METADATA."
+(defun vertico--format-candidates (metadata)
+  "Format current candidates with METADATA."
   (let* ((group (completion-metadata-get metadata 'x-group-function))
          (group-format (and group vertico-group-format (concat 
vertico-group-format "\n")))
          (index (min (max 0 (- vertico--index (/ vertico-count 2) (if 
group-format -1 0)))
@@ -321,7 +335,7 @@
          (candidates
           (thread-last (seq-subseq vertico--candidates index
                                    (min (+ index vertico-count) 
vertico--total))
-            (vertico--highlight (substring content (car bounds)) metadata)
+            (funcall vertico--highlight)
             (vertico--annotate metadata)))
          (max-width (- (window-width) 4))
          (current-line 0) (title) (lines))
@@ -434,7 +448,7 @@
       (vertico--update-candidates pt content bounds metadata))
     (vertico--prompt-selection)
     (vertico--display-count)
-    (vertico--display-candidates (vertico--format-candidates content bounds 
metadata))))
+    (vertico--display-candidates (vertico--format-candidates metadata))))
 
 (defun vertico--require-match ()
   "Return t if match is required."
@@ -525,8 +539,7 @@
   (setq vertico--input t
         vertico--candidates-ov (make-overlay (point-max) (point-max) nil t t)
         vertico--count-ov (make-overlay (point-min) (point-min) nil t t))
-  (setq-local orderless-skip-highlighting t ;; Orderless optimization
-              resize-mini-windows 'grow-only
+  (setq-local resize-mini-windows 'grow-only
               truncate-lines t
               max-mini-window-height 1.0)
   (use-local-map vertico-map)



reply via email to

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