From 66729f3e5080f8853393e5f88ce6f062b45164b7 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Fri, 8 May 2026 12:45:00 +0200 Subject: [PATCH] New variable 'completion-frontend-properties' (bug#80990) Allow completion "frontends" to provide extra information that the backends they call can use to adjust or optimize their behavior. See some relevant discussion at https://yhetil.org/emacs/jwv7bpl28y6.fsf-monnier+emacs@gnu.org/ * lisp/minibuffer.el (completion-frontend-properties): New variable. (completion-lazy-hilit-p): New function. (completion-hilit-commonality, completion-lazy-hilit) (completion-pcm--hilit-commonality) (completion-flex-all-completions): Use it instead of checking the 'completion-lazy-hilit' variable directly. * lisp/completion-preview.el (completion-preview--capf-wrapper): Bind 'completion-frontend-properties'. (completion-preview--try-table): Add comment. * etc/NEWS: Announce 'completion-frontend-properties'. --- etc/NEWS | 7 +++++++ lisp/completion-preview.el | 11 +++++++++-- lisp/minibuffer.el | 35 +++++++++++++++++++++++++++++------ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index edb682a4968..73a4ad72180 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -45,6 +45,13 @@ applies, and please also update docstrings as needed. * Lisp Changes in Emacs 32.1 +--- +** New variable 'completion-frontend-properties'. +This variable generalizes the 'completion-lazy-hilit' variable added in +Emacs 30. It allows Lisp programs that present completion candidates +("completion frontends") to provide additional information which can be +used to adjust or optimize completion candidates computation. + * Changes in Emacs 32.1 on Non-Free Operating Systems diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el index ff348ebf9af..c38bcd70654 100644 --- a/lisp/completion-preview.el +++ b/lisp/completion-preview.el @@ -499,7 +499,12 @@ candidates or if there are multiple matching completions and (sort-fn (or (completion-metadata-get md 'cycle-sort-function) (completion-metadata-get md 'display-sort-function) completion-preview-sort-function)) - (all (let ((completion-lazy-hilit t) + (all (let (;; This is somewhat redundant since we also specify + ;; non-nil `lazy-highlight' in + ;; `completion-frontend-properties', but we keep it + ;; for compatibility with backends that do not know + ;; about `completion-frontend-properties' yet. + (completion-lazy-hilit t) ;; FIXME: This does not override styles prescribed ;; by the completion category via ;; e.g. `completion-category-defaults'. @@ -525,7 +530,9 @@ candidates or if there are multiple matching completions and (defun completion-preview--capf-wrapper (capf) "Translate return value of CAPF to properties for completion preview overlay." - (let ((res (ignore-errors (funcall capf)))) + (let* ((completion-frontend-properties '((no-annotations . t) + (lazy-highlight . t))) + (res (ignore-errors (funcall capf)))) (and (consp res) (not (functionp res)) (seq-let (beg end table &rest plist) res diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 636d0951645..744e20cf444 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2586,7 +2586,7 @@ and with BASE-SIZE appended as the last element." com-str-len (1+ com-str-len) 'face 'completions-first-difference str)) str))) - (if completion-lazy-hilit + (if (completion-lazy-hilit-p) (setq completion-lazy-hilit-fn hilit-fn) (setq completions (mapcar @@ -2604,6 +2604,11 @@ and with BASE-SIZE appended as the last element." completions))) (nconc completions base-size)))) +(defun completion-lazy-hilit-p () + "Return non-nil if the completion frontend supports lazy highlighting." + (or completion-lazy-hilit + (alist-get 'lazy-highlight completion-frontend-properties))) + (defun display-completion-list (completions &optional common-substring group-fun) "Display the list of completions, COMPLETIONS, using `standard-output'. Each element may be just a symbol or string @@ -3198,6 +3203,23 @@ Also respects the obsolete wrapper hook `completion-in-region-functions'. (delq (assq 'completion-in-region-mode minor-mode-map-alist) minor-mode-map-alist)) +(defvar completion-frontend-properties nil + "Alist of properties describing the current completion frontend. + +Frontends may let-bind this variable while calling a completion backend +to provide information which the backend can use to optimize or adjust +its behavior. More specifically, frontends should bind this variable +when calling `completion-try-completion' or `completion-all-completions'. + +Currently known frontend properties are: + +- \\+`no-annotations': if non-nil, the frontend ignores any + `annotation-function'/`affixation-function'. + +- \\+`lazy-highlight': If non-nil, the front-end does not require + `completion-all-completions' completions to be highlighted and knows + to call the function `completion-lazy-hilit' as needed instead.") + (defvar completion-at-point-functions '(tags-completion-at-point-function) "Special hook to find the completion table for the entity at point. Each function on this hook is called in turn without any argument and @@ -4501,9 +4523,10 @@ strings with the `face' property.") (defun completion-lazy-hilit (str) "Return a copy of completion candidate STR that is `face'-propertized. -See documentation of the variable `completion-lazy-hilit' for more -details." - (if (and completion-lazy-hilit completion-lazy-hilit-fn) +Apply `completion-lazy-hilit-fn' if it is set and the frontend supports +lazy highlighting (see `completion-lazy-hilit-p'), otherwise return STR +as is." + (if (and (completion-lazy-hilit-p) completion-lazy-hilit-fn) (funcall completion-lazy-hilit-fn (copy-sequence str)) str)) @@ -4556,7 +4579,7 @@ see) for later lazy highlighting." (re (completion-pcm--segments->regex segments 'group)) (point-idx (completion-pcm--segments-point-idx segments))) (setq completion-pcm--regexp re) - (cond (completion-lazy-hilit + (cond ((completion-lazy-hilit-p) (setq completion-lazy-hilit-fn (lambda (str) (completion--hilit-from-re str re point-idx))) completions) @@ -5036,7 +5059,7 @@ usual. Returns (ALL PAT PREFIX SUFFIX)." (1+ special-match) (+ 2 special-match) 'completions-first-difference nil str)))) str)) - (unless completion-lazy-hilit + (unless (completion-lazy-hilit-p) (setq all (mapcar completion-lazy-hilit-fn all))) ;; Store pattern for adjust-metadata to use (setq completion-flex--pattern-str pattern-str)