]> git.eshelyaron.com Git - emacs.git/commitdiff
xref.el: Cease depending on Semantic
authorEshel Yaron <me@eshelyaron.com>
Sun, 9 Jun 2024 17:20:22 +0000 (19:20 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sun, 9 Jun 2024 17:20:22 +0000 (19:20 +0200)
lisp/cedet/semantic/symref/grep.el
lisp/progmodes/grep.el
lisp/progmodes/xref.el

index cc4d1546c85288690acfcc04b6caa25f36271606..13cb9c7e0725ff9dce39a80917684bcb10408dc2 100644 (file)
@@ -42,35 +42,18 @@ This tool uses EDE to find the root of the project, then executes
 `find-grep' in the project.  The output is parsed for hits and
 those hits returned.")
 
-(defvar semantic-symref-filepattern-alist
-  '((c-mode "*.[ch]")
-    (c++-mode "*.[chCH]" "*.[ch]pp" "*.cc" "*.hh")
-    (html-mode "*.html" "*.shtml" "*.php")
-    (mhtml-mode "*.html" "*.shtml" "*.php") ; FIXME: remove
-                                            ; duplication of
-                                            ; HTML-related patterns.
-                                            ; Maybe they belong in the
-                                            ; major mode definition?
-    (ruby-mode "*.r[bu]" "*.rake" "*.gemspec" "*.erb" "*.haml"
-               "Rakefile" "Thorfile" "Capfile" "Guardfile" "Vagrantfile")
-    (python-mode "*.py" "*.pyi" "*.pyw")
-    (perl-mode "*.pl" "*.PL")
-    (lisp-interaction-mode "*.el" "*.ede" ".emacs" "_emacs")
-    )
-  "List of major modes and file extension pattern.
-See find -name man page for format.")
+(defvar semantic-symref-filepattern-alist nil "Unused obsolete variable.")
+(make-obsolete-variable 'semantic-symref-filepattern-alist
+                        'grep-filepattern-alist "30.1")
 
 (defun semantic-symref-derive-find-filepatterns (&optional mode)
-  ;; FIXME: This should be moved to grep.el, where it could be used
-  ;; for "C-u M-x grep" as well.
   "Derive a list of file (glob) patterns for the current buffer.
-Looks first in `semantic-symref-filepattern-alist'.  If it is not
-there, it then looks in `auto-mode-alist', and attempts to derive something
-from that.
+Looks first in `grep-filepattern-alist'.  If it is not there, it then
+looks in `auto-mode-alist', and attempts to derive something from that.
 Optional argument MODE specifies the `major-mode' to test."
   ;; First, try the filepattern alist.
   (let* ((mode (or mode major-mode))
-        (pat (cdr (assoc mode semantic-symref-filepattern-alist))))
+        (pat (cdr (assoc mode grep-filepattern-alist))))
     (when (not pat)
       ;; No hit, try auto-mode-alist.
       (dolist (X auto-mode-alist)
@@ -80,7 +63,7 @@ Optional argument MODE specifies the `major-mode' to test."
           (push (concat "*." (match-string 1 (car X))) pat))))
     ;; Convert the list into some find-flags.
     (if (null pat)
-        (error "Customize `semantic-symref-filepattern-alist' for %S"
+        (error "Customize `grep-filepattern-alist' for %S"
                major-mode)
       (let ((args `("-name" ,(car pat))))
         (if (null (cdr pat))
index dc2d9519746100d51ac1473de1fa65fa41229069..7c8a3124da42a0901be592720458b9122fc1a4ae 100644 (file)
@@ -1489,6 +1489,91 @@ The returned file name is relative."
 ;;;###autoload
 (defalias 'rzgrep #'zrgrep)
 
-(provide 'grep)
+(defvar grep-filepattern-alist
+  '((c-mode "*.[ch]")
+    (c++-mode "*.[chCH]" "*.[ch]pp" "*.cc" "*.hh")
+    (html-mode "*.html" "*.shtml" "*.php")
+    (mhtml-mode "*.html" "*.shtml" "*.php")
+    (ruby-mode "*.r[bu]" "*.rake" "*.gemspec" "*.erb" "*.haml"
+               "Rakefile" "Thorfile" "Capfile" "Guardfile" "Vagrantfile")
+    (python-mode "*.py" "*.pyi" "*.pyw")
+    (perl-mode "*.pl" "*.PL")
+    (lisp-interaction-mode "*.el" "*.ede" ".emacs" "_emacs"))
+  "Association list of major modes and file extension patterns.")
+
+(defun grep-derive-find-filepatterns (&optional mode)
+  "Derive a list of file (glob) patterns for major MODE.
+
+If MODE is nil or omitted, it defaults to the current major mode.
+
+If MODE has an entry in `grep-filepattern-alist', return the
+corresponding pattern from there.  Otherwise, try to derive a pattern
+from `auto-mode-alist' entries."
+  ;; First, try the filepattern alist.
+  (let* ((mode (or mode major-mode))
+        (pat (cdr (assoc mode grep-filepattern-alist))))
+    (unless pat
+      ;; No hit, try `auto-mode-alist'.
+      (dolist (x auto-mode-alist)
+       (when (and (eq (cdr x) mode)
+                   ;; Only take in simple patterns, so try to convert this one.
+                   (string-match "\\\\\\.\\([^\\'>]+\\)\\\\'" (car x)))
+          (push (concat "*." (match-string 1 (car x))) pat))))
+    (when pat
+      ;; Convert the list into some find-flags.
+      (let ((args `("-name" ,(car pat))))
+        (if (cdr pat)
+            `("(" ,@args
+              ,@(mapcan (lambda (s) `("-o" "-name" ,s)) (cdr pat))
+              ")")
+          args)))))
+
+(defun grep-use-template (rootdir filepattern flags pattern)
+  "Use the grep template expand feature to create a grep command.
+ROOTDIR is the root location to run the `find' from.
+FILEPATTERN is a string representing find flags for searching file patterns.
+FLAGS are flags passed to Grep, such as -n or -l.
+PATTERN is the pattern used by Grep."
+  (grep-compute-defaults)
+  (grep-expand-template grep-find-template pattern filepattern rootdir nil flags))
+
+(defun grep--quote-grep (string)
+  "Quote STRING as a grep-syntax regexp."
+  (replace-regexp-in-string (rx (in ".^$*[\\"))
+                            (lambda (s) (concat "\\" s))
+                            string nil t))
+
+(defun grep--parse-output (buf dir)
+  "Parse buffer BUF containing Grep results in DIR, return list of matches."
+  (with-current-buffer buf
+    (goto-char (point-min))
+    (let ((result nil)
+         (hit nil))
+      (while (setq hit
+                   (pcase-let
+                       ((`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist)))
+                     (when (re-search-forward grep-re nil t)
+                       (list (string-to-number (match-string line-group))
+                             (concat dir (substring (match-string file-group) 1))
+                             (buffer-substring-no-properties (point) (line-end-position))))))
+       (setq result (cons hit result)))
+      (nreverse result))))
+
+;;;###autoload
+(defun grep-perform-search (symbol dir)
+  "Perform a search for SYMBOL in DIR with Grep."
+  (let* (;; Find the file patterns to use.
+        (filepatterns (grep-derive-find-filepatterns))
+         (filepattern (mapconcat #'shell-quote-argument filepatterns " "))
+         (greppat (grep--quote-grep symbol))
+        ;; Misc
+        (buf (get-buffer-create " *Grep Search*")))
+    (with-current-buffer buf
+      (erase-buffer)
+      (setq default-directory dir)
+      (process-file shell-file-name nil buf nil shell-command-switch
+                    (grep-use-template "." filepattern '("-nw") greppat)))
+    (grep--parse-output buf (directory-file-name (file-local-name dir)))))
 
+(provide 'grep)
 ;;; grep.el ends here
index d234aa1a026ac864710d5f815b205b3126b7aeb9..720266bee69febd643575b8c187b0220ed33e1c1 100644 (file)
@@ -268,11 +268,7 @@ To create an xref object, call `xref-make'.")
 (cl-defgeneric xref-backend-references (_backend identifier)
   "Find references of IDENTIFIER.
 The result must be a list of xref objects.  If no references can
-be found, return nil.
-
-The default implementation uses `semantic-symref-tool-alist' to
-find a search tool; by default, this uses \"find | grep\" in the
-current project's main and external roots."
+be found, return nil."
   (mapcan
    (lambda (dir)
      (message "Searching %s..." dir)
@@ -1891,41 +1887,16 @@ and just use etags."
         (kill-local-variable 'xref-backend-functions))
     (setq-local xref-backend-functions xref-etags-mode--saved)))
 
-(declare-function semantic-symref-instantiate "semantic/symref")
-(declare-function semantic-symref-perform-search "semantic/symref")
 (declare-function grep-expand-template "grep")
-(defvar ede-minor-mode) ;; ede.el
 
 ;;;###autoload
 (defun xref-references-in-directory (symbol dir)
   "Find all references to SYMBOL in directory DIR.
-Return a list of xref values.
-
-This function uses the Semantic Symbol Reference API, see
-`semantic-symref-tool-alist' for details on which tools are used,
-and when."
+Return a list of xref values."
   (cl-assert (directory-name-p dir))
-  (require 'semantic/symref)
-  (defvar semantic-symref-tool)
-
-  ;; Some symref backends use `ede-project-root-directory' as the root
-  ;; directory for the search, rather than `default-directory'. Since
-  ;; the caller has specified `dir', we bind `ede-minor-mode' to nil
-  ;; to force the backend to use `default-directory'.
-  (let* ((ede-minor-mode nil)
-         (default-directory dir)
-         ;; FIXME: Remove CScope and Global from the recognized tools?
-         ;; The current implementations interpret the symbol search as
-         ;; "find all calls to the given function", but not function
-         ;; definition. And they return nothing when passed a variable
-         ;; name, even a global one.
-         (semantic-symref-tool 'detect)
-         (case-fold-search nil)
-         (inst (semantic-symref-instantiate :searchfor symbol
-                                            :searchtype 'symbol
-                                            :searchscope 'subdirs
-                                            :resulttype 'line-and-text)))
-    (xref--convert-hits (semantic-symref-perform-search inst)
+  (let* ((default-directory dir)
+         (case-fold-search nil))
+    (xref--convert-hits (grep-perform-search symbol dir)
                         (format "\\_<%s\\_>" (regexp-quote symbol)))))
 
 (define-obsolete-function-alias