1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

Improve ibuffer-diff-with-file

* lisp/ibuf-ext.el (ibuffer-diff-with-file): Link to diff-command in
docstring.  Make Diff buffer read-only from outset and inhibit as
needed to avoid surprises.  Check whether diff-command
supports --label.  Leave point at BOB and clean up any excess
newline inserted by ibuffer-diff-buffer-with-file-1.  Prefer
pop-to-buffer-same-window over switch-to-buffer.

(ibuffer-diff-buffer-with-file-1): Add docstring.  Remove unused
unwind-protect and copypasta from diff-no-select (bug#62599).  Use
diff-file-local-copy, string-join, and redisplay in place of
analogues.  Condition --label use on availability, and label buffers
consistently with diff-no-select.  Leave empty line between runs.
Let diff-sentinel delete temporary files.  Leave point at EOB for
next run.
This commit is contained in:
Basil L. Contovounesios 2023-04-01 15:14:34 +01:00
parent 9848ae1716
commit 10b58633b5

View file

@ -1650,68 +1650,67 @@ a prefix argument reverses the meaning of that variable."
(error "No buffer with name %s" name) (error "No buffer with name %s" name)
(goto-char buf-point))))) (goto-char buf-point)))))
(declare-function diff-check-labels "diff" (&optional force))
(declare-function diff-file-local-copy "diff" (file-or-buf))
(declare-function diff-sentinel "diff" (declare-function diff-sentinel "diff"
(code &optional old-temp-file new-temp-file)) (code &optional old-temp-file new-temp-file))
(defun ibuffer-diff-buffer-with-file-1 (buffer) (defun ibuffer-diff-buffer-with-file-1 (buffer)
(let ((bufferfile (buffer-local-value 'buffer-file-name buffer)) "Compare BUFFER with its associated file, if any.
(tempfile (make-temp-file "buffer-content-"))) Unlike `diff-no-select', insert output into current buffer
(when bufferfile without erasing it."
(unwind-protect (when-let ((old (buffer-file-name buffer)))
(progn (defvar diff-use-labels)
(with-current-buffer buffer (let* ((new buffer)
(write-region nil nil tempfile nil 'nomessage)) (oldtmp (diff-file-local-copy old))
(let* ((old (expand-file-name bufferfile)) (newtmp (diff-file-local-copy new))
(new (expand-file-name tempfile))
(oldtmp (file-local-copy old))
(newtmp (file-local-copy new))
(switches diff-switches) (switches diff-switches)
(command (command
(mapconcat (string-join
'identity
`(,diff-command `(,diff-command
;; Use explicitly specified switches
,@(if (listp switches) switches (list switches)) ,@(if (listp switches) switches (list switches))
,@(if (or old new) ,@(and (eq diff-use-labels t)
(list "-L" (shell-quote-argument old) (list "--label" (shell-quote-argument old)
"-L" (shell-quote-argument "--label" (shell-quote-argument (format "%S" new))))
(format "Buffer %s" (buffer-name buffer)))))
,(shell-quote-argument (or oldtmp old)) ,(shell-quote-argument (or oldtmp old))
,(shell-quote-argument (or newtmp new))) ,(shell-quote-argument (or newtmp new)))
" "))) " "))
(let ((inhibit-read-only t)) (inhibit-read-only t))
(insert command "\n") (insert ?\n command ?\n)
(diff-sentinel (diff-sentinel (call-process shell-file-name nil t nil
(call-process shell-file-name nil shell-command-switch command)
(current-buffer) nil oldtmp newtmp)
shell-command-switch command)) (goto-char (point-max)))
(insert "\n"))))) (redisplay)))
(sit-for 0)
(when (file-exists-p tempfile)
(delete-file tempfile)))))
;;;###autoload ;;;###autoload
(defun ibuffer-diff-with-file () (defun ibuffer-diff-with-file ()
"View the differences between marked buffers and their associated files. "View the differences between marked buffers and their associated files.
If no buffers are marked, use buffer at point. If no buffers are marked, use buffer at point.
This requires the external program \"diff\" to be in your `exec-path'." This requires the external program `diff-command' to be in your
`exec-path'."
(interactive) (interactive)
(require 'diff) (require 'diff)
(let ((marked-bufs (ibuffer-get-marked-buffers))) (let ((marked-bufs (or (ibuffer-get-marked-buffers)
(when (null marked-bufs) (list (ibuffer-current-buffer t))))
(setq marked-bufs (list (ibuffer-current-buffer t)))) (diff-buf (get-buffer-create "*Ibuffer Diff*")))
(with-current-buffer (get-buffer-create "*Ibuffer Diff*") (with-current-buffer diff-buf
(setq buffer-read-only nil) (setq buffer-read-only t)
(buffer-disable-undo (current-buffer)) (buffer-disable-undo)
(erase-buffer) (let ((inhibit-read-only t))
(buffer-enable-undo (current-buffer)) (erase-buffer))
(buffer-enable-undo)
(diff-mode) (diff-mode)
(diff-check-labels)
(dolist (buf marked-bufs) (dolist (buf marked-bufs)
(unless (buffer-live-p buf) (unless (buffer-live-p buf)
(error "Buffer %s has been killed" buf)) (error "Buffer %s has been killed" buf))
(ibuffer-diff-buffer-with-file-1 buf)) (ibuffer-diff-buffer-with-file-1 buf))
(setq buffer-read-only t))) (goto-char (point-min))
(switch-to-buffer "*Ibuffer Diff*")) (when (= (following-char) ?\n)
(let ((inhibit-read-only t))
(delete-char 1))))
(pop-to-buffer-same-window diff-buf)))
;;;###autoload ;;;###autoload
(defun ibuffer-copy-filename-as-kill (&optional arg) (defun ibuffer-copy-filename-as-kill (&optional arg)