emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 0896328: Add xref-find-regexp


From: Dmitry Gutov
Subject: [Emacs-diffs] master 0896328: Add xref-find-regexp
Date: Sun, 10 May 2015 23:38:55 +0000

branch: master
commit 089632800a1d408d2d2a9f0ecc5c52ce9c5319c6
Author: Dmitry Gutov <address@hidden>
Commit: Dmitry Gutov <address@hidden>

    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.
---
 lisp/progmodes/elisp-mode.el |   14 ++++++---
 lisp/progmodes/etags.el      |   21 ++++++++------
 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 7bc7798..e06b920 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."
 (declare-function xref-make-elisp-location "xref" (symbol type file))
 (declare-function xref-make-bogus-location "xref" (message))
 (declare-function xref-make "xref" (description location))
-(declare-function xref-collect-references "xref" (name dir))
+(declare-function xref-collect-matches "xref" (input dir &optional kind))
 
 (defun elisp-xref-find (action id)
   (require 'find-func)
@@ -591,7 +591,9 @@ It can be quoted, or be inside a quoted form."
         (when sym
           (elisp--xref-find-definitions sym))))
     (`references
-     (elisp--xref-find-references id))
+     (elisp--xref-find-matches id 'symbol))
+    (`matches
+     (elisp--xref-find-matches id 'regexp))
     (`apropos
      (elisp--xref-find-apropos id))))
 
@@ -652,12 +654,14 @@ It can be quoted, or be inside a quoted form."
 
 (defvar package-user-dir)
 
-(defun elisp--xref-find-references (symbol)
+(defun elisp--xref-find-matches (symbol kind)
   (let* ((dirs (sort
                 (mapcar
                  (lambda (dir)
                    (file-name-as-directory (expand-file-name dir)))
-                 ;; FIXME: Why add package-user-dir?
+                 ;; It's one level above a number of `load-path'
+                 ;; elements (one for each installed package).
+                 ;; Save us some process calls.
                  (cons package-user-dir load-path))
                 #'string<))
          (ref dirs))
@@ -669,7 +673,7 @@ It can be quoted, or be inside a quoted form."
     (cl-mapcan
      (lambda (dir)
        (and (file-exists-p dir)
-            (xref-collect-references symbol dir)))
+            (xref-collect-matches symbol dir kind)))
      dirs)))
 
 (defun elisp--xref-find-apropos (regexp)
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 9a93176..7a87377 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -2082,17 +2082,20 @@ for \\[find-tag] (which see)."
 (defun etags-xref-find (action id)
   (pcase action
     (`definitions (etags--xref-find-definitions id))
-    (`references
-     (let ((dirs (if tags-table-list
-                     (mapcar #'file-name-directory tags-table-list)
-                   ;; If no tags files are loaded, prompt for the dir.
-                   (list (read-directory-name "In directory: " nil nil t)))))
-       (cl-mapcan
-        (lambda (dir)
-          (xref-collect-references id dir))
-        dirs)))
+    (`references (etags--xref-find-matches id 'symbol))
+    (`matches (etags--xref-find-matches id 'regexp))
     (`apropos (etags--xref-find-definitions id t))))
 
+(defun etags--xref-find-matches (input kind)
+  (let ((dirs (if tags-table-list
+                  (mapcar #'file-name-directory tags-table-list)
+                ;; If no tags files are loaded, prompt for the dir.
+                (list (read-directory-name "In directory: " nil nil t)))))
+    (cl-mapcan
+     (lambda (dir)
+       (xref-collect-matches input dir kind))
+     dirs)))
+
 (defun etags--xref-find-definitions (pattern &optional regexp?)
   ;; This emulates the behaviour of `find-tag-in-order' but instead of
   ;; 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 f6faaf6..ef46e34 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -207,6 +207,9 @@ found, return nil.
  (apropos PATTERN): Find all symbols that match PATTERN.  PATTERN
 is a regexp.
 
+ (matches REGEXP): Find all matches for REGEXP in the related
+files.  REGEXP is an Emacs regular expression.
+
 IDENTIFIER can be any string returned by
 `xref-identifier-at-point-function', or from the table returned
 by `xref-identifier-completion-table-function'.
@@ -661,6 +664,12 @@ With prefix argument, prompt for the identifier."
   (interactive (list (xref--read-identifier "Find references of: ")))
   (xref--show-xrefs identifier 'references identifier nil))
 
+;;;###autoload
+(defun xref-find-regexp (regexp)
+  "Find all matches for REGEXP."
+  (interactive (list (xref--read-identifier "Find regexp: ")))
+  (xref--show-xrefs regexp 'matches regexp nil))
+
 (declare-function apropos-parse-pattern "apropos" (pattern))
 
 ;;;###autoload
@@ -713,38 +722,64 @@ and just use etags."
                 (cdr xref-etags-mode--saved))))
 
 (declare-function semantic-symref-find-references-by-name "semantic/symref")
+(declare-function semantic-symref-find-text "semantic/symref")
 (declare-function semantic-find-file-noselect "semantic/fw")
 
-(defun xref-collect-references (name dir)
-  "Collect mentions of NAME inside DIR.
-Uses the Semantic Symbol Reference API, see
-`semantic-symref-find-references-by-name' for details on which
-tools are used, and when."
+(defun xref-collect-matches (input dir &optional kind)
+  "Collect KIND matches for INPUT inside DIR according.
+KIND can be `symbol', `regexp' or nil, the last of which means
+literal matches.  This function uses the Semantic Symbol
+Reference API, see `semantic-symref-find-references-by-name' for
+details on which tools are used, and when."
   (require 'semantic/symref)
   (defvar semantic-symref-tool)
   (cl-assert (directory-name-p dir))
+  (when (null kind)
+    (setq input (regexp-quote input)))
   (let* ((default-directory dir)
          (semantic-symref-tool 'detect)
-         (res (semantic-symref-find-references-by-name name 'subdirs))
+         (res (if (eq kind 'symbol)
+                  (semantic-symref-find-references-by-name input 'subdirs)
+                (semantic-symref-find-text (xref--regexp-to-extended input)
+                                           'subdirs)))
          (hits (and res (oref res :hit-lines)))
          (orig-buffers (buffer-list)))
     (unwind-protect
         (delq nil
-              (mapcar (lambda (hit) (xref--collect-reference hit name)) hits))
+              (mapcar (lambda (hit) (xref--collect-match hit input kind)) 
hits))
       (mapc #'kill-buffer
             (cl-set-difference (buffer-list) orig-buffers)))))
 
-(defun xref--collect-reference (hit name)
+(defun xref--regexp-to-extended (str)
+  (replace-regexp-in-string
+   ;; FIXME: Add tests.  Move to subr.el, make a public function.
+   ;; Maybe error on Emacs-only constructs.
+   "\\(?:\\\\\\\\\\)*\\(?:\\\\[][]\\)?\\(?:\\[.+?\\]\\|\\(\\\\?[(){}|]\\)\\)"
+   (lambda (str)
+     (cond
+      ((not (match-beginning 1))
+       str)
+      ((eq (length (match-string 1 str)) 2)
+       (concat (substring str 0 (match-beginning 1))
+               (substring (match-string 1 str) 1 2)))
+      (t
+       (concat (substring str 0 (match-beginning 1))
+               "\\"
+               (match-string 1 str)))))
+   str t t))
+
+(defun xref--collect-match (hit input kind)
   (pcase-let* ((`(,line . ,file) hit)
                (buf (or (find-buffer-visiting file)
-                        (semantic-find-file-noselect file))))
+                        (semantic-find-file-noselect file)))
+               (input (if (eq kind 'symbol)
+                          (format "\\_<%s\\_>" (regexp-quote input))
+                        input)))
     (with-current-buffer buf
       (save-excursion
         (goto-char (point-min))
         (forward-line (1- line))
-        (when (re-search-forward (format "\\_<%s\\_>"
-                                         (regexp-quote name))
-                                 (line-end-position) t)
+        (when (re-search-forward input (line-end-position) t)
           (goto-char (match-beginning 0))
           (xref-make (buffer-substring
                       (line-beginning-position)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]