diff options
Diffstat (limited to 'lisp/vc')
| -rw-r--r-- | lisp/vc/diff-mode.el | 190 | ||||
| -rw-r--r-- | lisp/vc/ediff-init.el | 46 |
2 files changed, 126 insertions, 110 deletions
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index b7ad8e8ebd8..31c33e6a720 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el | |||
| @@ -437,6 +437,9 @@ See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html") | |||
| 437 | (defconst diff-hunk-header-re | 437 | (defconst diff-hunk-header-re |
| 438 | (concat "^\\(?:" diff-hunk-header-re-unified ".*\\|\\*\\{15\\}.*\n\\*\\*\\* .+ \\*\\*\\*\\*\\|[0-9]+\\(,[0-9]+\\)?[acd][0-9]+\\(,[0-9]+\\)?\\)$")) | 438 | (concat "^\\(?:" diff-hunk-header-re-unified ".*\\|\\*\\{15\\}.*\n\\*\\*\\* .+ \\*\\*\\*\\*\\|[0-9]+\\(,[0-9]+\\)?[acd][0-9]+\\(,[0-9]+\\)?\\)$")) |
| 439 | (defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+ \\|\\*\\*\\* .+\n--- \\|[^-+!<>0-9@* \n]\\).+\n" (substring diff-hunk-header-re 1))) | 439 | (defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+ \\|\\*\\*\\* .+\n--- \\|[^-+!<>0-9@* \n]\\).+\n" (substring diff-hunk-header-re 1))) |
| 440 | |||
| 441 | (defconst diff-separator-re "^--+ ?$") | ||
| 442 | |||
| 440 | (defvar diff-narrowed-to nil) | 443 | (defvar diff-narrowed-to nil) |
| 441 | 444 | ||
| 442 | (defun diff-hunk-style (&optional style) | 445 | (defun diff-hunk-style (&optional style) |
| @@ -501,7 +504,8 @@ See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html") | |||
| 501 | ;; "index ", "old mode", "new mode", "new file mode" and | 504 | ;; "index ", "old mode", "new mode", "new file mode" and |
| 502 | ;; "deleted file mode" are output by git-diff. | 505 | ;; "deleted file mode" are output by git-diff. |
| 503 | (defconst diff-file-junk-re | 506 | (defconst diff-file-junk-re |
| 504 | "diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode\\|=== modified file") | 507 | (concat "Index: \\|=\\{20,\\}\\|" ; SVN |
| 508 | "diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode\\|=== modified file")) | ||
| 505 | 509 | ||
| 506 | ;; If point is in a diff header, then return beginning | 510 | ;; If point is in a diff header, then return beginning |
| 507 | ;; of hunk position otherwise return nil. | 511 | ;; of hunk position otherwise return nil. |
| @@ -545,7 +549,8 @@ next hunk if TRY-HARDER is non-nil; otherwise signal an error." | |||
| 545 | (error "Can't find the beginning of the hunk"))) | 549 | (error "Can't find the beginning of the hunk"))) |
| 546 | ((re-search-backward regexp nil t)) ; In the middle of a hunk. | 550 | ((re-search-backward regexp nil t)) ; In the middle of a hunk. |
| 547 | ((re-search-forward regexp nil t) ; At first hunk header. | 551 | ((re-search-forward regexp nil t) ; At first hunk header. |
| 548 | (forward-line 0)) | 552 | (forward-line 0) |
| 553 | (point)) | ||
| 549 | (t (error "Can't find the beginning of the hunk")))))) | 554 | (t (error "Can't find the beginning of the hunk")))))) |
| 550 | 555 | ||
| 551 | (defun diff-unified-hunk-p () | 556 | (defun diff-unified-hunk-p () |
| @@ -645,28 +650,36 @@ If the prefix ARG is given, restrict the view to the current file instead." | |||
| 645 | (if arg (diff-bounds-of-file) (diff-bounds-of-hunk))) | 650 | (if arg (diff-bounds-of-file) (diff-bounds-of-hunk))) |
| 646 | (set (make-local-variable 'diff-narrowed-to) (if arg 'file 'hunk))) | 651 | (set (make-local-variable 'diff-narrowed-to) (if arg 'file 'hunk))) |
| 647 | 652 | ||
| 653 | (defun diff--some-hunks-p () | ||
| 654 | (save-excursion | ||
| 655 | (goto-char (point-min)) | ||
| 656 | (re-search-forward diff-hunk-header-re nil t))) | ||
| 657 | |||
| 648 | (defun diff-hunk-kill () | 658 | (defun diff-hunk-kill () |
| 649 | "Kill the hunk at point." | 659 | "Kill the hunk at point." |
| 650 | (interactive) | 660 | (interactive) |
| 651 | (let* ((hunk-bounds (diff-bounds-of-hunk)) | 661 | (if (not (diff--some-hunks-p)) |
| 652 | (file-bounds (ignore-errors (diff-bounds-of-file))) | 662 | (error "No hunks") |
| 653 | ;; If the current hunk is the only one for its file, kill the | 663 | (diff-beginning-of-hunk t) |
| 654 | ;; file header too. | 664 | (let* ((hunk-bounds (diff-bounds-of-hunk)) |
| 655 | (bounds (if (and file-bounds | 665 | (file-bounds (ignore-errors (diff-bounds-of-file))) |
| 656 | (progn (goto-char (car file-bounds)) | 666 | ;; If the current hunk is the only one for its file, kill the |
| 657 | (= (progn (diff-hunk-next) (point)) | 667 | ;; file header too. |
| 658 | (car hunk-bounds))) | 668 | (bounds (if (and file-bounds |
| 659 | (progn (goto-char (cadr hunk-bounds)) | 669 | (progn (goto-char (car file-bounds)) |
| 660 | ;; bzr puts a newline after the last hunk. | 670 | (= (progn (diff-hunk-next) (point)) |
| 661 | (while (looking-at "^\n") | 671 | (car hunk-bounds))) |
| 662 | (forward-char 1)) | 672 | (progn (goto-char (cadr hunk-bounds)) |
| 663 | (= (point) (cadr file-bounds)))) | 673 | ;; bzr puts a newline after the last hunk. |
| 664 | file-bounds | 674 | (while (looking-at "^\n") |
| 665 | hunk-bounds)) | 675 | (forward-char 1)) |
| 666 | (inhibit-read-only t)) | 676 | (= (point) (cadr file-bounds)))) |
| 667 | (apply 'kill-region bounds) | 677 | file-bounds |
| 668 | (goto-char (car bounds)) | 678 | hunk-bounds)) |
| 669 | (diff-beginning-of-hunk t))) | 679 | (inhibit-read-only t)) |
| 680 | (apply 'kill-region bounds) | ||
| 681 | (goto-char (car bounds)) | ||
| 682 | (ignore-errors (diff-beginning-of-hunk t))))) | ||
| 670 | 683 | ||
| 671 | (defun diff-beginning-of-file-and-junk () | 684 | (defun diff-beginning-of-file-and-junk () |
| 672 | "Go to the beginning of file-related diff-info. | 685 | "Go to the beginning of file-related diff-info. |
| @@ -718,9 +731,12 @@ data such as \"Index: ...\" and such." | |||
| 718 | (defun diff-file-kill () | 731 | (defun diff-file-kill () |
| 719 | "Kill current file's hunks." | 732 | "Kill current file's hunks." |
| 720 | (interactive) | 733 | (interactive) |
| 721 | (let ((inhibit-read-only t)) | 734 | (if (not (diff--some-hunks-p)) |
| 722 | (apply 'kill-region (diff-bounds-of-file))) | 735 | (error "No hunks") |
| 723 | (diff-beginning-of-hunk t)) | 736 | (diff-beginning-of-hunk t) |
| 737 | (let ((inhibit-read-only t)) | ||
| 738 | (apply 'kill-region (diff-bounds-of-file))) | ||
| 739 | (ignore-errors (diff-beginning-of-hunk t)))) | ||
| 724 | 740 | ||
| 725 | (defun diff-kill-junk () | 741 | (defun diff-kill-junk () |
| 726 | "Kill spurious empty diffs." | 742 | "Kill spurious empty diffs." |
| @@ -1535,15 +1551,20 @@ Only works for unified diffs." | |||
| 1535 | (pcase (char-after) | 1551 | (pcase (char-after) |
| 1536 | (?\s (cl-decf before) (cl-decf after) t) | 1552 | (?\s (cl-decf before) (cl-decf after) t) |
| 1537 | (?- | 1553 | (?- |
| 1538 | (if (and (looking-at diff-file-header-re) | 1554 | (cond |
| 1539 | (zerop before) (zerop after)) | 1555 | ((and (looking-at diff-separator-re) |
| 1540 | ;; No need to query: this is a case where two patches | 1556 | (zerop before) (zerop after)) |
| 1541 | ;; are concatenated and only counting the lines will | 1557 | nil) |
| 1542 | ;; give the right result. Let's just add an empty | 1558 | ((and (looking-at diff-file-header-re) |
| 1543 | ;; line so that our code which doesn't count lines | 1559 | (zerop before) (zerop after)) |
| 1544 | ;; will not get confused. | 1560 | ;; No need to query: this is a case where two patches |
| 1545 | (progn (save-excursion (insert "\n")) nil) | 1561 | ;; are concatenated and only counting the lines will |
| 1546 | (cl-decf before) t)) | 1562 | ;; give the right result. Let's just add an empty |
| 1563 | ;; line so that our code which doesn't count lines | ||
| 1564 | ;; will not get confused. | ||
| 1565 | (save-excursion (insert "\n")) nil) | ||
| 1566 | (t | ||
| 1567 | (cl-decf before) t))) | ||
| 1547 | (?+ (cl-decf after) t) | 1568 | (?+ (cl-decf after) t) |
| 1548 | (_ | 1569 | (_ |
| 1549 | (cond | 1570 | (cond |
| @@ -1998,57 +2019,58 @@ Return new point, if it was moved." | |||
| 1998 | "Highlight changes of hunk at point at a finer granularity." | 2019 | "Highlight changes of hunk at point at a finer granularity." |
| 1999 | (interactive) | 2020 | (interactive) |
| 2000 | (require 'smerge-mode) | 2021 | (require 'smerge-mode) |
| 2001 | (save-excursion | 2022 | (when (diff--some-hunks-p) |
| 2002 | (diff-beginning-of-hunk t) | 2023 | (save-excursion |
| 2003 | (let* ((start (point)) | 2024 | (diff-beginning-of-hunk t) |
| 2004 | (style (diff-hunk-style)) ;Skips the hunk header as well. | 2025 | (let* ((start (point)) |
| 2005 | (beg (point)) | 2026 | (style (diff-hunk-style)) ;Skips the hunk header as well. |
| 2006 | (props-c '((diff-mode . fine) (face diff-refine-changed))) | 2027 | (beg (point)) |
| 2007 | (props-r '((diff-mode . fine) (face diff-refine-removed))) | 2028 | (props-c '((diff-mode . fine) (face diff-refine-changed))) |
| 2008 | (props-a '((diff-mode . fine) (face diff-refine-added))) | 2029 | (props-r '((diff-mode . fine) (face diff-refine-removed))) |
| 2009 | ;; Be careful to go back to `start' so diff-end-of-hunk gets | 2030 | (props-a '((diff-mode . fine) (face diff-refine-added))) |
| 2010 | ;; to read the hunk header's line info. | 2031 | ;; Be careful to go back to `start' so diff-end-of-hunk gets |
| 2011 | (end (progn (goto-char start) (diff-end-of-hunk) (point)))) | 2032 | ;; to read the hunk header's line info. |
| 2012 | 2033 | (end (progn (goto-char start) (diff-end-of-hunk) (point)))) | |
| 2013 | (remove-overlays beg end 'diff-mode 'fine) | 2034 | |
| 2014 | 2035 | (remove-overlays beg end 'diff-mode 'fine) | |
| 2015 | (goto-char beg) | 2036 | |
| 2016 | (pcase style | 2037 | (goto-char beg) |
| 2017 | (`unified | 2038 | (pcase style |
| 2018 | (while (re-search-forward "^-" end t) | 2039 | (`unified |
| 2019 | (let ((beg-del (progn (beginning-of-line) (point))) | 2040 | (while (re-search-forward "^-" end t) |
| 2020 | beg-add end-add) | 2041 | (let ((beg-del (progn (beginning-of-line) (point))) |
| 2021 | (when (and (diff--forward-while-leading-char ?- end) | 2042 | beg-add end-add) |
| 2022 | ;; Allow for "\ No newline at end of file". | 2043 | (when (and (diff--forward-while-leading-char ?- end) |
| 2023 | (progn (diff--forward-while-leading-char ?\\ end) | 2044 | ;; Allow for "\ No newline at end of file". |
| 2024 | (setq beg-add (point))) | 2045 | (progn (diff--forward-while-leading-char ?\\ end) |
| 2025 | (diff--forward-while-leading-char ?+ end) | 2046 | (setq beg-add (point))) |
| 2026 | (progn (diff--forward-while-leading-char ?\\ end) | 2047 | (diff--forward-while-leading-char ?+ end) |
| 2027 | (setq end-add (point)))) | 2048 | (progn (diff--forward-while-leading-char ?\\ end) |
| 2028 | (smerge-refine-subst beg-del beg-add beg-add end-add | 2049 | (setq end-add (point)))) |
| 2029 | nil 'diff-refine-preproc props-r props-a))))) | 2050 | (smerge-refine-subst beg-del beg-add beg-add end-add |
| 2030 | (`context | 2051 | nil 'diff-refine-preproc props-r props-a))))) |
| 2031 | (let* ((middle (save-excursion (re-search-forward "^---"))) | 2052 | (`context |
| 2032 | (other middle)) | 2053 | (let* ((middle (save-excursion (re-search-forward "^---"))) |
| 2033 | (while (re-search-forward "^\\(?:!.*\n\\)+" middle t) | 2054 | (other middle)) |
| 2034 | (smerge-refine-subst (match-beginning 0) (match-end 0) | 2055 | (while (re-search-forward "^\\(?:!.*\n\\)+" middle t) |
| 2035 | (save-excursion | 2056 | (smerge-refine-subst (match-beginning 0) (match-end 0) |
| 2036 | (goto-char other) | 2057 | (save-excursion |
| 2037 | (re-search-forward "^\\(?:!.*\n\\)+" end) | 2058 | (goto-char other) |
| 2038 | (setq other (match-end 0)) | 2059 | (re-search-forward "^\\(?:!.*\n\\)+" end) |
| 2039 | (match-beginning 0)) | 2060 | (setq other (match-end 0)) |
| 2040 | other | 2061 | (match-beginning 0)) |
| 2041 | (if diff-use-changed-face props-c) | 2062 | other |
| 2042 | 'diff-refine-preproc | 2063 | (if diff-use-changed-face props-c) |
| 2043 | (unless diff-use-changed-face props-r) | 2064 | 'diff-refine-preproc |
| 2044 | (unless diff-use-changed-face props-a))))) | 2065 | (unless diff-use-changed-face props-r) |
| 2045 | (_ ;; Normal diffs. | 2066 | (unless diff-use-changed-face props-a))))) |
| 2046 | (let ((beg1 (1+ (point)))) | 2067 | (_ ;; Normal diffs. |
| 2047 | (when (re-search-forward "^---.*\n" end t) | 2068 | (let ((beg1 (1+ (point)))) |
| 2048 | ;; It's a combined add&remove, so there's something to do. | 2069 | (when (re-search-forward "^---.*\n" end t) |
| 2049 | (smerge-refine-subst beg1 (match-beginning 0) | 2070 | ;; It's a combined add&remove, so there's something to do. |
| 2050 | (match-end 0) end | 2071 | (smerge-refine-subst beg1 (match-beginning 0) |
| 2051 | nil 'diff-refine-preproc props-r props-a)))))))) | 2072 | (match-end 0) end |
| 2073 | nil 'diff-refine-preproc props-r props-a))))))))) | ||
| 2052 | 2074 | ||
| 2053 | (defun diff-undo (&optional arg) | 2075 | (defun diff-undo (&optional arg) |
| 2054 | "Perform `undo', ignoring the buffer's read-only status." | 2076 | "Perform `undo', ignoring the buffer's read-only status." |
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el index 95568b29c7c..0235926fbe4 100644 --- a/lisp/vc/ediff-init.el +++ b/lisp/vc/ediff-init.el | |||
| @@ -150,6 +150,26 @@ It needs to be killed when we quit the session.") | |||
| 150 | (defsubst ediff-get-symbol-from-alist (buf-type alist) | 150 | (defsubst ediff-get-symbol-from-alist (buf-type alist) |
| 151 | (cdr (assoc buf-type alist))) | 151 | (cdr (assoc buf-type alist))) |
| 152 | 152 | ||
| 153 | ;; Vector of differences between the variants. Each difference is | ||
| 154 | ;; represented by a vector of two overlays plus a vector of fine diffs, | ||
| 155 | ;; plus a no-fine-diffs flag. The first overlay spans the | ||
| 156 | ;; difference region in the A buffer and the second overlays the diff in | ||
| 157 | ;; the B buffer. If a difference section is empty, the corresponding | ||
| 158 | ;; overlay's endpoints coincide. | ||
| 159 | ;; | ||
| 160 | ;; The precise form of a Difference Vector for one buffer is: | ||
| 161 | ;; [diff diff diff ...] | ||
| 162 | ;; where each diff has the form: | ||
| 163 | ;; [diff-overlay fine-diff-vector no-fine-diffs-flag state-of-diff] | ||
| 164 | ;; fine-diff-vector is a vector [fine-diff-overlay fine-diff-overlay ...] | ||
| 165 | ;; no-fine-diffs-flag says if there are fine differences. | ||
| 166 | ;; state-of-difference is A, B, C, or nil, indicating which buffer is | ||
| 167 | ;; different from the other two (used only in 3-way jobs. | ||
| 168 | (ediff-defvar-local ediff-difference-vector-A nil "") | ||
| 169 | (ediff-defvar-local ediff-difference-vector-B nil "") | ||
| 170 | (ediff-defvar-local ediff-difference-vector-C nil "") | ||
| 171 | (ediff-defvar-local ediff-difference-vector-Ancestor nil "") | ||
| 172 | ;; A-list of diff vector types associated with buffer types | ||
| 153 | (defconst ediff-difference-vector-alist | 173 | (defconst ediff-difference-vector-alist |
| 154 | '((A . ediff-difference-vector-A) | 174 | '((A . ediff-difference-vector-A) |
| 155 | (B . ediff-difference-vector-B) | 175 | (B . ediff-difference-vector-B) |
| @@ -642,32 +662,6 @@ shown in brighter colors." | |||
| 642 | ;;buffer-read-only | 662 | ;;buffer-read-only |
| 643 | mode-line-format)) | 663 | mode-line-format)) |
| 644 | 664 | ||
| 645 | ;; Vector of differences between the variants. Each difference is | ||
| 646 | ;; represented by a vector of two overlays plus a vector of fine diffs, | ||
| 647 | ;; plus a no-fine-diffs flag. The first overlay spans the | ||
| 648 | ;; difference region in the A buffer and the second overlays the diff in | ||
| 649 | ;; the B buffer. If a difference section is empty, the corresponding | ||
| 650 | ;; overlay's endpoints coincide. | ||
| 651 | ;; | ||
| 652 | ;; The precise form of a Difference Vector for one buffer is: | ||
| 653 | ;; [diff diff diff ...] | ||
| 654 | ;; where each diff has the form: | ||
| 655 | ;; [diff-overlay fine-diff-vector no-fine-diffs-flag state-of-diff] | ||
| 656 | ;; fine-diff-vector is a vector [fine-diff-overlay fine-diff-overlay ...] | ||
| 657 | ;; no-fine-diffs-flag says if there are fine differences. | ||
| 658 | ;; state-of-difference is A, B, C, or nil, indicating which buffer is | ||
| 659 | ;; different from the other two (used only in 3-way jobs. | ||
| 660 | (ediff-defvar-local ediff-difference-vector-A nil "") | ||
| 661 | (ediff-defvar-local ediff-difference-vector-B nil "") | ||
| 662 | (ediff-defvar-local ediff-difference-vector-C nil "") | ||
| 663 | (ediff-defvar-local ediff-difference-vector-Ancestor nil "") | ||
| 664 | ;; A-list of diff vector types associated with buffer types | ||
| 665 | (defconst ediff-difference-vector-alist | ||
| 666 | '((A . ediff-difference-vector-A) | ||
| 667 | (B . ediff-difference-vector-B) | ||
| 668 | (C . ediff-difference-vector-C) | ||
| 669 | (Ancestor . ediff-difference-vector-Ancestor))) | ||
| 670 | |||
| 671 | ;; [ status status status ...] | 665 | ;; [ status status status ...] |
| 672 | ;; Each status: [state-of-merge state-of-ancestor] | 666 | ;; Each status: [state-of-merge state-of-ancestor] |
| 673 | ;; state-of-merge is default-A, default-B, prefer-A, or prefer-B. It | 667 | ;; state-of-merge is default-A, default-B, prefer-A, or prefer-B. It |