branch: externals/vertico commit 930aa814ef2ee5fc958a02bc6690dc55d6cf8ae2 Author: Daniel Mendler <m...@daniel-mendler.de> Commit: Daniel Mendler <m...@daniel-mendler.de>
Add vertico-sort-history-duplicate to prioritize duplicate history elements --- CHANGELOG.org | 3 +++ extensions/vertico-sort.el | 22 +++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.org b/CHANGELOG.org index 393e388c78..6df5c29e6f 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -6,6 +6,9 @@ - =vertico-flat-format=: Customizable =:spacer= string. - =vertico-sort=: Extracted sort functions to separate extension. +- =vertico-sort-history-duplicate=: New customization option to adjust weight of + duplicate history elements, such that they appear earlier in the completion + list. * Version 2.0 (2025-03-11) diff --git a/extensions/vertico-sort.el b/extensions/vertico-sort.el index d35e253c63..4a40bac998 100644 --- a/extensions/vertico-sort.el +++ b/extensions/vertico-sort.el @@ -38,6 +38,16 @@ (defvar-local vertico-sort--history nil "History hash table and corresponding base string.") +(defcustom vertico-sort-history-duplicate 1.0 + "Weight of duplicate elements, multiplied by the length of the history. +Duplicate elements in the history are prioritized such that they appear +earlier in the completion list. The value should be between 0.0 and +1.0. For 0, only the recency of history elements matters. If the value +is 1.0, frequency is more relevant than recency. Note that duplicates +occur only if `history-delete-duplicates' is disabled." + :type 'float + :group 'vertico) + (defun vertico-sort--history () "Recompute history hash table and return it." (or (and (equal (car vertico-sort--history) vertico--base) (cdr vertico-sort--history)) @@ -45,13 +55,15 @@ (base-len (length base)) (hist (and (not (eq minibuffer-history-variable t)) ;; Disabled for `t'. (symbol-value minibuffer-history-variable))) - (hash (make-hash-table :test #'equal :size (length hist))) + (hist-len (length hist)) + (ht (make-hash-table :test #'equal :size hist-len)) (file-p (and (> base-len 0) ;; Step-wise completion, unlike `project-find-file' (eq minibuffer-history-variable 'file-name-history))) (curr-file (when-let ((win (and file-p (minibuffer-selected-window))) (file (buffer-file-name (window-buffer win)))) - (abbreviate-file-name file)))) - (cl-loop for elem in hist for index from 0 do + (abbreviate-file-name file))) + (dup (round (* hist-len vertico-sort-history-duplicate)))) + (cl-loop for elem in hist for idx from 0 do (when (and (not (equal curr-file elem)) ;; Deprioritize current file (or (= base-len 0) (and (>= (length elem) base-len) @@ -60,8 +72,8 @@ ;; Drop base string from history elements & special file handling. (when (or (> base-len 0) file-sep) (setq elem (substring elem base-len (and file-sep (1+ file-sep))))) - (unless (gethash elem hash) (puthash elem index hash))))) - (cdr (setq vertico-sort--history (cons base hash)))))) + (puthash elem (if-let ((n (gethash elem ht))) (- n dup) idx) ht)))) + (cdr (setq vertico-sort--history (cons base ht)))))) (defun vertico-sort--length-string< (x y) "Sorting predicate which compares X and Y first by length then by `string<'."