diff options
| author | Dmitry Gutov | 2015-05-11 02:07:27 +0300 |
|---|---|---|
| committer | Dmitry Gutov | 2015-05-11 02:07:27 +0300 |
| commit | 089632800a1d408d2d2a9f0ecc5c52ce9c5319c6 (patch) | |
| tree | dd6aae433cbcfbbd793af3f52186a9a9d571df9a | |
| parent | e20b70bf505a9ac699cfdba534fe20210923f474 (diff) | |
| download | emacs-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.el | 14 | ||||
| -rw-r--r-- | lisp/progmodes/etags.el | 21 | ||||
| -rw-r--r-- | lisp/progmodes/xref.el | 59 |
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 |
| 208 | is a regexp. | 208 | is a regexp. |
| 209 | 209 | ||
| 210 | (matches REGEXP): Find all matches for REGEXP in the related | ||
| 211 | files. REGEXP is an Emacs regular expression. | ||
| 212 | |||
| 210 | IDENTIFIER can be any string returned by | 213 | IDENTIFIER 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 |
| 212 | by `xref-identifier-completion-table-function'. | 215 | by `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. |
| 720 | Uses the Semantic Symbol Reference API, see | 730 | KIND can be `symbol', `regexp' or nil, the last of which means |
| 721 | `semantic-symref-find-references-by-name' for details on which | 731 | literal matches. This function uses the Semantic Symbol |
| 722 | tools are used, and when." | 732 | Reference API, see `semantic-symref-find-references-by-name' for |
| 733 | details 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) |