X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d8462361f2d087d6f7c745305c61a266843ee19c..cc0b713210a4ae3e273571f8c829122db2b143cf:/lisp/cedet/semantic/symref/grep.el diff --git a/lisp/cedet/semantic/symref/grep.el b/lisp/cedet/semantic/symref/grep.el index 981dab8a8b..868e6c3f72 100644 --- a/lisp/cedet/semantic/symref/grep.el +++ b/lisp/cedet/semantic/symref/grep.el @@ -1,6 +1,6 @@ ;;; semantic/symref/grep.el --- Symref implementation using find/grep -;; Copyright (C) 2008-2015 Free Software Foundation, Inc. +;; Copyright (C) 2008-2016 Free Software Foundation, Inc. ;; Author: Eric M. Ludlam @@ -46,11 +46,17 @@ and those hits returned.") '((c-mode "*.[ch]") (c++-mode "*.[chCH]" "*.[ch]pp" "*.cc" "*.hh") (html-mode "*.s?html" "*.php") + (ruby-mode "*.r[bu]" "*.rake" "*.gemspec" "*.erb" "*.haml" + "Rakefile" "Thorfile" "Capfile" "Guardfile" "Vagrantfile") + (perl-mode "*.pl" "*.PL") + (cperl-mode "*.pl" "*.PL") ) - "List of major modes and file extension pattern regexp. -See find -regex man page for format.") + "List of major modes and file extension pattern. +See find -name man page for format.") (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 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 @@ -62,28 +68,23 @@ Optional argument MODE specifies the `major-mode' to test." (when (not pat) ;; No hit, try auto-mode-alist. (dolist (X auto-mode-alist) - (when (eq (cdr X) mode) - ;; Only take in simple patterns, so try to convert this one. - (let ((Xp - (cond ((string-match "\\\\\\.\\([^\\'>]+\\)\\\\'" (car X)) - (concat "*." (match-string 1 (car X)))) - (t nil)))) - (when Xp - (setq pat (cons Xp pat)))) - ))) + (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)))) ;; Convert the list into some find-flags. - (cond ((= (length pat) 1) - (concat "-name \"" (car pat) "\"")) - ((consp pat) - (concat "\\( " - (mapconcat (lambda (s) - (concat "-name \"" s "\"")) - pat - " -o ") - " \\)")) - (t - (error "Customize `semantic-symref-filepattern-alist' for %s" major-mode)) - ))) + (if (null pat) + (error "Customize `semantic-symref-filepattern-alist' for %S" + major-mode) + (let ((args `("-name" ,(car pat)))) + (if (null (cdr args)) + args + `("(" ,@args + ,@(apply #'nconc (mapcar (lambda (s) `("-o" "-name" ,s)) pat)) + ")")))))) + +(defvar grepflags) +(defvar greppattern) (defvar semantic-symref-grep-expand-keywords (condition-case nil @@ -96,7 +97,7 @@ Optional argument MODE specifies the `major-mode' to test." (error nil)) "Grep expand keywords used when expanding templates for symref.") -(defun semantic-symref-grep-use-template (rootdir filepattern grepflags greppattern) +(defun semantic-symref-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. @@ -104,18 +105,29 @@ GREPFLAGS are flags passed to grep, such as -n or -l. GREPPATTERN is the pattern used by grep." ;; We have grep-compute-defaults. Let's use it. (grep-compute-defaults) - (let* ((grep-expand-keywords semantic-symref-grep-expand-keywords) - (cmd (grep-expand-template grep-find-template - greppattern - filepattern - rootdir))) - ;; For some reason, my default has no in it. + (let* ((grepflags flags) + (greppattern pattern) + (grep-expand-keywords semantic-symref-grep-expand-keywords) + (cmd (grep-expand-template + (if (memq system-type '(windows-nt ms-dos)) + ;; grep-find uses '--color=always' on MS-Windows + ;; because it wants the colorized output, to show + ;; it to the user. By contrast, here we don't show + ;; the output, and the SGR escapes get in the way + ;; of parsing the output. + (replace-regexp-in-string "--color=always" "" + grep-find-template t t) + grep-find-template) + greppattern + filepattern + rootdir))) + ;; http://debbugs.gnu.org/20719 (when (string-match "find \\(\\.\\)" cmd) (setq cmd (replace-match rootdir t t cmd 1))) ;;(message "New command: %s" cmd) cmd)) -(defcustom semantic-symref-grep-shell "sh" +(defcustom semantic-symref-grep-shell shell-file-name "The shell command to use for executing find/grep. This shell should support pipe redirect syntax." :group 'semantic @@ -125,22 +137,29 @@ This shell should support pipe redirect syntax." "Perform a search with Grep." ;; Grep doesn't support some types of searches. (let ((st (oref tool :searchtype))) - (when (not (eq st 'symbol)) + (when (not (memq st '(symbol regexp))) (error "Symref impl GREP does not support searchtype of %s" st)) ) ;; Find the root of the project, and do a find-grep... (let* (;; Find the file patterns to use. - (pat (cdr (assoc major-mode semantic-symref-filepattern-alist))) (rootdir (semantic-symref-calculate-rootdir)) - (filepattern (semantic-symref-derive-find-filepatterns)) + (filepatterns (semantic-symref-derive-find-filepatterns)) + (filepattern (mapconcat #'shell-quote-argument filepatterns " ")) ;; Grep based flags. (grepflags (cond ((eq (oref tool :resulttype) 'file) - "-l ") - (t "-n "))) - (greppat (cond ((eq (oref tool :searchtype) 'regexp) - (oref tool searchfor)) - (t - (concat "'\\<" (oref tool searchfor) "\\>'")))) + "-l ") + ((eq (oref tool :searchtype) 'regexp) + "-nE ") + (t "-n "))) + (greppat (shell-quote-argument + (cond ((eq (oref tool :searchtype) 'regexp) + (oref tool searchfor)) + (t + ;; Can't use the word boundaries: Grep + ;; doesn't always agrees with the language + ;; syntax on those. + (format "\\(^\\|\\W\\)%s\\(\\W\\|$\\)" + (oref tool searchfor)))))) ;; Misc (b (get-buffer-create "*Semantic SymRef*")) (ans nil) @@ -158,15 +177,20 @@ This shell should support pipe redirect syntax." (let ((cmd (concat "find " default-directory " -type f " filepattern " -print0 " "| xargs -0 grep -H " grepflags "-e " greppat))) ;;(message "Old command: %s" cmd) - (call-process semantic-symref-grep-shell nil b nil "-c" cmd) + (call-process semantic-symref-grep-shell nil b nil + shell-command-switch cmd) ) (let ((cmd (semantic-symref-grep-use-template rootdir filepattern grepflags greppat))) - (call-process semantic-symref-grep-shell nil b nil "-c" cmd)) + (call-process semantic-symref-grep-shell nil b nil + shell-command-switch cmd)) )) (setq ans (semantic-symref-parse-tool-output tool b)) ;; Return the answer ans)) +(defconst semantic-symref-grep--line-re + "^\\(\\(?:[a-zA-Z]:\\)?[^:\n]+\\):\\([0-9]+\\):") + (cl-defmethod semantic-symref-parse-tool-output-one-line ((tool semantic-symref-tool-grep)) "Parse one line of grep output, and return it as a match list. Moves cursor to end of the match." @@ -174,8 +198,13 @@ Moves cursor to end of the match." ;; Search for files (when (re-search-forward "^\\([^\n]+\\)$" nil t) (match-string 1))) + ((eq (oref tool :resulttype) 'line-and-text) + (when (re-search-forward semantic-symref-grep--line-re nil t) + (list (string-to-number (match-string 2)) + (match-string 1) + (buffer-substring-no-properties (point) (line-end-position))))) (t - (when (re-search-forward "^\\(\\(?:[a-zA-Z]:\\)?[^:\n]+\\):\\([0-9]+\\):" nil t) + (when (re-search-forward semantic-symref-grep--line-re nil t) (cons (string-to-number (match-string 2)) (match-string 1)) ))))