diff options
| author | Stefan Monnier | 2008-02-25 03:54:54 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2008-02-25 03:54:54 +0000 |
| commit | f52d2f9c301760f4554e2e800bf9908430b87bba (patch) | |
| tree | 5b24297a84a20c0c770935e9e62b6e314865fefe /lisp/diff-mode.el | |
| parent | 31143cfcd3e0f663f7f10bbb95d176a83a840470 (diff) | |
| download | emacs-f52d2f9c301760f4554e2e800bf9908430b87bba.tar.gz emacs-f52d2f9c301760f4554e2e800bf9908430b87bba.zip | |
* diff-mode.el (diff-file-junk-re): New const.
(diff-beginning-of-file-and-junk): Use it.
(diff-file-kill): Make sure we were really inside a file diff.
* diff-mode.el: Make it more robust in the presence of empty context
lines in unified hunks.
(diff-valid-unified-empty-line): New var.
(diff-unified->context, diff-sanity-check-hunk): Obey it.
(diff-end-of-hunk): Obey it. New arg `donttrustheader'.
(diff-fixup-modifs, diff-post-command-hook): Use this new arg.
(diff-hunk-header-re-unified): New const.
(diff-font-lock-keywords, diff-hunk-header-re, diff-split-hunk)
(diff-fixup-modifs, diff-unified->context, diff-next-complex-hunk)
(diff-sanity-check-hunk): Use it.
* diff-mode.el (diff-beginning-of-file-and-junk): If we're on the
Index: line, don't search backward for the previous one.
Diffstat (limited to 'lisp/diff-mode.el')
| -rw-r--r-- | lisp/diff-mode.el | 167 |
1 files changed, 117 insertions, 50 deletions
diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el index 57cfc56e472..8a3433537b0 100644 --- a/lisp/diff-mode.el +++ b/lisp/diff-mode.el | |||
| @@ -352,10 +352,12 @@ when editing big diffs)." | |||
| 352 | (while (re-search-backward re start t) | 352 | (while (re-search-backward re start t) |
| 353 | (replace-match "" t t))))))) | 353 | (replace-match "" t t))))))) |
| 354 | 354 | ||
| 355 | (defconst diff-hunk-header-re-unified | ||
| 356 | "^@@ -\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)? \\+\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\) @@") | ||
| 355 | 357 | ||
| 356 | (defvar diff-font-lock-keywords | 358 | (defvar diff-font-lock-keywords |
| 357 | `(("^\\(@@ -[0-9,]+ \\+[0-9,]+ @@\\)\\(.*\\)$" ;unified | 359 | `((,(concat "\\(" diff-hunk-header-re-unified "\\)\\(.*\\)$") |
| 358 | (1 diff-hunk-header-face) (2 diff-function-face)) | 360 | (1 diff-hunk-header-face) (6 diff-function-face)) |
| 359 | ("^\\(\\*\\{15\\}\\)\\(.*\\)$" ;context | 361 | ("^\\(\\*\\{15\\}\\)\\(.*\\)$" ;context |
| 360 | (1 diff-hunk-header-face) (2 diff-function-face)) | 362 | (1 diff-hunk-header-face) (2 diff-function-face)) |
| 361 | ("^\\*\\*\\* .+ \\*\\*\\*\\*". diff-hunk-header-face) ;context | 363 | ("^\\*\\*\\* .+ \\*\\*\\*\\*". diff-hunk-header-face) ;context |
| @@ -395,7 +397,14 @@ when editing big diffs)." | |||
| 395 | ;;;; Movement | 397 | ;;;; Movement |
| 396 | ;;;; | 398 | ;;;; |
| 397 | 399 | ||
| 398 | (defconst diff-hunk-header-re "^\\(@@ -[0-9,]+ \\+[0-9,]+ @@.*\\|\\*\\{15\\}.*\n\\*\\*\\* .+ \\*\\*\\*\\*\\|[0-9]+\\(,[0-9]+\\)?[acd][0-9]+\\(,[0-9]+\\)?\\)$") | 400 | (defvar diff-valid-unified-empty-line t |
| 401 | "If non-nil, empty lines are valid in unified diffs. | ||
| 402 | Some versions of diff replace all-blank context lines in unified format with | ||
| 403 | empty lines. This makes the format less robust, but is tolerated. | ||
| 404 | See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html") | ||
| 405 | |||
| 406 | (defconst diff-hunk-header-re | ||
| 407 | (concat "^\\(?:" diff-hunk-header-re-unified ".*\\|\\*\\{15\\}.*\n\\*\\*\\* .+ \\*\\*\\*\\*\\|[0-9]+\\(,[0-9]+\\)?[acd][0-9]+\\(,[0-9]+\\)?\\)$")) | ||
| 399 | (defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+ \\|\\*\\*\\* .+\n--- \\|[^-+!<>0-9@* ]\\).+\n" (substring diff-hunk-header-re 1))) | 408 | (defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+ \\|\\*\\*\\* .+\n--- \\|[^-+!<>0-9@* ]\\).+\n" (substring diff-hunk-header-re 1))) |
| 400 | (defvar diff-narrowed-to nil) | 409 | (defvar diff-narrowed-to nil) |
| 401 | 410 | ||
| @@ -405,18 +414,39 @@ when editing big diffs)." | |||
| 405 | (goto-char (match-end 0))) | 414 | (goto-char (match-end 0))) |
| 406 | style) | 415 | style) |
| 407 | 416 | ||
| 408 | (defun diff-end-of-hunk (&optional style) | 417 | (defun diff-end-of-hunk (&optional style donttrustheader) |
| 409 | ;; Especially important for unified (because headers are ambiguous). | 418 | (let (end) |
| 410 | (setq style (diff-hunk-style style)) | 419 | (when (looking-at diff-hunk-header-re) |
| 411 | (let ((end (and (re-search-forward (case style | 420 | ;; Especially important for unified (because headers are ambiguous). |
| 412 | ;; A `unified' header is ambiguous. | 421 | (setq style (diff-hunk-style style)) |
| 413 | (unified (concat "^[^-+# \\]\\|" | 422 | (goto-char (match-end 0)) |
| 414 | diff-file-header-re)) | 423 | (when (and (not donttrustheader) (match-end 2)) |
| 415 | (context "^[^-+#! \\]") | 424 | (save-excursion |
| 416 | (normal "^[^<>#\\]") | 425 | (re-search-forward (if diff-valid-unified-empty-line |
| 417 | (t "^[^-+#!<> \\]")) | 426 | "^[- \n]" "^[- ]") |
| 418 | nil t) | 427 | nil t |
| 419 | (match-beginning 0)))) | 428 | (string-to-number (match-string 2))) |
| 429 | (setq end (line-beginning-position 2))))) | ||
| 430 | ;; We may have a first evaluation of `end' thanks to the hunk header. | ||
| 431 | (unless end | ||
| 432 | (setq end (and (re-search-forward | ||
| 433 | (case style | ||
| 434 | (unified (concat (if diff-valid-unified-empty-line | ||
| 435 | "^[^-+# \\\n]\\|" "^[^-+# \\]\\|") | ||
| 436 | ;; A `unified' header is ambiguous. | ||
| 437 | diff-file-header-re)) | ||
| 438 | (context "^[^-+#! \\]") | ||
| 439 | (normal "^[^<>#\\]") | ||
| 440 | (t "^[^-+#!<> \\]")) | ||
| 441 | nil t) | ||
| 442 | (match-beginning 0))) | ||
| 443 | (when diff-valid-unified-empty-line | ||
| 444 | ;; While empty lines may be valid inside hunks, they are also likely | ||
| 445 | ;; to be unrelated to the hunk. | ||
| 446 | (goto-char (or end (point-max))) | ||
| 447 | (while (eq ?\n (char-before (1- (point)))) | ||
| 448 | (forward-char -1) | ||
| 449 | (setq end (point))))) | ||
| 420 | ;; The return value is used by easy-mmode-define-navigation. | 450 | ;; The return value is used by easy-mmode-define-navigation. |
| 421 | (goto-char (or end (point-max))))) | 451 | (goto-char (or end (point-max))))) |
| 422 | 452 | ||
| @@ -509,11 +539,19 @@ If the prefix ARG is given, restrict the view to the current file instead." | |||
| 509 | (diff-end-of-hunk) | 539 | (diff-end-of-hunk) |
| 510 | (kill-region start (point))))) | 540 | (kill-region start (point))))) |
| 511 | 541 | ||
| 542 | (defconst diff-file-junk-re "diff \\|index ") ; "index " is output by git-diff. | ||
| 543 | |||
| 512 | (defun diff-beginning-of-file-and-junk () | 544 | (defun diff-beginning-of-file-and-junk () |
| 513 | "Go to the beginning of file-related diff-info. | 545 | "Go to the beginning of file-related diff-info. |
| 514 | This is like `diff-beginning-of-file' except it tries to skip back over leading | 546 | This is like `diff-beginning-of-file' except it tries to skip back over leading |
| 515 | data such as \"Index: ...\" and such." | 547 | data such as \"Index: ...\" and such." |
| 516 | (let* ((start (point)) | 548 | (let* ((orig (point)) |
| 549 | ;; Skip forward over what might be "leading junk" so as to get | ||
| 550 | ;; closer to the actual diff. | ||
| 551 | (_ (progn (beginning-of-line) | ||
| 552 | (while (looking-at diff-file-junk-re) | ||
| 553 | (forward-line 1)))) | ||
| 554 | (start (point)) | ||
| 517 | (prevfile (condition-case err | 555 | (prevfile (condition-case err |
| 518 | (save-excursion (diff-beginning-of-file) (point)) | 556 | (save-excursion (diff-beginning-of-file) (point)) |
| 519 | (error err))) | 557 | (error err))) |
| @@ -527,6 +565,7 @@ data such as \"Index: ...\" and such." | |||
| 527 | (if (numberp prevfile) (goto-char prevfile)) | 565 | (if (numberp prevfile) (goto-char prevfile)) |
| 528 | (diff-hunk-prev) (point)))) | 566 | (diff-hunk-prev) (point)))) |
| 529 | (previndex (save-excursion | 567 | (previndex (save-excursion |
| 568 | (forward-line 1) ;In case we're looking at "Index:". | ||
| 530 | (re-search-backward "^Index: " prevhunk t)))) | 569 | (re-search-backward "^Index: " prevhunk t)))) |
| 531 | ;; If we're in the junk, we should use nextfile instead of prevfile. | 570 | ;; If we're in the junk, we should use nextfile instead of prevfile. |
| 532 | (if (and (numberp nextfile) | 571 | (if (and (numberp nextfile) |
| @@ -536,20 +575,28 @@ data such as \"Index: ...\" and such." | |||
| 536 | (if (and previndex (numberp prevfile) (< previndex prevfile)) | 575 | (if (and previndex (numberp prevfile) (< previndex prevfile)) |
| 537 | (setq prevfile previndex)) | 576 | (setq prevfile previndex)) |
| 538 | (if (and (numberp prevfile) (<= prevfile start)) | 577 | (if (and (numberp prevfile) (<= prevfile start)) |
| 539 | (goto-char prevfile) | 578 | (progn |
| 579 | (goto-char prevfile) | ||
| 580 | ;; Now skip backward over the leading junk we may have before the | ||
| 581 | ;; diff itself. | ||
| 582 | (while (save-excursion | ||
| 583 | (and (zerop (forward-line -1)) | ||
| 584 | (looking-at diff-file-junk-re))) | ||
| 585 | (forward-line -1))) | ||
| 540 | ;; File starts *after* the starting point: we really weren't in | 586 | ;; File starts *after* the starting point: we really weren't in |
| 541 | ;; a file diff but elsewhere. | 587 | ;; a file diff but elsewhere. |
| 542 | (goto-char start) | 588 | (goto-char orig) |
| 543 | (signal (car err) (cdr err))))) | 589 | (signal (car err) (cdr err))))) |
| 544 | 590 | ||
| 545 | (defun diff-file-kill () | 591 | (defun diff-file-kill () |
| 546 | "Kill current file's hunks." | 592 | "Kill current file's hunks." |
| 547 | (interactive) | 593 | (interactive) |
| 548 | (diff-beginning-of-file-and-junk) | 594 | (let ((orig (point)) |
| 549 | (let* ((start (point)) | 595 | (start (progn (diff-beginning-of-file-and-junk) (point))) |
| 550 | (inhibit-read-only t)) | 596 | (inhibit-read-only t)) |
| 551 | (diff-end-of-file) | 597 | (diff-end-of-file) |
| 552 | (if (looking-at "^\n") (forward-char 1)) ;`tla' generates such diffs. | 598 | (if (looking-at "^\n") (forward-char 1)) ;`tla' generates such diffs. |
| 599 | (if (> orig (point)) (error "Not inside a file diff")) | ||
| 553 | (kill-region start (point)))) | 600 | (kill-region start (point)))) |
| 554 | 601 | ||
| 555 | (defun diff-kill-junk () | 602 | (defun diff-kill-junk () |
| @@ -587,11 +634,11 @@ data such as \"Index: ...\" and such." | |||
| 587 | (beginning-of-line) | 634 | (beginning-of-line) |
| 588 | (let ((pos (point)) | 635 | (let ((pos (point)) |
| 589 | (start (progn (diff-beginning-of-hunk) (point)))) | 636 | (start (progn (diff-beginning-of-hunk) (point)))) |
| 590 | (unless (looking-at "@@ -\\([0-9]+\\),[0-9]+ \\+\\([0-9]+\\),[0-9]+ @@") | 637 | (unless (looking-at diff-hunk-header-re-unified) |
| 591 | (error "diff-split-hunk only works on unified context diffs")) | 638 | (error "diff-split-hunk only works on unified context diffs")) |
| 592 | (forward-line 1) | 639 | (forward-line 1) |
| 593 | (let* ((start1 (string-to-number (match-string 1))) | 640 | (let* ((start1 (string-to-number (match-string 1))) |
| 594 | (start2 (string-to-number (match-string 2))) | 641 | (start2 (string-to-number (match-string 3))) |
| 595 | (newstart1 (+ start1 (diff-count-matches "^[- \t]" (point) pos))) | 642 | (newstart1 (+ start1 (diff-count-matches "^[- \t]" (point) pos))) |
| 596 | (newstart2 (+ start2 (diff-count-matches "^[+ \t]" (point) pos))) | 643 | (newstart2 (+ start2 (diff-count-matches "^[+ \t]" (point) pos))) |
| 597 | (inhibit-read-only t)) | 644 | (inhibit-read-only t)) |
| @@ -754,7 +801,10 @@ else cover the whole buffer." | |||
| 754 | (inhibit-read-only t)) | 801 | (inhibit-read-only t)) |
| 755 | (save-excursion | 802 | (save-excursion |
| 756 | (goto-char start) | 803 | (goto-char start) |
| 757 | (while (and (re-search-forward "^\\(\\(---\\) .+\n\\(\\+\\+\\+\\) .+\\|@@ -\\([0-9]+\\),\\([0-9]+\\) \\+\\([0-9]+\\),\\([0-9]+\\) @@.*\\)$" nil t) | 804 | (while (and (re-search-forward |
| 805 | (concat "^\\(\\(---\\) .+\n\\(\\+\\+\\+\\) .+\\|" | ||
| 806 | diff-hunk-header-re-unified ".*\\)$") | ||
| 807 | nil t) | ||
| 758 | (< (point) end)) | 808 | (< (point) end)) |
| 759 | (combine-after-change-calls | 809 | (combine-after-change-calls |
| 760 | (if (match-beginning 2) | 810 | (if (match-beginning 2) |
| @@ -765,9 +815,11 @@ else cover the whole buffer." | |||
| 765 | (replace-match "***" t t nil 2)) | 815 | (replace-match "***" t t nil 2)) |
| 766 | ;; we matched a hunk header | 816 | ;; we matched a hunk header |
| 767 | (let ((line1 (match-string 4)) | 817 | (let ((line1 (match-string 4)) |
| 768 | (lines1 (match-string 5)) | 818 | (lines1 (if (match-end 5) |
| 819 | (string-to-number (match-string 5)) 1)) | ||
| 769 | (line2 (match-string 6)) | 820 | (line2 (match-string 6)) |
| 770 | (lines2 (match-string 7)) | 821 | (lines2 (if (match-end 7) |
| 822 | (string-to-number (match-string 7)) 1)) | ||
| 771 | ;; Variables to use the special undo function. | 823 | ;; Variables to use the special undo function. |
| 772 | (old-undo buffer-undo-list) | 824 | (old-undo buffer-undo-list) |
| 773 | (old-end (marker-position end)) | 825 | (old-end (marker-position end)) |
| @@ -776,11 +828,12 @@ else cover the whole buffer." | |||
| 776 | (replace-match | 828 | (replace-match |
| 777 | (concat "***************\n*** " line1 "," | 829 | (concat "***************\n*** " line1 "," |
| 778 | (number-to-string (+ (string-to-number line1) | 830 | (number-to-string (+ (string-to-number line1) |
| 779 | (string-to-number lines1) | 831 | lines1 -1)) " ****")) |
| 780 | -1)) " ****")) | ||
| 781 | (forward-line 1) | ||
| 782 | (save-restriction | 832 | (save-restriction |
| 783 | (narrow-to-region (point) | 833 | (narrow-to-region (line-beginning-position 2) |
| 834 | ;; Call diff-end-of-hunk from just before | ||
| 835 | ;; the hunk header so it can use the hunk | ||
| 836 | ;; header info. | ||
| 784 | (progn (diff-end-of-hunk 'unified) (point))) | 837 | (progn (diff-end-of-hunk 'unified) (point))) |
| 785 | (let ((hunk (buffer-string))) | 838 | (let ((hunk (buffer-string))) |
| 786 | (goto-char (point-min)) | 839 | (goto-char (point-min)) |
| @@ -802,13 +855,15 @@ else cover the whole buffer." | |||
| 802 | (?\\ (when (save-excursion (forward-line -1) | 855 | (?\\ (when (save-excursion (forward-line -1) |
| 803 | (= (char-after) ?+)) | 856 | (= (char-after) ?+)) |
| 804 | (delete-region (point) last-pt) (setq modif t))) | 857 | (delete-region (point) last-pt) (setq modif t))) |
| 858 | ;; diff-valid-unified-empty-line. | ||
| 859 | (?\n (insert " ") (setq modif nil) (backward-char 2)) | ||
| 805 | (t (setq modif nil)))))) | 860 | (t (setq modif nil)))))) |
| 806 | (goto-char (point-max)) | 861 | (goto-char (point-max)) |
| 807 | (save-excursion | 862 | (save-excursion |
| 808 | (insert "--- " line2 "," | 863 | (insert "--- " line2 "," |
| 809 | (number-to-string (+ (string-to-number line2) | 864 | (number-to-string (+ (string-to-number line2) |
| 810 | (string-to-number lines2) | 865 | lines2 -1)) |
| 811 | -1)) " ----\n" hunk)) | 866 | " ----\n" hunk)) |
| 812 | ;;(goto-char (point-min)) | 867 | ;;(goto-char (point-min)) |
| 813 | (forward-line 1) | 868 | (forward-line 1) |
| 814 | (if (not (save-excursion (re-search-forward "^+" nil t))) | 869 | (if (not (save-excursion (re-search-forward "^+" nil t))) |
| @@ -835,6 +890,9 @@ else cover the whole buffer." | |||
| 835 | (?\\ (when (save-excursion (forward-line 1) | 890 | (?\\ (when (save-excursion (forward-line 1) |
| 836 | (not (eobp))) | 891 | (not (eobp))) |
| 837 | (setq delete t) (setq modif t))) | 892 | (setq delete t) (setq modif t))) |
| 893 | ;; diff-valid-unified-empty-line. | ||
| 894 | (?\n (insert " ") (setq modif nil) (backward-char 2) | ||
| 895 | (setq reversible nil)) | ||
| 838 | (t (setq modif nil))) | 896 | (t (setq modif nil))) |
| 839 | (let ((last-pt (point))) | 897 | (let ((last-pt (point))) |
| 840 | (forward-line 1) | 898 | (forward-line 1) |
| @@ -1005,7 +1063,8 @@ else cover the whole buffer." | |||
| 1005 | (t (when (and first last (< first last)) | 1063 | (t (when (and first last (< first last)) |
| 1006 | (insert (delete-and-extract-region first last))) | 1064 | (insert (delete-and-extract-region first last))) |
| 1007 | (setq first nil last nil) | 1065 | (setq first nil last nil) |
| 1008 | (equal ?\s c))) | 1066 | (memq c (if diff-valid-unified-empty-line |
| 1067 | '(?\s ?\n) '(?\s))))) | ||
| 1009 | (forward-line 1)))))))))) | 1068 | (forward-line 1)))))))))) |
| 1010 | 1069 | ||
| 1011 | (defun diff-fixup-modifs (start end) | 1070 | (defun diff-fixup-modifs (start end) |
| @@ -1017,11 +1076,11 @@ else cover the whole buffer." | |||
| 1017 | (list (point-min) (point-max)))) | 1076 | (list (point-min) (point-max)))) |
| 1018 | (let ((inhibit-read-only t)) | 1077 | (let ((inhibit-read-only t)) |
| 1019 | (save-excursion | 1078 | (save-excursion |
| 1020 | (goto-char end) (diff-end-of-hunk) | 1079 | (goto-char end) (diff-end-of-hunk nil 'donttrustheader) |
| 1021 | (let ((plus 0) (minus 0) (space 0) (bang 0)) | 1080 | (let ((plus 0) (minus 0) (space 0) (bang 0)) |
| 1022 | (while (and (= (forward-line -1) 0) (<= start (point))) | 1081 | (while (and (= (forward-line -1) 0) (<= start (point))) |
| 1023 | (if (not (looking-at | 1082 | (if (not (looking-at |
| 1024 | (concat "@@ -[0-9,]+ \\+[0-9,]+ @@" | 1083 | (concat diff-hunk-header-re-unified |
| 1025 | "\\|[-*][-*][-*] [0-9,]+ [-*][-*][-*][-*]$" | 1084 | "\\|[-*][-*][-*] [0-9,]+ [-*][-*][-*][-*]$" |
| 1026 | "\\|--- .+\n\\+\\+\\+ "))) | 1085 | "\\|--- .+\n\\+\\+\\+ "))) |
| 1027 | (case (char-after) | 1086 | (case (char-after) |
| @@ -1032,13 +1091,17 @@ else cover the whole buffer." | |||
| 1032 | ((?\\ ?#) nil) | 1091 | ((?\\ ?#) nil) |
| 1033 | (t (setq space 0 plus 0 minus 0 bang 0))) | 1092 | (t (setq space 0 plus 0 minus 0 bang 0))) |
| 1034 | (cond | 1093 | (cond |
| 1035 | ((looking-at "@@ -[0-9]+,\\([0-9]*\\) \\+[0-9]+,\\([0-9]*\\) @@.*$") | 1094 | ((looking-at diff-hunk-header-re-unified) |
| 1036 | (let* ((old1 (match-string 1)) | 1095 | (let* ((old1 (match-string 2)) |
| 1037 | (old2 (match-string 2)) | 1096 | (old2 (match-string 4)) |
| 1038 | (new1 (number-to-string (+ space minus))) | 1097 | (new1 (number-to-string (+ space minus))) |
| 1039 | (new2 (number-to-string (+ space plus)))) | 1098 | (new2 (number-to-string (+ space plus)))) |
| 1040 | (unless (string= new2 old2) (replace-match new2 t t nil 2)) | 1099 | (if old2 |
| 1041 | (unless (string= new1 old1) (replace-match new1 t t nil 1)))) | 1100 | (unless (string= new2 old2) (replace-match new2 t t nil 4)) |
| 1101 | (goto-char (match-end 4)) (insert "," new2)) | ||
| 1102 | (if old1 | ||
| 1103 | (unless (string= new1 old1) (replace-match new1 t t nil 2)) | ||
| 1104 | (goto-char (match-end 2)) (insert "," new1)))) | ||
| 1042 | ((looking-at "--- \\([0-9]+\\),\\([0-9]*\\) ----$") | 1105 | ((looking-at "--- \\([0-9]+\\),\\([0-9]*\\) ----$") |
| 1043 | (when (> (+ space bang plus) 0) | 1106 | (when (> (+ space bang plus) 0) |
| 1044 | (let* ((old1 (match-string 1)) | 1107 | (let* ((old1 (match-string 1)) |
| @@ -1106,7 +1169,7 @@ See `after-change-functions' for the meaning of BEG, END and LEN." | |||
| 1106 | ;; (diff-fixup-modifs (point) (cdr diff-unhandled-changes)) | 1169 | ;; (diff-fixup-modifs (point) (cdr diff-unhandled-changes)) |
| 1107 | (diff-beginning-of-hunk) | 1170 | (diff-beginning-of-hunk) |
| 1108 | (when (save-excursion | 1171 | (when (save-excursion |
| 1109 | (diff-end-of-hunk) | 1172 | (diff-end-of-hunk nil 'donttrustheader) |
| 1110 | (>= (point) (cdr diff-unhandled-changes))) | 1173 | (>= (point) (cdr diff-unhandled-changes))) |
| 1111 | (diff-fixup-modifs (point) (cdr diff-unhandled-changes))))) | 1174 | (diff-fixup-modifs (point) (cdr diff-unhandled-changes))))) |
| 1112 | (setq diff-unhandled-changes nil))) | 1175 | (setq diff-unhandled-changes nil))) |
| @@ -1221,9 +1284,8 @@ a diff with \\[diff-reverse-direction]. | |||
| 1221 | Only works for unified diffs." | 1284 | Only works for unified diffs." |
| 1222 | (interactive) | 1285 | (interactive) |
| 1223 | (while | 1286 | (while |
| 1224 | (and (re-search-forward "^@@ [-0-9]+,\\([0-9]+\\) [+0-9]+,\\([0-9]+\\) @@" | 1287 | (and (re-search-forward diff-hunk-header-re-unified nil t) |
| 1225 | nil t) | 1288 | (equal (match-string 2) (match-string 4))))) |
| 1226 | (equal (match-string 1) (match-string 2))))) | ||
| 1227 | 1289 | ||
| 1228 | (defun diff-sanity-check-context-hunk-half (lines) | 1290 | (defun diff-sanity-check-context-hunk-half (lines) |
| 1229 | (let ((count lines)) | 1291 | (let ((count lines)) |
| @@ -1261,7 +1323,7 @@ Only works for unified diffs." | |||
| 1261 | (error "Unrecognized context diff first hunk header format") | 1323 | (error "Unrecognized context diff first hunk header format") |
| 1262 | (forward-line 2) | 1324 | (forward-line 2) |
| 1263 | (diff-sanity-check-context-hunk-half | 1325 | (diff-sanity-check-context-hunk-half |
| 1264 | (if (match-string 2) | 1326 | (if (match-end 2) |
| 1265 | (1+ (- (string-to-number (match-string 2)) | 1327 | (1+ (- (string-to-number (match-string 2)) |
| 1266 | (string-to-number (match-string 1)))) | 1328 | (string-to-number (match-string 1)))) |
| 1267 | 1)) | 1329 | 1)) |
| @@ -1269,18 +1331,19 @@ Only works for unified diffs." | |||
| 1269 | (error "Unrecognized context diff second hunk header format") | 1331 | (error "Unrecognized context diff second hunk header format") |
| 1270 | (forward-line) | 1332 | (forward-line) |
| 1271 | (diff-sanity-check-context-hunk-half | 1333 | (diff-sanity-check-context-hunk-half |
| 1272 | (if (match-string 2) | 1334 | (if (match-end 2) |
| 1273 | (1+ (- (string-to-number (match-string 2)) | 1335 | (1+ (- (string-to-number (match-string 2)) |
| 1274 | (string-to-number (match-string 1)))) | 1336 | (string-to-number (match-string 1)))) |
| 1275 | 1))))) | 1337 | 1))))) |
| 1276 | 1338 | ||
| 1277 | ;; A unified diff. | 1339 | ;; A unified diff. |
| 1278 | ((eq (char-after) ?@) | 1340 | ((eq (char-after) ?@) |
| 1279 | (if (not (looking-at | 1341 | (if (not (looking-at diff-hunk-header-re-unified)) |
| 1280 | "@@ -[0-9]+\\(?:,\\([0-9]+\\)\\)? \\+[0-9]+\\(?:,\\([0-9]+\\)\\)? @@")) | ||
| 1281 | (error "Unrecognized unified diff hunk header format") | 1342 | (error "Unrecognized unified diff hunk header format") |
| 1282 | (let ((before (if (match-string 1) (string-to-number (match-string 1)) 1)) | 1343 | (let ((before (if (match-end 2) |
| 1283 | (after (if (match-string 2) (string-to-number (match-string 2)) 1))) | 1344 | (string-to-number (match-string 2)) 1)) |
| 1345 | (after (if (match-end 4) | ||
| 1346 | (string-to-number (match-string 4)) 1))) | ||
| 1284 | (forward-line) | 1347 | (forward-line) |
| 1285 | (while | 1348 | (while |
| 1286 | (case (char-after) | 1349 | (case (char-after) |
| @@ -1298,12 +1361,16 @@ Only works for unified diffs." | |||
| 1298 | (?+ (decf after) t) | 1361 | (?+ (decf after) t) |
| 1299 | (t | 1362 | (t |
| 1300 | (cond | 1363 | (cond |
| 1364 | ((and diff-valid-unified-empty-line | ||
| 1365 | ;; Not just (eolp) so we don't infloop at eob. | ||
| 1366 | (eq (char-after) ?\n)) | ||
| 1367 | (decf before) (decf after) t) | ||
| 1301 | ((and (zerop before) (zerop after)) nil) | 1368 | ((and (zerop before) (zerop after)) nil) |
| 1302 | ((or (< before 0) (< after 0)) | 1369 | ((or (< before 0) (< after 0)) |
| 1303 | (error (if (or (zerop before) (zerop after)) | 1370 | (error (if (or (zerop before) (zerop after)) |
| 1304 | "End of hunk ambiguously marked" | 1371 | "End of hunk ambiguously marked" |
| 1305 | "Hunk seriously messed up"))) | 1372 | "Hunk seriously messed up"))) |
| 1306 | ((not (y-or-n-p "Try to auto-fix whitespace loss and word-wrap damage? ")) | 1373 | ((not (y-or-n-p (concat "Try to auto-fix " (if (eolp) "whitespace loss" "word-wrap damage") "? "))) |
| 1307 | (error "Abort!")) | 1374 | (error "Abort!")) |
| 1308 | ((eolp) (insert " ") (forward-line -1) t) | 1375 | ((eolp) (insert " ") (forward-line -1) t) |
| 1309 | (t (insert " ") | 1376 | (t (insert " ") |