aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/vc
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/vc')
-rw-r--r--lisp/vc/diff-mode.el190
-rw-r--r--lisp/vc/ediff-init.el46
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