From 7488cb5dcacb82fdbe0b080e8c45febfce5b1b91 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Mon, 16 Jun 2025 22:45:23 +0200 Subject: [PATCH] elisp-mode.el: Some Xref improvements --- lisp/progmodes/elisp-mode.el | 18 ++++--------- lisp/progmodes/xref.el | 49 +++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 50cb318cd0a..d4a8a13c3d4 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1504,19 +1504,11 @@ confidence." (push (elisp--xref-find-definitions sym) lst)) (nreverse lst)))) -(defvar elisp--xref-identifier-completion-table - (apply-partially #'completion-table-with-predicate - obarray - (lambda (sym) - (or (boundp sym) - (fboundp sym) - (featurep sym) - (facep sym))) - 'strict)) - -(cl-defmethod xref-backend-identifier-completion-table ((_backend - (eql 'elisp))) - elisp--xref-identifier-completion-table) +(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql 'elisp))) + (completion-table-with-metadata obarray '((category . elisp-xref)))) + +(cl-defmethod xref-backend-identifier-completion-predicate ((_backend (eql 'elisp))) + #'elisp-completion-at-point-default-predicate) (cl-defstruct (xref-elisp-location (:constructor xref-make-elisp-location (symbol type file))) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index b5b2e368e43..3a647856c4b 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -323,6 +323,10 @@ recognize and then delegate the work to an external process." (cl-defgeneric xref-backend-identifier-completion-table (backend) "Return the completion table for identifiers.") +(cl-defgeneric xref-backend-identifier-completion-predicate (_backend) + "Return the completion predicate for identifiers." + nil) + (cl-defgeneric xref-backend-identifier-completion-ignore-case (_backend) "Return t if case is not significant in identifier completion." completion-ignore-case) @@ -1526,7 +1530,6 @@ between them by typing in the minibuffer with completion." (let* ((xrefs (funcall fetcher)) (xref-alist (xref--analyze xrefs)) xref-alist-with-line-info) - (pcase-dolist (`(,group . ,xrefs) xref-alist) (dolist (xref xrefs) (let* ((summary (xref-item-summary xref)) @@ -1633,7 +1636,7 @@ The meanings of both arguments are the same as documented in `xref-show-xrefs-function'." (xref--show-xrefs fetcher display-action)) -(defun xref--show-xrefs (fetcher display-action &optional _always-show-list) +(defun xref--show-xrefs (fetcher &optional display-action _always-show-list) (unless (functionp fetcher) ;; Old convention. (let ((xrefs fetcher)) @@ -1654,7 +1657,7 @@ The meanings of both arguments are the same as documented in (auto-jump . ,xref-auto-jump-to-first-xref))) (xref--push-markers cb pt win)))) -(defun xref--show-defs (xrefs display-action) +(defun xref--show-defs (xrefs &optional display-action) (let ((cb (current-buffer)) (pt (point)) (win (selected-window))) @@ -1686,19 +1689,29 @@ The meanings of both arguments are the same as documented in (not (memq command (cdr xref-prompt-for-identifier))) (memq command xref-prompt-for-identifier)))) -(defun xref--read-identifier (prompt) +(defun xref--read-identifier (prompt &optional kind) "Return the identifier at point or prompt for it with PROMPT." (if-let* ((backend (xref-find-backend))) - (let ((def (xref-backend-identifier-at-point backend)) - (completion-ignore-case - (xref-backend-identifier-completion-ignore-case backend))) + (let ((def (xref-backend-identifier-at-point backend))) (cond ((or current-prefix-arg (not def) (xref--prompt-p this-command)) (let ((id - (completing-read - (format-prompt prompt def) - (xref-backend-identifier-completion-table backend) - nil nil nil - 'xref--read-identifier-history def t))) + (minibuffer-with-setup-hook + (lambda () + (setq minibuffer-action + (cons + (lambda (str) + (save-selected-window + (xref--show-xrefs + (xref--create-fetcher str (or kind 'references) str backend)))) + "show")) + (setq-local completion-ignore-case + (xref-backend-identifier-completion-ignore-case backend))) + (completing-read + (format-prompt prompt def) + (xref-backend-identifier-completion-table backend) + (xref-backend-identifier-completion-predicate backend) + nil nil + 'xref--read-identifier-history def t)))) (if (string-empty-p id) (user-error "You didn't specify an identifier") id))) @@ -1753,12 +1766,12 @@ The fetcher function returns a list of xrefs, and sets (xref--not-found-error kind input)) xrefs))))) -(defun xref--create-fetcher (input kind arg) +(defun xref--create-fetcher (input kind arg &optional backend) "Return an xref list fetcher function. It revisits the saved position and delegates the finding logic to the xref backend method indicated by KIND and passes ARG to it." - (xref-make-fetcher (or (xref-find-backend) (error "No Xref backend found")) + (xref-make-fetcher (or backend (xref-find-backend) (error "No Xref backend found")) input kind arg (current-buffer) (copy-marker (point)))) @@ -1778,19 +1791,19 @@ Otherwise, display the list of the possible definitions in a buffer where the user can select from the list. Use \\[xref-go-back] to return back to where you invoked this command." - (interactive (list (xref--read-identifier "Find definitions of"))) + (interactive (list (xref--read-identifier "Find definitions of" 'definitions))) (xref--find-definitions identifier nil)) ;;;###autoload (defun xref-find-definitions-other-window (identifier) "Like `xref-find-definitions' but switch to the other window." - (interactive (list (xref--read-identifier "Find definitions of"))) + (interactive (list (xref--read-identifier "Find definitions of" 'definitions))) (xref--find-definitions identifier 'window)) ;;;###autoload (defun xref-find-definitions-other-frame (identifier) "Like `xref-find-definitions' but switch to the other frame." - (interactive (list (xref--read-identifier "Find definitions of"))) + (interactive (list (xref--read-identifier "Find definitions of" 'definitions))) (xref--find-definitions identifier 'frame)) ;;;###autoload @@ -1801,7 +1814,7 @@ offering the symbol at point as the default. With prefix argument, or if `xref-prompt-for-identifier' is t, always prompt for the identifier. If `xref-prompt-for-identifier' is nil, prompt only if there's no usable symbol at point." - (interactive (list (xref--read-identifier "Find references of"))) + (interactive (list (xref--read-identifier "Find references of" 'references))) (xref--find-xrefs identifier 'references identifier nil)) (defun xref-find-references-and-replace (from to) -- 2.39.5