aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2015-05-11 02:07:27 +0300
committerDmitry Gutov2015-05-11 02:07:27 +0300
commit089632800a1d408d2d2a9f0ecc5c52ce9c5319c6 (patch)
treedd6aae433cbcfbbd793af3f52186a9a9d571df9a
parente20b70bf505a9ac699cfdba534fe20210923f474 (diff)
downloademacs-089632800a1d408d2d2a9f0ecc5c52ce9c5319c6.tar.gz
emacs-089632800a1d408d2d2a9f0ecc5c52ce9c5319c6.zip
Add xref-find-regexp
* lisp/progmodes/xref.el (xref-find-function): Describe the `matches' action. (xref-find-regexp): New command, using it. (xref-collect-references): Rename to xref-collect-matches. (xref--collect-reference): Rename to xref--collect-match. (xref-collect-matches, xref--collect-match): Accept new argument, KIND. Update accordingly. (xref--regexp-to-extended): New function. * lisp/progmodes/elisp-mode.el (elisp-xref-find): Support the `matches' action. (elisp--xref-find-matches): Accept new argument. Resolve a FIXME. * lisp/progmodes/etags.el (etags-xref-find): Support the `matches' action. (etags--xref-find-matches): New function.
-rw-r--r--lisp/progmodes/elisp-mode.el14
-rw-r--r--lisp/progmodes/etags.el21
-rw-r--r--lisp/progmodes/xref.el59
3 files changed, 68 insertions, 26 deletions
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 7bc7798be03..e06b920e5d7 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -581,7 +581,7 @@ It can be quoted, or be inside a quoted form."
581(declare-function xref-make-elisp-location "xref" (symbol type file)) 581(declare-function xref-make-elisp-location "xref" (symbol type file))
582(declare-function xref-make-bogus-location "xref" (message)) 582(declare-function xref-make-bogus-location "xref" (message))
583(declare-function xref-make "xref" (description location)) 583(declare-function xref-make "xref" (description location))
584(declare-function xref-collect-references "xref" (name dir)) 584(declare-function xref-collect-matches "xref" (input dir &optional kind))
585 585
586(defun elisp-xref-find (action id) 586(defun elisp-xref-find (action id)
587 (require 'find-func) 587 (require 'find-func)
@@ -591,7 +591,9 @@ It can be quoted, or be inside a quoted form."
591 (when sym 591 (when sym
592 (elisp--xref-find-definitions sym)))) 592 (elisp--xref-find-definitions sym))))
593 (`references 593 (`references
594 (elisp--xref-find-references id)) 594 (elisp--xref-find-matches id 'symbol))
595 (`matches
596 (elisp--xref-find-matches id 'regexp))
595 (`apropos 597 (`apropos
596 (elisp--xref-find-apropos id)))) 598 (elisp--xref-find-apropos id))))
597 599
@@ -652,12 +654,14 @@ It can be quoted, or be inside a quoted form."
652 654
653(defvar package-user-dir) 655(defvar package-user-dir)
654 656
655(defun elisp--xref-find-references (symbol) 657(defun elisp--xref-find-matches (symbol kind)
656 (let* ((dirs (sort 658 (let* ((dirs (sort
657 (mapcar 659 (mapcar
658 (lambda (dir) 660 (lambda (dir)
659 (file-name-as-directory (expand-file-name dir))) 661 (file-name-as-directory (expand-file-name dir)))
660 ;; FIXME: Why add package-user-dir? 662 ;; It's one level above a number of `load-path'
663 ;; elements (one for each installed package).
664 ;; Save us some process calls.
661 (cons package-user-dir load-path)) 665 (cons package-user-dir load-path))
662 #'string<)) 666 #'string<))
663 (ref dirs)) 667 (ref dirs))
@@ -669,7 +673,7 @@ It can be quoted, or be inside a quoted form."
669 (cl-mapcan 673 (cl-mapcan
670 (lambda (dir) 674 (lambda (dir)
671 (and (file-exists-p dir) 675 (and (file-exists-p dir)
672 (xref-collect-references symbol dir))) 676 (xref-collect-matches symbol dir kind)))
673 dirs))) 677 dirs)))
674 678
675(defun elisp--xref-find-apropos (regexp) 679(defun elisp--xref-find-apropos (regexp)
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 9a93176e742..7a87377503d 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -2082,17 +2082,20 @@ for \\[find-tag] (which see)."
2082(defun etags-xref-find (action id) 2082(defun etags-xref-find (action id)
2083 (pcase action 2083 (pcase action
2084 (`definitions (etags--xref-find-definitions id)) 2084 (`definitions (etags--xref-find-definitions id))
2085 (`references 2085 (`references (etags--xref-find-matches id 'symbol))
2086 (let ((dirs (if tags-table-list 2086 (`matches (etags--xref-find-matches id 'regexp))
2087 (mapcar #'file-name-directory tags-table-list)
2088 ;; If no tags files are loaded, prompt for the dir.
2089 (list (read-directory-name "In directory: " nil nil t)))))
2090 (cl-mapcan
2091 (lambda (dir)
2092 (xref-collect-references id dir))
2093 dirs)))
2094 (`apropos (etags--xref-find-definitions id t)))) 2087 (`apropos (etags--xref-find-definitions id t))))
2095 2088
2089(defun etags--xref-find-matches (input kind)
2090 (let ((dirs (if tags-table-list
2091 (mapcar #'file-name-directory tags-table-list)
2092 ;; If no tags files are loaded, prompt for the dir.
2093 (list (read-directory-name "In directory: " nil nil t)))))
2094 (cl-mapcan
2095 (lambda (dir)
2096 (xref-collect-matches input dir kind))
2097 dirs)))
2098
2096(defun etags--xref-find-definitions (pattern &optional regexp?) 2099(defun etags--xref-find-definitions (pattern &optional regexp?)
2097 ;; This emulates the behaviour of `find-tag-in-order' but instead of 2100 ;; This emulates the behaviour of `find-tag-in-order' but instead of
2098 ;; returning one match at a time all matches are returned as list. 2101 ;; returning one match at a time all matches are returned as list.
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index f6faaf640b2..ef46e34e78f 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -207,6 +207,9 @@ found, return nil.
207 (apropos PATTERN): Find all symbols that match PATTERN. PATTERN 207 (apropos PATTERN): Find all symbols that match PATTERN. PATTERN
208is a regexp. 208is a regexp.
209 209
210 (matches REGEXP): Find all matches for REGEXP in the related
211files. REGEXP is an Emacs regular expression.
212
210IDENTIFIER can be any string returned by 213IDENTIFIER can be any string returned by
211`xref-identifier-at-point-function', or from the table returned 214`xref-identifier-at-point-function', or from the table returned
212by `xref-identifier-completion-table-function'. 215by `xref-identifier-completion-table-function'.
@@ -661,6 +664,12 @@ With prefix argument, prompt for the identifier."
661 (interactive (list (xref--read-identifier "Find references of: "))) 664 (interactive (list (xref--read-identifier "Find references of: ")))
662 (xref--show-xrefs identifier 'references identifier nil)) 665 (xref--show-xrefs identifier 'references identifier nil))
663 666
667;;;###autoload
668(defun xref-find-regexp (regexp)
669 "Find all matches for REGEXP."
670 (interactive (list (xref--read-identifier "Find regexp: ")))
671 (xref--show-xrefs regexp 'matches regexp nil))
672
664(declare-function apropos-parse-pattern "apropos" (pattern)) 673(declare-function apropos-parse-pattern "apropos" (pattern))
665 674
666;;;###autoload 675;;;###autoload
@@ -713,38 +722,64 @@ and just use etags."
713 (cdr xref-etags-mode--saved)))) 722 (cdr xref-etags-mode--saved))))
714 723
715(declare-function semantic-symref-find-references-by-name "semantic/symref") 724(declare-function semantic-symref-find-references-by-name "semantic/symref")
725(declare-function semantic-symref-find-text "semantic/symref")
716(declare-function semantic-find-file-noselect "semantic/fw") 726(declare-function semantic-find-file-noselect "semantic/fw")
717 727
718(defun xref-collect-references (name dir) 728(defun xref-collect-matches (input dir &optional kind)
719 "Collect mentions of NAME inside DIR. 729 "Collect KIND matches for INPUT inside DIR according.
720Uses the Semantic Symbol Reference API, see 730KIND can be `symbol', `regexp' or nil, the last of which means
721`semantic-symref-find-references-by-name' for details on which 731literal matches. This function uses the Semantic Symbol
722tools are used, and when." 732Reference API, see `semantic-symref-find-references-by-name' for
733details on which tools are used, and when."
723 (require 'semantic/symref) 734 (require 'semantic/symref)
724 (defvar semantic-symref-tool) 735 (defvar semantic-symref-tool)
725 (cl-assert (directory-name-p dir)) 736 (cl-assert (directory-name-p dir))
737 (when (null kind)
738 (setq input (regexp-quote input)))
726 (let* ((default-directory dir) 739 (let* ((default-directory dir)
727 (semantic-symref-tool 'detect) 740 (semantic-symref-tool 'detect)
728 (res (semantic-symref-find-references-by-name name 'subdirs)) 741 (res (if (eq kind 'symbol)
742 (semantic-symref-find-references-by-name input 'subdirs)
743 (semantic-symref-find-text (xref--regexp-to-extended input)
744 'subdirs)))
729 (hits (and res (oref res :hit-lines))) 745 (hits (and res (oref res :hit-lines)))
730 (orig-buffers (buffer-list))) 746 (orig-buffers (buffer-list)))
731 (unwind-protect 747 (unwind-protect
732 (delq nil 748 (delq nil
733 (mapcar (lambda (hit) (xref--collect-reference hit name)) hits)) 749 (mapcar (lambda (hit) (xref--collect-match hit input kind)) hits))
734 (mapc #'kill-buffer 750 (mapc #'kill-buffer
735 (cl-set-difference (buffer-list) orig-buffers))))) 751 (cl-set-difference (buffer-list) orig-buffers)))))
736 752
737(defun xref--collect-reference (hit name) 753(defun xref--regexp-to-extended (str)
754 (replace-regexp-in-string
755 ;; FIXME: Add tests. Move to subr.el, make a public function.
756 ;; Maybe error on Emacs-only constructs.
757 "\\(?:\\\\\\\\\\)*\\(?:\\\\[][]\\)?\\(?:\\[.+?\\]\\|\\(\\\\?[(){}|]\\)\\)"
758 (lambda (str)
759 (cond
760 ((not (match-beginning 1))
761 str)
762 ((eq (length (match-string 1 str)) 2)
763 (concat (substring str 0 (match-beginning 1))
764 (substring (match-string 1 str) 1 2)))
765 (t
766 (concat (substring str 0 (match-beginning 1))
767 "\\"
768 (match-string 1 str)))))
769 str t t))
770
771(defun xref--collect-match (hit input kind)
738 (pcase-let* ((`(,line . ,file) hit) 772 (pcase-let* ((`(,line . ,file) hit)
739 (buf (or (find-buffer-visiting file) 773 (buf (or (find-buffer-visiting file)
740 (semantic-find-file-noselect file)))) 774 (semantic-find-file-noselect file)))
775 (input (if (eq kind 'symbol)
776 (format "\\_<%s\\_>" (regexp-quote input))
777 input)))
741 (with-current-buffer buf 778 (with-current-buffer buf
742 (save-excursion 779 (save-excursion
743 (goto-char (point-min)) 780 (goto-char (point-min))
744 (forward-line (1- line)) 781 (forward-line (1- line))
745 (when (re-search-forward (format "\\_<%s\\_>" 782 (when (re-search-forward input (line-end-position) t)
746 (regexp-quote name))
747 (line-end-position) t)
748 (goto-char (match-beginning 0)) 783 (goto-char (match-beginning 0))
749 (xref-make (buffer-substring 784 (xref-make (buffer-substring
750 (line-beginning-position) 785 (line-beginning-position)