From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Augusto Stoffel Newsgroups: gmane.emacs.bugs Subject: bug#59888: [PATCH] Add 'grep-use-headings' Date: Sun, 11 Dec 2022 12:30:42 +0100 Message-ID: <87ilii41p9.fsf@gmail.com> References: <87v8mndrla.fsf@gmail.com> <87ilime025.fsf@gmail.com> <86359pm55x.fsf@mail.linkov.net> <87o7scdb45.fsf_-_@gmail.com> <837cz0z7wj.fsf@gnu.org> <87k0301h16.fsf@gmail.com> <831qp8z5gp.fsf@gnu.org> <87sfhn3tui.fsf@gmail.com> <83wn6zui9n.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="32481"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: stefankangas@gmail.com, 59888@debbugs.gnu.org, juri@linkov.net To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Dec 11 12:31:16 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1p4KY8-0008Jb-2V for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 11 Dec 2022 12:31:16 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p4KY2-0002iI-TQ; Sun, 11 Dec 2022 06:31:10 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p4KXu-0002fI-Ib for bug-gnu-emacs@gnu.org; Sun, 11 Dec 2022 06:31:05 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1p4KXu-0007TJ-9m for bug-gnu-emacs@gnu.org; Sun, 11 Dec 2022 06:31:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1p4KXu-0000tw-5W for bug-gnu-emacs@gnu.org; Sun, 11 Dec 2022 06:31:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Augusto Stoffel Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 11 Dec 2022 11:31:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 59888 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 59888-submit@debbugs.gnu.org id=B59888.16707582553458 (code B ref 59888); Sun, 11 Dec 2022 11:31:02 +0000 Original-Received: (at 59888) by debbugs.gnu.org; 11 Dec 2022 11:30:55 +0000 Original-Received: from localhost ([127.0.0.1]:46344 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1p4KXm-0000ti-SX for submit@debbugs.gnu.org; Sun, 11 Dec 2022 06:30:55 -0500 Original-Received: from mail-ej1-f47.google.com ([209.85.218.47]:38509) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1p4KXj-0000tZ-Fh for 59888@debbugs.gnu.org; Sun, 11 Dec 2022 06:30:54 -0500 Original-Received: by mail-ej1-f47.google.com with SMTP id m18so21466231eji.5 for <59888@debbugs.gnu.org>; Sun, 11 Dec 2022 03:30:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=lVGD3AdemrYGcTUwfcirmJCtV4ftE2WlA6cy56FHXv8=; b=J1cJYysnVWBg29KWyEu8iIxvKKc795+9kJJ6aP1ltJ2k86x83zgd8cdv1IL8HaTDZB Eb4v91BFOTXR17r38bpHCZxTkIbiDF5i0EOjVOlNIGYmIByi3f3JN00ZgY+HxKZoVPOE FQOocrAECpxhqg6bWmoWu6697r4biq3XhWDnhfU+L/foXYjeSkIIqEj2vTklSw14QmpD 3lGZIpl40s+KSwjT1dyncpg/3Zu+QNIMFlyKVaB11bKm96KvUJVFm4vb5VBrWPSeQuvR hw3OQJBmgHJ8UbgfI3RPEojzw1dtZY7RbThfDRQU9Z3VjjAwtUD1bgBUlpI36Cy22sHA llyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=lVGD3AdemrYGcTUwfcirmJCtV4ftE2WlA6cy56FHXv8=; b=UK+jR1oHl2TgopV/PeMXNk/85xud/2Alf/Yu2+fqpJ5eWTltVMQyVZc25vdMzWfQLU pFgCnWdNfMhBNZQBYqmJy2GWZ7JpL3jy1pV5R6xHHWQUlQXXAvYA/IAWY3jDTDUXhau0 kLfcZb1g1u1Une3hiLCRz04Pvi4jjxBodMXUtifCQ0q3tJaYyenpsn0GlFZSLxvbKoBn QsgzjJmPJHtkVszfz2N9lFYdHya2mmjjQ6+NGbVxi4xdPYeUk43Rf5rLMiN/Hoivwkbo RKQTn5zeMCQe/Qst+IrmGiTYnl/qVknf826pE1gGoJwYktKTxN0aJYgkGpaPwLY+rJ0Y Mt9w== X-Gm-Message-State: ANoB5pku+OgfuPxquRZtTNoXlxZ0PyuAPFrGgp/FSTjUQ7+vPEEUUcqq 28l5a1MZilciw0SGs1hEs+VJ66Ad04hDFQ== X-Google-Smtp-Source: AA0mqf66orer0hGTfEMIbnRRiWFPRpwUFlUcQAQFPYPLZuftJiIMilABGkA2kB2yOGGhGLTybdRcig== X-Received: by 2002:a17:907:7603:b0:7c1:6091:e73 with SMTP id jx3-20020a170907760300b007c160910e73mr2631381ejc.1.1670758245104; Sun, 11 Dec 2022 03:30:45 -0800 (PST) Original-Received: from ars3 ([2a02:8109:8ac0:56d0::a4bf]) by smtp.gmail.com with ESMTPSA id rh16-20020a17090720f000b007c0efbaa8a0sm2037114ejb.4.2022.12.11.03.30.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Dec 2022 03:30:43 -0800 (PST) In-Reply-To: <83wn6zui9n.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 10 Dec 2022 22:16:04 +0200") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:250597 Archived-At: --=-=-= Content-Type: text/plain I've attached a new version of the patch incorporating the latest discussions. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Introduce-compilation-annotation-text-property.patch >From 8aa2bebbe1b12094963fdeb3251f3ef3c22ea5e9 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Thu, 8 Dec 2022 21:05:10 +0100 Subject: [PATCH 1/2] Introduce 'compilation-annotation' text property It is meant to mark parts of compilation buffers which do not correspond to process output. * lisp/progmodes/compile.el (compilation-insert-annotation): New function. (compilation-start, compilation-handle-exit): Use it. (compilation--ensure-parse) Rely on 'compilation-annotation' property instead of 'compilation-header-end'. --- lisp/progmodes/compile.el | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index e8ada9388e..3aa6867533 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -1675,7 +1675,7 @@ compilation--ensure-parse (set-marker (make-marker) (save-excursion (goto-char (point-min)) - (text-property-search-forward 'compilation-header-end) + (text-property-search-forward 'compilation-annotation) ;; If we have no end marker, this will be ;; `point-min' still. (point))))) @@ -1823,6 +1823,14 @@ compilation--update-in-progress-mode-line ;; buffers when it changes from nil to non-nil or vice-versa. (unless compilation-in-progress (force-mode-line-update t))) +(defun compilation-insert-annotation (&rest args) + "Insert ARGS at point, adding the `compilation-annotation' text property. +This property is used to distinguish output of the compilation +process from additional information inserted by Emacs." + (let ((start (point))) + (apply #'insert args) + (put-text-property start (point) 'compilation-annotation t))) + ;;;###autoload (defun compilation-start (command &optional mode name-function highlight-regexp continue) @@ -1944,17 +1952,16 @@ compilation-start (setq-local compilation-auto-jump-to-next t)) (when (zerop (buffer-size)) ;; Output a mode setter, for saving and later reloading this buffer. - (insert "-*- mode: " name-of-mode - "; default-directory: " - (prin1-to-string (abbreviate-file-name default-directory)) - " -*-\n")) - (insert (format "%s started at %s\n\n" - mode-name - (substring (current-time-string) 0 19)) - command "\n") - ;; Mark the end of the header so that we don't interpret - ;; anything in it as an error. - (put-text-property (1- (point)) (point) 'compilation-header-end t) + (compilation-insert-annotation + "-*- mode: " name-of-mode + "; default-directory: " + (prin1-to-string (abbreviate-file-name default-directory)) + " -*-\n")) + (compilation-insert-annotation + (format "%s started at %s\n\n" + mode-name + (substring (current-time-string) 0 19)) + command "\n") (setq thisdir default-directory)) (set-buffer-modified-p nil)) ;; Pop up the compilation buffer. @@ -2436,13 +2443,13 @@ compilation-handle-exit (cur-buffer (current-buffer))) ;; Record where we put the message, so we can ignore it later on. (goto-char omax) - (insert ?\n mode-name " " (car status)) + (compilation-insert-annotation ?\n mode-name " " (car status)) (if (and (numberp compilation-window-height) (zerop compilation-window-height)) (message "%s" (cdr status))) (if (bolp) (forward-char -1)) - (insert " at " (substring (current-time-string) 0 19)) + (compilation-insert-annotation " at " (substring (current-time-string) 0 19)) (goto-char (point-max)) ;; Prevent that message from being recognized as a compilation error. (add-text-properties omax (point) -- 2.38.1 --=-=-= Content-Type: text/x-patch; charset=utf-8 Content-Disposition: attachment; filename=0002-New-user-option-grep-use-headings.patch Content-Transfer-Encoding: quoted-printable >From e1209a93e09792cbb61bde9ae3ac8838c76861a5 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Wed, 7 Dec 2022 18:44:07 +0100 Subject: [PATCH 2/2] New user option 'grep-use-headings' * lisp/progmodes/grep.el (grep-heading-regexp): New user option. (grep-heading): New face. (grep--heading-format, grep--heading-state, grep--heading-filter): Filter function for grep processes and supporting variables. (grep-use-headings): New user option. (grep-mode): Use the above, if applicable. --- etc/NEWS | 8 ++++ lisp/progmodes/grep.el | 69 +++++++++++++++++++++++++++++++ test/lisp/progmodes/grep-tests.el | 14 +++++++ 3 files changed, 91 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index 3eeef0ab4c..ac5ed7cbf3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -41,6 +41,14 @@ connection. * Changes in Specialized Modes and Packages in Emacs 30.1 =20 +** Compile + +*** New user option 'grep-use-headings'. +When non-nil, the output of Grep 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 =20 --- diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 2446e86abb..c6be39fbb7 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -30,6 +30,7 @@ ;;; Code: =20 (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'rx)) (require 'compile) =20 (defgroup grep nil @@ -457,6 +458,35 @@ grep-search-path :type '(repeat (choice (const :tag "Default" nil) (string :tag "Directory")))) =20 +(defcustom grep-use-headings nil + "If non-nil, subdivide grep output into sections, one per file." + :type 'boolean + :version "30.1") + +(defcustom grep-heading-regexp + (rx bol + (or + (group-n 2 + (group-n 1 (+ (not (any 0 ?\n)))) + 0) + (group-n 2 + (group-n 1 (+? nonl)) + (any ?: ?- ?=3D))) + (+ digit) + (any ?: ?- ?=3D)) + "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 ,grep-hit-face)) + "Face of headings when using `grep-heading-mode'." + :version "30.1") + (defvar grep-find-abbreviate-properties (let ((ellipsis (if (char-displayable-p ?=E2=80=A6) "[=E2=80=A6]" "[...]= ")) (map (make-sparse-keymap))) @@ -612,6 +642,40 @@ grep-filter (while (re-search-forward "\033\\[[0-9;]*[mK]" end 1) (replace-match "" t t)))))) =20 +(defvar grep--heading-format + (eval-when-compile + (let ((title (propertize "%s" + 'font-lock-face 'grep-heading + 'outline-level 1))) + (propertize (concat title "\n") 'compilation-annotation t))) + "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--heading-state nil + "Variable to keep track of the `grep--heading-filter' state.") + +(defun grep--heading-filter () + "Filter function to add headings to output of a grep process." + (unless grep--heading-state + (setq grep--heading-state (cons (point-min-marker) nil))) + (save-excursion + (let ((limit (car grep--heading-state))) + ;; Move point to the old limit and update limit marker. + (move-marker limit (prog1 (pos-bol) (goto-char limit))) + (while (re-search-forward grep-heading-regexp limit t) + (unless (get-text-property (point) 'compilation-annotation) + (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 (cdr grep--heading-stat= e)))) + (save-excursion + (forward-line 0) + (insert-before-markers (format grep--heading-format headin= g))) + (setf (cdr grep--heading-state) heading)))))))) + (defun grep-probe (command args &optional func result) (let (process-file-side-effects) (equal (condition-case nil @@ -906,6 +970,11 @@ grep-mode (add-function :filter-return (local 'kill-transform-function) (lambda (string) (string-replace "\0" ":" string))) + (when grep-use-headings + (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)))) (add-hook 'compilation-filter-hook #'grep-filter nil t)) =20 (defun grep--save-buffers () diff --git a/test/lisp/progmodes/grep-tests.el b/test/lisp/progmodes/grep-t= ests.el index 101052c5ad..51f4606639 100644 --- a/test/lisp/progmodes/grep-tests.el +++ b/test/lisp/progmodes/grep-tests.el @@ -66,4 +66,18 @@ grep-tests--rgrep-abbreviate-properties-windows-nt-sh-se= mantics (cl-letf (((symbol-function 'w32-shell-dos-semantics) #'ignore)) (grep-tests--check-rgrep-abbreviation)))) =20 +(ert-deftest grep-tests--grep-heading-regexp-without-null () + (dolist (sep '(?: ?- ?=3D)) + (let ((string (format "filename%c123%ctext" sep sep))) + (should (string-match grep-heading-regexp string)) + (should (equal (match-string 1 string) "filename")) + (should (equal (match-string 2 string) (format "filename%c" sep)))))) + +(ert-deftest grep-tests--grep-heading-regexp-with-null () + (dolist (sep '(?: ?- ?=3D)) + (let ((string (format "funny:0:filename%c123%ctext" 0 sep))) + (should (string-match grep-heading-regexp string)) + (should (equal (match-string 1 string) "funny:0:filename")) + (should (equal (match-string 2 string) "funny:0:filename\0"))))) + ;;; grep-tests.el ends here --=20 2.38.1 --=-=-= Content-Type: text/plain There is still an issue I'm aware of: if one saves a grep buffer to a file and later opens the file, the headings are inserted a second time. I've tried a bit to display the headings only using text display properties (instead of inserting the actual text into the buffer), but wasn't successful so far. Other, less elegant solutions are possible (e.g. deleting all headings either when saving or when reading again the file). We could install this change now and polish it later or continue this discussion -- both are fine by me. --=-=-=--