diff options
author | Dmitry Gutov <dgutov@yandex.ru> | 2018-12-27 23:01:08 +0200 |
---|---|---|
committer | Dmitry Gutov <dgutov@yandex.ru> | 2018-12-27 23:01:08 +0200 |
commit | b40d95133653f93c7e2f710a96b237529b84cdb4 (patch) | |
tree | 53486a871b32aad68cfa4036555179071f95e849 | |
parent | 806ae9fc48f59751a8fce543be40ffe473f548bf (diff) | |
download | emacs-b40d95133653f93c7e2f710a96b237529b84cdb4.tar.gz |
Add project-files-pipe-grep
-rw-r--r-- | lisp/progmodes/project.el | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index f3f29cbac94..c8ac0a982c8 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -362,6 +362,48 @@ pattern to search for." (user-error "No matches for: %s" regexp)) (xref--show-xrefs xrefs nil))) +(defun project-files-pipe-grep (project regexp) + (pcase-let* + ((files (project-files project)) + (infile (make-temp-file "pftg")) + (output (get-buffer-create " *project grep output*")) + (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist)) + (status nil) + (hits nil) + (xrefs nil)) + (with-temp-buffer + (insert (mapconcat #'identity files "\0")) + ;; FIXME: Try without a temporary file. + (write-region (point-min) (point-max) infile)) + (with-current-buffer output + (erase-buffer) + (setq status + (process-file-shell-command + (format "xargs -0 -P 1 grep %s -nHe %s" + (if (and case-fold-search + (isearch-no-upper-case-p regexp t)) + "-i" + "") + (shell-quote-argument (xref--regexp-to-extended regexp))) + infile + t)) + (goto-char (point-min)) + (when (and (/= (point-min) (point-max)) + (not (looking-at grep-re)) + ;; TODO: Show these matches as well somehow? + (not (looking-at "Binary file .* matches"))) + (user-error "Search failed with status %d: %s" status + (buffer-substring (point-min) (line-end-position)))) + (while (re-search-forward grep-re nil t) + (push (list (string-to-number (match-string line-group)) + (match-string file-group) + (buffer-substring-no-properties (point) (line-end-position))) + hits))) + (setq xrefs (xref--convert-hits (nreverse hits) regexp)) + (unless xrefs + (user-error "No matches for: %s" regexp)) + (xref--show-xrefs xrefs nil))) + ;;;###autoload (defun project-find-file () "Visit a file (with completion) in the current project's roots. |