emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/urgrep 6f5813ba78 062/115: Add support for wgrep; resol


From: ELPA Syncer
Subject: [elpa] externals/urgrep 6f5813ba78 062/115: Add support for wgrep; resolves #2
Date: Wed, 10 May 2023 03:00:44 -0400 (EDT)

branch: externals/urgrep
commit 6f5813ba78de5b90c47596b0ed05d91b3d128661
Author: Jim Porter <jporterbugs@gmail.com>
Commit: Jim Porter <jporterbugs@gmail.com>

    Add support for wgrep; resolves #2
---
 urgrep-wgrep.el | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 urgrep.el       |   2 +-
 2 files changed, 152 insertions(+), 1 deletion(-)

diff --git a/urgrep-wgrep.el b/urgrep-wgrep.el
new file mode 100644
index 0000000000..9da9592f1a
--- /dev/null
+++ b/urgrep-wgrep.el
@@ -0,0 +1,151 @@
+;;; urgrep-wgrep.el --- Universal recursive grep -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Jim Porter
+
+;; Author: Jim Porter
+;; URL: https://github.com/jimporter/urgrep
+;; Version: 0.1-dev
+;; Keywords:
+;; Package-Requires: ((urgrep "0.1-dev"))
+
+;; This program is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by the Free
+;; Software Foundation, either version 3 of the License, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+;; more details.
+
+;; You should have received a copy of the GNU General Public License along with
+;; this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A compatibility layer between urgrep and wgrep.
+
+;;; Code:
+
+(require 'wgrep)
+
+(defvar urgrep-wgrep--grouped-result-regexp
+  (concat "^\\(?:"
+          ;; A match or context line.
+          "\\(?2:[1-9][0-9]*\\)[:=-]"
+          "\\|"
+          ;; A separator line.
+          "\\(?3:--$\\)"
+          "\\)")
+  "The regexp to use to match results using grouped output.
+Group 2 is the line number, and group 3 is the \"--\" separator used when
+displaying context.  Group 1 is unused.")
+
+(defvar urgrep-wgrep--ungrouped-result-regexp
+  (concat "^\\(?:"
+          ;; A match or context line using a null terminator after the 
filename.
+          "\\(?1:[^\0\n]+\\)\0\\(?2:[0-9]+\\)[:=-]"
+          "\\|"
+          ;; A match or context line without a null terminator; see also
+          ;; `urgrep-regexp-alist'.
+          "\\(?1:[^\n]*?[^\n/]\\)[:=-]\\(?2:[1-9][0-9]*\\)[:=-]"
+          "\\|"
+          ;; A separator line.
+          "\\(?3:--$\\)"
+          "\\)")
+    "The regexp to use to match results using ungrouped output.
+Group 1 is the filename, group 2 is the line number, and group 3 is the \"--\"
+separator used when displaying context.")
+
+(defun urgrep-wgrep--propertize-lines (begin end &optional file-name)
+  "Apply wgrep properties to result lines between BEGIN and END.
+If END is nil, continue to the end of the (narrowed) buffer.
+FILE-NAME, if non-nil is the name of the file for this section of
+grouped results; if nil, assume the results are ungrouped."
+  (let ((line-regexp (if file-name
+                         urgrep-wgrep--grouped-result-regexp
+                       urgrep-wgrep--ungrouped-result-regexp)))
+    (goto-char begin)
+    (while (and (zerop (forward-line 1))
+                (looking-at line-regexp)
+                (or (not end) (< (point) end)))
+      (if (match-beginning 3)
+          ;; Ignore the separator line ("--").
+          (add-text-properties (match-beginning 0) (match-end 0)
+                               '(wgrep-ignore t))
+        ;; If results are ungrouped, mark the filename with
+        ;; `wgrep-construct-filename-property'.
+        (unless file-name
+          (let ((this-file (match-string-no-properties 1)))
+            (add-text-properties
+             (match-beginning 1) (match-end 1)
+             (list (wgrep-construct-filename-property file-name) file-name))))
+        ;; Mark the line with the filename and line number.
+        (add-text-properties
+         (match-beginning 0) (match-end 0)
+         (list 'wgrep-line-filename file-name
+               'wgrep-line-number (string-to-number (match-string 2))))))))
+
+(defun urgrep-wgrep-header/footer-parser ()
+  "Mark the header and footer of the urgrep results.
+This lets wgrep know what to ignore."
+  (save-excursion
+    ;; Look for the beginning of the results.
+    (goto-char (point-min))
+    (if (not (text-property-search-forward 'urgrep-file-name))
+        ;; No results, mark the entire buffer as a header.
+        (add-text-properties (point-min) (point-max)
+                             '(read-only t wgrep-header t))
+      ;; Found some results, mark the preceding part of the buffer as a header.
+      (add-text-properties (point-min) (line-beginning-position)
+                           '(read-only t wgrep-header t))
+      ;; Look for the end of the results.
+      (goto-char (point-max))
+      (text-property-search-backward 'compilation-message)
+      ;; If there's a footer, mark it.
+      (when (zerop (forward-line 1))
+        (add-text-properties (point) (point-max)
+                             '(read-only t wgrep-footer t))))))
+
+(defun urgrep-wgrep-results-parser ()
+  "Parse the urgrep results and apply properties for wgrep."
+  (save-excursion
+    (let ((this-group)
+          (next-group (text-property-search-forward 'urgrep-file-name)))
+      (if (eolp)
+          ;; Grouped results
+          (while (prog1 (setq this-group next-group)
+                   (setq next-group (text-property-search-forward
+                                     'urgrep-file-name)))
+            (let* ((file-name-begin (prop-match-beginning this-group))
+                   (file-name-end (prop-match-end this-group))
+                   (file-name (buffer-substring-no-properties file-name-begin
+                                                              file-name-end)))
+              ;; Mark the filename with `wgrep-construct-filename-property'.
+              (add-text-properties
+               file-name-begin file-name-end
+               (list 'wgrep-ignore t
+                     (wgrep-construct-filename-property file-name) file-name))
+              (urgrep-wgrep--propertize-lines
+               (prop-match-end this-group)
+               (when next-group (prop-match-beginning next-group))
+               file-name)))
+        ;; Ungrouped results
+        (urgrep-wgrep--propertize-lines (point-min) nil)))))
+
+;;;###autoload
+(defun urgrep-wgrep-setup ()
+  "Set up a urgrep buffer to use wgrep."
+  (setq-local wgrep-header/footer-parser #'urgrep-wgrep-header/footer-parser
+              wgrep-results-parser #'urgrep-wgrep-results-parser)
+  (wgrep-setup-internal))
+
+;;;###autoload
+(add-hook 'urgrep-setup-hook #'urgrep-wgrep-setup)
+
+(defun urgrep-wgrep-unload-function ()
+  "Unload wgrep from urgrep."
+  (remove-hook 'urgrep-setup-hook #'urgrep-wgrep-setup))
+
+(provide 'urgrep-wgrep)
+;;; urgrep-wgrep.el ends here
diff --git a/urgrep.el b/urgrep.el
index ee8f67b280..cfe0925d5e 100644
--- a/urgrep.el
+++ b/urgrep.el
@@ -23,7 +23,7 @@
 
 ;;; Commentary:
 
-;; A universal frontend to various grep-like tools. Currently, ugrep, ripgrep,
+;; A universal frontend to various grep-like tools.  Currently, ugrep, ripgrep,
 ;; ag, ack, git-grep, and grep are supported.  The primary entry point to this
 ;; package is the interactive function `urgrep' (which see).
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]