[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v
From: |
Stefan Monnier |
Subject: |
[Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v |
Date: |
Tue, 09 Oct 2007 04:12:25 +0000 |
CVSROOT: /sources/emacs
Module name: emacs
Changes by: Stefan Monnier <monnier> 07/10/09 04:12:24
Index: lisp/diff-mode.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/diff-mode.el,v
retrieving revision 1.113
retrieving revision 1.114
diff -u -b -r1.113 -r1.114
--- lisp/diff-mode.el 11 Sep 2007 06:59:13 -0000 1.113
+++ lisp/diff-mode.el 9 Oct 2007 04:12:22 -0000 1.114
@@ -386,12 +386,15 @@
(defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+ \\|\\*\\*\\*
.+\n--- \\|[^-+!<>address@hidden ]\\).+\n" (substring diff-hunk-header-re 1)))
(defvar diff-narrowed-to nil)
-(defun diff-end-of-hunk (&optional style)
+(defun diff-hunk-style (&optional style)
(when (looking-at diff-hunk-header-re)
- (unless style
- ;; Especially important for unified (because headers are ambiguous).
- (setq style (cdr (assq (char-after) '((?@ . unified) (?* . context))))))
+ (setq style (cdr (assq (char-after) '((?@ . unified) (?* . context)))))
(goto-char (match-end 0)))
+ style)
+
+(defun diff-end-of-hunk (&optional style)
+ ;; Especially important for unified (because headers are ambiguous).
+ (setq style (diff-hunk-style style))
(let ((end (and (re-search-forward (case style
;; A `unified' header is ambiguous.
(unified (concat "^[^-+# \\]\\|"
@@ -858,7 +861,11 @@
;; we matched a hunk header
(let ((line1s (match-string 4))
(line1e (match-string 5))
- (pt1 (match-beginning 0)))
+ (pt1 (match-beginning 0))
+ ;; Variables to use the special undo function.
+ (old-undo buffer-undo-list)
+ (old-end (marker-position end))
+ (reversible t))
(replace-match "")
(unless (re-search-forward
"^--- \\([0-9]+\\),\\(-?[0-9]+\\) ----$" nil t)
@@ -873,24 +880,32 @@
(forward-line 1)
(while (< (point) pt2)
(case (char-after)
- ((?! ?-) (delete-char 2) (insert "-") (forward-line 1))
+ (?! (delete-char 2) (insert "-") (forward-line 1))
+ (?- (forward-char 1) (delete-char 1) (forward-line 1))
(?\s ;merge with the other half of the chunk
(let* ((endline2
(save-excursion
- (goto-char pt2) (forward-line 1) (point)))
- (c (char-after pt2)))
- (case c
+ (goto-char pt2) (forward-line 1) (point))))
+ (case (char-after pt2)
((?! ?+)
(insert "+"
(prog1 (buffer-substring (+ pt2 2) endline2)
(delete-region pt2 endline2))))
- (?\s ;FIXME: check consistency
+ (?\s
+ (unless (= (- endline2 pt2)
+ (- (line-beginning-position 2) (point)))
+ ;; If the two lines we're merging don't have the
+ ;; same length (can happen with "diff -b"), then
+ ;; diff-unified->context will not properly undo
+ ;; this operation.
+ (setq reversible nil))
(delete-region pt2 endline2)
(delete-char 1)
(forward-line 1))
(?\\ (forward-line 1))
- (t (delete-char 1) (forward-line 1)))))
- (t (forward-line 1))))
+ (t (setq reversible nil)
+ (delete-char 1) (forward-line 1)))))
+ (t (setq reversible nil) (forward-line 1))))
(while (looking-at "[+! ] ")
(if (/= (char-after) ?!) (forward-char 1)
(delete-char 1) (insert "+"))
@@ -904,7 +919,16 @@
" +" line2s ","
(number-to-string (- (string-to-number line2e)
(string-to-number line2s)
- -1)) " @@")))))))))))
+ -1)) " @@"))
+ (set-marker pt2 nil)
+ ;; The whole procedure succeeded, let's replace the myriad
+ ;; of undo elements with just a single special one.
+ (unless (or (not reversible) (eq buffer-undo-list t))
+ (setq buffer-undo-list
+ (cons (list 'apply (- old-end end) pt1 (point)
+ 'diff-unified->context pt1 (point))
+ old-undo)))
+ )))))))))
(defun diff-reverse-direction (start end)
"Reverse the direction of the diffs.
@@ -1610,6 +1634,63 @@
(delete-file file1)
(delete-file file2))))
+;;; Fine change highlighting.
+
+(defface diff-fine-change
+ '((t :background "yellow"))
+ "Face used for char-based changes shown by `diff-fine-highlight'.")
+
+(defun diff-fine-highlight-preproc ()
+ (while (re-search-forward "^." nil t)
+ ;; Replace the hunk's leading prefix (+, -, !, <, or >) on each line
+ ;; with something constant, otherwise it'll be flagged as changes
+ ;; (since it's typically "-" on one side and "+" on the other).
+ ;; Note that we keep the same number of chars: we treat the prefix
+ ;; as part of the texts-to-diff, so that finding the right char
+ ;; afterwards will be easier. This only makes sense because we make
+ ;; diffs at char-granularity.
+ (replace-match " ")))
+
+(defun diff-fine-highlight ()
+ "Highlight changes of hunk at point at a finer granularity."
+ (interactive)
+ (require 'smerge-mode)
+ (diff-beginning-of-hunk 'try-harder)
+ (let* ((style (diff-hunk-style)) ;Skips the hunk header as well.
+ (beg (point))
+ (props '((diff-mode . fine) (face diff-fine-change)))
+ (end (progn (diff-end-of-hunk) (point))))
+
+ (remove-overlays beg end 'diff-mode 'fine)
+
+ (goto-char beg)
+ (case style
+ (unified
+ (while (re-search-forward "^\\(?:-.*\n\\)+\\(\\)\\(?:\\+.*\n\\)+" end t)
+ (smerge-refine-subst (match-beginning 0) (match-end 1)
+ (match-end 1) (match-end 0)
+ props 'diff-fine-highlight-preproc)))
+ (context
+ (let* ((middle (save-excursion (re-search-forward "^---")))
+ (other middle))
+ (while (re-search-forward "^\\(?:!.*\n\\)+" middle t)
+ (smerge-refine-subst (match-beginning 0) (match-end 0)
+ (save-excursion
+ (goto-char other)
+ (re-search-forward "^\\(?:!.*\n\\)+" end)
+ (setq other (match-end 0))
+ (match-beginning 0))
+ other
+ props 'diff-fine-highlight-preproc))))
+ (t ;; Normal diffs.
+ (let ((beg1 (1+ (point))))
+ (when (re-search-forward "^---.*\n" end t)
+ ;; It's a combined add&remove, so there's something to do.
+ (smerge-refine-subst beg1 (match-beginning 0)
+ (match-end 0) end
+ props 'diff-fine-highlight-preproc)))))))
+
+
;; provide the package
(provide 'diff-mode)
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v,
Stefan Monnier <=
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Stefan Monnier, 2007/10/09
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Miles Bader, 2007/10/09
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Stefan Monnier, 2007/10/12
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Dan Nicolaescu, 2007/10/12
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Stefan Monnier, 2007/10/19
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Stefan Monnier, 2007/10/19
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Dan Nicolaescu, 2007/10/20
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Dan Nicolaescu, 2007/10/21