diff options
Diffstat (limited to 'lisp/diff-mode.el')
| -rw-r--r-- | lisp/diff-mode.el | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el index 9226c537531..edf7317f2b4 100644 --- a/lisp/diff-mode.el +++ b/lisp/diff-mode.el | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | ;;; diff-mode.el --- a mode for viewing/editing context diffs | 1 | ;;; diff-mode.el --- a mode for viewing/editing context diffs |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, | 3 | ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
| 4 | ;; 2005, 2006 Free Software Foundation, Inc. | 4 | ;; 2005, 2006, 2007 Free Software Foundation, Inc. |
| 5 | 5 | ||
| 6 | ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> | 6 | ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> |
| 7 | ;; Keywords: convenience patch diff | 7 | ;; Keywords: convenience patch diff |
| @@ -1083,6 +1083,83 @@ Only works for unified diffs." | |||
| 1083 | nil t) | 1083 | nil t) |
| 1084 | (equal (match-string 1) (match-string 2))))) | 1084 | (equal (match-string 1) (match-string 2))))) |
| 1085 | 1085 | ||
| 1086 | (defun diff-sanity-check-context-hunk-half (lines) | ||
| 1087 | (let ((count lines)) | ||
| 1088 | (while | ||
| 1089 | (cond | ||
| 1090 | ((and (memq (char-after) '(?\s ?! ?+ ?-)) | ||
| 1091 | (memq (char-after (1+ (point))) '(?\s ?\t))) | ||
| 1092 | (decf count) t) | ||
| 1093 | ((or (zerop count) (= count lines)) nil) | ||
| 1094 | ((memq (char-after) '(?! ?+ ?-)) | ||
| 1095 | (if (not (and (eq (char-after (1+ (point))) ?\n) | ||
| 1096 | (y-or-n-p "Try to auto-fix whitespace loss damage? "))) | ||
| 1097 | (error "End of hunk ambiguously marked") | ||
| 1098 | (forward-char 1) (insert " ") (forward-line -1) t)) | ||
| 1099 | ((< lines 0) | ||
| 1100 | (error "End of hunk ambiguously marked")) | ||
| 1101 | ((not (y-or-n-p "Try to auto-fix whitespace loss and word-wrap damage? ")) | ||
| 1102 | (error "Abort!")) | ||
| 1103 | ((eolp) (insert " ") (forward-line -1) t) | ||
| 1104 | (t (insert " ") (delete-region (- (point) 2) (- (point) 1)) t)) | ||
| 1105 | (forward-line)))) | ||
| 1106 | |||
| 1107 | (defun diff-sanity-check-hunk () | ||
| 1108 | (let (;; Every modification is protected by a y-or-n-p, so it's probably | ||
| 1109 | ;; OK to override a read-only setting. | ||
| 1110 | (inhibit-read-only t)) | ||
| 1111 | (save-excursion | ||
| 1112 | (cond | ||
| 1113 | ((not (looking-at diff-hunk-header-re)) | ||
| 1114 | (error "Not recognizable hunk header")) | ||
| 1115 | |||
| 1116 | ;; A context diff. | ||
| 1117 | ((eq (char-after) ?*) | ||
| 1118 | (if (not (looking-at "\\*\\{15\\}\n\\*\\*\\* \\([0-9]+\\),\\([0-9]+\\) \\*\\*\\*\\*$")) | ||
| 1119 | (error "Unrecognized context diff first hunk header format") | ||
| 1120 | (forward-line 2) | ||
| 1121 | (diff-sanity-check-context-hunk-half | ||
| 1122 | (1+ (- (string-to-number (match-string 2)) | ||
| 1123 | (string-to-number (match-string 1))))) | ||
| 1124 | (if (not (looking-at "--- \\([0-9]+\\),\\([0-9]+\\) ----$")) | ||
| 1125 | (error "Unrecognized context diff second hunk header format") | ||
| 1126 | (forward-line) | ||
| 1127 | (diff-sanity-check-context-hunk-half | ||
| 1128 | (1+ (- (string-to-number (match-string 2)) | ||
| 1129 | (string-to-number (match-string 1)))))))) | ||
| 1130 | |||
| 1131 | ;; A unified diff. | ||
| 1132 | ((eq (char-after) ?@) | ||
| 1133 | (if (not (looking-at | ||
| 1134 | "@@ -[0-9]+,\\([0-9]+\\) \\+[0-9]+,\\([0-9]+\\) @@$")) | ||
| 1135 | (error "Unrecognized unified diff hunk header format") | ||
| 1136 | (let ((before (string-to-number (match-string 1))) | ||
| 1137 | (after (string-to-number (match-string 2)))) | ||
| 1138 | (forward-line) | ||
| 1139 | (while | ||
| 1140 | (case (char-after) | ||
| 1141 | (?\s (decf before) (decf after) t) | ||
| 1142 | (?- (decf before) t) | ||
| 1143 | (?+ (decf after) t) | ||
| 1144 | (t | ||
| 1145 | (cond | ||
| 1146 | ((and (zerop before) (zerop after)) nil) | ||
| 1147 | ((or (< before 0) (< after 0)) | ||
| 1148 | (error (if (or (zerop before) (zerop after)) | ||
| 1149 | "End of hunk ambiguously marked" | ||
| 1150 | "Hunk seriously messed up"))) | ||
| 1151 | ((not (y-or-n-p "Try to auto-fix whitespace loss and word-wrap damage? ")) | ||
| 1152 | (error "Abort!")) | ||
| 1153 | ((eolp) (insert " ") (forward-line -1) t) | ||
| 1154 | (t (insert " ") | ||
| 1155 | (delete-region (- (point) 2) (- (point) 1)) t)))) | ||
| 1156 | (forward-line))))) | ||
| 1157 | |||
| 1158 | ;; A plain diff. | ||
| 1159 | (t | ||
| 1160 | ;; TODO. | ||
| 1161 | ))))) | ||
| 1162 | |||
| 1086 | (defun diff-hunk-text (hunk destp char-offset) | 1163 | (defun diff-hunk-text (hunk destp char-offset) |
| 1087 | "Return the literal source text from HUNK as (TEXT . OFFSET). | 1164 | "Return the literal source text from HUNK as (TEXT . OFFSET). |
| 1088 | If DESTP is nil, TEXT is the source, otherwise the destination text. | 1165 | If DESTP is nil, TEXT is the source, otherwise the destination text. |
| @@ -1210,6 +1287,11 @@ SWITCHED is non-nil if the patch is already applied." | |||
| 1210 | (save-excursion | 1287 | (save-excursion |
| 1211 | (let* ((other (diff-xor other-file diff-jump-to-old-file)) | 1288 | (let* ((other (diff-xor other-file diff-jump-to-old-file)) |
| 1212 | (char-offset (- (point) (progn (diff-beginning-of-hunk) (point)))) | 1289 | (char-offset (- (point) (progn (diff-beginning-of-hunk) (point)))) |
| 1290 | ;; Check that the hunk is well-formed. Otherwise diff-mode and | ||
| 1291 | ;; the user may disagree on what constitutes the hunk | ||
| 1292 | ;; (e.g. because an empty line truncates the hunk mid-course), | ||
| 1293 | ;; leading to potentially nasty surprises for the user. | ||
| 1294 | (_ (diff-sanity-check-hunk)) | ||
| 1213 | (hunk (buffer-substring (point) | 1295 | (hunk (buffer-substring (point) |
| 1214 | (save-excursion (diff-end-of-hunk) (point)))) | 1296 | (save-excursion (diff-end-of-hunk) (point)))) |
| 1215 | (old (diff-hunk-text hunk reverse char-offset)) | 1297 | (old (diff-hunk-text hunk reverse char-offset)) |