xref-find-by-kind 34c8ed0ae55: xref-find-by-kind: Do filter by "kind" in identifier completion

Dmitry Gutov <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: xref-find-by-kind
commit 34c8ed0ae5521a0ad6ea95ca3efc39060a229aa9
Author: Dmitry Gutov <[email protected]>
Commit: Dmitry Gutov <[email protected]>

    xref-find-by-kind: Do filter by "kind" in identifier completion
    
    When the backend allows, of course.
    
    * lisp/progmodes/elisp-mode.el
    (xref-backend-identifier-kind-predicate): One implementation.
    (xref-backend-xrefs-by-kind): Make sure generic functions and
    methods are recognized as "functions" too.
    
    * lisp/progmodes/xref.el (xref-backend-identifier-kind-predicate):
    New generic function.
    (xref-find-by-kind): Use it here.
    (xref-read-identifier): New argument PREDICATE.
---
 lisp/progmodes/elisp-mode.el | 24 +++++++++++++++++++++++-
 lisp/progmodes/xref.el       | 13 ++++++++++---
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 0b44d228991..c303aefa75b 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -1683,7 +1683,10 @@ namespace but with lower confidence."
       (let* ((defs (elisp--xref-find-definitions sym)))
         (cl-loop for d in defs
                  for def-kind = (xref-elisp-location-type (xref-item-location d))
-                 when (eq def-kind kind)
+                 when (if kind
+                          (eq def-kind kind)
+                        (memq def-kind '( nil cl-defgeneric cl-defmethod
+                                          define-type defalias)))
                  collect d)))))
 
 (declare-function xref-apropos-regexp "xref" (pattern))
@@ -1710,6 +1713,25 @@ namespace but with lower confidence."
                                                          (eql 'elisp)))
   elisp--xref-identifier-completion-table)
 
+(cl-defmethod xref-backend-identifier-kind-predicate ((_backend (eql 'elisp)) kind)
+  (lambda (identifier)
+    (let ((sym (intern-soft identifier)))
+      (cl-ecase kind
+        ((nil) (fboundp sym))
+        (defvar (boundp sym))
+        (cl-defgeneric (cl--generic sym))
+        (cl-defmethod (and (cl--generic sym)
+                           (cl--generic-method-table (cl--generic sym))))
+        (define-type (and (functionp sym)
+                          (let ((doc (documentation sym t)))
+                            (and doc
+                                 (string-search "Constructor for objects of type" doc)))))
+        (defalias (and (symbolp sym)
+                       (symbol-function sym)
+                       (symbolp (symbol-function sym))))
+        (defface (facep sym))
+        (feature (featurep sym))))))
+
 (cl-defstruct (xref-elisp-location
                (:constructor xref-make-elisp-location (symbol type file)))
   "Location of an Emacs Lisp symbol definition."
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 2e6037e742a..10db6229520 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -312,6 +312,10 @@ recognize and then delegate the work to an external process."
   "Return the completion table for identifiers."
   nil)
 
+(cl-defgeneric xref-backend-identifier-kind-predicate (_backend _kind)
+  "Return the completion predicate for identifiers based on KIND."
+  nil)
+
 (cl-defgeneric xref-backend-identifier-completion-ignore-case (_backend)
   "Return t if case is not significant in identifier completion."
   completion-ignore-case)
@@ -1697,7 +1701,7 @@ 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 predicate)
   "Return the identifier at point or read it from the minibuffer.
 
 Reads and returns the identifier to use as input for the command being
@@ -1726,7 +1730,8 @@ from `xref-backend-identifier-completion-table'."
                                  def)
                        prompt))
                    (xref-backend-identifier-completion-table backend)
-                   nil nil nil
+                   predicate
+                   nil nil
                    'xref--read-identifier-history def t)))
              (if (equal id "")
                  (or def (user-error "There is no default identifier"))
@@ -1844,7 +1849,9 @@ When called programmatically, KIND should be one of supported symbols."
                   ;; probably only the elisp backend would have it.
                   (xref-read-identifier
                    (format-message (or (plist-get desc :prompt-format) "Find %s")
-                                   (plist-get desc :name)))
+                                   (plist-get desc :name))
+                   (xref-backend-identifier-kind-predicate (xref-find-backend)
+                                                           kind))
                   kind)))
   (let ((kind-desc (cl-find-if
                     (lambda (kind-desc) (eq (plist-get kind-desc :kind) kind))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.