diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 6e99e9d8ac..7c0c54e6eb 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -1390,6 +1390,7 @@ xref-matches-in-files ;; The 'auto' default would be fine too, but ripgrep can't handle ;; the options we pass in that case. (grep-highlight-matches nil) + (multiline (string-match-p "\n" regexp)) (command (grep-expand-template (cdr (or (assoc @@ -1397,7 +1398,14 @@ xref-matches-in-files xref-search-program-alist) (user-error "Unknown search program `%s'" xref-search-program))) - (xref--regexp-to-extended regexp)))) + (xref--regexp-to-extended regexp) + nil + nil + nil + (when multiline '("-U"))))) + (if (and multiline (not (eq xref-search-program 'ripgrep))) + (user-error "Sorry, multiline searches are not supported with `%s'" + xref-search-program)) (when remote-id (require 'tramp) (setq files (mapcar @@ -1425,6 +1433,27 @@ xref-matches-in-files (not (looking-at "Binary file .* matches"))) (user-error "Search failed with status %d: %s" status (buffer-substring (point-min) (line-end-position)))) + (if multiline + (let (match line last-line file) + (while (re-search-forward grep-re nil t) + (if (and match + (equal file (match-string 1)) + (= (string-to-number (match-string 2)) + (1+ last-line))) + (progn + (setq last-line (string-to-number (match-string 2)) + match (concat match + "\n" + (buffer-substring + (match-end 0) + (line-end-position))))) + (when match + (push (list line file match (1+ (- last-line line))) hits)) + (setq match (buffer-substring (match-end 0) (line-end-position)) + file (match-string 1) + line (string-to-number (match-string 2)) + last-line line))) + (push (list line file match (1+ (- last-line line))) hits))) (while (re-search-forward grep-re nil t) (push (list (string-to-number (match-string line-group)) (match-string file-group) @@ -1536,7 +1565,7 @@ xref--convert-hits (kill-buffer tmp-buffer)))) (defun xref--collect-matches (hit regexp tmp-buffer) - (pcase-let* ((`(,line ,file ,text) hit) + (pcase-let* ((`(,line ,file ,text ,lines-num) hit) (remote-id (file-remote-p default-directory)) (file (and file (concat remote-id file))) (buf (xref--find-file-buffer file)) @@ -1548,7 +1577,7 @@ xref--collect-matches (forward-line (1- line)) (xref--collect-matches-1 regexp file line (line-beginning-position) - (line-end-position) + (line-end-position (or lines-num 1)) syntax-needed))) ;; Using the temporary buffer is both a performance and a buffer ;; management optimization.