diff options
| -rw-r--r-- | lisp/vc/diff-mode.el | 131 |
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. | ||
| 579 | Override the default diff-{hunk,file}-{next,prev} implementation | ||
| 580 | by skipping any lines that are associated with this hunk/file but | ||
| 581 | precede the hunk-start marker. For instance, a diff file could | ||
| 582 | contain | ||
| 583 | |||
| 584 | diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el | ||
| 585 | index 923de9a..6b1c24f 100644 | ||
| 586 | --- a/lisp/vc/diff-mode.el | ||
| 587 | +++ b/lisp/vc/diff-mode.el | ||
| 588 | @@ -590,6 +590,22 @@ | ||
| 589 | ....... | ||
| 590 | |||
| 591 | If a point is on 'index', then the point is considered to be in | ||
| 592 | this first hunk. Move the point to the @@... marker before | ||
| 593 | executing the default diff-hunk-next/prev implementation to move | ||
| 594 | to 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'. | |||
| 1665 | SWITCHED is non-nil if the patch is already applied. | 1761 | SWITCHED is non-nil if the patch is already applied. |
| 1666 | NOPROMPT, if non-nil, means not to prompt the user." | 1762 | NOPROMPT, 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 | ||