[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: |
Mon, 25 Feb 2008 03:54:56 +0000 |
CVSROOT: /sources/emacs
Module name: emacs
Changes by: Stefan Monnier <monnier> 08/02/25 03:54:55
Index: diff-mode.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/diff-mode.el,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -b -r1.128 -r1.129
--- diff-mode.el 10 Feb 2008 18:38:05 -0000 1.128
+++ diff-mode.el 25 Feb 2008 03:54:54 -0000 1.129
@@ -352,10 +352,12 @@
(while (re-search-backward re start t)
(replace-match "" t t)))))))
+(defconst diff-hunk-header-re-unified
+ "^@@ -\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)?
\\+\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\) @@")
(defvar diff-font-lock-keywords
- `(("^\\(@@ -[0-9,]+ \\+[0-9,]+ @@\\)\\(.*\\)$" ;unified
- (1 diff-hunk-header-face) (2 diff-function-face))
+ `((,(concat "\\(" diff-hunk-header-re-unified "\\)\\(.*\\)$")
+ (1 diff-hunk-header-face) (6 diff-function-face))
("^\\(\\*\\{15\\}\\)\\(.*\\)$" ;context
(1 diff-hunk-header-face) (2 diff-function-face))
("^\\*\\*\\* .+ \\*\\*\\*\\*". diff-hunk-header-face) ;context
@@ -395,7 +397,14 @@
;;;; Movement
;;;;
-(defconst diff-hunk-header-re "^\\(@@ -[0-9,]+ \\+[0-9,]+
@@.*\\|\\*\\{15\\}.*\n\\*\\*\\* .+
\\*\\*\\*\\*\\|[0-9]+\\(,[0-9]+\\)?[acd][0-9]+\\(,[0-9]+\\)?\\)$")
+(defvar diff-valid-unified-empty-line t
+ "If non-nil, empty lines are valid in unified diffs.
+Some versions of diff replace all-blank context lines in unified format with
+empty lines. This makes the format less robust, but is tolerated.
+See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html")
+
+(defconst diff-hunk-header-re
+ (concat "^\\(?:" diff-hunk-header-re-unified ".*\\|\\*\\{15\\}.*\n\\*\\*\\*
.+ \\*\\*\\*\\*\\|[0-9]+\\(,[0-9]+\\)?[acd][0-9]+\\(,[0-9]+\\)?\\)$"))
(defconst diff-file-header-re (concat "^\\(--- .+\n\\+\\+\\+ \\|\\*\\*\\*
.+\n--- \\|[^-+!<>address@hidden ]\\).+\n" (substring diff-hunk-header-re 1)))
(defvar diff-narrowed-to nil)
@@ -405,18 +414,39 @@
(goto-char (match-end 0)))
style)
-(defun diff-end-of-hunk (&optional style)
+(defun diff-end-of-hunk (&optional style donttrustheader)
+ (let (end)
+ (when (looking-at diff-hunk-header-re)
;; Especially important for unified (because headers are ambiguous).
(setq style (diff-hunk-style style))
- (let ((end (and (re-search-forward (case style
+ (goto-char (match-end 0))
+ (when (and (not donttrustheader) (match-end 2))
+ (save-excursion
+ (re-search-forward (if diff-valid-unified-empty-line
+ "^[- \n]" "^[- ]")
+ nil t
+ (string-to-number (match-string 2)))
+ (setq end (line-beginning-position 2)))))
+ ;; We may have a first evaluation of `end' thanks to the hunk header.
+ (unless end
+ (setq end (and (re-search-forward
+ (case style
+ (unified (concat (if diff-valid-unified-empty-line
+ "^[^-+# \\\n]\\|" "^[^-+# \\]\\|")
;; A `unified' header is ambiguous.
- (unified (concat "^[^-+# \\]\\|"
diff-file-header-re))
(context "^[^-+#! \\]")
(normal "^[^<>#\\]")
(t "^[^-+#!<> \\]"))
nil t)
- (match-beginning 0))))
+ (match-beginning 0)))
+ (when diff-valid-unified-empty-line
+ ;; While empty lines may be valid inside hunks, they are also likely
+ ;; to be unrelated to the hunk.
+ (goto-char (or end (point-max)))
+ (while (eq ?\n (char-before (1- (point))))
+ (forward-char -1)
+ (setq end (point)))))
;; The return value is used by easy-mmode-define-navigation.
(goto-char (or end (point-max)))))
@@ -509,11 +539,19 @@
(diff-end-of-hunk)
(kill-region start (point)))))
+(defconst diff-file-junk-re "diff \\|index ") ; "index " is output by git-diff.
+
(defun diff-beginning-of-file-and-junk ()
"Go to the beginning of file-related diff-info.
This is like `diff-beginning-of-file' except it tries to skip back over leading
data such as \"Index: ...\" and such."
- (let* ((start (point))
+ (let* ((orig (point))
+ ;; Skip forward over what might be "leading junk" so as to get
+ ;; closer to the actual diff.
+ (_ (progn (beginning-of-line)
+ (while (looking-at diff-file-junk-re)
+ (forward-line 1))))
+ (start (point))
(prevfile (condition-case err
(save-excursion (diff-beginning-of-file) (point))
(error err)))
@@ -527,6 +565,7 @@
(if (numberp prevfile) (goto-char prevfile))
(diff-hunk-prev) (point))))
(previndex (save-excursion
+ (forward-line 1) ;In case we're looking at "Index:".
(re-search-backward "^Index: " prevhunk t))))
;; If we're in the junk, we should use nextfile instead of prevfile.
(if (and (numberp nextfile)
@@ -536,20 +575,28 @@
(if (and previndex (numberp prevfile) (< previndex prevfile))
(setq prevfile previndex))
(if (and (numberp prevfile) (<= prevfile start))
+ (progn
(goto-char prevfile)
+ ;; Now skip backward over the leading junk we may have before the
+ ;; diff itself.
+ (while (save-excursion
+ (and (zerop (forward-line -1))
+ (looking-at diff-file-junk-re)))
+ (forward-line -1)))
;; File starts *after* the starting point: we really weren't in
;; a file diff but elsewhere.
- (goto-char start)
+ (goto-char orig)
(signal (car err) (cdr err)))))
(defun diff-file-kill ()
"Kill current file's hunks."
(interactive)
- (diff-beginning-of-file-and-junk)
- (let* ((start (point))
+ (let ((orig (point))
+ (start (progn (diff-beginning-of-file-and-junk) (point)))
(inhibit-read-only t))
(diff-end-of-file)
(if (looking-at "^\n") (forward-char 1)) ;`tla' generates such diffs.
+ (if (> orig (point)) (error "Not inside a file diff"))
(kill-region start (point))))
(defun diff-kill-junk ()
@@ -587,11 +634,11 @@
(beginning-of-line)
(let ((pos (point))
(start (progn (diff-beginning-of-hunk) (point))))
- (unless (looking-at "@@ -\\([0-9]+\\),[0-9]+ \\+\\([0-9]+\\),[0-9]+ @@")
+ (unless (looking-at diff-hunk-header-re-unified)
(error "diff-split-hunk only works on unified context diffs"))
(forward-line 1)
(let* ((start1 (string-to-number (match-string 1)))
- (start2 (string-to-number (match-string 2)))
+ (start2 (string-to-number (match-string 3)))
(newstart1 (+ start1 (diff-count-matches "^[- \t]" (point) pos)))
(newstart2 (+ start2 (diff-count-matches "^[+ \t]" (point) pos)))
(inhibit-read-only t))
@@ -754,7 +801,10 @@
(inhibit-read-only t))
(save-excursion
(goto-char start)
- (while (and (re-search-forward "^\\(\\(---\\) .+\n\\(\\+\\+\\+\\)
.+\\|@@ -\\([0-9]+\\),\\([0-9]+\\) \\+\\([0-9]+\\),\\([0-9]+\\) @@.*\\)$" nil t)
+ (while (and (re-search-forward
+ (concat "^\\(\\(---\\) .+\n\\(\\+\\+\\+\\) .+\\|"
+ diff-hunk-header-re-unified ".*\\)$")
+ nil t)
(< (point) end))
(combine-after-change-calls
(if (match-beginning 2)
@@ -765,9 +815,11 @@
(replace-match "***" t t nil 2))
;; we matched a hunk header
(let ((line1 (match-string 4))
- (lines1 (match-string 5))
+ (lines1 (if (match-end 5)
+ (string-to-number (match-string 5)) 1))
(line2 (match-string 6))
- (lines2 (match-string 7))
+ (lines2 (if (match-end 7)
+ (string-to-number (match-string 7)) 1))
;; Variables to use the special undo function.
(old-undo buffer-undo-list)
(old-end (marker-position end))
@@ -776,11 +828,12 @@
(replace-match
(concat "***************\n*** " line1 ","
(number-to-string (+ (string-to-number line1)
- (string-to-number lines1)
- -1)) " ****"))
- (forward-line 1)
+ lines1 -1)) " ****"))
(save-restriction
- (narrow-to-region (point)
+ (narrow-to-region (line-beginning-position 2)
+ ;; Call diff-end-of-hunk from just before
+ ;; the hunk header so it can use the hunk
+ ;; header info.
(progn (diff-end-of-hunk 'unified) (point)))
(let ((hunk (buffer-string)))
(goto-char (point-min))
@@ -802,13 +855,15 @@
(?\\ (when (save-excursion (forward-line -1)
(= (char-after) ?+))
(delete-region (point) last-pt) (setq modif
t)))
+ ;; diff-valid-unified-empty-line.
+ (?\n (insert " ") (setq modif nil) (backward-char
2))
(t (setq modif nil))))))
(goto-char (point-max))
(save-excursion
(insert "--- " line2 ","
(number-to-string (+ (string-to-number line2)
- (string-to-number lines2)
- -1)) " ----\n" hunk))
+ lines2 -1))
+ " ----\n" hunk))
;;(goto-char (point-min))
(forward-line 1)
(if (not (save-excursion (re-search-forward "^+" nil t)))
@@ -835,6 +890,9 @@
(?\\ (when (save-excursion (forward-line 1)
(not (eobp)))
(setq delete t) (setq modif t)))
+ ;; diff-valid-unified-empty-line.
+ (?\n (insert " ") (setq modif nil) (backward-char 2)
+ (setq reversible nil))
(t (setq modif nil)))
(let ((last-pt (point)))
(forward-line 1)
@@ -1005,7 +1063,8 @@
(t (when (and first last (< first last))
(insert (delete-and-extract-region first last)))
(setq first nil last nil)
- (equal ?\s c)))
+ (memq c (if diff-valid-unified-empty-line
+ '(?\s ?\n) '(?\s)))))
(forward-line 1))))))))))
(defun diff-fixup-modifs (start end)
@@ -1017,11 +1076,11 @@
(list (point-min) (point-max))))
(let ((inhibit-read-only t))
(save-excursion
- (goto-char end) (diff-end-of-hunk)
+ (goto-char end) (diff-end-of-hunk nil 'donttrustheader)
(let ((plus 0) (minus 0) (space 0) (bang 0))
(while (and (= (forward-line -1) 0) (<= start (point)))
(if (not (looking-at
- (concat "@@ -[0-9,]+ \\+[0-9,]+ @@"
+ (concat diff-hunk-header-re-unified
"\\|[-*][-*][-*] [0-9,]+ [-*][-*][-*][-*]$"
"\\|--- .+\n\\+\\+\\+ ")))
(case (char-after)
@@ -1032,13 +1091,17 @@
((?\\ ?#) nil)
(t (setq space 0 plus 0 minus 0 bang 0)))
(cond
- ((looking-at "@@ -[0-9]+,\\([0-9]*\\) \\+[0-9]+,\\([0-9]*\\)
@@.*$")
- (let* ((old1 (match-string 1))
- (old2 (match-string 2))
+ ((looking-at diff-hunk-header-re-unified)
+ (let* ((old1 (match-string 2))
+ (old2 (match-string 4))
(new1 (number-to-string (+ space minus)))
(new2 (number-to-string (+ space plus))))
- (unless (string= new2 old2) (replace-match new2 t t nil 2))
- (unless (string= new1 old1) (replace-match new1 t t nil 1))))
+ (if old2
+ (unless (string= new2 old2) (replace-match new2 t t nil 4))
+ (goto-char (match-end 4)) (insert "," new2))
+ (if old1
+ (unless (string= new1 old1) (replace-match new1 t t nil 2))
+ (goto-char (match-end 2)) (insert "," new1))))
((looking-at "--- \\([0-9]+\\),\\([0-9]*\\) ----$")
(when (> (+ space bang plus) 0)
(let* ((old1 (match-string 1))
@@ -1106,7 +1169,7 @@
;; (diff-fixup-modifs (point) (cdr diff-unhandled-changes))
(diff-beginning-of-hunk)
(when (save-excursion
- (diff-end-of-hunk)
+ (diff-end-of-hunk nil 'donttrustheader)
(>= (point) (cdr diff-unhandled-changes)))
(diff-fixup-modifs (point) (cdr diff-unhandled-changes)))))
(setq diff-unhandled-changes nil)))
@@ -1221,9 +1284,8 @@
Only works for unified diffs."
(interactive)
(while
- (and (re-search-forward "^@@ [-0-9]+,\\([0-9]+\\) [+0-9]+,\\([0-9]+\\)
@@"
- nil t)
- (equal (match-string 1) (match-string 2)))))
+ (and (re-search-forward diff-hunk-header-re-unified nil t)
+ (equal (match-string 2) (match-string 4)))))
(defun diff-sanity-check-context-hunk-half (lines)
(let ((count lines))
@@ -1261,7 +1323,7 @@
(error "Unrecognized context diff first hunk header format")
(forward-line 2)
(diff-sanity-check-context-hunk-half
- (if (match-string 2)
+ (if (match-end 2)
(1+ (- (string-to-number (match-string 2))
(string-to-number (match-string 1))))
1))
@@ -1269,18 +1331,19 @@
(error "Unrecognized context diff second hunk header format")
(forward-line)
(diff-sanity-check-context-hunk-half
- (if (match-string 2)
+ (if (match-end 2)
(1+ (- (string-to-number (match-string 2))
(string-to-number (match-string 1))))
1)))))
;; A unified diff.
((eq (char-after) ?@)
- (if (not (looking-at
- "@@ -[0-9]+\\(?:,\\([0-9]+\\)\\)?
\\+[0-9]+\\(?:,\\([0-9]+\\)\\)? @@"))
+ (if (not (looking-at diff-hunk-header-re-unified))
(error "Unrecognized unified diff hunk header format")
- (let ((before (if (match-string 1) (string-to-number (match-string
1)) 1))
- (after (if (match-string 2) (string-to-number (match-string
2)) 1)))
+ (let ((before (if (match-end 2)
+ (string-to-number (match-string 2)) 1))
+ (after (if (match-end 4)
+ (string-to-number (match-string 4)) 1)))
(forward-line)
(while
(case (char-after)
@@ -1298,12 +1361,16 @@
(?+ (decf after) t)
(t
(cond
+ ((and diff-valid-unified-empty-line
+ ;; Not just (eolp) so we don't infloop at eob.
+ (eq (char-after) ?\n))
+ (decf before) (decf after) t)
((and (zerop before) (zerop after)) nil)
((or (< before 0) (< after 0))
(error (if (or (zerop before) (zerop after))
"End of hunk ambiguously marked"
"Hunk seriously messed up")))
- ((not (y-or-n-p "Try to auto-fix whitespace loss and
word-wrap damage? "))
+ ((not (y-or-n-p (concat "Try to auto-fix " (if (eolp)
"whitespace loss" "word-wrap damage") "? ")))
(error "Abort!"))
((eolp) (insert " ") (forward-line -1) t)
(t (insert " ")
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Dan Nicolaescu, 2008/02/04
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Stefan Monnier, 2008/02/04
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Stefan Monnier, 2008/02/08
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Dan Nicolaescu, 2008/02/10
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v,
Stefan Monnier <=
- [Emacs-diffs] Changes to emacs/lisp/diff-mode.el,v, Miles Bader, 2008/02/29