From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 10 13:23:45 2023 Received: (at submit) by debbugs.gnu.org; 10 Sep 2023 17:23:45 +0000 Received: from localhost ([127.0.0.1]:51217 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfO9x-0001is-0x for submit@debbugs.gnu.org; Sun, 10 Sep 2023 13:23:45 -0400 Received: from lists.gnu.org ([2001:470:142::17]:36898) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfO9u-0001if-Oc for submit@debbugs.gnu.org; Sun, 10 Sep 2023 13:23:43 -0400 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 1qfO9l-0004M8-HD for bug-gnu-emacs@gnu.org; Sun, 10 Sep 2023 13:23:33 -0400 Received: from relay7-d.mail.gandi.net ([2001:4b98:dc4:8::227]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qfO9i-0004wN-D3 for bug-gnu-emacs@gnu.org; Sun, 10 Sep 2023 13:23:33 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 7DDEC20003 for ; Sun, 10 Sep 2023 17:23:24 +0000 (UTC) From: Juri Linkov To: bug-gnu-emacs@gnu.org Subject: Multi-file replacement diff Organization: LINKOV.NET Date: Sun, 10 Sep 2023 20:18:47 +0300 Message-ID: <86sf7mgd54.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-GND-Sasl: juri@linkov.net Received-SPF: pass client-ip=2001:4b98:dc4:8::227; envelope-from=juri@linkov.net; helo=relay7-d.mail.gandi.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: 0.7 (/) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.3 (/) --=-=-= Content-Type: text/plain Tags: patch As discussed on emacs-devel, here is the patch that implements a standalone command that reads a list of files and replacement strings, then shows a diff to review before applying replacements. Also provided the Dired integration to show the replacement diff on marked files. Later the same function could be used to show replacement diffs from the xref buffer and maybe from other packages as well. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=multi-file-replace-as-diff.patch diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 28513a2c61a..f27abc645bc 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -3655,6 +3655,20 @@ dired-do-query-replace-regexp delimited) (fileloop-continue)) +;;;###autoload +(defun dired-do-replace-regexp-as-diff (from to &optional delimited) + "Do `replace-regexp' of FROM with TO as diff, on all marked files. +Third arg DELIMITED (prefix arg) means replace only word-delimited matches." + (interactive + (let ((common + (query-replace-read-args + "Replace regexp as diff in marked files" t t))) + (list (nth 0 common) (nth 1 common) (nth 2 common)))) + (dired-post-do-command) + (multi-file-replace-regexp-as-diff + (dired-get-marked-files nil nil #'dired-nondirectory-p) + from to delimited)) + (declare-function xref-query-replace-in-results "xref") (declare-function project--files-in-directory "project") diff --git a/lisp/misearch.el b/lisp/misearch.el index 9ac28c26c48..da70d708a9e 100644 --- a/lisp/misearch.el +++ b/lisp/misearch.el @@ -387,6 +387,120 @@ multi-isearch-files-regexp (goto-char (if isearch-forward (point-min) (point-max))) (isearch-forward-regexp nil t))) + +;;; Global multi-file and multi-buffer replacements as diff + +(defun multi-file-diff-no-select (old new &optional switches buf label-old label-new) + ;; Based on `diff-no-select' tailored to multi-file diffs. + "Compare the OLD and NEW file/buffer. +If the optional SWITCHES is nil, the switches specified in the +variable `diff-switches' are passed to the diff command, +otherwise SWITCHES is used. SWITCHES can be a string or a list +of strings. BUF should be non-nil. LABEL-OLD and LABEL-NEW +specify labels to use for file names." + (unless (bufferp new) (setq new (expand-file-name new))) + (unless (bufferp old) (setq old (expand-file-name old))) + (or switches (setq switches diff-switches)) ; If not specified, use default. + (setq switches (ensure-list switches)) + (diff-check-labels) + (let* ((old-alt (diff-file-local-copy old)) + (new-alt (diff-file-local-copy new)) + (command + (mapconcat #'identity + `(,diff-command + ;; Use explicitly specified switches + ,@switches + ,@(mapcar #'shell-quote-argument + (nconc + (and (or old-alt new-alt) + (eq diff-use-labels t) + (list "--label" + (cond ((stringp label-old) label-old) + ((stringp old) old) + ((prin1-to-string old))) + "--label" + (cond ((stringp label-new) label-new) + ((stringp new) new) + ((prin1-to-string new))))) + (list (or old-alt old) + (or new-alt new))))) + " "))) + (with-current-buffer buf + (insert command "\n") + (call-process shell-file-name nil buf nil + shell-command-switch command) + (if old-alt (delete-file old-alt)) + (if new-alt (delete-file new-alt))))) + +(defun multi-file-replace-as-diff (files-or-buffers from-string replacements regexp-flag delimited-flag) + (require 'diff) + (let ((inhibit-message t) + (diff-buffer (get-buffer-create "*replace-diff*"))) + (with-current-buffer diff-buffer + (buffer-disable-undo (current-buffer)) + (let ((inhibit-read-only t)) + (erase-buffer)) + (diff-mode)) + (dolist (file-or-buffer files-or-buffers) + (let ((file-name (if (bufferp file-or-buffer) buffer-file-name file-or-buffer))) + (when file-name + (with-temp-buffer + (if (bufferp file-or-buffer) + (insert-buffer-substring file-or-buffer) + (insert-file-contents file-or-buffer)) + (goto-char (point-min)) + (perform-replace from-string replacements nil regexp-flag delimited-flag) + (multi-file-diff-no-select file-or-buffer (current-buffer) nil diff-buffer + (concat file-name "~") file-name))))) + (with-current-buffer diff-buffer + (setq-local buffer-read-only t) + (setq-local revert-buffer-function + (lambda (_ignore-auto _noconfirm) + (multi-file-replace-as-diff + files-or-buffers from-string replacements regexp-flag delimited-flag))) + (diff-setup-whitespace) + (font-lock-ensure) + (buffer-enable-undo (current-buffer)) + (goto-char (point-min))) + (pop-to-buffer diff-buffer))) + +;;;###autoload +(defun multi-file-replace-regexp-as-diff (files regexp to-string &optional delimited) + "Show replacements in FILES matching REGEXP with TO-STRING as diff. +With a prefix argument, ask for a wildcard, and replace in files +whose file names match the specified wildcard." + (interactive + (let ((files (if current-prefix-arg + (multi-isearch-read-matching-files) + (multi-isearch-read-files))) + (common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in files") + t t))) + (list files (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff files regexp to-string t delimited)) + +;;;###autoload +(defun multi-buffer-replace-regexp-as-diff (buffers regexp to-string &optional delimited) + "Show replacements in file BUFFERS matching REGEXP with TO-STRING as diff. +With a prefix argument, ask for a regexp, and replace in file buffers +whose names match the specified regexp." + (interactive + (let ((buffers (if current-prefix-arg + (multi-isearch-read-matching-buffers) + (multi-isearch-read-buffers))) + (common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in buffers") + t t))) + (list buffers (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff buffers regexp to-string t delimited)) + + (defvar unload-function-defs-list) (defun multi-isearch-unload-function () --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 10 13:58:19 2023 Received: (at 65854) by debbugs.gnu.org; 10 Sep 2023 17:58:20 +0000 Received: from localhost ([127.0.0.1]:51280 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfOhP-0005JV-IR for submit@debbugs.gnu.org; Sun, 10 Sep 2023 13:58:19 -0400 Received: from mail.eshelyaron.com ([107.175.124.16]:39852 helo=eshelyaron.com) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfOhN-0005JN-H8 for 65854@debbugs.gnu.org; Sun, 10 Sep 2023 13:58:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eshelyaron.com; s=mail; t=1694368693; bh=UVzQVteQZ54OtbjyJ6Rb5WeIzPtjDLN0gbi+/8aza2E=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=h0QVT2MxNCkg+HSABc+aMkMKyiNtCNv2ICNZTdFFY6nJxZtaNtKDNQ/SVLeAFUKER rBZ9A0ig8KNdwjY1+xq9XvBj1qrB92cLs75LBcirMMlHQc5q1OKaVMzhm3eqlY1Nf3 0qlc2HkIeqGLXo8DamPS1JvppwG54HcBHzjC/zvaHB9d/jAnOSDrL/ukQ7NTw8HAhV MGL1LK6VxzpS+NU9KTERdC4G483rtAozBdfnT5ufeKITI1bQKmwN/87EY9bjunfgN6 XTXz2nRqZapyhudHfnWIV4Nb0rnuf6MdnejQ97+XeO7tHJOAis5ERzXgPz9PdjFQ8m 0OyS2IWESnwYg== From: Eshel Yaron To: Juri Linkov Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <86sf7mgd54.fsf@mail.linkov.net> (Juri Linkov's message of "Sun, 10 Sep 2023 20:18:47 +0300") References: <86sf7mgd54.fsf@mail.linkov.net> X-Hashcash: 1:20:230910:juri@linkov.net::QlOl8StUJWtCWuKE:Hh7 X-Hashcash: 1:20:230910:65854@debbugs.gnu.org::kFScCU71+fm8+AFo:29/L Date: Sun, 10 Sep 2023 19:58:10 +0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi there, Juri Linkov writes: > +(defun multi-file-replace-as-diff (files-or-buffers from-string replacements regexp-flag delimited-flag) > + (require 'diff) > + (let ((inhibit-message t) > + (diff-buffer (get-buffer-create "*replace-diff*"))) > + (with-current-buffer diff-buffer > + (buffer-disable-undo (current-buffer)) > + (let ((inhibit-read-only t)) > + (erase-buffer)) > + (diff-mode)) > + (dolist (file-or-buffer files-or-buffers) > + (let ((file-name (if (bufferp file-or-buffer) buffer-file-name file-or-buffer))) > + (when file-name > + (with-temp-buffer > + (if (bufferp file-or-buffer) > + (insert-buffer-substring file-or-buffer) > + (insert-file-contents file-or-buffer)) I wonder what happens if I call `multi-file-replace-regexp-as-diff` and select a file `foo.txt`, that I already have open and modified in a buffer. IIUC, this will generate the diff based on the contents of the file on disk, not the buffer, so it might not match when I subsequently try to apply the diff to the buffer. WDYT? Eshel From debbugs-submit-bounces@debbugs.gnu.org Mon Sep 11 02:34:51 2023 Received: (at 65854) by debbugs.gnu.org; 11 Sep 2023 06:34:52 +0000 Received: from localhost ([127.0.0.1]:51950 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfaVX-0005sA-Kl for submit@debbugs.gnu.org; Mon, 11 Sep 2023 02:34:51 -0400 Received: from relay5-d.mail.gandi.net ([217.70.183.197]:50085) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfaVU-0005rv-BE for 65854@debbugs.gnu.org; Mon, 11 Sep 2023 02:34:50 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id AB00B1C0013; Mon, 11 Sep 2023 06:34:36 +0000 (UTC) From: Juri Linkov To: Eshel Yaron Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: (Eshel Yaron's message of "Sun, 10 Sep 2023 19:58:10 +0200") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> Date: Mon, 11 Sep 2023 09:33:06 +0300 Message-ID: <86bke943tp.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) >> +(defun multi-file-replace-as-diff (files-or-buffers from-string replacements regexp-flag delimited-flag) >> + (require 'diff) >> + (let ((inhibit-message t) >> + (diff-buffer (get-buffer-create "*replace-diff*"))) >> + (with-current-buffer diff-buffer >> + (buffer-disable-undo (current-buffer)) >> + (let ((inhibit-read-only t)) >> + (erase-buffer)) >> + (diff-mode)) >> + (dolist (file-or-buffer files-or-buffers) >> + (let ((file-name (if (bufferp file-or-buffer) buffer-file-name file-or-buffer))) >> + (when file-name >> + (with-temp-buffer >> + (if (bufferp file-or-buffer) >> + (insert-buffer-substring file-or-buffer) >> + (insert-file-contents file-or-buffer)) > > I wonder what happens if I call `multi-file-replace-regexp-as-diff` and > select a file `foo.txt`, that I already have open and modified in a > buffer. IIUC, this will generate the diff based on the contents of the > file on disk, not the buffer, so it might not match when I subsequently > try to apply the diff to the buffer. WDYT? For such cases you can use multi-buffer-replace-regexp-as-diff from this patch instead of multi-file-replace-regexp-as-diff. The former generates the diff based on the contents of the file in the buffer, the latter uses the contents on disk. From debbugs-submit-bounces@debbugs.gnu.org Mon Sep 11 03:23:49 2023 Received: (at 65854) by debbugs.gnu.org; 11 Sep 2023 07:23:49 +0000 Received: from localhost ([127.0.0.1]:52003 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfbGu-00075m-S9 for submit@debbugs.gnu.org; Mon, 11 Sep 2023 03:23:49 -0400 Received: from mail.eshelyaron.com ([107.175.124.16]:35022 helo=eshelyaron.com) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfbGr-00075c-Pq for 65854@debbugs.gnu.org; Mon, 11 Sep 2023 03:23:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eshelyaron.com; s=mail; t=1694417021; bh=Sqd6+Ss9GwogkUkq4PI3gHzAgTRIpKxKvhF1qQOcD4k=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=YW0OgPeCUkTLKzsIp0um3xPL6JSbIdLu6gBLM5O5GiKPLQf8KrCt/WC97DXOk2Xia 6xPUN2f9G+5PL6NZ+0LIENthkHAw50V+6K3EyqM8X/0d/gZjcUX6tDy6BZHz5wANAy OIpKm9nCCVtxdQU6KyTpGZ5V9bn7brAXy9ZrrvNYaQ1+rEj5TfD337pf5Dqr1HbjJ7 KsuCesM3XgxMjzxH5kPInIlhKsxF2n61Dw7mWPnNZ5OJOZcj2AVlVtkut4Uiha+B6V Dni60mtF8DKVtflBkIHMF6wLEUO706U4INnykTIyJvuVNLDZOAtcnoIbgjrvIUEM2Q YMkHMIWP2hNBg== From: Eshel Yaron To: Juri Linkov Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <86bke943tp.fsf@mail.linkov.net> (Juri Linkov's message of "Mon, 11 Sep 2023 09:33:06 +0300") References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> X-Hashcash: 1:20:230911:65854@debbugs.gnu.org::W+P1LiE+vnKK6EPx:ZxU X-Hashcash: 1:20:230911:juri@linkov.net::CqDqJGb0gI+nT4mo:4g5P Date: Mon, 11 Sep 2023 09:23:37 +0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi Juri, Juri Linkov writes: >>> +(defun multi-file-replace-as-diff (files-or-buffers from-string replacements regexp-flag delimited-flag) >>> + (require 'diff) >>> + (let ((inhibit-message t) >>> + (diff-buffer (get-buffer-create "*replace-diff*"))) >>> + (with-current-buffer diff-buffer >>> + (buffer-disable-undo (current-buffer)) >>> + (let ((inhibit-read-only t)) >>> + (erase-buffer)) >>> + (diff-mode)) >>> + (dolist (file-or-buffer files-or-buffers) >>> + (let ((file-name (if (bufferp file-or-buffer) buffer-file-name file-or-buffer))) >>> + (when file-name >>> + (with-temp-buffer >>> + (if (bufferp file-or-buffer) >>> + (insert-buffer-substring file-or-buffer) >>> + (insert-file-contents file-or-buffer)) >> >> I wonder what happens if I call `multi-file-replace-regexp-as-diff` and >> select a file `foo.txt`, that I already have open and modified in a >> buffer. IIUC, this will generate the diff based on the contents of the >> file on disk, not the buffer, so it might not match when I subsequently >> try to apply the diff to the buffer. WDYT? > > For such cases you can use multi-buffer-replace-regexp-as-diff > from this patch instead of multi-file-replace-regexp-as-diff. Well, in the simple example of one file, yes that possible, but the point is that you don't always know (or worry about) whether there's an overlap between the files you have open and modified and the files your regexp/wildcard matches. Let's say I'm editing an HTML file, and find something that I'd like to change. So I do it. Than I think "actually, let's change that across all my HTML files in this directory". IMO It would be great if I could use this new command, `multi-file-replace-regexp-as-diff`, to get a diff showing how that'd look. But in the proposed implementation, that won't work if one of those HTML files is open and modified--without any warning, Emacs would create a diff that doesn't apply. > The former generates the diff based on the contents of the > file in the buffer, the latter uses the contents on disk. Yes, but what is the use case for generating the diff based on the contents on disk when the file is modified in Emacs? Basically, my suggestion is to check in `multi-file-replace-regexp-as-diff` if any of the matching files are visited by some buffer, and if so simply pass the buffer instead of the file name for that file to `multi-file-replace-as-diff`. That way you always get an up-to-date diff, and you don't need to manually check that you don't have any of the matching files open by any chance. Does that make sense? From debbugs-submit-bounces@debbugs.gnu.org Mon Sep 11 03:40:36 2023 Received: (at 65854) by debbugs.gnu.org; 11 Sep 2023 07:40:36 +0000 Received: from localhost ([127.0.0.1]:52020 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfbXA-0007UH-5B for submit@debbugs.gnu.org; Mon, 11 Sep 2023 03:40:36 -0400 Received: from relay7-d.mail.gandi.net ([2001:4b98:dc4:8::227]:34227) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfbX4-0007Tx-R7 for 65854@debbugs.gnu.org; Mon, 11 Sep 2023 03:40:33 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 639B320016; Mon, 11 Sep 2023 07:40:16 +0000 (UTC) From: Juri Linkov To: Eshel Yaron Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: (Eshel Yaron's message of "Mon, 11 Sep 2023 09:23:37 +0200") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> Date: Mon, 11 Sep 2023 10:38:56 +0300 Message-ID: <86zg1t2m7j.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) > Yes, but what is the use case for generating the diff based on the > contents on disk when the file is modified in Emacs? Basically, my > suggestion is to check in `multi-file-replace-regexp-as-diff` if any of > the matching files are visited by some buffer, and if so simply pass the > buffer instead of the file name for that file to > `multi-file-replace-as-diff`. That way you always get an up-to-date > diff, and you don't need to manually check that you don't have any of > the matching files open by any chance. Does that make sense? Thanks for the idea, this makes sense and will help to reduce the number of commands from 2 to 1 by merging multi-buffer-replace-regexp-as-diff with multi-file-replace-regexp-as-diff. From debbugs-submit-bounces@debbugs.gnu.org Mon Sep 11 08:36:17 2023 Received: (at 65854) by debbugs.gnu.org; 11 Sep 2023 12:36:17 +0000 Received: from localhost ([127.0.0.1]:52304 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfg9I-0003QV-OS for submit@debbugs.gnu.org; Mon, 11 Sep 2023 08:36:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59312) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfg9G-0003QG-Os for 65854@debbugs.gnu.org; Mon, 11 Sep 2023 08:36:16 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qfg96-00044C-9M; Mon, 11 Sep 2023 08:36:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=SMpcmKLjbJzv16dCwUtiH428P/PhrWfP0ENyBkGZG1M=; b=LMZe2jeDCjTz doQ3UmyaDHSrn/5CwktfUVDraOCp1FJb8ZJM1f7g7TdD6Omd0aNxWCI9/M8GGQkTTlCGc6q3dDDnh HJtTFy9kkT81xK6NyvLBzvugvIPzf06QcPQOXbk1rTm9eT1F71jjlxtcCDZcLwA5XwvOgl8lSgWLj ERgutnOBeYbN9KFMyjIvAzpz/MJhK+wyFKiokH8EBdjT2LbNBpwMfNWunzsIbbpqg3k+ECFV3ZByl cID9nov2/PAB5woJEzazf7X0ODzuwdGr7V9TpdLTZdNIXkNy543+nmmuFC99cYDfuOiuEdyTy00yu iMZhvtqB/MQjCX9tqCxirQ==; Date: Mon, 11 Sep 2023 15:35:47 +0300 Message-Id: <83jzswrios.fsf@gnu.org> From: Eli Zaretskii To: Eshel Yaron In-Reply-To: (bug-gnu-emacs@gnu.org) Subject: Re: bug#65854: Multi-file replacement diff References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org, juri@linkov.net X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > Cc: 65854@debbugs.gnu.org > Date: Mon, 11 Sep 2023 09:23:37 +0200 > From: Eshel Yaron via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" > > >> I wonder what happens if I call `multi-file-replace-regexp-as-diff` and > >> select a file `foo.txt`, that I already have open and modified in a > >> buffer. IIUC, this will generate the diff based on the contents of the > >> file on disk, not the buffer, so it might not match when I subsequently > >> try to apply the diff to the buffer. WDYT? > > > > For such cases you can use multi-buffer-replace-regexp-as-diff > > from this patch instead of multi-file-replace-regexp-as-diff. > > Well, in the simple example of one file, yes that possible, but the > point is that you don't always know (or worry about) whether there's an > overlap between the files you have open and modified and the files your > regexp/wildcard matches. Let's say I'm editing an HTML file, and find > something that I'd like to change. So I do it. Than I think "actually, > let's change that across all my HTML files in this directory". IMO It > would be great if I could use this new command, > `multi-file-replace-regexp-as-diff`, to get a diff showing how that'd > look. But in the proposed implementation, that won't work if one of > those HTML files is open and modified--without any warning, Emacs would > create a diff that doesn't apply. Our usual paradigm for these commands is to offer saving any buffers with unsaved edits, before running the main part of the command. From debbugs-submit-bounces@debbugs.gnu.org Tue Sep 12 03:30:44 2023 Received: (at 65854) by debbugs.gnu.org; 12 Sep 2023 07:30:44 +0000 Received: from localhost ([127.0.0.1]:55968 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfxr9-0006WA-Sg for submit@debbugs.gnu.org; Tue, 12 Sep 2023 03:30:44 -0400 Received: from relay1-d.mail.gandi.net ([2001:4b98:dc4:8::221]:38875) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfxr7-0006Vu-W3 for 65854@debbugs.gnu.org; Tue, 12 Sep 2023 03:30:42 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 2CB06240048; Tue, 12 Sep 2023 07:29:24 +0000 (UTC) From: Juri Linkov To: Eshel Yaron Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <86zg1t2m7j.fsf@mail.linkov.net> (Juri Linkov's message of "Mon, 11 Sep 2023 10:38:56 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <86zg1t2m7j.fsf@mail.linkov.net> Date: Tue, 12 Sep 2023 09:49:17 +0300 Message-ID: <86bke7q34y.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) >> Yes, but what is the use case for generating the diff based on the >> contents on disk when the file is modified in Emacs? Basically, my >> suggestion is to check in `multi-file-replace-regexp-as-diff` if any of >> the matching files are visited by some buffer, and if so simply pass the >> buffer instead of the file name for that file to >> `multi-file-replace-as-diff`. That way you always get an up-to-date >> diff, and you don't need to manually check that you don't have any of >> the matching files open by any chance. Does that make sense? > > Thanks for the idea, this makes sense and will help to > reduce the number of commands from 2 to 1 by merging > multi-buffer-replace-regexp-as-diff with > multi-file-replace-regexp-as-diff. Actually, separate commands are still needed when we will add a command to show replacement diffs on the buffers marked on the buffer list from M-x list-buffers. But it seems we can't avoid the limitation that such buffers should be file-visiting. I see no way to generate a diff for non-file buffers because 'C-c C-a' from diff-mode needs a file name to apply the hunk to the file buffer. Also another useful command that probably will be used the most often is to show a replacement diff for the current buffer as a counterpart of query-replace: ``` diff --git a/lisp/misearch.el b/lisp/misearch.el index da70d708a9e..9aa639af5fe 100644 --- a/lisp/misearch.el +++ b/lisp/misearch.el @@ -500,6 +501,22 @@ multi-buffer-replace-regexp-as-diff (list buffers (nth 0 common) (nth 1 common) (nth 2 common)))) (multi-file-replace-as-diff buffers regexp to-string t delimited)) +;;;###autoload +(defun replace-regexp-as-diff (regexp to-string &optional delimited) + "Show replacements in the current file buffer matching REGEXP with TO-STRING as diff. +With a prefix argument, ask for a regexp, and replace in file buffers +whose names match the specified regexp." + (interactive + (let ((common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in buffers") + t t))) + (list (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff + (list (current-buffer)) regexp to-string t delimited)) + (defvar unload-function-defs-list) ``` From debbugs-submit-bounces@debbugs.gnu.org Tue Sep 12 03:32:11 2023 Received: (at 65854) by debbugs.gnu.org; 12 Sep 2023 07:32:11 +0000 Received: from localhost ([127.0.0.1]:55972 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfxsZ-0006YW-Cy for submit@debbugs.gnu.org; Tue, 12 Sep 2023 03:32:11 -0400 Received: from relay5-d.mail.gandi.net ([2001:4b98:dc4:8::225]:53721) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qfxsX-0006YI-Je for 65854@debbugs.gnu.org; Tue, 12 Sep 2023 03:32:10 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id D98811C0030; Tue, 12 Sep 2023 07:30:32 +0000 (UTC) From: Juri Linkov To: Eli Zaretskii Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <83jzswrios.fsf@gnu.org> (Eli Zaretskii's message of "Mon, 11 Sep 2023 15:35:47 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> Date: Tue, 12 Sep 2023 09:52:42 +0300 Message-ID: <86o7i7oo9t.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: Eshel Yaron , 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) >> Well, in the simple example of one file, yes that possible, but the >> point is that you don't always know (or worry about) whether there's an >> overlap between the files you have open and modified and the files your >> regexp/wildcard matches. Let's say I'm editing an HTML file, and find >> something that I'd like to change. So I do it. Than I think "actually, >> let's change that across all my HTML files in this directory". IMO It >> would be great if I could use this new command, >> `multi-file-replace-regexp-as-diff`, to get a diff showing how that'd >> look. But in the proposed implementation, that won't work if one of >> those HTML files is open and modified--without any warning, Emacs would >> create a diff that doesn't apply. > > Our usual paradigm for these commands is to offer saving any buffers > with unsaved edits, before running the main part of the command. I don't know if users will find this too annoying, maybe not, but probably this is what should be done to solve such dilemma that the same diff can be used in two ways: by applying the diff to the buffers with 'C-c C-a', or by applying to the files with 'git apply'. Without saving the buffers before running the command, either will fail: 'C-c C-a' will fail on changes produced from files, 'git apply' will fail on changes produced from unsaved buffers. From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 15 02:47:04 2023 Received: (at 65854) by debbugs.gnu.org; 15 Sep 2023 06:47:04 +0000 Received: from localhost ([127.0.0.1]:41882 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh2bX-0005gf-Cw for submit@debbugs.gnu.org; Fri, 15 Sep 2023 02:47:04 -0400 Received: from relay3-d.mail.gandi.net ([217.70.183.195]:49287) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh2bR-0005fc-Rj for 65854@debbugs.gnu.org; Fri, 15 Sep 2023 02:46:59 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 66F1260005; Fri, 15 Sep 2023 06:46:43 +0000 (UTC) From: Juri Linkov To: Eli Zaretskii Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <86o7i7oo9t.fsf@mail.linkov.net> (Juri Linkov's message of "Tue, 12 Sep 2023 09:52:42 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> Date: Fri, 15 Sep 2023 09:40:21 +0300 Message-ID: <86sf7g548a.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: Eshel Yaron , 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --=-=-= Content-Type: text/plain > I don't know if users will find this too annoying, maybe not, > but probably this is what should be done to solve such dilemma that > the same diff can be used in two ways: by applying the diff to the > buffers with 'C-c C-a', or by applying to the files with 'git apply'. > Without saving the buffers before running the command, either > will fail: 'C-c C-a' will fail on changes produced from files, > 'git apply' will fail on changes produced from unsaved buffers. Here is a new customizable option 'multi-file-diff-unsaved' that defines what to do with unsaved changes. When it is 'use-buffer' then it handles the case Eshel demonstrated where changes are applied over unsaved buffers. But when the value is 'save-buffers', then 'save-some-buffers' is called before producing the diff. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=multi-file-diff-unsaved.patch diff --git a/lisp/misearch.el b/lisp/misearch.el index 9ac28c26c48..23872335c2d 100644 --- a/lisp/misearch.el +++ b/lisp/misearch.el @@ -387,6 +387,160 @@ multi-isearch-files-regexp (goto-char (if isearch-forward (point-min) (point-max))) (isearch-forward-regexp nil t))) + +;;; Global multi-file and multi-buffer replacements as diff + +(defcustom multi-file-diff-unsaved 'use-file + "A choice defining what to do with unsaved changes. +If the value is `use-file', use text from the file. +If the value is `use-buffer', use text from the file-visiting buffer +to be able to use unsaved changes. However, when the file is +not visited in a buffer, read contents from the file. +If the value is `save-buffers', save unsaved buffers before creating diff." + :type '(choice + (const :tag "Use file" use-file) + (const :tag "Use buffer" use-buffer) + (const :tag "Save buffers" save-buffers)) + :version "30.1") + +(defun multi-file-replace-as-diff (files-or-buffers from-string replacements regexp-flag delimited-flag) + (require 'diff) + (let ((inhibit-message t) + (diff-buffer (get-buffer-create "*replace-diff*"))) + (when (eq multi-file-diff-unsaved 'save-buffers) + (save-some-buffers t (lambda () + (seq-some (lambda (f-or-b) + (if (bufferp f-or-b) + (eq f-or-b (current-buffer)) + (equal f-or-b (buffer-file-name)))) + files-or-buffers)))) + (with-current-buffer diff-buffer + (setq-local buffer-read-only t) + (erase-buffer) + (diff-mode) + (setq-local buffer-read-only nil) + (buffer-disable-undo (current-buffer))) + (dolist (file-or-buffer files-or-buffers) + (let ((file-name (if (bufferp file-or-buffer) buffer-file-name file-or-buffer))) + (when file-name + (with-temp-buffer + (if (bufferp file-or-buffer) + (insert-buffer-substring file-or-buffer) + (if (or (eq multi-file-diff-unsaved 'use-file) + (not (find-buffer-visiting file-or-buffer))) + (insert-file-contents file-or-buffer) + (insert-buffer-substring (find-buffer-visiting file-or-buffer)))) + (goto-char (point-min)) + (perform-replace from-string replacements nil regexp-flag delimited-flag) + (multi-file-diff-no-select file-or-buffer (current-buffer) nil diff-buffer + (concat file-name "~") file-name))))) + (with-current-buffer diff-buffer + (diff-setup-whitespace) + (font-lock-ensure) + (buffer-enable-undo (current-buffer)) + (setq-local buffer-read-only t) + (setq-local revert-buffer-function + (lambda (_ignore-auto _noconfirm) + (multi-file-replace-as-diff + files-or-buffers from-string replacements regexp-flag delimited-flag))) + (goto-char (point-min))) + (pop-to-buffer diff-buffer))) + +(defun multi-file-diff-no-select (old new &optional switches buf label-old label-new) + ;; Based on `diff-no-select' tailored to multi-file diffs. + "Compare the OLD and NEW file/buffer. +If the optional SWITCHES is nil, the switches specified in the +variable `diff-switches' are passed to the diff command, +otherwise SWITCHES is used. SWITCHES can be a string or a list +of strings. BUF should be non-nil. LABEL-OLD and LABEL-NEW +specify labels to use for file names." + (unless (bufferp new) (setq new (expand-file-name new))) + (unless (bufferp old) (setq old (expand-file-name old))) + (or switches (setq switches diff-switches)) ; If not specified, use default. + (setq switches (ensure-list switches)) + (diff-check-labels) + (let* ((old-alt (diff-file-local-copy old)) + (new-alt (diff-file-local-copy new)) + (command + (mapconcat #'identity + `(,diff-command + ;; Use explicitly specified switches + ,@switches + ,@(mapcar #'shell-quote-argument + (nconc + (and (or old-alt new-alt) + (eq diff-use-labels t) + (list "--label" + (cond ((stringp label-old) label-old) + ((stringp old) old) + ((prin1-to-string old))) + "--label" + (cond ((stringp label-new) label-new) + ((stringp new) new) + ((prin1-to-string new))))) + (list (or old-alt old) + (or new-alt new))))) + " "))) + (with-current-buffer buf + (insert command "\n") + (call-process shell-file-name nil buf nil + shell-command-switch command) + (if old-alt (delete-file old-alt)) + (if new-alt (delete-file new-alt))))) + +;;;###autoload +(defun multi-file-replace-regexp-as-diff (files regexp to-string &optional delimited) + "Show replacements in FILES matching REGEXP with TO-STRING as diff. +With a prefix argument, ask for a wildcard, and replace in files +whose file names match the specified wildcard." + (interactive + (let ((files (if current-prefix-arg + (multi-isearch-read-matching-files) + (multi-isearch-read-files))) + (common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in files") + t t))) + (list files (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff files regexp to-string t delimited)) + +;;;###autoload +(defun multi-buffer-replace-regexp-as-diff (buffers regexp to-string &optional delimited) + "Show replacements in file BUFFERS matching REGEXP with TO-STRING as diff. +With a prefix argument, ask for a regexp, and replace in file buffers +whose names match the specified regexp." + (interactive + (let ((buffers (if current-prefix-arg + (multi-isearch-read-matching-buffers) + (multi-isearch-read-buffers))) + (common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in buffers") + t t))) + (list buffers (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff buffers regexp to-string t delimited)) + +;;;###autoload +(defun replace-regexp-as-diff (regexp to-string &optional delimited) + "Show replacements in the current file buffer matching REGEXP with TO-STRING as diff. +With a prefix argument, ask for a regexp, and replace in file buffers +whose names match the specified regexp." + (interactive + (let ((common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in buffers") + t t))) + (list (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff + (list (current-buffer)) regexp to-string t delimited)) + + (defvar unload-function-defs-list) (defun multi-isearch-unload-function () --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 15 03:03:09 2023 Received: (at 65854) by debbugs.gnu.org; 15 Sep 2023 07:03:09 +0000 Received: from localhost ([127.0.0.1]:41911 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh2r7-0006Ci-3g for submit@debbugs.gnu.org; Fri, 15 Sep 2023 03:03:09 -0400 Received: from mail.eshelyaron.com ([107.175.124.16]:58060 helo=eshelyaron.com) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh2r3-0006CY-A6 for 65854@debbugs.gnu.org; Fri, 15 Sep 2023 03:03:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eshelyaron.com; s=mail; t=1694761378; bh=51QncFo91TLcdFOWfTGjBzjJ8dS8m3dZvwAVaCeg+qU=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=E++lUUXB8PDWBv/MC0OBS+woqvAVlNV/fFqNfip5JQdyS2K4ZJSS6eMTEO5vyz4ES WbuPG9nYiqeBDZVkFjlD+wIAFWF7/GIDhfXWwXeKEVQ4Vr11UeOlWGe2QfjPSKeAEW wFdoZAP3V/U8GUo5Mgz2Himlpgl8NXS9iBkdZ5VKJhsKKlQyzAr1WiQeSk9rluefoO g615293EgQLNTEauVC6mtv4QweHHtm/ygpJM2Y1QKHviKNKfhrKzrh+5ZvGdk3WwLr atUkyEd0S4G1uxqKuFmAamMq6lUVaTvM1FOMty4enoz1UCqI869uQM5D5TPj00G91I 85fTpnL5imU6A== From: Eshel Yaron To: Juri Linkov Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <86sf7g548a.fsf@mail.linkov.net> (Juri Linkov's message of "Fri, 15 Sep 2023 09:40:21 +0300") References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> X-Hashcash: 1:20:230915:juri@linkov.net::fDONZvwZq2EMDdJp:094k X-Hashcash: 1:20:230915:eliz@gnu.org::ko371C5XcruTxXw2:3HBt X-Hashcash: 1:20:230915:65854@debbugs.gnu.org::NHoZajfUuiCgNqkw:BEMK Date: Fri, 15 Sep 2023 09:02:55 +0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 65854 Cc: Eli Zaretskii , 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Juri Linkov writes: > > Here is a new customizable option 'multi-file-diff-unsaved' > that defines what to do with unsaved changes. When it is > 'use-buffer' then it handles the case Eshel demonstrated > where changes are applied over unsaved buffers. But when > the value is 'save-buffers', then 'save-some-buffers' is > called before producing the diff. > Nice! One thought about the default choice: > +(defcustom multi-file-diff-unsaved 'use-file I wonder if it wouldn't be better to use save-buffers by default, ISTM that it's the "least surprising" choice. Cheers, Eshel From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 15 03:38:45 2023 Received: (at 65854) by debbugs.gnu.org; 15 Sep 2023 07:38:45 +0000 Received: from localhost ([127.0.0.1]:41955 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh3PY-0007BV-RM for submit@debbugs.gnu.org; Fri, 15 Sep 2023 03:38:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:49460) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh3PW-0007BG-Cg for 65854@debbugs.gnu.org; Fri, 15 Sep 2023 03:38:43 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qh3PK-0008PQ-Ko; Fri, 15 Sep 2023 03:38:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=/m05aJgJ12VXpWtBSkQTk1TTxPL6OPNWly/I+SEsXZs=; b=EtnI4W2VjZAb MDTLXJ2+r47vn9f6i384IPyLA/eu/pf6aPi7eiln7xKIUNOp5j1aUjRju0B2mm1hkcECYrT2KjtuV HclpRn+UJTrUHAmNUkZJQYbrhKzlDU5WUeUIJneX/sXM1Zfv2XFx2+7eQP856+ujgy/KUkL+prhhG Df/Dy7vKIQW4wavCEzIk88U++A1W8T/6h2GysOtRA3v2M3Us58f5GPPmLnWMOo/Fad5nPwm7KQviX EOfImnwlewEbo8X0/9sGDAp9keAKxumDvf5nmJ1ScUrdVVg/oI+12Yxumam7HPtCqyxyYxgi1Bqp4 3SQRZ/NG+/YJM+lzE21HQw==; Date: Fri, 15 Sep 2023 10:38:23 +0300 Message-Id: <83pm2jkhsg.fsf@gnu.org> From: Eli Zaretskii To: Juri Linkov In-Reply-To: <86sf7g548a.fsf@mail.linkov.net> (message from Juri Linkov on Fri, 15 Sep 2023 09:40:21 +0300) Subject: Re: bug#65854: Multi-file replacement diff References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Juri Linkov > Cc: Eshel Yaron , 65854@debbugs.gnu.org > Date: Fri, 15 Sep 2023 09:40:21 +0300 > > +(defcustom multi-file-diff-unsaved 'use-file > + "A choice defining what to do with unsaved changes. This first sentence is too general. I suggest What to do with unsaved edits when showing multi-file replacements as diffs. > +(defun multi-file-replace-regexp-as-diff (files regexp to-string &optional delimited) > + "Show replacements in FILES matching REGEXP with TO-STRING as diff. Show as diffs replacements of REGEXP with TO-STRING in FILES. > +With a prefix argument, ask for a wildcard, and replace in files "replace"? Does this command perform replacements or just shows them as diffs? The first sentence seems to convey the latter. > +(defun multi-buffer-replace-regexp-as-diff (buffers regexp to-string &optional delimited) > + "Show replacements in file BUFFERS matching REGEXP with TO-STRING as diff. > +With a prefix argument, ask for a regexp, and replace in file buffers > +whose names match the specified regexp." Same comments here. > +(defun replace-regexp-as-diff (regexp to-string &optional delimited) > + "Show replacements in the current file buffer matching REGEXP with TO-STRING as diff. > +With a prefix argument, ask for a regexp, and replace in file buffers > +whose names match the specified regexp." And here. Thanks. From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 15 06:53:21 2023 Received: (at control) by debbugs.gnu.org; 15 Sep 2023 10:53:21 +0000 Received: from localhost ([127.0.0.1]:42230 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh6Rt-0004OL-JL for submit@debbugs.gnu.org; Fri, 15 Sep 2023 06:53:21 -0400 Received: from mail-lj1-x229.google.com ([2a00:1450:4864:20::229]:48619) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qh6Rr-0004Nv-Mo for control@debbugs.gnu.org; Fri, 15 Sep 2023 06:53:20 -0400 Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-2bceb02fd2bso31353641fa.1 for ; Fri, 15 Sep 2023 03:53:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1694775187; x=1695379987; darn=debbugs.gnu.org; h=to:subject:message-id:date:mime-version:from:from:to:cc:subject :date:message-id:reply-to; bh=duLdV4Xdr26LXwAVlC+lxW8DdL5QZTVQGCWPEF/X4mE=; b=Zz1RwXhKLryK0Qjx4qtX/dFHkuCi/BVhjf8H8fsQnbDimsk/RthkXk8el3kcym73G2 CGHPOOL0e05FHzj6RCZsFanOfsqryYUuDMzP/h1NGI4WYpRQ5CriZmqIMGjWmbdO6f91 7y2ZsJW1LIwp6VFPmt3PTSNFHI1eI2uDMkQAyFoKsaqOzcFreuHC4AV09RE65JUayRy7 63+yMSbH9Jr8C8gYb4xllTcoEudym7NcbXLsSOuHFV6gPymfJCi25j5aU8vePC5Ig9mz sRAK9VNjKd1yfqyDoE4HP+tnuQSxO7cpVOZyYwb/cHn9EnrYOkH36AztbBslFW/cv2EL dS4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694775187; x=1695379987; h=to:subject:message-id:date:mime-version:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=duLdV4Xdr26LXwAVlC+lxW8DdL5QZTVQGCWPEF/X4mE=; b=WEpwHqlrBSe59d5QgjfJy5q3MXhgiWEE7ee6WGoj2SKzzyephqPUc/Pf3PwdjbU1jJ tGc3EQBZpfQaZx3ahGEfKDKDhqVuLIbkrrOnMLI7BTijqABbqopeGqMh6UtkgWAiTqXc 3WXSGYhKO6Ronav6F0pdTy/MF8adycxMxYX4wmBn8srPu4IFl58ZJaVOM+xW6K7oOcDy tOTV286c5clrWCq6kDoQWp9F3nbXvK6eVq8+cDbPnwZKEEbVAzBbhm6AK9iaAcVJE3RE dG+LYAcPU7wwCxJ4xp/GN7mpAh31DDs8UhtBOIlOOeAk033Vy9wcHckgDFHQplaFPPL7 sDmg== X-Gm-Message-State: AOJu0Ywy/VoBN7G4TTEJsIxkO966Cyc2g70nZ61GA0R5vqlRcXt40uqf snmIMYKo5ndeAffnIdb5y+iiV7Df8PpK310Xmmn1hMKl X-Google-Smtp-Source: AGHT+IFBBpe9wlJV7rrqCq7evOUvupOnGylC30/Sjv17RI448nbrEz4bGCYbn0Hm2dLyXY0einma1m8Z+JbspDoXXAc= X-Received: by 2002:a2e:875a:0:b0:2bc:beac:53e7 with SMTP id q26-20020a2e875a000000b002bcbeac53e7mr1301367ljj.14.1694775187415; Fri, 15 Sep 2023 03:53:07 -0700 (PDT) Received: from 753933720722 named unknown by gmailapi.google.com with HTTPREST; Fri, 15 Sep 2023 03:53:07 -0700 From: Stefan Kangas MIME-Version: 1.0 Date: Fri, 15 Sep 2023 03:53:07 -0700 Message-ID: Subject: control message for bug #65854 To: control@debbugs.gnu.org Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) severity 65854 wishlist quit From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 22 03:09:51 2023 Received: (at 65854) by debbugs.gnu.org; 22 Sep 2023 07:09:51 +0000 Received: from localhost ([127.0.0.1]:35191 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjaIQ-0008Vo-C0 for submit@debbugs.gnu.org; Fri, 22 Sep 2023 03:09:51 -0400 Received: from relay8-d.mail.gandi.net ([2001:4b98:dc4:8::228]:46559) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjaIJ-0008V8-Gd for 65854@debbugs.gnu.org; Fri, 22 Sep 2023 03:09:44 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id E890B1BF20E; Fri, 22 Sep 2023 07:09:24 +0000 (UTC) From: Juri Linkov To: Eli Zaretskii Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <83pm2jkhsg.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 15 Sep 2023 10:38:23 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> Date: Fri, 22 Sep 2023 09:55:40 +0300 Message-ID: <86msxeu1q3.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --=-=-= Content-Type: text/plain >> +(defcustom multi-file-diff-unsaved 'use-file >> + "A choice defining what to do with unsaved changes. > > This first sentence is too general. I suggest > > What to do with unsaved edits when showing multi-file replacements as diffs. Fixed, and changed the default to 'save-buffers' like Eshel suggested. >> +(defun multi-file-replace-regexp-as-diff (files regexp to-string &optional delimited) >> + "Show replacements in FILES matching REGEXP with TO-STRING as diff. > > Show as diffs replacements of REGEXP with TO-STRING in FILES. Fixed with more small changes: --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=multi-file-diff-unsaved.patch diff --git a/lisp/misearch.el b/lisp/misearch.el index 9ac28c26c48..44023d029d9 100644 --- a/lisp/misearch.el +++ b/lisp/misearch.el @@ -387,6 +387,148 @@ multi-isearch-files-regexp (goto-char (if isearch-forward (point-min) (point-max))) (isearch-forward-regexp nil t))) + +;;; Global multi-file and multi-buffer replacements as diff + +(defcustom multi-file-diff-unsaved 'save-buffers + "What to do with unsaved edits when showing multi-file replacements as diffs. +If the value is `save-buffers', save unsaved buffers before creating diff. +If the value is `use-file', use text from the file even when the visiting +file buffer is modified. +If the value is `use-modified-buffer', use text from the file-visiting +modified buffer to be able to use unsaved changes. However, when the file +is not visited in a buffer, or the buffer is not modified, still read +contents from the file." + :type '(choice + (const :tag "Save buffers" save-buffers) + (const :tag "Use file" use-file) + (const :tag "Use modified buffer" use-modified-buffer)) + :version "30.1") + +(defun multi-file-replace-as-diff (files-or-buffers from-string replacements regexp-flag delimited-flag) + "Show as diffs replacements of FROM-STRING with REPLACEMENTS. +FILES-OR-BUFFERS is a list of either file names or buffers. +REGEXP-FLAG and DELIMITED-FLAG have the same meaning as in `perform-replace'." + (require 'diff) + (let ((inhibit-message t) + (diff-buffer (get-buffer-create "*replace-diff*"))) + (when (eq multi-file-diff-unsaved 'save-buffers) + (save-some-buffers t (lambda () + (seq-some (lambda (f-or-b) + (if (bufferp f-or-b) + (eq f-or-b (current-buffer)) + (equal f-or-b (buffer-file-name)))) + files-or-buffers)))) + (with-current-buffer diff-buffer + (setq-local buffer-read-only t) + (erase-buffer) + (diff-mode) + (setq-local buffer-read-only nil) + (buffer-disable-undo (current-buffer))) + (dolist (file-or-buffer files-or-buffers) + (let ((file-name (if (bufferp file-or-buffer) buffer-file-name file-or-buffer)) + (file-buffer (when (eq multi-file-diff-unsaved 'use-modified-buffer) + (find-buffer-visiting file-or-buffer)))) + (when file-name + (with-temp-buffer + (if (bufferp file-or-buffer) + (insert-buffer-substring file-or-buffer) + (if (and file-buffer (buffer-modified-p file-buffer)) + (insert-buffer-substring file-buffer) + (insert-file-contents file-or-buffer))) + (goto-char (point-min)) + (perform-replace from-string replacements nil regexp-flag delimited-flag) + (multi-file-diff-no-select file-or-buffer (current-buffer) nil diff-buffer + (concat file-name "~") file-name))))) + (with-current-buffer diff-buffer + (diff-setup-whitespace) + (font-lock-ensure) + (buffer-enable-undo (current-buffer)) + (setq-local buffer-read-only t) + (setq-local revert-buffer-function + (lambda (_ignore-auto _noconfirm) + (multi-file-replace-as-diff + files-or-buffers from-string replacements regexp-flag delimited-flag))) + (goto-char (point-min))) + (pop-to-buffer diff-buffer))) + +;;;###autoload +(defun multi-file-replace-regexp-as-diff (files regexp to-string &optional delimited) + "Show as diffs replacements of REGEXP with TO-STRING in FILES. +DELIMITED has the same meaning as in `replace-regexp'. +With a prefix argument, ask for a wildcard, and show diffs for files +whose file names match the specified wildcard." + (interactive + (let ((files (if current-prefix-arg + (multi-isearch-read-matching-files) + (multi-isearch-read-files))) + (common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in files") + t t))) + (list files (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff files regexp to-string t delimited)) + +;;;###autoload +(defun replace-regexp-as-diff (regexp to-string &optional delimited) + "Show as diffs replacements of REGEXP with TO-STRING in the current buffer. +DELIMITED has the same meaning as in `replace-regexp'." + (interactive + (let ((common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff") + t t))) + (list (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff + (list (current-buffer)) regexp to-string t delimited)) + +(defun multi-file-diff-no-select (old new &optional switches buf label-old label-new) + ;; Based on `diff-no-select' tailored to multi-file diffs. + "Compare the OLD and NEW file/buffer. +If the optional SWITCHES is nil, the switches specified in the +variable `diff-switches' are passed to the diff command, +otherwise SWITCHES is used. SWITCHES can be a string or a list +of strings. BUF should be non-nil. LABEL-OLD and LABEL-NEW +specify labels to use for file names." + (unless (bufferp new) (setq new (expand-file-name new))) + (unless (bufferp old) (setq old (expand-file-name old))) + (or switches (setq switches diff-switches)) ; If not specified, use default. + (setq switches (ensure-list switches)) + (diff-check-labels) + (let* ((old-alt (diff-file-local-copy old)) + (new-alt (diff-file-local-copy new)) + (command + (mapconcat #'identity + `(,diff-command + ;; Use explicitly specified switches + ,@switches + ,@(mapcar #'shell-quote-argument + (nconc + (and (or old-alt new-alt) + (eq diff-use-labels t) + (list "--label" + (cond ((stringp label-old) label-old) + ((stringp old) old) + ((prin1-to-string old))) + "--label" + (cond ((stringp label-new) label-new) + ((stringp new) new) + ((prin1-to-string new))))) + (list (or old-alt old) + (or new-alt new))))) + " "))) + (with-current-buffer buf + (insert command "\n") + (call-process shell-file-name nil buf nil + shell-command-switch command) + (if old-alt (delete-file old-alt)) + (if new-alt (delete-file new-alt))))) + + (defvar unload-function-defs-list) (defun multi-isearch-unload-function () --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 22 03:25:36 2023 Received: (at 65854) by debbugs.gnu.org; 22 Sep 2023 07:25:36 +0000 Received: from localhost ([127.0.0.1]:35213 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjaXg-0000T3-Bj for submit@debbugs.gnu.org; Fri, 22 Sep 2023 03:25:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35336) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjaXd-0000Sq-QH for 65854@debbugs.gnu.org; Fri, 22 Sep 2023 03:25:34 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qjaXM-0003QM-PA; Fri, 22 Sep 2023 03:25:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=DtBlSdIOLFH4VvqJVeASe2Y5ykpWKNW966Fq+QzSaIE=; b=ijN2RbvsW/Mt B9XOtt/NpmcIbFcl7ZsjKpTQiH26FVVn15eSzEqftDgWISq1V5AYDL2zgQ/S8XiVAqr4rOBfmN/Pu fDZyd9BUGgf3XHzlU8wT0i5wwdgQRb6g0D7lPoKcWEcWP9QWkiE9HdCoxCJfQpNcJ35xY5uOc//KQ vH/hrPbVx4y8+6iLSNWIYDNgveJuWIrnKbt67xuiWOn2/QiVUsWbDuwp/vW6mYSHuYgTfOCwhXHYT 2BZbs6XnlrgvBlN0sOPz712utL/wn8YNKsAMJKJcctSCy2rcfEpQr6RcQU8azevBCwguhD5QWxgRw llqWD7YnEZjJgErPZnzs7w==; Date: Fri, 22 Sep 2023 10:25:24 +0300 Message-Id: <83zg1e7jq3.fsf@gnu.org> From: Eli Zaretskii To: Juri Linkov In-Reply-To: <86msxeu1q3.fsf@mail.linkov.net> (message from Juri Linkov on Fri, 22 Sep 2023 09:55:40 +0300) Subject: Re: bug#65854: Multi-file replacement diff References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Juri Linkov > Cc: me@eshelyaron.com, 65854@debbugs.gnu.org > Date: Fri, 22 Sep 2023 09:55:40 +0300 > > +(defcustom multi-file-diff-unsaved 'save-buffers > + "What to do with unsaved edits when showing multi-file replacements as diffs. > +If the value is `save-buffers', save unsaved buffers before creating diff. > +If the value is `use-file', use text from the file even when the visiting > +file buffer is modified. > +If the value is `use-modified-buffer', use text from the file-visiting > +modified buffer to be able to use unsaved changes. However, when the file > +is not visited in a buffer, or the buffer is not modified, still read > +contents from the file." Please use consistent wording to describe the same entities. If you use "file-visiting buffer", use it everywhere, when you sometimes use that and sometimes "visiting file buffer", you are already half way to confusing the reader. Also, this part: > + However, when the file > +is not visited in a buffer, or the buffer is not modified, still read > +contents from the file." Seems to describe an implementation detail, and I don't think it should be there. E.g., what if the file visited by the buffer no longer exists? Thanks. From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 22 12:03:33 2023 Received: (at 65854) by debbugs.gnu.org; 22 Sep 2023 16:03:33 +0000 Received: from localhost ([127.0.0.1]:37169 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjicu-0005HS-QP for submit@debbugs.gnu.org; Fri, 22 Sep 2023 12:03:33 -0400 Received: from relay1-d.mail.gandi.net ([217.70.183.193]:57187) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjice-0005GW-IU for 65854@debbugs.gnu.org; Fri, 22 Sep 2023 12:03:17 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id B285C240005; Fri, 22 Sep 2023 16:02:58 +0000 (UTC) From: Juri Linkov To: Eli Zaretskii Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <83zg1e7jq3.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 22 Sep 2023 10:25:24 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> <83zg1e7jq3.fsf@gnu.org> Date: Fri, 22 Sep 2023 19:02:33 +0300 Message-ID: <86o7hunqyu.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --=-=-= Content-Type: text/plain >> +(defcustom multi-file-diff-unsaved 'save-buffers >> + "What to do with unsaved edits when showing multi-file replacements as diffs. >> +If the value is `save-buffers', save unsaved buffers before creating diff. >> +If the value is `use-file', use text from the file even when the visiting >> +file buffer is modified. >> +If the value is `use-modified-buffer', use text from the file-visiting >> +modified buffer to be able to use unsaved changes. However, when the file >> +is not visited in a buffer, or the buffer is not modified, still read >> +contents from the file." > > Please use consistent wording to describe the same entities. If you > use "file-visiting buffer", use it everywhere, when you sometimes use > that and sometimes "visiting file buffer", you are already half way to > confusing the reader. Ok, fixed below. > Also, this part: > >> + However, when the file >> +is not visited in a buffer, or the buffer is not modified, still read >> +contents from the file." > > Seems to describe an implementation detail, and I don't think it > should be there. E.g., what if the file visited by the buffer no > longer exists? If the file visited by the buffer no longer exists, then the standard error is signaled. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=multi-file-diff-unsaved.patch diff --git a/lisp/misearch.el b/lisp/misearch.el index 9ac28c26c48..25d1b115af8 100644 --- a/lisp/misearch.el +++ b/lisp/misearch.el @@ -387,6 +387,150 @@ multi-isearch-files-regexp (goto-char (if isearch-forward (point-min) (point-max))) (isearch-forward-regexp nil t))) + +;;; Global multi-file and multi-buffer replacements as diff + +(defcustom multi-file-diff-unsaved 'save-buffers + "What to do with unsaved edits when showing multi-file replacements as diffs. +If the value is `save-buffers', save unsaved buffers before creating diff. +If the value is `use-file', use text from the file even when the +file-visiting buffer is modified. +If the value is `use-modified-buffer', use text from the file-visiting +modified buffer to be able to use unsaved changes." + :type '(choice + (const :tag "Save buffers" save-buffers) + (const :tag "Use file" use-file) + (const :tag "Use modified buffer" use-modified-buffer)) + :version "30.1") + +(declare-function diff-setup-whitespace "diff-mode" ()) +(declare-function diff-setup-buffer-type "diff-mode" ()) + +(defun multi-file-replace-as-diff (files from-string replacements regexp-flag delimited-flag) + "Show as diffs replacements of FROM-STRING with REPLACEMENTS. +FILES is a list of file names. REGEXP-FLAG and DELIMITED-FLAG have +the same meaning as in `perform-replace'." + (require 'diff) + (let ((inhibit-message t) + (diff-buffer (get-buffer-create "*replace-diff*"))) + (when (eq multi-file-diff-unsaved 'save-buffers) + (save-some-buffers t (lambda () + (seq-some (lambda (f-or-b) + (equal f-or-b buffer-file-name)) + files)))) + (with-current-buffer diff-buffer + (buffer-disable-undo (current-buffer)) + (let ((inhibit-read-only t)) + (erase-buffer)) + ;; Make the *vc-diff* buffer read only, the diff-mode key + ;; bindings are nicer for read only buffers. + (setq buffer-read-only t) + (diff-mode)) + (dolist (file-name files) + (let ((file-buffer (when (eq multi-file-diff-unsaved 'use-modified-buffer) + (find-buffer-visiting file-name)))) + (when file-name + (with-temp-buffer + (if (and file-buffer (buffer-modified-p file-buffer)) + (insert-buffer-substring file-buffer) + (insert-file-contents file-name)) + (goto-char (point-min)) + (perform-replace from-string replacements nil regexp-flag delimited-flag) + (multi-file-diff-no-select file-name (current-buffer) nil diff-buffer + (concat file-name "~") file-name))))) + (with-current-buffer diff-buffer + (diff-setup-whitespace) + (diff-setup-buffer-type) + (buffer-enable-undo (current-buffer)) + (setq-local revert-buffer-function + (lambda (_ignore-auto _noconfirm) + (multi-file-replace-as-diff + files from-string replacements regexp-flag delimited-flag))) + (goto-char (point-min))) + (pop-to-buffer diff-buffer))) + +;;;###autoload +(defun multi-file-replace-regexp-as-diff (files regexp to-string &optional delimited) + "Show as diffs replacements of REGEXP with TO-STRING in FILES. +DELIMITED has the same meaning as in `replace-regexp'. +With a prefix argument, ask for a wildcard, and show diffs for files +whose file names match the specified wildcard." + (interactive + (let ((files (if current-prefix-arg + (multi-isearch-read-matching-files) + (multi-isearch-read-files))) + (common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff in files") + t t))) + (list files (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff files regexp to-string t delimited)) + +;;;###autoload +(defun replace-regexp-as-diff (regexp to-string &optional delimited) + "Show as diffs replacements of REGEXP with TO-STRING in the current buffer. +DELIMITED has the same meaning as in `replace-regexp'." + (interactive + (let ((common + (query-replace-read-args + (concat "Replace" + (if current-prefix-arg " word" "") + " regexp as diff") + t t))) + (list (nth 0 common) (nth 1 common) (nth 2 common)))) + (multi-file-replace-as-diff + (list buffer-file-name) regexp to-string t delimited)) + +(defvar diff-use-labels) +(declare-function diff-check-labels "diff" (&optional force)) +(declare-function diff-file-local-copy "diff" (file-or-buf)) + +(defun multi-file-diff-no-select (old new &optional switches buf label-old label-new) + ;; Based on `diff-no-select' tailored to multi-file diffs. + "Compare the OLD and NEW file/buffer. +If the optional SWITCHES is nil, the switches specified in the +variable `diff-switches' are passed to the diff command, +otherwise SWITCHES is used. SWITCHES can be a string or a list +of strings. BUF should be non-nil. LABEL-OLD and LABEL-NEW +specify labels to use for file names." + (unless (bufferp new) (setq new (expand-file-name new))) + (unless (bufferp old) (setq old (expand-file-name old))) + (or switches (setq switches diff-switches)) ; If not specified, use default. + (setq switches (ensure-list switches)) + (diff-check-labels) + (let* ((old-alt (diff-file-local-copy old)) + (new-alt (diff-file-local-copy new)) + (command + (mapconcat #'identity + `(,diff-command + ;; Use explicitly specified switches + ,@switches + ,@(mapcar #'shell-quote-argument + (nconc + (and (or old-alt new-alt) + (eq diff-use-labels t) + (list "--label" + (cond ((stringp label-old) label-old) + ((stringp old) old) + ((prin1-to-string old))) + "--label" + (cond ((stringp label-new) label-new) + ((stringp new) new) + ((prin1-to-string new))))) + (list (or old-alt old) + (or new-alt new))))) + " "))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (insert command "\n") + (call-process shell-file-name nil buf nil + shell-command-switch command)) + (if old-alt (delete-file old-alt)) + (if new-alt (delete-file new-alt))))) + + (defvar unload-function-defs-list) (defun multi-isearch-unload-function () --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Fri Sep 22 12:06:29 2023 Received: (at 65854) by debbugs.gnu.org; 22 Sep 2023 16:06:29 +0000 Received: from localhost ([127.0.0.1]:37181 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjifl-0005Mq-7r for submit@debbugs.gnu.org; Fri, 22 Sep 2023 12:06:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50860) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjifg-0005Mb-Te for 65854@debbugs.gnu.org; Fri, 22 Sep 2023 12:06:28 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qjifP-0007tz-Vz; Fri, 22 Sep 2023 12:06:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=DDOyQDPHLQg6kdrzQl35eWlRM/zmieZ1px7G5wnfMcQ=; b=jyn1Xen/66eN Aj+xf31694gbpDp03HsfAqY3S7flA7Nbr5BTl6up8LE8f85SF/7WFzti3Lx0GPF0Y5Rkl+Sap+uMx 0TKyJOricG6FIMBqQnjPMYjt6U59BT39X+YOjVbRHsJCTHaUg64oIixosGAWMty5wpmBPtNA1ZKvo lVcng813YlXTfY/05xNuL+siDQcZ4uU0yY3lLSbCKuoRGuaQhsyDNOadlZ8iT2vsI7Gp/nkL9hQYe w2wGz8R/Vd+yw6BGjl44ubx58AYnMix+v8WWYM+ppRD6leYzsVGGYE7i1HzQGQGtx5uhRfAHqG5ad EI+vsi65XRz0wgo/WA9pMg==; Date: Fri, 22 Sep 2023 19:06:12 +0300 Message-Id: <83jzsi5h1n.fsf@gnu.org> From: Eli Zaretskii To: Juri Linkov In-Reply-To: <86o7hunqyu.fsf@mail.linkov.net> (message from Juri Linkov on Fri, 22 Sep 2023 19:02:33 +0300) Subject: Re: bug#65854: Multi-file replacement diff References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> <83zg1e7jq3.fsf@gnu.org> <86o7hunqyu.fsf@mail.linkov.net> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Juri Linkov > Cc: me@eshelyaron.com, 65854@debbugs.gnu.org > Date: Fri, 22 Sep 2023 19:02:33 +0300 > > >> + However, when the file > >> +is not visited in a buffer, or the buffer is not modified, still read > >> +contents from the file." > > > > Seems to describe an implementation detail, and I don't think it > > should be there. E.g., what if the file visited by the buffer no > > longer exists? > > If the file visited by the buffer no longer exists, then > the standard error is signaled. Which means in that case it is better to use the buffer text, no? From debbugs-submit-bounces@debbugs.gnu.org Sat Sep 23 13:39:31 2023 Received: (at 65854) by debbugs.gnu.org; 23 Sep 2023 17:39:31 +0000 Received: from localhost ([127.0.0.1]:40580 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qk6bL-0007uC-Je for submit@debbugs.gnu.org; Sat, 23 Sep 2023 13:39:31 -0400 Received: from relay2-d.mail.gandi.net ([2001:4b98:dc4:8::222]:42815) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qk6bJ-0007tq-Nl for 65854@debbugs.gnu.org; Sat, 23 Sep 2023 13:39:30 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id D12D340002; Sat, 23 Sep 2023 17:39:11 +0000 (UTC) From: Juri Linkov To: Eli Zaretskii Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <83jzsi5h1n.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 22 Sep 2023 19:06:12 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> <83zg1e7jq3.fsf@gnu.org> <86o7hunqyu.fsf@mail.linkov.net> <83jzsi5h1n.fsf@gnu.org> Date: Sat, 23 Sep 2023 20:36:02 +0300 Message-ID: <86r0movlkt.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) >> >> + However, when the file >> >> +is not visited in a buffer, or the buffer is not modified, still read >> >> +contents from the file." >> > >> > Seems to describe an implementation detail, and I don't think it >> > should be there. E.g., what if the file visited by the buffer no >> > longer exists? >> >> If the file visited by the buffer no longer exists, then >> the standard error is signaled. > > Which means in that case it is better to use the buffer text, no? Since replacement diffs are not supported in non-file buffers, better to signal an error for heads up. From debbugs-submit-bounces@debbugs.gnu.org Sat Sep 23 14:56:12 2023 Received: (at 65854) by debbugs.gnu.org; 23 Sep 2023 18:56:12 +0000 Received: from localhost ([127.0.0.1]:40616 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qk7nY-0001h7-Aa for submit@debbugs.gnu.org; Sat, 23 Sep 2023 14:56:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42770) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qk7nV-0001gn-7D for 65854@debbugs.gnu.org; Sat, 23 Sep 2023 14:56:11 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qk7nD-0001CV-Lh; Sat, 23 Sep 2023 14:55:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=fls9P5ddjW8hCZFw/MN6PVugTULMXsbPIVt1wYAbLIs=; b=Q+hqJs0x/VTK p5BwQ/NDYh7/4zh2Ar6eYkwBFASDFCUaPCSxn34Rk2E63By86cuWdmOeuuZrSxiwiPbb9IypOGWZZ BO+bzOgXe/OP5+lJzhX0o48PWChg/ZJWdKMQSNULWMgJQgTllI71bUqEGhORNWLnCG6wPYhoJY31V jNiPzDTZsDtue8Ye1x9rb+b1fg5Sjgq3tSM+O7jv6N1UdpfzRSs4kjQZAH1shWbrF6/sD9jeMmmhK bKf3crmS0jyF/fd/S+sWOFq+T9B1uJPv8Ryr2hD4esdA/+k3s41cmnoJsf6lqr9kiUS/mSwDkwSlY QRnbEhS64RQR6lGTM/mXag==; Date: Sat, 23 Sep 2023 21:56:01 +0300 Message-Id: <83h6nk4t32.fsf@gnu.org> From: Eli Zaretskii To: Juri Linkov In-Reply-To: <86r0movlkt.fsf@mail.linkov.net> (message from Juri Linkov on Sat, 23 Sep 2023 20:36:02 +0300) Subject: Re: bug#65854: Multi-file replacement diff References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> <83zg1e7jq3.fsf@gnu.org> <86o7hunqyu.fsf@mail.linkov.net> <83jzsi5h1n.fsf@gnu.org> <86r0movlkt.fsf@mail.linkov.net> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Juri Linkov > Cc: me@eshelyaron.com, 65854@debbugs.gnu.org > Date: Sat, 23 Sep 2023 20:36:02 +0300 > > >> >> + However, when the file > >> >> +is not visited in a buffer, or the buffer is not modified, still read > >> >> +contents from the file." > >> > > >> > Seems to describe an implementation detail, and I don't think it > >> > should be there. E.g., what if the file visited by the buffer no > >> > longer exists? > >> > >> If the file visited by the buffer no longer exists, then > >> the standard error is signaled. > > > > Which means in that case it is better to use the buffer text, no? > > Since replacement diffs are not supported in non-file buffers, > better to signal an error for heads up. But it _is_ a file-visiting buffer. It's just that its file was deleted meanwhile. From debbugs-submit-bounces@debbugs.gnu.org Sat Sep 23 21:43:23 2023 Received: (at 65854) by debbugs.gnu.org; 24 Sep 2023 01:43:23 +0000 Received: from localhost ([127.0.0.1]:40781 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkE9a-0004h1-Oj for submit@debbugs.gnu.org; Sat, 23 Sep 2023 21:43:23 -0400 Received: from wout4-smtp.messagingengine.com ([64.147.123.20]:40705) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkE9Y-0004gn-SM for 65854@debbugs.gnu.org; Sat, 23 Sep 2023 21:43:21 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.west.internal (Postfix) with ESMTP id 9E3643200786; Sat, 23 Sep 2023 21:43:03 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sat, 23 Sep 2023 21:43:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gutov.dev; h=cc :content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to; s=fm1; t= 1695519783; x=1695606183; bh=lOAMqT8thDyjY3puQXjVx/8mjQTnlFzEiOQ CSn6dARQ=; b=Kp6Ed2GCs8QqlfEzBoitqXBx5jJWZkrdtmTeO60hwBvxfm90b8w QqpRirN404XKWWzOM0kh7lJShGVzK3lwxv/CbrkQ9nAqogAhHzxkOlkMMV0jrvp9 3Pe2eFrJUwBsi18r7vlDf32Derr031MId3taeECaKngLy97gFU0g9qx8FPQcpgXr fXkQnZwP5A2E8O7IeeNX46c9sI1pgYm3HmVUC+kPqIt6lR3Ur/7TRd4Ewwkui/Jc c51o+0foYOGIT1O2NGvro9HSHryKVnG7RPVFnN6aVCG0m88dFiQFJ6D4GQYQqDsF id9rJGPLXJRDgm5I2HA2MJOVVVKuu5UxI/Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1695519783; x= 1695606183; bh=lOAMqT8thDyjY3puQXjVx/8mjQTnlFzEiOQCSn6dARQ=; b=l Br5blJjaQtz9IOUlyuw2xIdVKXmsz5d3Q2ZEnBspNBxhTu17oaMZG/R2ovZtmiVY FuyILffqa3bVcHt0sK/dvNnIpZEUS3GKmk/SOdtH58eIq1RryuPvuLgY8nTcBxWe sOjXmsM54FmD5KSXY8XWtQykbX8QAEl9P8sGQpU/4Cr40OkBT5orJ4dztUzQtOZP w2EYP4q2dRw/zJU8bFCFfZDwyb7Q+vySogSJFnHoXlO/vX58XBo2TONtIekRb2qo WuF35Bytsswd3SQAot8Xf8fyPAviRDVsrzIUcC6SzfuiJjBbkyICHkA//KTw4mc7 h29TRLfmXmyYGmEAF1oWw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedviedrudeluddghedtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepkfffgggfuffvfhfhjggtgfesthejredttdefjeenucfhrhhomhepffhmihht rhihucfiuhhtohhvuceoughmihhtrhihsehguhhtohhvrdguvghvqeenucggtffrrghtth gvrhhnpeeghedthedujeeiteeutddtjeekheejteeukeehffdutdejuedvfeevueeviedu udenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegumh hithhrhiesghhuthhovhdruggvvh X-ME-Proxy: Feedback-ID: i0e71465a:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sat, 23 Sep 2023 21:43:02 -0400 (EDT) Message-ID: <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> Date: Sun, 24 Sep 2023 04:43:00 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0 Subject: Re: bug#65854: Multi-file replacement diff Content-Language: en-US To: Juri Linkov , 65854@debbugs.gnu.org References: <86sf7mgd54.fsf@mail.linkov.net> From: Dmitry Gutov In-Reply-To: <86sf7mgd54.fsf@mail.linkov.net> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Score: -2.2 (--) X-Debbugs-Envelope-To: 65854 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.2 (---) Hi! On 10/09/2023 20:18, Juri Linkov wrote: > As discussed on emacs-devel, here is the patch that implements > a standalone command that reads a list of files and replacement strings, > then shows a diff to review before applying replacements. > Also provided the Dired integration to show the replacement diff > on marked files. Later the same function could be used > to show replacement diffs from the xref buffer and maybe > from other packages as well. Here's a counter-proposal: we were talking about a "refactoring" packages on emacs-devel, maybe a week ago. And I suggested a function that would take a list of changes (as some data) and present them using some customizable logic: the current Eglot's solution uses a diff, and I'll add an implementation that shows a tree-like buffer with checkmarks, probably. I'll be starting on this any day now ;-( So... provided this won't take too long, I would suggest your code here just focuses on creating a list of changes (those shouldn't require buffers to visit files), and then you'd be able to pass them on to 'refact-show-changes' (name under construction), which would then use the interface that the user prefers. This was we'll also consolidate the diff-generating code for features of this sort. From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 24 03:42:29 2023 Received: (at 65854) by debbugs.gnu.org; 24 Sep 2023 07:42:29 +0000 Received: from localhost ([127.0.0.1]:40931 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkJl7-0006AX-4U for submit@debbugs.gnu.org; Sun, 24 Sep 2023 03:42:29 -0400 Received: from relay7-d.mail.gandi.net ([2001:4b98:dc4:8::227]:40399) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkJl2-0006A0-KI for 65854@debbugs.gnu.org; Sun, 24 Sep 2023 03:42:26 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 778E420003; Sun, 24 Sep 2023 07:42:03 +0000 (UTC) From: Juri Linkov To: Dmitry Gutov Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> (Dmitry Gutov's message of "Sun, 24 Sep 2023 04:43:00 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> Date: Sun, 24 Sep 2023 10:36:20 +0300 Message-ID: <86zg1cvx8l.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) >> As discussed on emacs-devel, here is the patch that implements >> a standalone command that reads a list of files and replacement strings, >> then shows a diff to review before applying replacements. >> Also provided the Dired integration to show the replacement diff >> on marked files. Later the same function could be used >> to show replacement diffs from the xref buffer and maybe >> from other packages as well. > > Here's a counter-proposal: we were talking about a "refactoring" packages > on emacs-devel, maybe a week ago. And I suggested a function that would > take a list of changes (as some data) and present them using some > customizable logic: the current Eglot's solution uses a diff, and I'll add > an implementation that shows a tree-like buffer with checkmarks, probably. > > I'll be starting on this any day now ;-( > > So... provided this won't take too long, I would suggest your code here > just focuses on creating a list of changes (those shouldn't require buffers > to visit files), and then you'd be able to pass them on to > 'refact-show-changes' (name under construction), which would then use the > interface that the user prefers. > > This was we'll also consolidate the diff-generating code for features of > this sort. I'm not sure this complication is necessary. The proposed patch does its job already. So more generalizations could be added later. From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 24 03:42:36 2023 Received: (at 65854) by debbugs.gnu.org; 24 Sep 2023 07:42:37 +0000 Received: from localhost ([127.0.0.1]:40933 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkJlE-0006Aq-LW for submit@debbugs.gnu.org; Sun, 24 Sep 2023 03:42:36 -0400 Received: from relay8-d.mail.gandi.net ([217.70.183.201]:56187) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkJl5-0006A7-11 for 65854@debbugs.gnu.org; Sun, 24 Sep 2023 03:42:29 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id E97341BF206; Sun, 24 Sep 2023 07:42:07 +0000 (UTC) From: Juri Linkov To: Eli Zaretskii Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <83h6nk4t32.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 23 Sep 2023 21:56:01 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> <83zg1e7jq3.fsf@gnu.org> <86o7hunqyu.fsf@mail.linkov.net> <83jzsi5h1n.fsf@gnu.org> <86r0movlkt.fsf@mail.linkov.net> <83h6nk4t32.fsf@gnu.org> Date: Sun, 24 Sep 2023 10:37:54 +0300 Message-ID: <86ttrkvx65.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) >> >> >> + However, when the file >> >> >> +is not visited in a buffer, or the buffer is not modified, still read >> >> >> +contents from the file." >> >> > >> >> > Seems to describe an implementation detail, and I don't think it >> >> > should be there. E.g., what if the file visited by the buffer no >> >> > longer exists? >> >> >> >> If the file visited by the buffer no longer exists, then >> >> the standard error is signaled. >> > >> > Which means in that case it is better to use the buffer text, no? >> >> Since replacement diffs are not supported in non-file buffers, >> better to signal an error for heads up. > > But it _is_ a file-visiting buffer. It's just that its file was > deleted meanwhile. The generated diff could not be applied to the deleted file. So generating a diff to the deleted file makes no sense anyway. From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 24 04:13:44 2023 Received: (at 65854) by debbugs.gnu.org; 24 Sep 2023 08:13:44 +0000 Received: from localhost ([127.0.0.1]:40946 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkKFL-00073m-QC for submit@debbugs.gnu.org; Sun, 24 Sep 2023 04:13:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:48136) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkKFI-00073U-7p for 65854@debbugs.gnu.org; Sun, 24 Sep 2023 04:13:42 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qkKF0-0006QY-8j; Sun, 24 Sep 2023 04:13:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=yqciYbtnJn+eyU4mMXxFxESnH6aNY2kxHJa9vQxhcSU=; b=fDNiuSYjw0Tv llTb8UyIwJbGCZKmrIjeJumN3Vb0MdN/IVG9M9MxFAv5IaWNLZkJo8R1tNdMWabhU+RQTfNwBxJvr D8PjZ/zoWhBC/9JGJcDj/T0sEICP260kEzvJVHbRHDnBXze9Q6gp26L7/0HYRmJZoycaq4YYMvJMz QAIkv+4wEzFkEZU9BbXljgY7Tvw75OcHekzTerzDARszDCHsipvlIR7tcjW+8GTRlgdCeg8iXE/ie JkyuOZysNRVr6DfKbJVqSMztYR78YdnqjVtKKoPfXYhfdDAX+TSuCiZ8PfvTC+MJZq9/mJ/OP/njv 6iGKWdpA0gVU6GIYifC0mg==; Date: Sun, 24 Sep 2023 11:12:51 +0300 Message-Id: <831qeo3s70.fsf@gnu.org> From: Eli Zaretskii To: Juri Linkov In-Reply-To: <86ttrkvx65.fsf@mail.linkov.net> (message from Juri Linkov on Sun, 24 Sep 2023 10:37:54 +0300) Subject: Re: bug#65854: Multi-file replacement diff References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> <83zg1e7jq3.fsf@gnu.org> <86o7hunqyu.fsf@mail.linkov.net> <83jzsi5h1n.fsf@gnu.org> <86r0movlkt.fsf@mail.linkov.net> <83h6nk4t32.fsf@gnu.org> <86ttrkvx65.fsf@mail.linkov.net> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Juri Linkov > Cc: me@eshelyaron.com, 65854@debbugs.gnu.org > Date: Sun, 24 Sep 2023 10:37:54 +0300 > > >> >> >> + However, when the file > >> >> >> +is not visited in a buffer, or the buffer is not modified, still read > >> >> >> +contents from the file." > >> >> > > >> >> > Seems to describe an implementation detail, and I don't think it > >> >> > should be there. E.g., what if the file visited by the buffer no > >> >> > longer exists? > >> >> > >> >> If the file visited by the buffer no longer exists, then > >> >> the standard error is signaled. > >> > > >> > Which means in that case it is better to use the buffer text, no? > >> > >> Since replacement diffs are not supported in non-file buffers, > >> better to signal an error for heads up. > > > > But it _is_ a file-visiting buffer. It's just that its file was > > deleted meanwhile. > > The generated diff could not be applied to the deleted file. > So generating a diff to the deleted file makes no sense anyway. I suggest not to second-guess what the user wants to do with the generated diffs. What if they just want to email it or something? The basic rule of the least surprise is pertinent here: we have the data, so why not generate the diffs when we can? But if you feel strongly about signaling an error in that case, I won't object. From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 24 07:09:37 2023 Received: (at 65854) by debbugs.gnu.org; 24 Sep 2023 11:09:37 +0000 Received: from localhost ([127.0.0.1]:41168 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkMzY-0003bw-Lh for submit@debbugs.gnu.org; Sun, 24 Sep 2023 07:09:37 -0400 Received: from wout5-smtp.messagingengine.com ([64.147.123.21]:35943) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkMzV-0003bV-TX for 65854@debbugs.gnu.org; Sun, 24 Sep 2023 07:09:35 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id BE33B3200981; Sun, 24 Sep 2023 07:09:15 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Sun, 24 Sep 2023 07:09:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gutov.dev; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to; s=fm1; t= 1695553754; x=1695640154; bh=4jsmR+VFuCH+3xNK9jbt/CqBpWQlP0AWMk/ bO1gmsdA=; b=3D0RBnl+i7IT2yShp9Z0gwIbgQJWxfxzDF1FajWz9v42YFFQnOt y1KkGiIX/XsImKW9O3sqMWbaraEbLLcOqNjtHqSh4WNrn2QDgDSDJePbwbv4XEhy OcAtl9npTrGu/VhHqCDAETbrqwMHz2OPjDxld+xuugOy4ZDalXJYgn5rlvq8VAZZ lx9lUPt+DJ1piTZwAghXnbSHkbXAv3QONtFGyxus6idwvOgMf8QVb8XQtu0hJtSi AItjqO7ltXVKlrCsQTVxRs1D8g59FIOvYSogcoMEEvyiRcwDz41oPX4zL3FU7qHT /znH5+xjasulyzDo31XSt4evfj8vyW7TFIg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t= 1695553754; x=1695640154; bh=4jsmR+VFuCH+3xNK9jbt/CqBpWQlP0AWMk/ bO1gmsdA=; b=XdQNpm9LK7wAwAv2fFw3eB/IijzNxgokmN6PtIkhPiu03RQ0ayi z4z1kR5KSV/gVCPttTFKkIItTrjx7TNnu/sLJZ1yeUfJsCpo/teuoNiKz67Z4+jO ImQuFwjrxhNkx2rS0RsQTMz2aKThOAk0IPySpoxOUbZL5EzjrdMXi+myt8B8+b0g VFxnecypf6WrhLBMLrJOb03EcOP3kZn4lpXw5oWNB5zQw5GkyfZMJ8POcsBLFptV SYu/+ohIenOr1ivpom1VWFhK7ld8l4vkTIUzfQTaOwN58zG4BBito9kfE6Aecfx1 OIRXQm7VDFPYXAeFGp8P1EDauOYaG0DNmgQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedviedrudelvddgfeeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepkfffgggfuffvvehfhfgjtgfgsehtjeertddtfeejnecuhfhrohhmpeffmhhi thhrhicuifhuthhovhcuoegumhhithhrhiesghhuthhovhdruggvvheqnecuggftrfgrth htvghrnhepiefgteevheevveffheeltdeukeeiieekueefgedugfefgefhudelgfefveel vdevnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepug hmihhtrhihsehguhhtohhvrdguvghv X-ME-Proxy: Feedback-ID: i0e71465a:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 24 Sep 2023 07:09:13 -0400 (EDT) Message-ID: Date: Sun, 24 Sep 2023 14:09:11 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0 Subject: Re: bug#65854: Multi-file replacement diff Content-Language: en-US To: Juri Linkov References: <86sf7mgd54.fsf@mail.linkov.net> <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> <86zg1cvx8l.fsf@mail.linkov.net> From: Dmitry Gutov In-Reply-To: <86zg1cvx8l.fsf@mail.linkov.net> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Score: -2.2 (--) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.2 (---) On 24/09/2023 10:36, Juri Linkov wrote: >>> As discussed on emacs-devel, here is the patch that implements >>> a standalone command that reads a list of files and replacement strings, >>> then shows a diff to review before applying replacements. >>> Also provided the Dired integration to show the replacement diff >>> on marked files. Later the same function could be used >>> to show replacement diffs from the xref buffer and maybe >>> from other packages as well. >> Here's a counter-proposal: we were talking about a "refactoring" packages >> on emacs-devel, maybe a week ago. And I suggested a function that would >> take a list of changes (as some data) and present them using some >> customizable logic: the current Eglot's solution uses a diff, and I'll add >> an implementation that shows a tree-like buffer with checkmarks, probably. >> >> I'll be starting on this any day now ;-( >> >> So... provided this won't take too long, I would suggest your code here >> just focuses on creating a list of changes (those shouldn't require buffers >> to visit files), and then you'd be able to pass them on to >> 'refact-show-changes' (name under construction), which would then use the >> interface that the user prefers. >> >> This was we'll also consolidate the diff-generating code for features of >> this sort. > I'm not sure this complication is necessary. The proposed patch > does its job already. So more generalizations could be added later. If you are sure. I just wouldn't want to keep unnecessary defcustoms around. From debbugs-submit-bounces@debbugs.gnu.org Mon Sep 25 14:00:26 2023 Received: (at 65854) by debbugs.gnu.org; 25 Sep 2023 18:00:26 +0000 Received: from localhost ([127.0.0.1]:46624 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkpsg-0004o0-0K for submit@debbugs.gnu.org; Mon, 25 Sep 2023 14:00:26 -0400 Received: from relay9-d.mail.gandi.net ([2001:4b98:dc4:8::229]:38799) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkpse-0004S6-Q1 for 65854@debbugs.gnu.org; Mon, 25 Sep 2023 14:00:25 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 0158AFF80B; Mon, 25 Sep 2023 18:00:02 +0000 (UTC) From: Juri Linkov To: Dmitry Gutov Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: (Dmitry Gutov's message of "Sun, 24 Sep 2023 14:09:11 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> <86zg1cvx8l.fsf@mail.linkov.net> Date: Mon, 25 Sep 2023 20:58:59 +0300 Message-ID: <86cyy6yw0s.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) > On 24/09/2023 10:36, Juri Linkov wrote: >>>> As discussed on emacs-devel, here is the patch that implements >>>> a standalone command that reads a list of files and replacement strings, >>>> then shows a diff to review before applying replacements. >>>> Also provided the Dired integration to show the replacement diff >>>> on marked files. Later the same function could be used >>>> to show replacement diffs from the xref buffer and maybe >>>> from other packages as well. >>> Here's a counter-proposal: we were talking about a "refactoring" packages >>> on emacs-devel, maybe a week ago. And I suggested a function that would >>> take a list of changes (as some data) and present them using some >>> customizable logic: the current Eglot's solution uses a diff, and I'll add >>> an implementation that shows a tree-like buffer with checkmarks, probably. >>> >>> I'll be starting on this any day now ;-( >>> >>> So... provided this won't take too long, I would suggest your code here >>> just focuses on creating a list of changes (those shouldn't require buffers >>> to visit files), and then you'd be able to pass them on to >>> 'refact-show-changes' (name under construction), which would then use the >>> interface that the user prefers. >>> >>> This was we'll also consolidate the diff-generating code for features of >>> this sort. >> I'm not sure this complication is necessary. The proposed patch >> does its job already. So more generalizations could be added later. > > If you are sure. > > I just wouldn't want to keep unnecessary defcustoms around. Actually my point was that there is already eglot--propose-changes-as-diff. And now with addition of multi-file-replace-as-diff you will have two cases to generalize that would be simpler to do than with only one case. From debbugs-submit-bounces@debbugs.gnu.org Mon Sep 25 14:51:25 2023 Received: (at 65854) by debbugs.gnu.org; 25 Sep 2023 18:51:25 +0000 Received: from localhost ([127.0.0.1]:46670 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkqg1-0001zN-7J for submit@debbugs.gnu.org; Mon, 25 Sep 2023 14:51:25 -0400 Received: from relay5-d.mail.gandi.net ([217.70.183.197]:32901) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qkqfy-0001z8-0c for 65854@debbugs.gnu.org; Mon, 25 Sep 2023 14:51:23 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id AAFF61C0004; Mon, 25 Sep 2023 18:51:01 +0000 (UTC) From: Juri Linkov To: Eli Zaretskii Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <831qeo3s70.fsf@gnu.org> (Eli Zaretskii's message of "Sun, 24 Sep 2023 11:12:51 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <86bke943tp.fsf@mail.linkov.net> <83jzswrios.fsf@gnu.org> <86o7i7oo9t.fsf@mail.linkov.net> <86sf7g548a.fsf@mail.linkov.net> <83pm2jkhsg.fsf@gnu.org> <86msxeu1q3.fsf@mail.linkov.net> <83zg1e7jq3.fsf@gnu.org> <86o7hunqyu.fsf@mail.linkov.net> <83jzsi5h1n.fsf@gnu.org> <86r0movlkt.fsf@mail.linkov.net> <83h6nk4t32.fsf@gnu.org> <86ttrkvx65.fsf@mail.linkov.net> <831qeo3s70.fsf@gnu.org> Date: Mon, 25 Sep 2023 21:18:49 +0300 Message-ID: <86r0mmxf5a.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: me@eshelyaron.com, 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --=-=-= Content-Type: text/plain >> >> >> >> + However, when the file >> >> >> >> +is not visited in a buffer, or the buffer is not modified, still read >> >> >> >> +contents from the file." >> >> >> > >> >> >> > Seems to describe an implementation detail, and I don't think it >> >> >> > should be there. E.g., what if the file visited by the buffer no >> >> >> > longer exists? >> >> >> >> >> >> If the file visited by the buffer no longer exists, then >> >> >> the standard error is signaled. >> >> > >> >> > Which means in that case it is better to use the buffer text, no? >> >> >> >> Since replacement diffs are not supported in non-file buffers, >> >> better to signal an error for heads up. >> > >> > But it _is_ a file-visiting buffer. It's just that its file was >> > deleted meanwhile. >> >> The generated diff could not be applied to the deleted file. >> So generating a diff to the deleted file makes no sense anyway. > > I suggest not to second-guess what the user wants to do with the > generated diffs. What if they just want to email it or something? > > The basic rule of the least surprise is pertinent here: we have the > data, so why not generate the diffs when we can? > > But if you feel strongly about signaling an error in that case, I > won't object. I don't disagree. My only concern was extra complexity and performance of file-exists-p for such rare case. But if this is not a problem, here is a patch over the previous patch: --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=multi-file-replace-as-diff.patch diff --git a/lisp/misearch.el b/lisp/misearch.el index 25d1b115af8..06bb6f57777 100644 --- a/lisp/misearch.el +++ b/lisp/misearch.el @@ -427,17 +427,24 @@ multi-file-replace-as-diff (setq buffer-read-only t) (diff-mode)) (dolist (file-name files) - (let ((file-buffer (when (eq multi-file-diff-unsaved 'use-modified-buffer) - (find-buffer-visiting file-name)))) + (let* ((file-exists (file-exists-p file-name)) + (file-buffer + (when (or (not file-exists) + (eq multi-file-diff-unsaved 'use-modified-buffer)) + (find-buffer-visiting file-name)))) (when file-name (with-temp-buffer - (if (and file-buffer (buffer-modified-p file-buffer)) + (if (and file-buffer + (or (not file-exists) + (buffer-modified-p file-buffer))) (insert-buffer-substring file-buffer) (insert-file-contents file-name)) (goto-char (point-min)) (perform-replace from-string replacements nil regexp-flag delimited-flag) - (multi-file-diff-no-select file-name (current-buffer) nil diff-buffer - (concat file-name "~") file-name))))) + (multi-file-diff-no-select + (if file-exists file-name file-buffer) + (current-buffer) nil diff-buffer + (concat file-name "~") file-name))))) (with-current-buffer diff-buffer (diff-setup-whitespace) (diff-setup-buffer-type) --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Tue Sep 26 17:39:35 2023 Received: (at 65854) by debbugs.gnu.org; 26 Sep 2023 21:39:35 +0000 Received: from localhost ([127.0.0.1]:49984 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qlFmI-0004LL-O1 for submit@debbugs.gnu.org; Tue, 26 Sep 2023 17:39:35 -0400 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:51077) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qlFmF-0004L6-Ub for 65854@debbugs.gnu.org; Tue, 26 Sep 2023 17:39:33 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailout.nyi.internal (Postfix) with ESMTP id D62405C2638; Tue, 26 Sep 2023 17:39:12 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Tue, 26 Sep 2023 17:39:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gutov.dev; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to; s=fm1; t= 1695764352; x=1695850752; bh=5tBhWu/WTvC+n6nAlZ9rNmONzggT0GbhsCD iA9PyeZA=; b=UWCNz6Lp53QCVdKvChKpPmvwjQPIADYD3beaAhy57YoZB1hGHhP Mqh3q2f9Cg6+QJdOL4X/NIs5Llek4puyeB8l5H3T2q8glKmRDPSrxc7FxPW2cJGE Drg6UcQZ7/4TPGk3tRjCaOCGSW7fE2dTstUQfz9/KDLbgv2BSmbANionzNRGprxq Y5ubqCGwZo15NvAcAemKzFeYjpiwKVngNYvIUFvT1JQIhJFqVBf5EF4twoijtbyx 7/WW6WuQ/KMRRKAb2+686FUg67xoT4f/GTy6oGlrD4Cev6G5pGhaWCfIvPgcpdAB Hj9MTrUcuXSN7pMWlN1aVW2RqW4B8ssaBKQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t= 1695764352; x=1695850752; bh=5tBhWu/WTvC+n6nAlZ9rNmONzggT0GbhsCD iA9PyeZA=; b=dxKefMV0NVK/3PsCpUpITESttJN1v8ghRGRd0Hu9h2SF6rpChsN Vf3TO0SEMWrTBKcYMuzMbwsVYeSCVffSpBC581gi/naIxJdGA/din3Dwm1gb3YjQ qTKgsBPuECmZNCj+ecH9VETv0QJIF2wNhbWf7so+5TznpzNQte9ubESdZXjK609d c5SPWBA2j1AY1bJ2Q3c+NneeKvIkDT6IPYe18h9t+sSkuERo87mOelvzxtR3tYOr zWiwvtdRsfbpy0D1QlWxHMT9W/iUaDwbxsiNHE1AgXNlSkl8zjbVDEl1p1Yj7k1I Wm1+7k7te01u2PPj76/c8TRHy7RDPpYNJgg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvjedrtddugddtudcutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefkffggfgfuvfevfhfhjggtgfesthejredttdefjeenucfhrhhomhepffhmihht rhihucfiuhhtohhvuceoughmihhtrhihsehguhhtohhvrdguvghvqeenucggtffrrghtth gvrhhnpeeigfetveehveevffehledtueekieeikeeufeegudfgfeeghfdulefgfeevledv veenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegumh hithhrhiesghhuthhovhdruggvvh X-ME-Proxy: Feedback-ID: i0e71465a:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 26 Sep 2023 17:39:11 -0400 (EDT) Message-ID: <551d5fee-28ab-f642-3ed4-baf0029cdef9@gutov.dev> Date: Wed, 27 Sep 2023 00:39:09 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0 Subject: Re: bug#65854: Multi-file replacement diff Content-Language: en-US To: Juri Linkov References: <86sf7mgd54.fsf@mail.linkov.net> <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> <86zg1cvx8l.fsf@mail.linkov.net> <86cyy6yw0s.fsf@mail.linkov.net> From: Dmitry Gutov In-Reply-To: <86cyy6yw0s.fsf@mail.linkov.net> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Score: -2.2 (--) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.2 (---) On 25/09/2023 20:58, Juri Linkov wrote: >> On 24/09/2023 10:36, Juri Linkov wrote: >>>>> As discussed on emacs-devel, here is the patch that implements >>>>> a standalone command that reads a list of files and replacement strings, >>>>> then shows a diff to review before applying replacements. >>>>> Also provided the Dired integration to show the replacement diff >>>>> on marked files. Later the same function could be used >>>>> to show replacement diffs from the xref buffer and maybe >>>>> from other packages as well. >>>> Here's a counter-proposal: we were talking about a "refactoring" packages >>>> on emacs-devel, maybe a week ago. And I suggested a function that would >>>> take a list of changes (as some data) and present them using some >>>> customizable logic: the current Eglot's solution uses a diff, and I'll add >>>> an implementation that shows a tree-like buffer with checkmarks, probably. >>>> >>>> I'll be starting on this any day now ;-( >>>> >>>> So... provided this won't take too long, I would suggest your code here >>>> just focuses on creating a list of changes (those shouldn't require buffers >>>> to visit files), and then you'd be able to pass them on to >>>> 'refact-show-changes' (name under construction), which would then use the >>>> interface that the user prefers. >>>> >>>> This was we'll also consolidate the diff-generating code for features of >>>> this sort. >>> I'm not sure this complication is necessary. The proposed patch >>> does its job already. So more generalizations could be added later. >> If you are sure. >> >> I just wouldn't want to keep unnecessary defcustoms around. > Actually my point was that there is already eglot--propose-changes-as-diff. > And now with addition of multi-file-replace-as-diff you will have two cases > to generalize that would be simpler to do than with only one case. Yes, that should help. Even having your patch in the bug tracker to refer to already helps (as well as the discussion around it). I'm just saying that if Eglot has its own existing custom vars, and misearch.el has its own, it will take extra effort to unify them (or keep extra options inside said packages, I guess, increasing unavoidable duplication). From debbugs-submit-bounces@debbugs.gnu.org Wed Sep 27 13:41:10 2023 Received: (at 65854) by debbugs.gnu.org; 27 Sep 2023 17:41:10 +0000 Received: from localhost ([127.0.0.1]:52457 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qlYX8-0006Ry-Dc for submit@debbugs.gnu.org; Wed, 27 Sep 2023 13:41:10 -0400 Received: from relay1-d.mail.gandi.net ([217.70.183.193]:53983) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qlYX5-0006RG-8e; Wed, 27 Sep 2023 13:41:09 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 4E4C1240005; Wed, 27 Sep 2023 17:40:42 +0000 (UTC) From: Juri Linkov To: Dmitry Gutov Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <551d5fee-28ab-f642-3ed4-baf0029cdef9@gutov.dev> (Dmitry Gutov's message of "Wed, 27 Sep 2023 00:39:09 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> <86zg1cvx8l.fsf@mail.linkov.net> <86cyy6yw0s.fsf@mail.linkov.net> <551d5fee-28ab-f642-3ed4-baf0029cdef9@gutov.dev> Date: Wed, 27 Sep 2023 20:21:38 +0300 Message-ID: <86jzsbo7kt.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) close 65854 30.0.50 thanks > I'm just saying that if Eglot has its own existing custom vars, and > misearch.el has its own, it will take extra effort to unify them (or keep > extra options inside said packages, I guess, increasing unavoidable > duplication). It's not a problem to unify custom vars until the next release. So the current version is pushed to master. From debbugs-submit-bounces@debbugs.gnu.org Sat Sep 30 13:49:27 2023 Received: (at 65854) by debbugs.gnu.org; 30 Sep 2023 17:49:27 +0000 Received: from localhost ([127.0.0.1]:59721 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qme5f-0005Jv-Vg for submit@debbugs.gnu.org; Sat, 30 Sep 2023 13:49:27 -0400 Received: from relay1-d.mail.gandi.net ([2001:4b98:dc4:8::221]:52327) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qme5P-0005IR-Df for 65854@debbugs.gnu.org; Sat, 30 Sep 2023 13:49:03 -0400 Received: by mail.gandi.net (Postfix) with ESMTPSA id 4B1CB240004; Sat, 30 Sep 2023 17:48:38 +0000 (UTC) From: Juri Linkov To: Dmitry Gutov Subject: Re: bug#65854: Multi-file replacement diff In-Reply-To: <551d5fee-28ab-f642-3ed4-baf0029cdef9@gutov.dev> (Dmitry Gutov's message of "Wed, 27 Sep 2023 00:39:09 +0300") Organization: LINKOV.NET References: <86sf7mgd54.fsf@mail.linkov.net> <0f06a505-a441-133f-00a1-50dd55d18b33@gutov.dev> <86zg1cvx8l.fsf@mail.linkov.net> <86cyy6yw0s.fsf@mail.linkov.net> <551d5fee-28ab-f642-3ed4-baf0029cdef9@gutov.dev> Date: Sat, 30 Sep 2023 20:42:54 +0300 Message-ID: <86cyxz1rs1.fsf@mail.linkov.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain X-GND-Sasl: juri@linkov.net X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 65854 Cc: 65854@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) >> Actually my point was that there is already eglot--propose-changes-as-diff. >> And now with addition of multi-file-replace-as-diff you will have two cases >> to generalize that would be simpler to do than with only one case. > > Yes, that should help. Even having your patch in the bug tracker to refer > to already helps (as well as the discussion around it). And adding a third implementation could help more ;-) What is still missing is doing replacements as diffs from xref buffers - I discovered this is much needed as poor-man's renamings in projects without eglot support. From unknown Sat Aug 16 16:19:53 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Sun, 29 Oct 2023 11:24:09 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator