From: Eshel Yaron Date: Tue, 11 Mar 2025 10:16:49 +0000 (+0100) Subject: completion-preview.el: Provide an API. X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6ba4bec19699ad56838ce7ae91db4b418c48681f;p=emacs.git completion-preview.el: Provide an API. Add new functions for summoning and dismissing the completion preview programmatically. This lets Lisp code leverage the completion preview UI for different use cases. * lisp/completion-preview.el (completion-preview-show): New function. (completion-preview-hide): Rename to 'completion-preview--hide', use old name for new public API function. (completion-preview--hide): New name, see above. (completion-preview-active-mode) (completion-preview--update): Use new functions. --- diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el index 815879b26b1..e4bbb3165c1 100644 --- a/lisp/completion-preview.el +++ b/lisp/completion-preview.el @@ -133,6 +133,10 @@ ;; (lambda () ;; (setq-local completion-preview-overlay-priority 1200) ;; (completion-preview-mode))) +;; +;; This library also provides an API that you can use to summon and +;; dismiss the completion preview programmatically; see the functions +;; `completion-preview-show' and `completion-preview-hide' for details. ;;; Code: @@ -346,7 +350,7 @@ Completion Preview mode avoids updating the preview after these commands.") (and bounds (<= completion-preview-minimum-symbol-length (- (cdr bounds) (car bounds))))))) -(defun completion-preview-hide () +(defun completion-preview--hide () "Hide the completion preview." (when completion-preview--overlay (delete-overlay completion-preview--overlay) @@ -477,7 +481,7 @@ set to the value of this option while the completion preview is visible." (completion-preview--restore-cursor) (setq completion-preview--window nil completion-preview--buffer nil) - (completion-preview-hide))) + (completion-preview--hide))) (defun completion-preview--cleanup () "Dismiss completion preview and restore cursor shape if window changed." @@ -487,7 +491,7 @@ set to the value of this option while the completion preview is visible." (eq completion-preview--buffer (window-buffer (minibuffer-selected-window))))) (when (buffer-live-p completion-preview--buffer) (with-current-buffer completion-preview--buffer - (completion-preview-active-mode -1))) + (completion-preview-hide))) (completion-preview--restore-cursor) (remove-hook 'post-command-hook 'completion-preview--cleanup))) @@ -574,28 +578,7 @@ candidates or if there are multiple matching completions and (run-hook-wrapped 'completion-at-point-functions #'completion-preview--capf-wrapper) - (when-let ((suffix (car suffixes))) - (set-text-properties 0 (length suffix) - (list 'face (if (cdr suffixes) - 'completion-preview - 'completion-preview-exact)) - suffix) - (set-text-properties 0 (length common) - (list 'face (if (cdr suffixes) - 'completion-preview-common - 'completion-preview-exact)) - common) - (let ((ov (completion-preview--make-overlay - end (completion-preview--propertize-for-mouse - (concat (substring common (- end beg)) suffix))))) - (overlay-put ov 'completion-preview-beg beg) - (overlay-put ov 'completion-preview-end end) - (overlay-put ov 'completion-preview-index 0) - (overlay-put ov 'completion-preview-suffixes suffixes) - (overlay-put ov 'completion-preview-common common) - (overlay-put ov 'completion-preview-base base) - (overlay-put ov 'completion-preview-props props) - (completion-preview-active-mode))))) + (apply #'completion-preview-show beg end common suffixes base props))) (defun completion-preview--try-update () "Try to update completion preview, but give up as soon as input arrives." @@ -658,7 +641,7 @@ point, otherwise hide it." (substring cand (- end beg)))) 'completion-preview-end end) ;; The previous preview is no longer applicable, hide it. - (completion-preview-active-mode -1)))) + (completion-preview-hide)))) ;; Run `completion-at-point-functions' to get a new candidate. (if completion-preview-idle-delay (setq completion-preview--timer @@ -685,7 +668,7 @@ point, otherwise hide it." (completion-preview-require-minimum-symbol-length) (not buffer-read-only)) (completion-preview--show) - (completion-preview-active-mode -1))))) + (completion-preview-hide))))) (defun completion-preview--barf-if-no-preview () "Signal a `user-error' if completion preview is not active." @@ -705,7 +688,7 @@ point, otherwise hide it." :exit-function)) (aft (completion-preview--get 'after-string)) (str (concat pre com (nth ind all)))) - (completion-preview-active-mode -1) + (completion-preview-hide) (goto-char end) (insert-and-inherit (substring-no-properties aft)) (when (functionp efn) (funcall efn str 'finished)))) @@ -754,7 +737,7 @@ Beyond moving point, FUN should not modify the current buffer." (efn (plist-get (completion-preview--get 'completion-preview-props) :exit-function))) - (completion-preview-active-mode -1) + (completion-preview-hide) (when (functionp efn) (funcall efn (concat pre com (nth ind all)) 'finished)))) ;; If we kept anything, update preview overlay accordingly. @@ -819,7 +802,7 @@ completions list." (props (plist-put props :exit-function (when (functionp efn) (lambda (string status) - (completion-preview-active-mode -1) + (completion-preview-hide) (funcall efn string status))))) ;; The predicate is meant for the original completion ;; candidates, which may be symbols or cons cells, but @@ -841,7 +824,7 @@ completions list." ;; Remove stale preview since `efn' can make arbitrary ;; text and point modifications that might interfere with ;; a subsequent preview update. See bug#76606. - (completion-preview-active-mode -1) + (completion-preview-hide) (funcall efn (concat base com) (if (cdr all) 'exact 'finished))) ;; Otherwise, remove the common prefix from the preview. (completion-preview--inhibit-update) @@ -924,7 +907,7 @@ backward." (if completion-preview-mode (add-hook 'post-command-hook #'completion-preview--post-command 10 t) (remove-hook 'post-command-hook #'completion-preview--post-command t) - (when completion-preview-active-mode (completion-preview-active-mode -1)) + (when completion-preview-active-mode (completion-preview-hide)) (when (timerp completion-preview--timer) (cancel-timer completion-preview--timer) (setq completion-preview--timer nil)))) @@ -945,5 +928,56 @@ backward." wdired-mode) t)) + +;;; API + +(defun completion-preview-show (beg end common suffixes &optional base &rest props) + "Display an inline completion preview. + +BEG and END are buffer positions, the beginning and end of the buffer +text for which the preview shows a completion suggestion, respectively. +The completion preview is displayed right after END. + +COMMON is a common prefix of all available completion candidates. +SUFFIXES is a list of strings such that prepending COMMON to a suffix +yields a completion candidate. + +The completion preview initially displays the first completion +candidate, the candidate obtained by prepending COMMON to the first +element of SUFFIXES. + +PROPS is a list of extra metadata, like `completion-extra-properties'. +Currently the only meaningful property is `:exit-function'. + +Optional argument BASE, if non-nil, is an additional prefix to prepend +to a completion suggestion you accept before reporting it to the given +`:exit-function'. BASE does not influence completion." + (when-let ((suffix (car suffixes))) + (set-text-properties 0 (length suffix) + (list 'face (if (cdr suffixes) + 'completion-preview + 'completion-preview-exact)) + suffix) + (set-text-properties 0 (length common) + (list 'face (if (cdr suffixes) + 'completion-preview-common + 'completion-preview-exact)) + common) + (let ((ov (completion-preview--make-overlay + end (completion-preview--propertize-for-mouse + (concat (substring common (- end beg)) suffix))))) + (overlay-put ov 'completion-preview-beg beg) + (overlay-put ov 'completion-preview-end end) + (overlay-put ov 'completion-preview-index 0) + (overlay-put ov 'completion-preview-suffixes suffixes) + (overlay-put ov 'completion-preview-common (or common "")) + (overlay-put ov 'completion-preview-base (or base "")) + (overlay-put ov 'completion-preview-props props) + (completion-preview-active-mode)))) + +(defun completion-preview-hide () + "Hide the completion preview and reset its state." + (completion-preview-active-mode -1)) + (provide 'completion-preview) ;;; completion-preview.el ends here