branch: externals/corfu
commit 3a8a03110b3a3efa5357eb5ab2d8f3ff8e6a4547
Author: Daniel Mendler <m...@daniel-mendler.de>
Commit: Daniel Mendler <m...@daniel-mendler.de>

    Add corfu-history-duplicate
---
 CHANGELOG.org               |  5 +++++
 extensions/corfu-history.el | 24 +++++++++++++++++-------
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.org b/CHANGELOG.org
index 17d1b0ac5e..a88528b7f0 100644
--- a/CHANGELOG.org
+++ b/CHANGELOG.org
@@ -2,6 +2,11 @@
 #+author: Daniel Mendler
 #+language: en
 
+* Development
+
+- ~corfu-history-duplicate~: Prioritize duplicate history elements when 
sorting by
+  history via ~corfu-history-mode~.
+
 * Version 2.0 (2025-03-28)
 
 - ~corfu-quick~: Ensure that popup does not move.
diff --git a/extensions/corfu-history.el b/extensions/corfu-history.el
index d0821bc2d0..a93bc14754 100644
--- a/extensions/corfu-history.el
+++ b/extensions/corfu-history.el
@@ -49,6 +49,16 @@ or the property `history-length' of `corfu-history'.")
 (defvar corfu-history--hash nil
   "Hash table of Corfu candidates.")
 
+(defcustom corfu-history-duplicate 1.0
+  "Weight of duplicate elements, multiplied with `history-length'.
+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
+`history-delete-duplicates' must be disabled for duplicates to appear."
+  :type 'float
+  :group 'corfu)
+
 (defun corfu-history--sort-predicate (x y)
   "Sorting predicate which compares X and Y."
   (or (< (cdr x) (cdr y))
@@ -58,13 +68,13 @@ or the property `history-length' of `corfu-history'.")
 (defun corfu-history--sort (cands)
   "Sort CANDS by history."
   (unless corfu-history--hash
-    (let ((ht (make-hash-table :test #'equal :size (length corfu-history))))
-      (cl-loop for elem in corfu-history for index from 0 do
-               (unless (gethash elem ht) (puthash elem index ht)))
-      (setq corfu-history--hash ht)))
-  (cl-loop for ht = corfu-history--hash for max = most-positive-fixnum
-           for cand on cands do
-           (setcar cand (cons (car cand) (gethash (car cand) ht max))))
+    (setq corfu-history--hash (make-hash-table :test #'equal :size (length 
corfu-history)))
+    (cl-loop for weight = (round (* history-length corfu-history-duplicate))
+             for elem in corfu-history for idx from 0
+             for dup = (gethash elem corfu-history--hash) do
+             (puthash elem (if dup (- dup weight) idx) corfu-history--hash)))
+  (cl-loop for max = most-positive-fixnum for cand on cands do
+           (setcar cand (cons (car cand) (gethash (car cand) 
corfu-history--hash max))))
   (setq cands (sort cands #'corfu-history--sort-predicate))
   (cl-loop for cand on cands do (setcar cand (caar cand)))
   cands)

Reply via email to