unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Augusto Stoffel <arstoffel@gmail.com>
To: 59888@debbugs.gnu.org
Subject: bug#59888: [PATCH] Add 'grep-heading-mode'
Date: Wed, 07 Dec 2022 18:57:37 +0100	[thread overview]
Message-ID: <87v8mndrla.fsf@gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 763 bytes --]

Tags: patch

This simulates the --heading option of certain grep-like tools.  The
output is like this:

--8<---------------cut here---------------start------------->8---
-*- mode: grep; default-directory: "~/Projects/emacs/" -*-
Grep started at Wed Dec  7 18:43:40

find [...] -exec grep --color=auto -i -nH --null -e test \{\} +

./nextstep/Makefile.in
104:	find ${ns_appdir} -exec test \! -e {} \; -ls

./nextstep/INSTALL
12:Tested on GNU/Linux, may work on other systems.

./nextstep/Makefile
104:	find ${ns_appdir} -exec test \! -e {} \; -ls

./nextstep/README
62:  10.6.8 (Snow Leopard) to the latest official release.
86:* This allows other Emacs developers to test their changes on the NS
--8<---------------cut here---------------end--------------->8---


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-grep-heading-mode.patch --]
[-- Type: text/patch, Size: 4316 bytes --]

From 2247f006845000032fedc3dda9a073b14043a270 Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <arstoffel@gmail.com>
Date: Wed, 7 Dec 2022 18:44:07 +0100
Subject: [PATCH] Add 'grep-heading-mode'

New minor mode to subdivide grep output into sections, as in the
'--heading' option of certain grep-like programs.

* lisp/progmodes/grep.el (grep-heading-regexp): New user option.
(grep-heading): New face.
(grep--heading-format, grep--current-heading, grep--heading-filter):
Filter function for grep processes and supporting variables.
(grep-heading-mode): New minor mode.
---
 etc/NEWS               |  8 +++++
 lisp/progmodes/grep.el | 71 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index 3eeef0ab4c..54c3b2447a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -41,6 +41,14 @@ connection.
 \f
 * Changes in Specialized Modes and Packages in Emacs 30.1
 
+** Compile
+
+*** New minor mode 'grep-heading-mode'.
+In this mode, the grep output is split into sections, one for each
+file, instead of having file names prefixed to each line.  It is
+equivalent to the --heading option of some tools such as 'git grep'
+and 'rg.
+
 ** VC
 
 ---
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index 2446e86abb..132f905734 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -30,6 +30,7 @@
 ;;; Code:
 
 (eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'rx))
 (require 'compile)
 
 (defgroup grep nil
@@ -1407,6 +1408,76 @@ grep-file-at-point
 ;;;###autoload
 (defalias 'rzgrep #'zrgrep)
 
+;;; Headings mode
+(defcustom grep-heading-regexp
+  (rx bol
+      (or
+       (seq "Grep" (* (any "/a-zA-Z")) " "
+            (or "started" "finished" "exited" "interrupt" "killed" "terminated")
+            (* (not (any "\0\n"))))
+       (seq
+        (group-n 2
+          (group-n 1 (+? any))
+          (any "\0-:="))
+        (+ digit)
+        (any "-:="))))
+  "Regexp used to create headings from grep output lines.
+It should be anchored at beginning of line.  The first capture
+group, if present, should match the heading associated to the
+line.  The buffer range of the second capture, if present, is
+made invisible (presumably because displaying it would be
+redundant)."
+  :type 'regexp
+  :version "30.1")
+
+(defface grep-heading '((t :inherit font-lock-function-name-face))
+  "Face of headings when using `grep-heading-mode'.")
+
+(defvar grep--heading-format
+  #("\n%s\n" 1 3 (font-lock-face grep-heading outline-level 1))
+  "Format string of grep headings.
+This is passed to `format' with one argument, the text of the
+first capture group of `grep-heading-regexp'.")
+
+(defvar-local grep--current-heading nil
+  "Used by `grep--heading-filter' to keep track of the current heading.")
+
+(defun grep--heading-filter ()
+  "Filter function to add headings to output of a grep process."
+  (save-excursion
+    (let ((bound (copy-marker (pos-bol))))
+      (goto-char compilation-filter-start)
+      (forward-line 0)
+      (while (re-search-forward grep-heading-regexp bound t)
+        (let ((heading (match-string-no-properties 1))
+              (start (match-beginning 2))
+              (end (match-end 2)))
+          (when start
+            (put-text-property start end 'invisible t))
+          (when (and heading (not (equal heading grep--current-heading)))
+            (save-excursion
+              (forward-line 0)
+              (insert-before-markers (format grep--heading-format heading)))
+            (setq grep--current-heading heading)))))))
+
+;;;###autoload
+(define-minor-mode grep-heading-mode
+  "Subdivide grep output into sections, one per file."
+  :interactive 'grep-mode
+  (if (not grep-heading-mode)
+      (recompile)
+    (save-excursion
+      (save-restriction
+        (widen)
+        (let ((inhibit-read-only t)
+              (compilation-filter-start (point-min)))
+          (goto-char (point-max))
+          (grep--heading-filter))))
+    (add-hook 'compilation-filter-hook #'grep--heading-filter 80 t)
+    (setq-local outline-search-function #'outline-search-level
+                outline-level (lambda () (get-text-property
+                                          (point) 'outline-level)))))
+
 (provide 'grep)
 
 ;;; grep.el ends here
-- 
2.38.1


[-- Attachment #3: Type: text/plain, Size: 539 bytes --]


Some comments:

1. It's necessary to insert text into the grep buffer, which is a bit
   concerning because 'compilation-filter-start' is not a marker, just a
   number.  This could cause other filter functions to get confused.
   This is why I'm adding to 'compilation-filter-hook at a higher depth.
   Perhaps there are better approaches here.

2. One could get rid of the awkward first alternative of
   `grep-heading-regexp' if there was a way to distringuish the grep
   process output from the header and footer added by grep-mode.

             reply	other threads:[~2022-12-07 17:57 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-07 17:57 Augusto Stoffel [this message]
2022-12-07 18:14 ` bug#59888: [PATCH] Add 'grep-heading-mode' Eli Zaretskii
2022-12-08  8:59   ` Augusto Stoffel
2022-12-08 10:57     ` Eli Zaretskii
2022-12-08  0:19 ` Stefan Kangas
2022-12-08  9:06   ` Augusto Stoffel
2022-12-09  7:23     ` Juri Linkov
2022-12-09 11:58       ` Augusto Stoffel
2022-12-09 12:18       ` bug#59888: [PATCH] Add 'grep-use-headings' Augusto Stoffel
2022-12-09 19:36         ` Eli Zaretskii
2022-12-09 20:03           ` Augusto Stoffel
2022-12-09 20:29             ` Eli Zaretskii
2022-12-10 20:08               ` Augusto Stoffel
2022-12-10 20:16                 ` Eli Zaretskii
2022-12-11 11:30                   ` Augusto Stoffel
2022-12-15  8:05                     ` Juri Linkov
2023-02-25  8:34                       ` Augusto Stoffel
2023-02-25 18:00                         ` Juri Linkov
2023-02-26 13:17                         ` Robert Pluim
2023-02-26 15:07                           ` Augusto Stoffel
2023-02-27  6:24                             ` Robert Pluim
2023-02-27 11:26                               ` Augusto Stoffel
2023-02-27 16:51                                 ` Robert Pluim
2023-02-27 18:53                             ` Juri Linkov
2023-02-27 19:06                               ` Augusto Stoffel
2023-02-27 19:15                                 ` Juri Linkov
2023-02-28 17:24                                 ` Juri Linkov
2023-02-28 18:17                                   ` Augusto Stoffel
2023-03-01 17:52                                     ` Juri Linkov
2022-12-09 20:40             ` Gregory Heytings
2022-12-10 17:24             ` Juri Linkov
2022-12-08  9:57 ` bug#59888: [PATCH] Add 'grep-heading-mode' Mattias Engdegård
2022-12-08 10:28   ` Augusto Stoffel
2022-12-08 10:48     ` Mattias Engdegård
2023-02-27 14:18       ` Mattias Engdegård
2022-12-09  7:28 ` Juri Linkov
2022-12-09 11:58   ` Augusto Stoffel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87v8mndrla.fsf@gmail.com \
    --to=arstoffel@gmail.com \
    --cc=59888@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).