aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/vc/diff-mode.el131
1 files changed, 118 insertions, 13 deletions
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 58498cb6115..c9a5f89b9a1 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -551,7 +551,7 @@ next hunk if TRY-HARDER is non-nil; otherwise signal an error."
551 551
552;; Define diff-{hunk,file}-{prev,next} 552;; Define diff-{hunk,file}-{prev,next}
553(easy-mmode-define-navigation 553(easy-mmode-define-navigation
554 diff-hunk diff-hunk-header-re "hunk" diff-end-of-hunk diff-restrict-view 554 diff--internal-hunk diff-hunk-header-re "hunk" diff-end-of-hunk diff-restrict-view
555 (when diff-auto-refine-mode 555 (when diff-auto-refine-mode
556 (unless (prog1 diff--auto-refine-data 556 (unless (prog1 diff--auto-refine-data
557 (setq diff--auto-refine-data 557 (setq diff--auto-refine-data
@@ -570,7 +570,102 @@ next hunk if TRY-HARDER is non-nil; otherwise signal an error."
570 (diff-refine-hunk)))))))))))) 570 (diff-refine-hunk))))))))))))
571 571
572(easy-mmode-define-navigation 572(easy-mmode-define-navigation
573 diff-file diff-file-header-re "file" diff-end-of-file) 573 diff--internal-file diff-file-header-re "file" diff-end-of-file)
574
575(defun diff--wrap-navigation (skip-hunk-start
576 what orig
577 header-re goto-start-func count)
578 "Wrap diff-{hunk,file}-{next,prev} for more intuitive behavior.
579Override the default diff-{hunk,file}-{next,prev} implementation
580by skipping any lines that are associated with this hunk/file but
581precede the hunk-start marker. For instance, a diff file could
582contain
583
584diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
585index 923de9a..6b1c24f 100644
586--- a/lisp/vc/diff-mode.el
587+++ b/lisp/vc/diff-mode.el
588@@ -590,6 +590,22 @@
589.......
590
591If a point is on 'index', then the point is considered to be in
592this first hunk. Move the point to the @@... marker before
593executing the default diff-hunk-next/prev implementation to move
594to the NEXT marker."
595 (if (not skip-hunk-start)
596 (funcall orig count)
597
598 (let ((start (point)))
599 (funcall goto-start-func)
600
601 ;; Trap the error.
602 (condition-case nil
603 (funcall orig count)
604 (error nil))
605
606 (when (not (looking-at header-re))
607 (goto-char start)
608 (user-error (format "No %s" what))))))
609
610;; These functions all take a skip-hunk-start argument which controls
611;; whether we skip pre-hunk-start text or not. In interactive uses we
612;; always want to do this, but the simple behavior is still necessary
613;; to, for example, avoid an infinite loop:
614;;
615;; diff-hunk-next calls
616;; diff--wrap-navigation calls
617;; diff-bounds-of-hunk calls
618;; diff-beginning-of-hunk calls
619;; diff-hunk-next
620;;
621;; Here the outer diff-hunk-next has skip-hunk-start set to t, but the
622;; inner one does not, which breaks the loop.
623(defun diff-hunk-prev (&optional count skip-hunk-start)
624 "Go to the previous COUNT'th hunk."
625 (interactive (list (prefix-numeric-value current-prefix-arg) t))
626 (diff--wrap-navigation
627 skip-hunk-start
628 "prev hunk"
629 'diff--internal-hunk-prev
630 diff-hunk-header-re
631 (lambda () (goto-char (car (diff-bounds-of-hunk))))
632 count))
633
634(defun diff-hunk-next (&optional count skip-hunk-start)
635 "Go to the next COUNT'th hunk."
636 (interactive (list (prefix-numeric-value current-prefix-arg) t))
637 (diff--wrap-navigation
638 skip-hunk-start
639 "next hunk"
640 'diff--internal-hunk-next
641 diff-hunk-header-re
642 (lambda () (goto-char (car (diff-bounds-of-hunk))))
643 count))
644
645(defun diff-file-prev (&optional count skip-hunk-start)
646 "Go to the previous COUNT'th file."
647 (interactive (list (prefix-numeric-value current-prefix-arg) t))
648 (diff--wrap-navigation
649 skip-hunk-start
650 "prev file"
651 'diff--internal-file-prev
652 diff-file-header-re
653 (lambda () (goto-char (car (diff-bounds-of-file))) (diff--internal-hunk-next))
654 count))
655
656(defun diff-file-next (&optional count skip-hunk-start)
657 "Go to the next COUNT'th file."
658 (interactive (list (prefix-numeric-value current-prefix-arg) t))
659 (diff--wrap-navigation
660 skip-hunk-start
661 "next file"
662 'diff--internal-file-next
663 diff-file-header-re
664 (lambda () (goto-char (car (diff-bounds-of-file))) (diff--internal-hunk-next))
665 count))
666
667
668
574 669
575(defun diff-bounds-of-hunk () 670(defun diff-bounds-of-hunk ()
576 "Return the bounds of the diff hunk at point. 671 "Return the bounds of the diff hunk at point.
@@ -581,12 +676,13 @@ point is in a file header, return the bounds of the next hunk."
581 (let ((pos (point)) 676 (let ((pos (point))
582 (beg (diff-beginning-of-hunk t)) 677 (beg (diff-beginning-of-hunk t))
583 (end (diff-end-of-hunk))) 678 (end (diff-end-of-hunk)))
584 (cond ((>= end pos) 679 (cond ((> end pos)
585 (list beg end)) 680 (list beg end))
586 ;; If this hunk ends above POS, consider the next hunk. 681 ;; If this hunk ends above POS, consider the next hunk.
587 ((re-search-forward diff-hunk-header-re nil t) 682 ((re-search-forward diff-hunk-header-re nil t)
588 (list (match-beginning 0) (diff-end-of-hunk))) 683 (list (match-beginning 0) (diff-end-of-hunk)))
589 (t (error "No hunk found")))))) 684 ;; There's no next hunk, so just take the one we have.
685 (t (list beg end))))))
590 686
591(defun diff-bounds-of-file () 687(defun diff-bounds-of-file ()
592 "Return the bounds of the file segment at point. 688 "Return the bounds of the file segment at point.
@@ -1665,8 +1761,9 @@ SRC and DST are the two variants of text as returned by `diff-hunk-text'.
1665SWITCHED is non-nil if the patch is already applied. 1761SWITCHED is non-nil if the patch is already applied.
1666NOPROMPT, if non-nil, means not to prompt the user." 1762NOPROMPT, if non-nil, means not to prompt the user."
1667 (save-excursion 1763 (save-excursion
1668 (let* ((other (diff-xor other-file diff-jump-to-old-file)) 1764 (let* ((hunk-bounds (diff-bounds-of-hunk))
1669 (char-offset (- (point) (diff-beginning-of-hunk t))) 1765 (other (diff-xor other-file diff-jump-to-old-file))
1766 (char-offset (- (point) (goto-char (car hunk-bounds))))
1670 ;; Check that the hunk is well-formed. Otherwise diff-mode and 1767 ;; Check that the hunk is well-formed. Otherwise diff-mode and
1671 ;; the user may disagree on what constitutes the hunk 1768 ;; the user may disagree on what constitutes the hunk
1672 ;; (e.g. because an empty line truncates the hunk mid-course), 1769 ;; (e.g. because an empty line truncates the hunk mid-course),
@@ -1675,7 +1772,7 @@ NOPROMPT, if non-nil, means not to prompt the user."
1675 ;; Suppress check when NOPROMPT is non-nil (Bug#3033). 1772 ;; Suppress check when NOPROMPT is non-nil (Bug#3033).
1676 (_ (unless noprompt (diff-sanity-check-hunk))) 1773 (_ (unless noprompt (diff-sanity-check-hunk)))
1677 (hunk (buffer-substring 1774 (hunk (buffer-substring
1678 (point) (save-excursion (diff-end-of-hunk) (point)))) 1775 (point) (cadr hunk-bounds)))
1679 (old (diff-hunk-text hunk reverse char-offset)) 1776 (old (diff-hunk-text hunk reverse char-offset))
1680 (new (diff-hunk-text hunk (not reverse) char-offset)) 1777 (new (diff-hunk-text hunk (not reverse) char-offset))
1681 ;; Find the location specification. 1778 ;; Find the location specification.
@@ -1783,8 +1880,15 @@ With a prefix argument, REVERSE the hunk."
1783 ;; Display BUF in a window 1880 ;; Display BUF in a window
1784 (set-window-point (display-buffer buf) (+ (car pos) (cdr new))) 1881 (set-window-point (display-buffer buf) (+ (car pos) (cdr new)))
1785 (diff-hunk-status-msg line-offset (diff-xor switched reverse) nil) 1882 (diff-hunk-status-msg line-offset (diff-xor switched reverse) nil)
1883
1884 ;; Advance to the next hunk with skip-hunk-start set to t
1885 ;; because we want the behavior of moving to the next logical
1886 ;; hunk, not the original behavior where were would sometimes
1887 ;; stay on the curent hunk. This is the behavior we get when
1888 ;; navigating through hunks interactively, and we want it when
1889 ;; applying hunks too (see http://debbugs.gnu.org/17544).
1786 (when diff-advance-after-apply-hunk 1890 (when diff-advance-after-apply-hunk
1787 (diff-hunk-next)))))) 1891 (diff-hunk-next nil t))))))
1788 1892
1789 1893
1790(defun diff-test-hunk (&optional reverse) 1894(defun diff-test-hunk (&optional reverse)
@@ -1865,14 +1969,15 @@ For use in `add-log-current-defun-function'."
1865(defun diff-ignore-whitespace-hunk () 1969(defun diff-ignore-whitespace-hunk ()
1866 "Re-diff the current hunk, ignoring whitespace differences." 1970 "Re-diff the current hunk, ignoring whitespace differences."
1867 (interactive) 1971 (interactive)
1868 (let* ((char-offset (- (point) (diff-beginning-of-hunk t))) 1972 (let* ((hunk-bounds (diff-bounds-of-hunk))
1973 (char-offset (- (point) (goto-char (car hunk-bounds))))
1869 (opts (pcase (char-after) (?@ "-bu") (?* "-bc") (_ "-b"))) 1974 (opts (pcase (char-after) (?@ "-bu") (?* "-bc") (_ "-b")))
1870 (line-nb (and (or (looking-at "[^0-9]+\\([0-9]+\\)") 1975 (line-nb (and (or (looking-at "[^0-9]+\\([0-9]+\\)")
1871 (error "Can't find line number")) 1976 (error "Can't find line number"))
1872 (string-to-number (match-string 1)))) 1977 (string-to-number (match-string 1))))
1873 (inhibit-read-only t) 1978 (inhibit-read-only t)
1874 (hunk (delete-and-extract-region 1979 (hunk (delete-and-extract-region
1875 (point) (save-excursion (diff-end-of-hunk) (point)))) 1980 (point) (cadr hunk-bounds)))
1876 (lead (make-string (1- line-nb) ?\n)) ;Line nums start at 1. 1981 (lead (make-string (1- line-nb) ?\n)) ;Line nums start at 1.
1877 (file1 (make-temp-file "diff1")) 1982 (file1 (make-temp-file "diff1"))
1878 (file2 (make-temp-file "diff2")) 1983 (file2 (make-temp-file "diff2"))
@@ -1959,8 +2064,8 @@ For use in `add-log-current-defun-function'."
1959 (interactive) 2064 (interactive)
1960 (require 'smerge-mode) 2065 (require 'smerge-mode)
1961 (save-excursion 2066 (save-excursion
1962 (diff-beginning-of-hunk t) 2067 (let* ((hunk-bounds (diff-bounds-of-hunk))
1963 (let* ((start (point)) 2068 (start (goto-char (car hunk-bounds)))
1964 (style (diff-hunk-style)) ;Skips the hunk header as well. 2069 (style (diff-hunk-style)) ;Skips the hunk header as well.
1965 (beg (point)) 2070 (beg (point))
1966 (props-c '((diff-mode . fine) (face diff-refine-changed))) 2071 (props-c '((diff-mode . fine) (face diff-refine-changed)))
@@ -1968,7 +2073,7 @@ For use in `add-log-current-defun-function'."
1968 (props-a '((diff-mode . fine) (face diff-refine-added))) 2073 (props-a '((diff-mode . fine) (face diff-refine-added)))
1969 ;; Be careful to go back to `start' so diff-end-of-hunk gets 2074 ;; Be careful to go back to `start' so diff-end-of-hunk gets
1970 ;; to read the hunk header's line info. 2075 ;; to read the hunk header's line info.
1971 (end (progn (goto-char start) (diff-end-of-hunk) (point)))) 2076 (end (goto-char (cadr hunk-bounds))))
1972 2077
1973 (remove-overlays beg end 'diff-mode 'fine) 2078 (remove-overlays beg end 'diff-mode 'fine)
1974 2079