From: Eshel Yaron Date: Tue, 4 Mar 2025 15:05:47 +0000 (+0100) Subject: Improve elisp CAPF sorting X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=52b455fea27569748757ba9ebafcf55263a062f6;p=emacs.git Improve elisp CAPF sorting --- diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 35723faf185..323efca2d42 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3398,6 +3398,40 @@ obey `completion-styles').") (setq res nil)))) res)) +(defun completion-at-point-function-with-frecency-sorting + (capf &optional num-ts) + (let ((cache (make-hash-table :test #'equal)) + (num-ts (or num-ts 64))) + (lambda () + (let ((res (ignore-errors (funcall capf)))) + (and (consp res) + (not (functionp res)) + (seq-let (beg end table &rest plist) res + (let* ((pred (plist-get plist :predicate)) + (completion-extra-properties plist) + (md (completion-metadata (buffer-substring beg end) table pred)) + (sf (completion-metadata-get md 'sort-function))) + `( ,beg ,end + ,(completion-table-with-metadata + table + `((sort-function + . ,(lambda (completions) + (sort (if sf (funcall sf completions) completions) + :key (let ((now (float-time))) + (lambda (c) + (if-let ((ts (gethash c cache))) + (- (log (- now (car ts))) (length ts)) + 1.0e+INF))) + :in-place t))))) + ,@(plist-put + (copy-sequence plist) + :exit-function + (lambda (str _sts) + (let* ((str (substring-no-properties str)) + (ts (gethash str cache))) + (setf (gethash str cache) + (cons (float-time) (take num-ts ts)))))))))))))) + (defun completion-at-point () "Perform completion on the text around point. The completion method is determined by `completion-at-point-functions'." diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index bce12f35765..4ca5fe07060 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -652,7 +652,7 @@ be used instead. (setq-local project-vc-external-roots-function #'elisp-load-path-roots) (setq-local syntax-propertize-function #'elisp-mode-syntax-propertize) (add-hook 'completion-at-point-functions - #'elisp-completion-at-point nil 'local) + #'elisp-capf nil 'local) (add-hook 'flymake-diagnostic-functions #'elisp-flymake-checkdoc nil t) (add-hook 'flymake-diagnostic-functions #'elisp-flymake-byte-compile nil t) @@ -799,6 +799,21 @@ in `completion-at-point-functions' (which see)." (defun elisp--shorthand-aware-boundp (sym) (boundp (intern-soft (symbol-name sym)))) +(defun elisp--sort-completions (completions) + (sort completions + (lambda (l r) + (let ((li (string-match "--" l)) + (ri (string-match "--" r))) + (if li + (and ri + (or (< (length l) (length r)) + (and (= (length l) (length r)) + (string< l r)))) + (or ri + (< (length l) (length r)) + (and (= (length l) (length r)) + (string< l r)))))))) + (defun elisp-completion-at-point () (with-syntax-table emacs-lisp-mode-syntax-table (when-let ((pos (point)) @@ -845,7 +860,13 @@ in `completion-at-point-functions' (which see)." (beg-end (bounds-of-thing-at-point 'symbol)) (beg (car beg-end)) (end (cdr beg-end))) - (list beg end (elisp--completion-local-symbols) :predicate predicate :exclusive 'no)))) + (list beg end (elisp--completion-local-symbols) + :predicate predicate :exclusive 'no + :sort-function #'elisp--sort-completions)))) + +(defalias 'elisp-capf + (completion-at-point-function-with-frecency-sorting + #'elisp-completion-at-point)) (defun elisp--company-kind (str) (let ((sym (intern-soft str)))