Fix 'd' command in 'query-replace' in buffers not visiting files

* lisp/vc/diff.el (diff-file-local-copy): Use proper coding-system
when writing a local copy of a non-file visiting buffer.

* lisp/misearch.el (coding-system--for-buffer-diff): New variable.
(multi-file-replace-as-diff): Bind it to 'utf-8-emacs'.
(multi-file-diff-no-select): Use proper coding-system when reading
output of Diff.  (Bug#79761)
This commit is contained in:
Eli Zaretskii 2025-11-23 10:32:18 +02:00
parent 6c30c6c87d
commit bb1f70c901
2 changed files with 16 additions and 3 deletions

View file

@ -406,6 +406,9 @@ modified buffer to be able to use unsaved changes."
(declare-function diff-setup-whitespace "diff-mode" ())
(declare-function diff-setup-buffer-type "diff-mode" ())
(defvar coding-system--for-buffer-diff nil
"Used to pass encoding down to callees of `multi-file-diff-no-select'.")
;;;###autoload
(defun multi-file-replace-as-diff (files from-string replacements regexp-flag delimited-flag)
"Show as diffs replacements of FROM-STRING with REPLACEMENTS.
@ -439,7 +442,11 @@ as in `perform-replace'."
file-name
(when (or (not file-exists)
(eq multi-file-diff-unsaved 'use-modified-buffer))
(find-buffer-visiting file-name)))))
(find-buffer-visiting file-name))))
;; Make sure any supported characters can be written to a
;; file without asking the user to select a safe
;; coding-system.
(coding-system--for-buffer-diff 'utf-8-emacs))
(when non-file-buffer (setq file-name (buffer-name file-name)))
(when (or file-exists file-buffer)
(with-temp-buffer
@ -540,7 +547,9 @@ specify labels to use for file names."
(or new-alt new)))))
" ")))
(with-current-buffer buf
(let ((inhibit-read-only t))
(let ((inhibit-read-only t)
(coding-system-for-read (or coding-system--for-buffer-diff
coding-system-for-read)))
(insert command "\n")
(call-process shell-file-name nil buf nil
shell-command-switch command))

View file

@ -118,13 +118,17 @@ Non-interactively, OLD and NEW may each be a file or a buffer."
(display-buffer
(diff-no-select old new switches no-async)))
(defvar coding-system--for-buffer-diff) ; from misearch.el
(defun diff-file-local-copy (file-or-buf)
"Like `file-local-copy' but also supports a buffer as the argument.
When FILE-OR-BUF is a buffer, return the filename of a local
temporary file with the buffer's contents."
(if (bufferp file-or-buf)
(with-current-buffer file-or-buf
(let ((tempfile (make-temp-file "buffer-content-")))
(let ((tempfile (make-temp-file "buffer-content-"))
(coding-system-for-write (or coding-system--for-buffer-diff
coding-system-for-write)))
(if diff-entire-buffers
(write-region nil nil tempfile nil 'nomessage)
(write-region (point-min) (point-max) tempfile nil 'nomessage))