]> git.eshelyaron.com Git - emacs.git/commitdiff
New command diff-revert-and-kill-hunk
authorSean Whitton <spwhitton@spwhitton.name>
Tue, 24 Sep 2024 08:38:43 +0000 (09:38 +0100)
committerEshel Yaron <me@eshelyaron.com>
Fri, 27 Sep 2024 10:22:59 +0000 (12:22 +0200)
* lisp/vc/diff-mode.el (diff-revert-and-kill-hunk): New
command (bug#73407).
(diff-ask-before-revert-and-kill-hunk): New user option.
(diff-apply-buffer): New optional BEG, END and REVERSE
arguments.  Return nil if buffers were saved, or the number of
failed applications.
(diff-mode-map): Bind the new command to C-c M-r.
(diff-mode-menu): New entry for the new command.
* doc/emacs/files.texi (Diff Mode):
* etc/NEWS: Document the change.

(cherry picked from commit f2e3e563d4909ff503bb2d3aeb6d2de9804e3047)

doc/emacs/files.texi
etc/NEWS
lisp/vc/diff-mode.el

index 8c3df9cc2267f195478416dcf2ca82b0a23e51d4..c9d4d0b6b243a391626e2bde16e426a23adc090c 100644 (file)
@@ -1680,6 +1680,21 @@ reverse of the hunk, which changes the ``new'' version into the ``old''
 version.  If @code{diff-jump-to-old-file} is non-@code{nil}, apply the
 hunk to the ``old'' version of the file instead.
 
+@findex diff-revert-and-kill-hunk
+@item C-c M-r
+Reverse-apply this hunk to the target file, and then kill it
+(@code{diff-revert-and-kill-hunk}).  Save the buffer visiting the target
+file.
+
+This command is useful in buffers generated by @w{@kbd{C-x v =}} and
+@w{@kbd{C-x v D}} (@pxref{Old Revisions}).  These buffers present you
+with a view of the changes you've made, and then you can use this
+command to drop changes you didn't intend, or no longer want.
+
+This is a destructive operation, so by default, this command asks you to
+confirm you really want to reverse-apply and kill the hunk.  You can
+customize @code{diff-ask-before-revert-and-kill-hunk} to change that.
+
 @findex diff-apply-buffer
 @item C-c @key{RET} a
 Apply all the hunks in the buffer (@code{diff-apply-buffer}).  If the
index 1ccb7e9bb0bb82a0832732919a1aab657673096d..ba63c6ce9ea884fc61c75d33e197496eea4f75c3 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -319,6 +319,20 @@ The host name for Kubernetes connections can be of kind
 used.  This overrides the setting in 'tramp-kubernetes-namespace', if
 any.
 
+** Diff
+
+---
+*** New command 'diff-kill-ring-save'.
+This command copies to the 'kill-ring' a region of text modified
+according to diffs in the current buffer, but without applying the diffs
+to the original text.  If the selected range extends a hunk, the
+command attempts to look up and copy the text in-between the hunks.
+
++++
+*** New command 'diff-revert-and-kill-hunk' bound to C-c M-r.
+This command reverse-applies the hunk at point, and then kills it.
+This is useful in buffers generated by C-x v = and C-x v D.
+
 ** php-ts-mode
 
 ---
index 0cea393538f30cfc6068ed2512ed09833b333a2f..ca06d189343fec706f6c5adb4cd5509ef7529a38 100644 (file)
@@ -217,6 +217,7 @@ The default \"-b\" means to ignore whitespace-only changes,
   "C-x 4 A" #'diff-add-change-log-entries-other-window
   ;; Misc operations.
   "C-c C-a" #'diff-apply-hunk
+  "C-c M-r" #'diff-revert-and-kill-hunk
   "C-c C-m a" #'diff-apply-buffer
   "C-c C-e" #'diff-ediff-patch
   "C-c C-n" #'diff-restrict-view
@@ -241,6 +242,8 @@ The default \"-b\" means to ignore whitespace-only changes,
      :help "Apply the current hunk to the source file and go to the next"]
     ["Test applying hunk"      diff-test-hunk
      :help "See whether it's possible to apply the current hunk"]
+    ["Revert and kill hunk"     diff-revert-and-kill-hunk
+     :help "Reverse-apply and then kill the current hunk."]
     ["Apply all hunks"         diff-apply-buffer
      :help "Apply all hunks in the current diff buffer"]
     ["Apply diff with Ediff"   diff-ediff-patch
@@ -2058,18 +2061,45 @@ With a prefix argument, try to REVERSE the hunk."
           (diff-hunk-kill)
         (diff-hunk-next)))))
 
-(defun diff-apply-buffer ()
+(defcustom diff-ask-before-revert-and-kill-hunk t
+  "If non-nil, `diff-revert-and-kill-hunk' will ask for confirmation."
+  :type 'boolean)
+
+(defun diff-revert-and-kill-hunk ()
+  "Reverse-apply and then kill the hunk at point.  Save changed buffer.
+
+This command is useful in buffers generated by \\[vc-diff] and \\[vc-root-diff],
+especially when preparing to commit the patch with \\[vc-next-action].
+You can use \\<diff-mode-map>\\[diff-hunk-kill] to temporarily remove changes that you intend to
+include in a separate commit or commits, and you can use this command
+to permanently drop changes you didn't intend, or no longer want.
+
+This is a destructive operation, so by default, this command asks you to
+confirm you really want to reverse-apply and kill the hunk.  You can
+customize `diff-ask-before-revert-and-kill-hunk' to change that."
+  (interactive)
+  (when (or (not diff-ask-before-revert-and-kill-hunk)
+            (yes-or-no-p "Really reverse-apply and kill this hunk?"))
+    (cl-destructuring-bind (beg end) (diff-bounds-of-hunk)
+      (when (null (diff-apply-buffer beg end t))
+        (diff-hunk-kill)))))
+
+(defun diff-apply-buffer (&optional beg end reverse)
   "Apply the diff in the entire diff buffer.
-When applying all hunks was successful, then save the changed buffers."
+When applying all hunks was successful, then save the changed buffers.
+When called from Lisp with optional arguments, restrict the application
+to hunks lying between BEG and END, and reverse-apply when REVERSE is
+non-nil.  Returns nil if buffers were saved, or the number of failed
+applications."
   (interactive)
   (let ((buffer-edits nil)
         (failures 0)
         (diff-refine nil))
     (save-excursion
-      (goto-char (point-min))
+      (goto-char (or beg (point-min)))
       (diff-beginning-of-hunk t)
-      (while (pcase-let ((`(,buf ,line-offset ,pos ,src ,dst ,switched)
-                          (diff-find-source-location nil nil)))
+      (while (pcase-let ((`(,buf ,line-offset ,pos ,_src ,dst ,switched)
+                          (diff-find-source-location nil reverse)))
                (cond ((and line-offset (not switched))
                       (push (cons pos dst)
                             (alist-get buf buffer-edits))
@@ -2078,6 +2108,7 @@ When applying all hunks was successful, then save the changed buffers."
                      (t (setq failures (1+ failures))))
                (and (not (eq (prog1 (point) (ignore-errors (diff-hunk-next)))
                              (point)))
+                    (or (not end) (< (point) end))
                     (looking-at-p diff-hunk-header-re)))))
     (cond ((zerop failures)
            (dolist (buf-edits (reverse buffer-edits))
@@ -2090,11 +2121,13 @@ When applying all hunks was successful, then save the changed buffers."
                    (delete-region (car pos) (cdr pos))
                    (insert (car dst))))
                (save-buffer)))
-           (message "Saved %d buffers" (length buffer-edits)))
+           (message "Saved %d buffers" (length buffer-edits))
+           nil)
           (t
            (message (ngettext "%d hunk failed; no buffers changed"
                               "%d hunks failed; no buffers changed"
-                              failures))))))
+                              failures))
+           failures))))
 
 (defalias 'diff-mouse-goto-source #'diff-goto-source)