mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-03 08:30:09 +00:00
Fixes for diff-hunk-kill.
* lisp/vc/diff-mode.el (diff-beginning-of-hunk): Return a meaningful value, for symmetry with diff-end-of-hunk. (diff-split-hunk, diff-find-source-location) (diff-ignore-whitespace-hunk, diff-refine-hunk): Use it. (diff-bounds-of-hunk, diff-bounds-of-file): New functions. (diff-restrict-view, diff-hunk-kill, diff-file-kill): Use them to compute the relevant hunk or file properly. (diff-file-junk-re): Add bzr's "modified file" tag. Fixes: debbugs:6041 debbugs:6005
This commit is contained in:
parent
8b71081d30
commit
cb3e7ae07a
@ -1,3 +1,14 @@
|
||||
2012-04-26 Chong Yidong <cyd@gnu.org>
|
||||
|
||||
* vc/diff-mode.el (diff-beginning-of-hunk): Return a meaningful
|
||||
value, for symmetry with diff-end-of-hunk.
|
||||
(diff-split-hunk, diff-find-source-location)
|
||||
(diff-ignore-whitespace-hunk, diff-refine-hunk): Use it.
|
||||
(diff-bounds-of-hunk, diff-bounds-of-file): New functions.
|
||||
(diff-restrict-view, diff-hunk-kill, diff-file-kill): Use them to
|
||||
compute the relevant hunk or file properly (Bug#6005).
|
||||
(diff-file-junk-re): Add bzr's "modified file" tag (Bug#6041).
|
||||
|
||||
2012-04-26 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* vc/vc-mtn.el:
|
||||
|
@ -434,6 +434,7 @@ See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html")
|
||||
style)
|
||||
|
||||
(defun diff-end-of-hunk (&optional style donttrustheader)
|
||||
"Advance to the end of the current hunk, and return its position."
|
||||
(let (end)
|
||||
(when (looking-at diff-hunk-header-re)
|
||||
;; Especially important for unified (because headers are ambiguous).
|
||||
@ -481,19 +482,21 @@ See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html")
|
||||
(goto-char (or end (point-max)))))
|
||||
|
||||
(defun diff-beginning-of-hunk (&optional try-harder)
|
||||
"Move back to beginning of hunk.
|
||||
If TRY-HARDER is non-nil, try to cater to the case where we're not in a hunk
|
||||
but in the file header instead, in which case move forward to the first hunk."
|
||||
"Move back to the previous hunk beginning, and return its position.
|
||||
If point is in a file header rather than a hunk, advance to the
|
||||
next hunk if TRY-HARDER is non-nil; otherwise signal an error."
|
||||
(beginning-of-line)
|
||||
(unless (looking-at diff-hunk-header-re)
|
||||
(if (looking-at diff-hunk-header-re)
|
||||
(point)
|
||||
(forward-line 1)
|
||||
(condition-case ()
|
||||
(re-search-backward diff-hunk-header-re)
|
||||
(error
|
||||
(if (not try-harder)
|
||||
(error "Can't find the beginning of the hunk")
|
||||
(diff-beginning-of-file-and-junk)
|
||||
(diff-hunk-next))))))
|
||||
(unless try-harder
|
||||
(error "Can't find the beginning of the hunk"))
|
||||
(diff-beginning-of-file-and-junk)
|
||||
(diff-hunk-next)
|
||||
(point)))))
|
||||
|
||||
(defun diff-unified-hunk-p ()
|
||||
(save-excursion
|
||||
@ -536,44 +539,72 @@ but in the file header instead, in which case move forward to the first hunk."
|
||||
(easy-mmode-define-navigation
|
||||
diff-file diff-file-header-re "file" diff-end-of-file)
|
||||
|
||||
(defun diff-bounds-of-hunk ()
|
||||
"Return the bounds of the diff hunk at point.
|
||||
The return value is a list (BEG END), which are the hunk's start
|
||||
and end positions. Signal an error if no hunk is found. If
|
||||
point is in a file header, return the bounds of the next hunk."
|
||||
(save-excursion
|
||||
(let ((pos (point))
|
||||
(beg (diff-beginning-of-hunk t))
|
||||
(end (diff-end-of-hunk)))
|
||||
(cond ((>= end pos)
|
||||
(list beg end))
|
||||
;; If this hunk ends above POS, consider the next hunk.
|
||||
((re-search-forward diff-hunk-header-re nil t)
|
||||
(list (match-beginning 0) (diff-end-of-hunk)))
|
||||
(t (error "No hunk found"))))))
|
||||
|
||||
(defun diff-bounds-of-file ()
|
||||
"Return the bounds of the file segment at point.
|
||||
The return value is a list (BEG END), which are the segment's
|
||||
start and end positions."
|
||||
(save-excursion
|
||||
(let ((pos (point))
|
||||
(beg (progn (diff-beginning-of-file-and-junk)
|
||||
(point))))
|
||||
(diff-end-of-file)
|
||||
;; bzr puts a newline after the last hunk.
|
||||
(while (looking-at "^\n")
|
||||
(forward-char 1))
|
||||
(if (> pos (point))
|
||||
(error "Not inside a file diff"))
|
||||
(list beg (point)))))
|
||||
|
||||
(defun diff-restrict-view (&optional arg)
|
||||
"Restrict the view to the current hunk.
|
||||
If the prefix ARG is given, restrict the view to the current file instead."
|
||||
(interactive "P")
|
||||
(save-excursion
|
||||
(if arg (diff-beginning-of-file) (diff-beginning-of-hunk 'try-harder))
|
||||
(narrow-to-region (point)
|
||||
(progn (if arg (diff-end-of-file) (diff-end-of-hunk))
|
||||
(point)))
|
||||
(set (make-local-variable 'diff-narrowed-to) (if arg 'file 'hunk))))
|
||||
|
||||
(apply 'narrow-to-region
|
||||
(if arg (diff-bounds-of-file) (diff-bounds-of-hunk)))
|
||||
(set (make-local-variable 'diff-narrowed-to) (if arg 'file 'hunk)))
|
||||
|
||||
(defun diff-hunk-kill ()
|
||||
"Kill current hunk."
|
||||
"Kill the hunk at point."
|
||||
(interactive)
|
||||
(diff-beginning-of-hunk)
|
||||
(let* ((start (point))
|
||||
;; Search the second match, since we're looking at the first.
|
||||
(nexthunk (when (re-search-forward diff-hunk-header-re nil t 2)
|
||||
(match-beginning 0)))
|
||||
(firsthunk (ignore-errors
|
||||
(goto-char start)
|
||||
(diff-beginning-of-file) (diff-hunk-next) (point)))
|
||||
(nextfile (ignore-errors (diff-file-next) (point)))
|
||||
(let* ((hunk-bounds (diff-bounds-of-hunk))
|
||||
(file-bounds (ignore-errors (diff-bounds-of-file)))
|
||||
;; If the current hunk is the only one for its file, kill the
|
||||
;; file header too.
|
||||
(bounds (if (and file-bounds
|
||||
(progn (goto-char (car file-bounds))
|
||||
(= (progn (diff-hunk-next) (point))
|
||||
(car hunk-bounds)))
|
||||
(progn (goto-char (cadr hunk-bounds))
|
||||
;; bzr puts a newline after the last hunk.
|
||||
(while (looking-at "^\n")
|
||||
(forward-char 1))
|
||||
(= (point) (cadr file-bounds))))
|
||||
file-bounds
|
||||
hunk-bounds))
|
||||
(inhibit-read-only t))
|
||||
(goto-char start)
|
||||
(if (and firsthunk (= firsthunk start)
|
||||
(or (null nexthunk)
|
||||
(and nextfile (> nexthunk nextfile))))
|
||||
;; It's the only hunk for this file, so kill the file.
|
||||
(diff-file-kill)
|
||||
(diff-end-of-hunk)
|
||||
(kill-region start (point)))))
|
||||
(apply 'kill-region bounds)
|
||||
(goto-char (car bounds))))
|
||||
|
||||
;; "index ", "old mode", "new mode", "new file mode" and
|
||||
;; "deleted file mode" are output by git-diff.
|
||||
(defconst diff-file-junk-re
|
||||
"diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode")
|
||||
"diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode\\|=== modified file")
|
||||
|
||||
(defun diff-beginning-of-file-and-junk ()
|
||||
"Go to the beginning of file-related diff-info.
|
||||
@ -625,13 +656,8 @@ data such as \"Index: ...\" and such."
|
||||
(defun diff-file-kill ()
|
||||
"Kill current file's hunks."
|
||||
(interactive)
|
||||
(let ((orig (point))
|
||||
(start (progn (diff-beginning-of-file-and-junk) (point)))
|
||||
(inhibit-read-only t))
|
||||
(diff-end-of-file)
|
||||
(if (looking-at "^\n") (forward-char 1)) ;`tla' generates such diffs.
|
||||
(if (> orig (point)) (error "Not inside a file diff"))
|
||||
(kill-region start (point))))
|
||||
(let ((inhibit-read-only t))
|
||||
(apply 'kill-region (diff-bounds-of-file))))
|
||||
|
||||
(defun diff-kill-junk ()
|
||||
"Kill spurious empty diffs."
|
||||
@ -667,7 +693,7 @@ data such as \"Index: ...\" and such."
|
||||
(interactive)
|
||||
(beginning-of-line)
|
||||
(let ((pos (point))
|
||||
(start (progn (diff-beginning-of-hunk) (point))))
|
||||
(start (diff-beginning-of-hunk)))
|
||||
(unless (looking-at diff-hunk-header-re-unified)
|
||||
(error "diff-split-hunk only works on unified context diffs"))
|
||||
(forward-line 1)
|
||||
@ -1589,8 +1615,7 @@ SWITCHED is non-nil if the patch is already applied.
|
||||
NOPROMPT, if non-nil, means not to prompt the user."
|
||||
(save-excursion
|
||||
(let* ((other (diff-xor other-file diff-jump-to-old-file))
|
||||
(char-offset (- (point) (progn (diff-beginning-of-hunk 'try-harder)
|
||||
(point))))
|
||||
(char-offset (- (point) (diff-beginning-of-hunk t)))
|
||||
;; Check that the hunk is well-formed. Otherwise diff-mode and
|
||||
;; the user may disagree on what constitutes the hunk
|
||||
;; (e.g. because an empty line truncates the hunk mid-course),
|
||||
@ -1777,8 +1802,7 @@ For use in `add-log-current-defun-function'."
|
||||
(defun diff-ignore-whitespace-hunk ()
|
||||
"Re-diff the current hunk, ignoring whitespace differences."
|
||||
(interactive)
|
||||
(let* ((char-offset (- (point) (progn (diff-beginning-of-hunk 'try-harder)
|
||||
(point))))
|
||||
(let* ((char-offset (- (point) (diff-beginning-of-hunk t)))
|
||||
(opts (case (char-after) (?@ "-bu") (?* "-bc") (t "-b")))
|
||||
(line-nb (and (or (looking-at "[^0-9]+\\([0-9]+\\)")
|
||||
(error "Can't find line number"))
|
||||
@ -1854,7 +1878,7 @@ For use in `add-log-current-defun-function'."
|
||||
(interactive)
|
||||
(require 'smerge-mode)
|
||||
(save-excursion
|
||||
(diff-beginning-of-hunk 'try-harder)
|
||||
(diff-beginning-of-hunk t)
|
||||
(let* ((start (point))
|
||||
(style (diff-hunk-style)) ;Skips the hunk header as well.
|
||||
(beg (point))
|
||||
|
Loading…
Reference in New Issue
Block a user