New command diff-delete-other-hunks

* lisp/vc/diff-mode.el (diff-delete-other-hunks): New
command (bug#73387).
(diff-mode-map): Bind the new command to C-c RET n.
(diff-mode-menu): New entry for the new command.
(vc-next-action): Stop, and warn, if the user attempts to commit
a patch from a narrowed buffer (bug#73387).
* doc/emacs/files.texi (Diff Mode):
* etc/NEWS: Document the new command.
This commit is contained in:
Sean Whitton 2024-09-30 21:08:38 +08:00
parent f95d4208b6
commit b64f69f6dc
4 changed files with 57 additions and 0 deletions

View file

@ -1703,6 +1703,11 @@ confirm you really want to revert and kill the hunk. You can customize
Apply all the hunks in the buffer (@code{diff-apply-buffer}). If the
diffs were applied successfully, save the changed buffers.
@findex diff-delete-other-hunks
@item C-c @key{RET} n
Delete all hunks other than the current hunk. If the region is active,
then delete all hunks that the region does not overlap.
@findex diff-refine-hunk
@item C-c C-b
Highlight the changes of the hunk at point with a finer granularity

View file

@ -382,6 +382,13 @@ Previously, 'diff-file-prev' and 'diff-hunk-prev' would move when point
is after the corresponding file or hunk header, but not when inside it.
Now they will always move to the start of the current header.
+++
*** New command 'diff-delete-other-hunks' bound to C-c RET n.
This command deletes all hunks other than the current hunk. It is
useful to prepare a *vc-diff* buffer for committing a single hunk.
When the region is active, it deletes all hunks that the region does not
overlap.
** php-ts-mode
---

View file

@ -220,6 +220,7 @@ The default \"-b\" means to ignore whitespace-only changes,
"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-m n" #'diff-delete-other-hunks
"C-c C-e" #'diff-ediff-patch
"C-c C-n" #'diff-restrict-view
"C-c C-s" #'diff-split-hunk
@ -278,6 +279,8 @@ The default \"-b\" means to ignore whitespace-only changes,
:help "Kill current hunk"]
["Kill current file's hunks" diff-file-kill
:help "Kill all current file's hunks"]
["Delete other hunks" diff-delete-other-hunks
:help "Delete hunks other than the current hunk"]
"-----"
["Previous Hunk" diff-hunk-prev
:help "Go to the previous count'th hunk"]
@ -814,6 +817,37 @@ If the prefix ARG is given, restrict the view to the current file instead."
(goto-char (car bounds))
(ignore-errors (diff-beginning-of-hunk t)))))
;; This is not `diff-kill-other-hunks' because we might need to make
;; copies of file headers in order to ensure the new kill ring entry
;; would be a patch with the same meaning. That is not implemented
;; because it does not seem like it would be useful.
(defun diff-delete-other-hunks (&optional beg end)
"Delete all hunks other than the current hunk.
Interactively, if the region is active, then delete all hunks that the
region does not overlap. When called from Lisp, the optional arguments
BEG and END specify the region of hunks not to delete."
(interactive (list (use-region-beginning) (use-region-end)))
(when (buffer-narrowed-p)
(user-error "Command is not safe in a narrowed buffer"))
(let ((inhibit-read-only t))
(save-excursion
(cond ((xor beg end)
(error "Require exactly zero or two arguments"))
(beg
(goto-char beg)
(setq beg (car (diff-bounds-of-hunk)))
(goto-char end)
(setq end (cadr (diff-bounds-of-hunk))))
(t
(pcase-setq `(,beg ,end) (diff-bounds-of-hunk))))
(delete-region end (point-max))
(goto-char beg)
(diff-beginning-of-file)
(diff-hunk-next)
(delete-region (point) beg)
(diff-beginning-of-file-and-junk)
(delete-region (point-min) (point)))))
(defun diff-beginning-of-file-and-junk ()
"Go to the beginning of file-related diff-info.
This is like `diff-beginning-of-file' except it tries to skip back over leading

View file

@ -1302,6 +1302,17 @@ from which to check out the file(s)."
;; Fileset comes from a diff-mode buffer, see
;; 'diff-vc-deduce-fileset', and the buffer is the patch to apply.
((eq model 'patch)
(when (buffer-narrowed-p)
;; If user used `diff-restrict-view' then we may not have the
;; file header, and the commit will not succeed (bug#73387).
(user-error "Cannot commit patch when narrowed; consider %s"
(mapconcat (lambda (c)
(key-description
(where-is-internal c nil t)))
'(widen
diff-delete-other-hunks
vc-next-action)
" ")))
(vc-checkin files backend nil nil nil (buffer-string)))
((or (null state) (eq state 'unregistered))
(cond (verbose