From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Visuwesh Newsgroups: gmane.emacs.bugs Subject: bug#70820: [PATCH] Editable grep buffers Date: Mon, 09 Sep 2024 20:09:22 +0530 Message-ID: <8734m8opr9.fsf@gmail.com> References: <87seytlhcq.fsf@gmail.com> <86pltxa40q.fsf@gnu.org> <87jzk5kmwk.fsf@gmail.com> <86ikzoa51h.fsf@gnu.org> <878r0klcp1.fsf@gmail.com> <864jb89zwq.fsf@gnu.org> <87wmo3jmws.fsf@gmail.com> <87fruny6xe.fsf@gmail.com> <86le47eafb.fsf@gnu.org> <86pltjceft.fsf@gnu.org> <86ikzbcces.fsf@gnu.org> <87le1lj4pv.fsf@gmail.com> <87bk1vzuw1.fsf@gmail.com> 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="33772"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: Eli Zaretskii , 70820@debbugs.gnu.org To: Stefan Monnier Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Sep 09 16:41:14 2024 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 1snfZp-0008cE-KX for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 09 Sep 2024 16:41:14 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1snfZb-0007oW-N7; Mon, 09 Sep 2024 10:40:59 -0400 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 1snfZb-0007lf-0S for bug-gnu-emacs@gnu.org; Mon, 09 Sep 2024 10:40:59 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1snfZa-0005vo-N2 for bug-gnu-emacs@gnu.org; Mon, 09 Sep 2024 10:40:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:References:In-Reply-To:From:To:Subject; bh=vy9w9Cwo+VJJSKlz1o/cqA9vaLR9WF6DrTojsU34TZw=; b=Dud37Ujn/0/96QIbGFuyedPSYjrOEqGtXuVS4/kQP3kOYZ1LaMn/luov9Yo8ZvDstUK0USRC1Kv6igs77PUhtsdcgpkNOdfB34O0lo2Jg1L/u/86/zaSMHTFSl9wVWgRvr0GC9lY61dSUrEweeYM6tc7SKe4GLy1fEE0/Bf4cCq4nhTG/aLYRakOqJ+5dNNqJVTWGq1QCfu42WOZxlfyVVSIWsEXQpkgyHs5WRjvvjALP0NM5i+ajHmfkfJXFFYKZfF6dRwQSr96jcBRv6LPImlgvhKa+XGxIdRvd4q+T+5Pp0rh4Vokf5/+diPMM69LdTJ2+0gm7pCsbxb5ZjX4gA==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1snfZe-0001dz-0B for bug-gnu-emacs@gnu.org; Mon, 09 Sep 2024 10:41:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Visuwesh Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 09 Sep 2024 14:41:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70820 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 70820-submit@debbugs.gnu.org id=B70820.17258928416268 (code B ref 70820); Mon, 09 Sep 2024 14:41:01 +0000 Original-Received: (at 70820) by debbugs.gnu.org; 9 Sep 2024 14:40:41 +0000 Original-Received: from localhost ([127.0.0.1]:33824 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1snfZI-0001d1-Ol for submit@debbugs.gnu.org; Mon, 09 Sep 2024 10:40:41 -0400 Original-Received: from mail-pl1-f196.google.com ([209.85.214.196]:52506) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1snfZG-0001cm-W1 for 70820@debbugs.gnu.org; Mon, 09 Sep 2024 10:40:39 -0400 Original-Received: by mail-pl1-f196.google.com with SMTP id d9443c01a7336-20543fdb7acso30273755ad.1 for <70820@debbugs.gnu.org>; Mon, 09 Sep 2024 07:40:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725892769; x=1726497569; darn=debbugs.gnu.org; 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=vy9w9Cwo+VJJSKlz1o/cqA9vaLR9WF6DrTojsU34TZw=; b=Ty2O+zKlYkbfzhaNf5aoKQLeU87hi72LHEwaKkNcbvyWvcKRfk7xIAW88w9eVNDwtu YPcHxPcnNhcFF4E8QdFkvtmPZ+PP9ZOuR5jK+bWsT8kZEGvZj53Ol5CIhRa1PNTdMmUJ 7hdSQVSZgIPzFFGYHfdb4I+YFutHaxcbB6qFXvlz/2byTfbZfoCEf949LBHUo2PmWgg9 OKKPESg6bTJV4jpSwJN6bEWEPFe2Qe+rgH8qJfbhuxd96jwcKtliOUfxjpdqxrptEsFt cjz3C2PqNQ/UfiL3/jWOXGI3diMLW4y7oqXFjXEic4J9ajXqLZn+lDLpu4hNV5BMRYas 98HQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725892769; x=1726497569; 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=vy9w9Cwo+VJJSKlz1o/cqA9vaLR9WF6DrTojsU34TZw=; b=jgfSKupwRW6psQXDLw+m5o3YqaBD3artOW/I24O4OHjnRPl4l9OYDRZQYiR/TRwbP/ Nq0MZAAPIYqiciM1ndm3B2uo+lwqj1zMq+RCJmggnYTJZgfYUpmdq9Rs6XkkI+UR5cdK N5btKwMDsg/gDNhOYD5LlGmu6xEkK4GQ0hTiIcejONa6EHScMZBrswZOkwPhSvIXubOt 7U2ULYBMkLfstLW0KLWEFyAQmC+yME5RANzHLno08N2rnm4ui1bBwxFWcqhaBPq0+MSv V0sXAgy+apHnz8ZkQ7pyfaHCKhpP87IOT/NbZMEKDvx4M7DcXh9tkokpTiio7QNjGDYR Xy4Q== X-Forwarded-Encrypted: i=1; AJvYcCWzKVXZQRGdZlc9BTNZhfnKxzGiuP+BFqtUiA5Vy3AAdhbIVHMGznK0QK04Z+sm/4bCHJG9tg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YwZibLeJERvYTDSZKfeAHw+rfMex17don4sfANb7G1Ubf+0FL+2 V9wOgT+E1Y3RRytUgg93hEYwcukL/z7RJdbIJAIQyc7Lh8Gq3mZ0 X-Google-Smtp-Source: AGHT+IEwj3V/c2vbKrlkIgEbdw//A9WbqPeVQ/E9Cwfhnlyt1xBH9M4FyJFw4H8UaXTv+C9/ERuGsQ== X-Received: by 2002:a17:902:d2d2:b0:206:b79e:5780 with SMTP id d9443c01a7336-206f0507dc6mr121792245ad.24.1725892769020; Mon, 09 Sep 2024 07:39:29 -0700 (PDT) Original-Received: from localhost ([1.7.159.70]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-20710e33a92sm34770385ad.105.2024.09.09.07.39.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Sep 2024 07:39:28 -0700 (PDT) In-Reply-To: <87bk1vzuw1.fsf@gmail.com> (Visuwesh's message of "Wed, 14 Aug 2024 08:13:42 +0530") 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:291505 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable [=E0=AE=AA=E0=AF=81=E0=AE=A4=E0=AE=A9=E0=AF=8D =E0=AE=86=E0=AE=95=E0=AE=B8= =E0=AF=8D=E0=AE=9F=E0=AF=8D 14, 2024] Visuwesh wrote: > [...] > If everyone is okay with the current patch, I can get to writing the > NEWS entry and updating the manual. Thanks. Sorry for the long delay. I've now attached a patch with such documentation changes. --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Make-the-grep-buffer-editable.patch >From 52e4d82dd3f28065e5e3ea390c4629783bcf139d Mon Sep 17 00:00:00 2001 From: Visuwesh Date: Mon, 9 Sep 2024 20:08:04 +0530 Subject: [PATCH] Make the *grep* buffer editable * lisp/progmodes/compile.el (compilation--update-markers): Factor out function... (compilation-next-error-function): from here. Adjust to use above. * lisp/progmodes/grep.el (grep-edit--prepare-buffer) (grep-edit-mode-map, grep-edit-mode-hook, grep-edit-mode) (grep-change-to-grep-edit-mode, grep-edit-save-changes): Add new grep-edit-mode to make the grep results editable like in 'occur-edit-mode' by using the 'occur' framework. (grep-mode-map): Bind 'e' to the new command 'grep-change-to-grep-edit-mode'. * doc/emacs/building.texi (Grep Searching): Update Info manual to include the above command. * etc/NEWS: Announce the change. (bug#70820) --- doc/emacs/building.texi | 10 +++++ etc/NEWS | 9 ++++ lisp/progmodes/compile.el | 95 +++++++++++++++++++++------------------ lisp/progmodes/grep.el | 86 +++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 44 deletions(-) diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index bb03d8cf325..4b2f1ed0649 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -528,6 +528,16 @@ Grep Searching shell commands, customize the option @code{grep-find-abbreviate} to a @code{nil} value. +@findex grep-change-to-grep-edit-mode +@cindex Grep Edit mode +@cindex mode, Grep Edit + Typing @kbd{e} in the @file{*grep*} buffer makes the buffer writiable +and enters the Grep Edit mode. Similar to Occur Edit mode (@pxref{Other +Repeating Search}), you can edit the matching lines reported by +@code{grep} and have those changes reflected in the buffer visiting the +originating file. Type @kbd{C-c C-c} to leave the Grep Edit mode and +return to the Grep mode. + @node Flymake @section Finding Syntax Errors On The Fly @cindex checking syntax diff --git a/etc/NEWS b/etc/NEWS index c6f8b0062e4..24b43108ecb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -290,6 +290,15 @@ the built-in Web server. Interactively, when invoked with a prefix argument, 'php-ts-mode-run-php-webserver' prompts for the config file as well as for other connection parameters. +** Grep + ++++ +*** Grep results can be edited to reflect changes in the originating file. +Like Occur Edit mode, typing 'e' in the '*grep*' buffer will now make +the 'grep' results editable. The edits will be reflected in the buffer +visiting the originating file. Typing 'C-c C-c' will leave the Grep +Edit mode. + * New Modes and Packages in Emacs 31.1 diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index d2e74aa44a6..a78ac1b6462 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -2855,6 +2855,53 @@ compilation-find-buffer (current-buffer) (next-error-find-buffer avoid-current 'compilation-buffer-internal-p))) +(defun compilation--update-markers (loc marker screen-columns first-column) + "Update markers in LOC, and set MARKER to location pointed by LOC. +SCREEN-COLUMNS and FIRST-COLUMN are the value of +`compilation-error-screen-columns' and `compilation-first-column' to use +if they are not set buffer-locally in the target buffer." + (with-current-buffer + (if (bufferp (caar (compilation--loc->file-struct loc))) + (caar (compilation--loc->file-struct loc)) + (apply #'compilation-find-file + marker + (caar (compilation--loc->file-struct loc)) + (cadr (car (compilation--loc->file-struct loc))) + (compilation--file-struct->formats + (compilation--loc->file-struct loc)))) + (let ((screen-columns + ;; Obey the compilation-error-screen-columns of the target + ;; buffer if its major mode set it buffer-locally. + (if (local-variable-p 'compilation-error-screen-columns) + compilation-error-screen-columns screen-columns)) + (compilation-first-column + (if (local-variable-p 'compilation-first-column) + compilation-first-column first-column)) + (last 1)) + (save-restriction + (widen) + (goto-char (point-min)) + ;; Treat file's found lines in forward order, 1 by 1. + (dolist (line (reverse (cddr (compilation--loc->file-struct loc)))) + (when (car line) ; else this is a filename without a line# + (compilation-beginning-of-line (- (car line) last -1)) + (setq last (car line))) + ;; Treat line's found columns and store/update a marker for each. + (dolist (col (cdr line)) + (if (compilation--loc->col col) + (if (eq (compilation--loc->col col) -1) + ;; Special case for range end. + (end-of-line) + (compilation-move-to-column (compilation--loc->col col) + screen-columns)) + (beginning-of-line) + (skip-chars-forward " \t")) + (if (compilation--loc->marker col) + (set-marker (compilation--loc->marker col) (point)) + (setf (compilation--loc->marker col) (point-marker))) + ;; (setf (compilation--loc->timestamp col) timestamp) + )))))) + ;;;###autoload (defun compilation-next-error-function (n &optional reset) "Advance to the next error message and visit the file where the error was. @@ -2864,7 +2911,6 @@ compilation-next-error-function (setq compilation-current-error nil)) (let* ((screen-columns compilation-error-screen-columns) (first-column compilation-first-column) - (last 1) (msg (compilation-next-error (or n 1) nil (or compilation-current-error compilation-messages-start @@ -2876,9 +2922,9 @@ compilation-next-error-function (user-error "No next error")) (setq compilation-current-error (point-marker) overlay-arrow-position - (if (bolp) - compilation-current-error - (copy-marker (line-beginning-position)))) + (if (bolp) + compilation-current-error + (copy-marker (line-beginning-position)))) ;; If loc contains no marker, no error in that file has been visited. ;; If the marker is invalid the buffer has been killed. ;; So, recalculate all markers for that file. @@ -2895,46 +2941,7 @@ compilation-next-error-function ;; (equal (compilation--loc->timestamp loc) ;; (setq timestamp compilation-buffer-modtime))) ) - (with-current-buffer - (if (bufferp (caar (compilation--loc->file-struct loc))) - (caar (compilation--loc->file-struct loc)) - (apply #'compilation-find-file - marker - (caar (compilation--loc->file-struct loc)) - (cadr (car (compilation--loc->file-struct loc))) - (compilation--file-struct->formats - (compilation--loc->file-struct loc)))) - (let ((screen-columns - ;; Obey the compilation-error-screen-columns of the target - ;; buffer if its major mode set it buffer-locally. - (if (local-variable-p 'compilation-error-screen-columns) - compilation-error-screen-columns screen-columns)) - (compilation-first-column - (if (local-variable-p 'compilation-first-column) - compilation-first-column first-column))) - (save-restriction - (widen) - (goto-char (point-min)) - ;; Treat file's found lines in forward order, 1 by 1. - (dolist (line (reverse (cddr (compilation--loc->file-struct loc)))) - (when (car line) ; else this is a filename without a line# - (compilation-beginning-of-line (- (car line) last -1)) - (setq last (car line))) - ;; Treat line's found columns and store/update a marker for each. - (dolist (col (cdr line)) - (if (compilation--loc->col col) - (if (eq (compilation--loc->col col) -1) - ;; Special case for range end. - (end-of-line) - (compilation-move-to-column (compilation--loc->col col) - screen-columns)) - (beginning-of-line) - (skip-chars-forward " \t")) - (if (compilation--loc->marker col) - (set-marker (compilation--loc->marker col) (point)) - (setf (compilation--loc->marker col) (point-marker))) - ;; (setf (compilation--loc->timestamp col) timestamp) - )))))) + (compilation--update-markers loc marker screen-columns first-column)) (compilation-goto-locus marker (compilation--loc->marker loc) (compilation--loc->marker end-loc)) (setf (compilation--loc->visited loc) t))) diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index d2d0baa235c..54006560224 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -310,6 +310,8 @@ grep-mode-map (define-key map "}" #'compilation-next-file) (define-key map "\t" #'compilation-next-error) (define-key map [backtab] #'compilation-previous-error) + + (define-key map "e" #'grep-change-to-grep-edit-mode) map) "Keymap for grep buffers. `compilation-minor-mode-map' is a cdr of this.") @@ -1052,6 +1054,90 @@ grep command-args) #'grep-mode)) +(defun grep-edit--prepare-buffer () + "Mark relevant regions read-only, and add relevant occur text-properties." + (save-excursion + (goto-char (point-min)) + (let ((inhibit-read-only t) + (dummy (make-marker)) + match) + (while (setq match (text-property-search-forward 'compilation-annotation)) + (add-text-properties (prop-match-beginning match) (prop-match-end match) + '(read-only t))) + (goto-char (point-min)) + (while (setq match (text-property-search-forward 'compilation-message)) + (add-text-properties (prop-match-beginning match) (prop-match-end match) + '(read-only t occur-prefix t)) + (let ((loc (compilation--message->loc (prop-match-value match))) + m) + ;; Update the markers if necessary. + (unless (and (compilation--loc->marker loc) + (marker-buffer (compilation--loc->marker loc))) + (compilation--update-markers loc dummy compilation-error-screen-columns compilation-first-column)) + (setq m (compilation--loc->marker loc)) + (add-text-properties (prop-match-beginning match) + (or (next-single-property-change + (prop-match-end match) + 'compilation-message) + (1+ (pos-eol))) + `(occur-target ((,m . ,m))))))))) + +(defvar grep-edit-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map text-mode-map) + (define-key map (kbd "C-c C-c") #'grep-edit-save-changes) + map) + "Keymap for `grep-edit-mode'.") + +(defvar grep-edit-mode-hook nil + "Hooks run when changing to Grep-Edit mode.") + +(defun grep-edit-mode () + "Major mode for editing *grep* buffers. +In this mode, changes to the *grep* buffer are applied to the +originating files. +\\ +Type \\[grep-edit-save-changes] to exit Grep-Edit mode, return to Grep +mode. + +The only editable texts in a Grep-Edit buffer are the match results." + (interactive) + (error "This mode can be enabled only by `grep-change-to-grep-edit-mode'")) +(put 'grep-edit-mode 'mode-class 'special) + +(defun grep-change-to-grep-edit-mode () + "Switch to `grep-edit-mode' to edit *grep* buffer." + (interactive) + (unless (derived-mode-p 'grep-mode) + (error "Not a Grep buffer")) + (when (get-buffer-process (current-buffer)) + (error "Cannot switch when grep is running")) + (use-local-map grep-edit-mode-map) + (grep-edit--prepare-buffer) + (setq buffer-read-only nil) + (setq major-mode 'grep-edit-mode) + (setq mode-name "Grep-Edit") + (buffer-enable-undo) + (set-buffer-modified-p nil) + (setq buffer-undo-list nil) + (add-hook 'after-change-functions #'occur-after-change-function nil t) + (run-mode-hooks 'grep-edit-mode-hook) + (message "Editing: \\[grep-edit-save-changes] to return to Grep mode")) + +(defun grep-edit-save-changes () + "Switch back to Grep mode." + (interactive) + (unless (derived-mode-p 'grep-edit-mode) + (error "Not a Grep-Edit buffer")) + (remove-hook 'after-change-functions #'occur-after-change-function t) + (use-local-map grep-mode-map) + (setq buffer-read-only t) + (setq major-mode 'grep-mode) + (setq mode-name "Grep") + (force-mode-line-update) + (buffer-disable-undo) + (setq buffer-undo-list t) + (message "Switching to Grep mode")) ;;;###autoload (defun grep-find (command-args) -- 2.45.2 --=-=-=--