;; Define diff-{hunk,file}-{prev,next}
(easy-mmode-define-navigation
- diff--internal-hunk diff-hunk-header-re "hunk" diff-end-of-hunk diff-restrict-view)
+ diff-hunk diff-hunk-header-re "hunk" diff-end-of-hunk diff-restrict-view
+ (when diff-auto-refine-mode
+ (unless (prog1 diff--auto-refine-data
+ (setq diff--auto-refine-data
+ (cons (current-buffer) (point-marker))))
+ (run-at-time 0.0 nil
+ (lambda ()
+ (when diff--auto-refine-data
+ (let ((buffer (car diff--auto-refine-data))
+ (point (cdr diff--auto-refine-data)))
+ (setq diff--auto-refine-data nil)
+ (with-local-quit
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char point)
+ (diff-refine-hunk))))))))))))
(easy-mmode-define-navigation
- diff--internal-file diff-file-header-re "file" diff-end-of-file)
-
-(defun diff--wrap-navigation (skip-hunk-start
- what orig
- header-re goto-start-func count)
- "Wrap diff-{hunk,file}-{next,prev} for more intuitive behavior.
-Override the default diff-{hunk,file}-{next,prev} implementation
-by skipping any lines that are associated with this hunk/file but
-precede the hunk-start marker. For instance, a diff file could
-contain
-
-diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
-index 923de9a..6b1c24f 100644
---- a/lisp/vc/diff-mode.el
-+++ b/lisp/vc/diff-mode.el
-@@ -590,6 +590,22 @@
-.......
-
-If a point is on 'index', then the point is considered to be in
-this first hunk. Move the point to the @@... marker before
-executing the default diff-hunk-next/prev implementation to move
-to the NEXT marker."
- (if (not skip-hunk-start)
- (funcall orig count)
-
- (let ((start (point)))
- (funcall goto-start-func)
-
- ;; Trap the error.
- (condition-case nil
- (funcall orig count)
- (error nil))
-
- (when (not (looking-at header-re))
- (goto-char start)
- (user-error (format "No %s" what)))
-
- ;; We successfully moved to the next/prev hunk/file. Apply the
- ;; auto-refinement if needed
- (when diff-auto-refine-mode
- (unless (prog1 diff--auto-refine-data
- (setq diff--auto-refine-data
- (cons (current-buffer) (point-marker))))
- (run-at-time 0.0 nil
- (lambda ()
- (when diff--auto-refine-data
- (let ((buffer (car diff--auto-refine-data))
- (point (cdr diff--auto-refine-data)))
- (setq diff--auto-refine-data nil)
- (with-local-quit
- (when (buffer-live-p buffer)
- (with-current-buffer buffer
- (save-excursion
- (goto-char point)
- (diff-refine-hunk))))))))))))))
-
-;; These functions all take a skip-hunk-start argument which controls
-;; whether we skip pre-hunk-start text or not. In interactive uses we
-;; always want to do this, but the simple behavior is still necessary
-;; to, for example, avoid an infinite loop:
-;;
-;; diff-hunk-next calls
-;; diff--wrap-navigation calls
-;; diff-bounds-of-hunk calls
-;; diff-beginning-of-hunk calls
-;; diff-hunk-next
-;;
-;; Here the outer diff-hunk-next has skip-hunk-start set to t, but the
-;; inner one does not, which breaks the loop.
-(defun diff-hunk-prev (&optional count skip-hunk-start)
- "Go to the previous COUNT'th hunk."
- (interactive (list (prefix-numeric-value current-prefix-arg) t))
- (diff--wrap-navigation
- skip-hunk-start
- "prev hunk"
- 'diff--internal-hunk-prev
- diff-hunk-header-re
- (lambda () (goto-char (car (diff-bounds-of-hunk))))
- count))
-
-(defun diff-hunk-next (&optional count skip-hunk-start)
- "Go to the next COUNT'th hunk."
- (interactive (list (prefix-numeric-value current-prefix-arg) t))
- (diff--wrap-navigation
- skip-hunk-start
- "next hunk"
- 'diff--internal-hunk-next
- diff-hunk-header-re
- (lambda () (goto-char (car (diff-bounds-of-hunk))))
- count))
-
-(defun diff-file-prev (&optional count skip-hunk-start)
- "Go to the previous COUNT'th file."
- (interactive (list (prefix-numeric-value current-prefix-arg) t))
- (diff--wrap-navigation
- skip-hunk-start
- "prev file"
- 'diff--internal-file-prev
- diff-file-header-re
- (lambda () (goto-char (car (diff-bounds-of-file))) (diff--internal-hunk-next))
- count))
-
-(defun diff-file-next (&optional count skip-hunk-start)
- "Go to the next COUNT'th file."
- (interactive (list (prefix-numeric-value current-prefix-arg) t))
- (diff--wrap-navigation
- skip-hunk-start
- "next file"
- 'diff--internal-file-next
- diff-file-header-re
- (lambda () (goto-char (car (diff-bounds-of-file))) (diff--internal-hunk-next))
- count))
-
-
-
+ 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.
(let ((pos (point))
(beg (diff-beginning-of-hunk t))
(end (diff-end-of-hunk)))
- (cond ((> end pos)
+ (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)))
- ;; There's no next hunk, so just take the one we have.
- (t (list beg end))))))
+ (t (error "No hunk found"))))))
(defun diff-bounds-of-file ()
"Return the bounds of the file segment at point.
(setq prevfile nextfile))
(if (and previndex (numberp prevfile) (< previndex prevfile))
(setq prevfile previndex))
- (if (numberp prevfile)
+ (if (and (numberp prevfile) (<= prevfile start))
(progn
(goto-char prevfile)
;; Now skip backward over the leading junk we may have before the
SWITCHED is non-nil if the patch is already applied.
NOPROMPT, if non-nil, means not to prompt the user."
(save-excursion
- (let* ((hunk-bounds (diff-bounds-of-hunk))
- (other (diff-xor other-file diff-jump-to-old-file))
- (char-offset (- (point) (goto-char (car hunk-bounds))))
+ (let* ((other (diff-xor other-file diff-jump-to-old-file))
+ (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),
;; Suppress check when NOPROMPT is non-nil (Bug#3033).
(_ (unless noprompt (diff-sanity-check-hunk)))
(hunk (buffer-substring
- (point) (cadr hunk-bounds)))
+ (point) (save-excursion (diff-end-of-hunk) (point))))
(old (diff-hunk-text hunk reverse char-offset))
(new (diff-hunk-text hunk (not reverse) char-offset))
;; Find the location specification.
;; Display BUF in a window
(set-window-point (display-buffer buf) (+ (car pos) (cdr new)))
(diff-hunk-status-msg line-offset (diff-xor switched reverse) nil)
-
- ;; Advance to the next hunk with skip-hunk-start set to t
- ;; because we want the behavior of moving to the next logical
- ;; hunk, not the original behavior where were would sometimes
- ;; stay on the current hunk. This is the behavior we get when
- ;; navigating through hunks interactively, and we want it when
- ;; applying hunks too (see http://debbugs.gnu.org/17544).
(when diff-advance-after-apply-hunk
- (diff-hunk-next nil t))))))
+ (diff-hunk-next))))))
(defun diff-test-hunk (&optional reverse)
(defun diff-ignore-whitespace-hunk ()
"Re-diff the current hunk, ignoring whitespace differences."
(interactive)
- (let* ((hunk-bounds (diff-bounds-of-hunk))
- (char-offset (- (point) (goto-char (car hunk-bounds))))
+ (let* ((char-offset (- (point) (diff-beginning-of-hunk t)))
(opts (pcase (char-after) (?@ "-bu") (?* "-bc") (_ "-b")))
(line-nb (and (or (looking-at "[^0-9]+\\([0-9]+\\)")
(error "Can't find line number"))
(string-to-number (match-string 1))))
(inhibit-read-only t)
(hunk (delete-and-extract-region
- (point) (cadr hunk-bounds)))
+ (point) (save-excursion (diff-end-of-hunk) (point))))
(lead (make-string (1- line-nb) ?\n)) ;Line nums start at 1.
(file1 (make-temp-file "diff1"))
(file2 (make-temp-file "diff2"))
(interactive)
(require 'smerge-mode)
(save-excursion
- (let* ((hunk-bounds (diff-bounds-of-hunk))
- (style (progn (goto-char (car hunk-bounds))
- (diff-hunk-style))) ;Skips the hunk header as well.
+ (diff-beginning-of-hunk t)
+ (let* ((start (point))
+ (style (diff-hunk-style)) ;Skips the hunk header as well.
(beg (point))
- (end (cadr hunk-bounds))
(props-c '((diff-mode . fine) (face diff-refine-changed)))
(props-r '((diff-mode . fine) (face diff-refine-removed)))
- (props-a '((diff-mode . fine) (face diff-refine-added))))
+ (props-a '((diff-mode . fine) (face diff-refine-added)))
+ ;; Be careful to go back to `start' so diff-end-of-hunk gets
+ ;; to read the hunk header's line info.
+ (end (progn (goto-char start) (diff-end-of-hunk) (point))))
(remove-overlays beg end 'diff-mode 'fine)