diff options
| author | Daniel Mendler <mail@daniel-mendler.de> | 2022-03-31 16:23:27 +0200 |
|---|---|---|
| committer | Daniel Mendler <mail@daniel-mendler.de> | 2022-03-31 16:29:59 +0200 |
| commit | 967a84ee7b33ce4c9cb3d7b4e33fcd07ba374404 (patch) | |
| tree | ae351da925ba0f1a2a46287e1662996914d15892 /extensions/corfu-history.el | |
| parent | c8e6607c90a89ff19062cd37afc17e8bbb86aba3 (diff) | |
Add corfu-history and corfu-info extensionsextensions
Diffstat (limited to 'extensions/corfu-history.el')
| -rw-r--r-- | extensions/corfu-history.el | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/extensions/corfu-history.el b/extensions/corfu-history.el new file mode 100644 index 0000000..80424bc --- /dev/null +++ b/extensions/corfu-history.el @@ -0,0 +1,101 @@ +;;; corfu-history.el --- Sorting by history for Corfu -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; Author: Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2021 +;; Version: 0.1 +;; Package-Requires: ((emacs "27.1") (corfu "0.20")) +;; Homepage: https://github.com/minad/corfu + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Sort candidates by their history position. Maintain a list of +;; recently selected candidates. + +;;; Code: + +(require 'corfu) + +(defcustom corfu-history-length nil + "Corfu history length." + :type '(choice (const nil) integer) + :group 'corfu) + +(defvar corfu-history--hash nil + "Hash table of Corfu candidates.") + +(defvar corfu-history nil + "History of Corfu candidates.") + +(defun corfu-history--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))))) + +(defun corfu-history--sort (candidates) + "Sort CANDIDATES by history." + (unless corfu-history--hash + (let ((index 0)) + (setq corfu-history--hash (make-hash-table :test #'equal :size (length corfu-history))) + (dolist (elt corfu-history) + (unless (gethash elt corfu-history--hash) + (puthash elt index corfu-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) corfu-history--hash #xFFFF) 13) + (length (car cand))))) + (pop cand))) + (setq candidates (sort candidates #'corfu-history--sort-predicate)) + ;; Drop decoration from the candidates + (let ((cand candidates)) + (while cand + (setcar cand (caar cand)) + (pop cand))) + candidates) + +(defun corfu-history--insert (&rest _) + "Advice for `corfu--insert'." + (when (>= corfu--index 0) + (add-to-history 'corfu-history + (nth corfu--index corfu--candidates) + corfu-history-length) + (setq corfu-history--hash nil))) + +;;;###autoload +(define-minor-mode corfu-history-mode + "Update Corfu history and sort completions by history." + :global t + :group 'corfu + (cond + (corfu-history-mode + (setq corfu-sort-function #'corfu-history--sort) + (advice-add #'corfu--insert :before #'corfu-history--insert)) + (t + (setq corfu-sort-function #'corfu-sort-length-alpha) + (advice-remove #'corfu--insert #'corfu-history--insert)))) + +(provide 'corfu-history) +;;; corfu-history.el ends here |
