Subject: [PATCH] Make project--find-regexp-in-files work with remote files

From: Felicián Németh <[email-masked]>
Date: Wed, 6 Feb 2019 09:18:02 +0100

Hi,

The attached patch enhances the remote file support of project.el. It also
has a new "require" statement, which might be problematic.  Additionally,
project--collect-matches will look very similar to xref-collect-matches
creating a chance to unify the two functions later.

Thanks,
Felicián
From 6f65ec9462eebfd405768e1b2c730fc3f4e65b4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felici=C3=A1n=20N=C3=A9meth?= <[email-masked]>
Date: Wed, 6 Feb 2019 08:59:34 +0100
Subject: [PATCH] Make project--find-regexp-in-files work with remote files

* project.el: Require seq.
(project--collect-matches): New function extracted
from project--find-regexp-in-files; handle remote files.
(project--find-regexp-in-files): Group files based on their
remote-id, call the new function on the groups.
---
 lisp/progmodes/project.el | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 815cc7cd3d..5833e6401b 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -88,6 +88,7 @@
 ;;; Code:
 
 (require 'cl-generic)
+(require 'seq)
 
 (defvar project-find-functions (list #'project-try-vc)
   "Special hook to find the project containing a given directory.
@@ -374,12 +375,29 @@ project-or-external-find-regexp
     (project--find-regexp-in-files regexp files)))
 
 (defun project--find-regexp-in-files (regexp files)
+  (let* ((xref-groups
+          (mapcar
+           (lambda (group)
+             (let* ((files (cdr group))
+                    (local-files (mapcar #'file-local-name files))
+                    (dir (file-name-directory (car files))))
+               (project--collect-matches regexp local-files dir)))
+           (seq-group-by #'file-remote-p files)))
+         (xrefs (apply #'append xref-groups)))
+    (unless xrefs
+      (user-error "No matches for: %s" regexp))
+    (xref--show-xrefs xrefs nil)))
+
+(defun project--collect-matches (regexp files dir)
+  "Collect matches for REGEXP inside FILES in DIR.
+FILES is a list of file names."
+  ;; Cf. `xref-collect-matches'.
   (pcase-let*
       ((output (get-buffer-create " *project grep output*"))
        (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist))
        (status nil)
        (hits nil)
-       (xrefs nil)
+       (remote-id (file-remote-p dir))
        (command (format "xargs -0 grep %s -nHe %s"
                         (if (and case-fold-search
                                  (isearch-no-upper-case-p regexp t))
@@ -390,6 +408,7 @@ project--find-regexp-in-files
       (erase-buffer)
       (with-temp-buffer
         (insert (mapconcat #'identity files "\0"))
+        (setq default-directory dir)
         (setq status
               (project--process-file-region (point-min)
                                             (point-max)
@@ -407,13 +426,10 @@ project--find-regexp-in-files
                     (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)
+                    (concat remote-id (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)))
+    (xref--convert-hits (nreverse hits) regexp)))
 
 (defun project--process-file-region (start end program
                                      &optional buffer display
-- 
2.11.0