aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath1992-07-29 05:06:36 +0000
committerRoland McGrath1992-07-29 05:06:36 +0000
commit646bd331030351fa24d4c46c0513f8dfb040ec55 (patch)
treea52555c057eae0920264f2bcc1d4a3daefab1b8d
parentc958d90f6dbebcd853cda61f8e9c5a97af66abf0 (diff)
downloademacs-646bd331030351fa24d4c46c0513f8dfb040ec55.tar.gz
emacs-646bd331030351fa24d4c46c0513f8dfb040ec55.zip
*** empty log message ***
-rw-r--r--lisp/diff.el363
-rw-r--r--lisp/progmodes/compile.el140
2 files changed, 261 insertions, 242 deletions
diff --git a/lisp/diff.el b/lisp/diff.el
index 885287f0ead..2c778c20610 100644
--- a/lisp/diff.el
+++ b/lisp/diff.el
@@ -1,10 +1,7 @@
1;;; diff.el --- "DIFF" mode for handling output from unix diff utility. 1;;; diff.el --- Run `diff' in compilation-mode.
2 2
3;; Copyright (C) 1990 Free Software Foundation, Inc. 3;; Copyright (C) 1992 Free Software Foundation, Inc.
4 4
5;; Author: Frank P. Bresz <fpb@ittc.wec.com>
6;; Maintainer: FSF
7;; Created: 27 Jan 1989
8;; Keyword: unix, tools 5;; Keyword: unix, tools
9 6
10;; This file is part of GNU Emacs. 7;; This file is part of GNU Emacs.
@@ -23,84 +20,180 @@
23;; along with GNU Emacs; see the file COPYING. If not, write to 20;; along with GNU Emacs; see the file COPYING. If not, write to
24;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 21;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25 22
26;;; Commentary:
27
28;; todo: diff-switches flexibility:
29;; (defconst diff-switches-function
30;; '(lambda (file)
31;; (if (string-match "\\.el$" file)
32;; "-c -F\"^(\""
33;; "-p"))
34;; "Function to return switches to pass to the `diff' utility, in \\[diff].
35;; This function is called with one arg, a file name, and returns a string
36;; containing 0 or more arguments which are passed on to `diff'.
37;; NOTE: This is not an ordinary hook; it may not be a list of functions.")
38
39;; - fpb@ittc.wec.com - Sep 25, 1990
40;; Added code to support sccs diffing.
41;; also fixed one minor glitch in the
42;; search for the pattern. If you only 1 addition you won't find the end
43;; of the pattern (minor)
44
45;;; Code: 23;;; Code:
46 24
47(defvar diff-switches nil 25(require 'compile)
48 "*A list of switches to pass to the diff program.")
49
50(defvar diff-search-pattern "^\\([0-9]\\|\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\)"
51 "Regular expression that delineates difference regions in diffs.")
52
53(defvar diff-rcs-extension ",v"
54 "*Extension to find RCS file, some systems do not use ,v")
55 26
56;; Initialize the keymap if it isn't already 27(defvar diff-switches nil
57(if (boundp 'diff-mode-map) 28 "*A string or list of strings specifying switches to be be passed to diff.")
58 nil 29
59 (setq diff-mode-map (make-keymap)) 30(defvar diff-regexp-alist
60 (suppress-keymap diff-mode-map) 31 '(
61 (define-key diff-mode-map "?" 'describe-mode) 32 ;; -u format: @@ -OLDSTART,OLDEND +NEWSTART,NEWEND @@
62 (define-key diff-mode-map "." 'diff-beginning-of-diff) 33 ("^@@ -\\([0-9]+\\),[0-9]+ \\+\\([0-9]+\\),[0-9]+ @@$" 1 2)
63 (define-key diff-mode-map " " 'scroll-up) 34
64 (define-key diff-mode-map "\177" 'scroll-down) 35 ;; -c format: *** OLDSTART,OLDEND ****
65 (define-key diff-mode-map "n" 'diff-next-difference) 36 ("^\\*\\*\\* \\([0-9]+\\),[0-9]+ \\*\\*\\*\\*$" 1 nil)
66 (define-key diff-mode-map "p" 'diff-previous-difference) 37 ;; --- NEWSTART,NEWEND ----
67 (define-key diff-mode-map "j" 'diff-show-difference)) 38 ("^--- \\([0-9]+\\),[0-9]+ ----$" nil 1)
39
40 ;; plain diff format: OLDSTART[,OLDEND]{a,d,c}NEWSTART[,NEWEND]
41 ("^\\([0-9]+\\)\\(,[0-9]+\\)?[adc]\\([0-9]+\\)\\(,[0-9]+\\)?$" 1 3)
42
43 ;; -e (ed) format: OLDSTART[,OLDEND]{a,d,c}
44 ("^\\([0-9]+\\)\\(,[0-9]+\\)?[adc]$" 1)
45
46 ;; -f format: {a,d,c}OLDSTART[ OLDEND]
47 ;; -n format: {a,d,c}OLDSTART LINES-CHANGED
48 ("^[adc]\\([0-9]+\\)\\( [0-9]+\\)?$" 1)
49 )
50 "Alist (REGEXP OLD-IDX NEW-IDX) of regular expressions to match difference
51sections in \\[diff] output. If REGEXP matches, the OLD-IDX'th
52subexpression gives the line number in the old file, and NEW-IDX'th
53subexpression gives the line number in the new file. If OLD-IDX or NEW-IDX
54is nil, REGEXP matches only half a section.")
55
56;; See compilation-parse-errors-function (compile.el).
57(defun diff-parse-differences (limit-search)
58 (setq compilation-error-list nil)
59 (message "Parsing differences...")
60
61 ;; Don't reparse diffs already seen at last parse.
62 (goto-char compilation-parsing-end)
63
64 ;; Construct in REGEXP a regexp composed of all those in dired-regexp-alist.
65 (let ((regexp (mapconcat (lambda (elt)
66 (concat "\\(" (car elt) "\\)"))
67 diff-regexp-alist
68 "\\|"))
69 ;; (GROUP-IDX OLD-IDX NEW-IDX)
70 (groups (let ((subexpr 1))
71 (mapcar (lambda (elt)
72 (prog1
73 (cons subexpr
74 (mapcar (lambda (n)
75 (and n
76 (+ subexpr n)))
77 (cdr elt)))
78 (setq subexpr (+ subexpr 1
79 (count-regexp-groupings
80 (car elt))))))
81 diff-regexp-alist)))
82
83 (new-error
84 (function (lambda (file subexpr)
85 (setq compilation-error-list
86 (cons
87 (cons (set-marker (make-marker)
88 (match-beginning subexpr)
89 (current-buffer))
90 (let ((line (string-to-int
91 (buffer-substring
92 (match-beginning subexpr)
93 (match-end subexpr)))))
94 (save-excursion
95 (set-buffer (find-file-noselect file))
96 (save-excursion
97 (goto-line line)
98 (point-marker)))))
99 compilation-error-list)))))
100
101 (found-desired nil)
102 g)
103
104 (while (and (not found-desired)
105 ;; We don't just pass LIMIT-SEARCH to re-search-forward
106 ;; because we want to find matches containing LIMIT-SEARCH
107 ;; but which extend past it.
108 (re-search-forward regexp nil t))
109
110 ;; Find which individual regexp matched.
111 (setq g groups)
112 (while (and g (null (match-beginning (car (car g)))))
113 (setq g (cdr g)))
114 (setq g (car g))
115
116 (if (nth 1 g) ;OLD-IDX
117 (funcall new-error diff-old-file (nth 1 g)))
118 (if (nth 2 g) ;NEW-IDX
119 (funcall new-error diff-new-file (nth 2 g)))
120
121 (and limit-search (>= (point) limit-search)
122 ;; The user wanted a specific diff, and we're past it.
123 (setq found-desired t)))
124 (if found-desired
125 (setq compilation-parsing-end (point))
126 ;; Set to point-max, not point, so we don't perpetually
127 ;; parse the last bit of text when it isn't a diff header.
128 (setq compilation-parsing-end (point-max))
129 (message "Parsing differences...done")))
130 (setq compilation-error-list (nreverse compilation-error-list)))
68 131
69;;;###autoload 132;;;###autoload
70(defun diff (old new) 133(defun diff (old new &optional switches)
71 "Find and display the differences between OLD and NEW files. 134 "Find and display the differences between OLD and NEW files.
72Interactively the current buffer's file name is the default for for NEW 135Interactively the current buffer's file name is the default for for NEW
73and a backup file for NEW is the default for OLD." 136and a backup file for NEW is the default for OLD.
137With prefix arg, prompt for diff switches."
74 (interactive 138 (interactive
75 (let (oldf newf) 139 (nconc
76 (reverse 140 (let (oldf newf)
77 (list 141 (nreverse
78 (setq newf (buffer-file-name) 142 (list
79 newf (if (and newf (file-exists-p newf)) 143 (setq newf (buffer-file-name)
80 (read-file-name 144 newf (if (and newf (file-exists-p newf))
81 (concat "Diff new file: (" 145 (read-file-name
82 (file-name-nondirectory newf) ") ") 146 (concat "Diff new file: ("
83 nil newf t) 147 (file-name-nondirectory newf) ") ")
84 (read-file-name "Diff new file: " nil nil t))) 148 nil newf t)
85 (setq oldf (file-newest-backup newf) 149 (read-file-name "Diff new file: " nil nil t)))
86 oldf (if (and oldf (file-exists-p oldf)) 150 (setq oldf (file-newest-backup newf)
87 (read-file-name 151 oldf (if (and oldf (file-exists-p oldf))
88 (concat "Diff original file: (" 152 (read-file-name
89 (file-name-nondirectory oldf) ") ") 153 (concat "Diff original file: ("
90 (file-name-directory oldf) oldf t) 154 (file-name-nondirectory oldf) ") ")
91 (read-file-name "Diff original file: " 155 (file-name-directory oldf) oldf t)
92 (file-name-directory newf) nil t))))))) 156 (read-file-name "Diff original file: "
157 (file-name-directory newf) nil t))))))
158 (if current-prefix-arg
159 (list (read-string "Diff switches: "
160 (if (stringp diff-switches)
161 diff-switches
162 (mapconcat 'identity diff-switches " "))))
163 nil)))
93 (message "Comparing files %s %s..." new old) 164 (message "Comparing files %s %s..." new old)
94 (setq new (expand-file-name new) 165 (setq new (expand-file-name new)
95 old (expand-file-name old)) 166 old (expand-file-name old))
96 (diff-internal-diff "diff" (append diff-switches (list new old)) nil)) 167 (let ((buf (compile-internal (mapconcat 'identity
168 (append '("diff")
169 (if (consp diff-switches)
170 diff-switches
171 (list diff-switches))
172 (list old)
173 (list new))
174 " ")
175 "No more differences" "Diff"
176 'diff-parse-differences)))
177 (save-excursion
178 (set-buffer buf)
179 (set (make-local-variable 'diff-old-file) old)
180 (set (make-local-variable 'diff-new-file) new))
181 buf))
97 182
98(defun diff-backup (file) 183;;;###autoload
184(defun diff-backup (file &optional switches)
99 "Diff this file with its backup file or vice versa. 185 "Diff this file with its backup file or vice versa.
100Uses the latest backup, if there are several numerical backups. 186Uses the latest backup, if there are several numerical backups.
101If this file is a backup, diff it with its original. 187If this file is a backup, diff it with its original.
102The backup file is the first file given to `diff'." 188The backup file is the first file given to `diff'."
103 (interactive "fDiff (file with backup): ") 189 (interactive (list (read-file-name "Diff (file with backup): ")
190 (if current-prefix-arg
191 (read-string "Diff switches: "
192 (if (stringp diff-switches)
193 diff-switches
194 (mapconcat 'identity
195 diff-switches " ")))
196 nil)))
104 (let (bak ori) 197 (let (bak ori)
105 (if (backup-file-name-p file) 198 (if (backup-file-name-p file)
106 (setq bak file 199 (setq bak file
@@ -108,7 +201,7 @@ The backup file is the first file given to `diff'."
108 (setq bak (or (diff-latest-backup-file file) 201 (setq bak (or (diff-latest-backup-file file)
109 (error "No backup found for %s" file)) 202 (error "No backup found for %s" file))
110 ori file)) 203 ori file))
111 (diff bak ori))) 204 (diff bak ori switches)))
112 205
113(defun diff-latest-backup-file (fn) ; actually belongs into files.el 206(defun diff-latest-backup-file (fn) ; actually belongs into files.el
114 "Return the latest existing backup of FILE, or nil." 207 "Return the latest existing backup of FILE, or nil."
@@ -133,138 +226,4 @@ The backup file is the first file given to `diff'."
133 (> (backup-extract-version fn1) 226 (> (backup-extract-version fn1)
134 (backup-extract-version fn2)))))))))) 227 (backup-extract-version fn2))))))))))
135 228
136(defun diff-internal-diff (diff-command sw strip)
137 (let ((buffer-read-only nil))
138 (with-output-to-temp-buffer "*Diff Output*"
139 (buffer-disable-undo standard-output)
140 (save-excursion
141 (set-buffer standard-output)
142 (erase-buffer)
143 (apply 'call-process diff-command nil t nil sw)))
144 (set-buffer "*Diff Output*")
145 (goto-char (point-min))
146 (while sw
147 (if (string= (car sw) "-c")
148 ;; strip leading filenames from context diffs
149 (progn (forward-line 2) (delete-region (point-min) (point))))
150 (if (and (string= (car sw) "-C") (string= "sccs" diff-command))
151 ;; strip stuff from SCCS context diffs
152 (progn (forward-line 2) (delete-region (point-min) (point))))
153 (setq sw (cdr sw)))
154 (if strip
155 ;; strip stuff from SCCS context diffs
156 (progn (forward-line strip) (delete-region (point-min) (point)))))
157 (diff-mode)
158 (if (string= "0" diff-total-differences)
159 (let ((buffer-read-only nil))
160 (insert (message "There are no differences.")))
161 (narrow-to-region (point) (progn
162 (forward-line 1)
163 (if (re-search-forward diff-search-pattern
164 nil t)
165 (goto-char (match-beginning 0))
166 (goto-char (point-max)))))
167 (setq diff-current-difference "1")))
168
169;; Take a buffer full of Unix diff output and go into a mode to easily
170;; see the next and previous difference
171(defun diff-mode ()
172 "Diff Mode is used by \\[diff] for perusing the output from the diff program.
173All normal editing commands are turned off. Instead, these are available:
174\\<diff-mode-map>
175\\[diff-beginning-of-diff] Move point to start of this difference.
176\\[scroll-up] Scroll to next screen of this difference.
177\\[scroll-down] Scroll to previous screen of this difference.
178\\[diff-next-difference] Move to Next Difference.
179\\[diff-previous-difference] Move to Previous Difference.
180\\[diff-show-difference] Jump to difference specified by numeric position.
181"
182 (interactive)
183 (use-local-map diff-mode-map)
184 (setq buffer-read-only t
185 major-mode 'diff-mode
186 mode-name "Diff"
187 mode-line-modified "--- "
188 mode-line-process
189 '(" " diff-current-difference "/" diff-total-differences))
190 (make-local-variable 'diff-current-difference)
191 (set (make-local-variable 'diff-total-differences)
192 (int-to-string (diff-count-differences))))
193
194(defun diff-next-difference (n)
195 "Go to the beginning of the next difference.
196Differences are delimited by `diff-search-pattern'."
197 (interactive "p")
198 (if (< n 0) (diff-previous-difference (- n))
199 (if (zerop n) ()
200 (goto-char (point-min))
201 (forward-line 1) ; to get past the match for the start of this diff
202 (widen)
203 (if (re-search-forward diff-search-pattern nil 'move n)
204 (let ((start (goto-char (match-beginning 0))))
205 (forward-line 1)
206 (if (re-search-forward diff-search-pattern nil 'move)
207 (goto-char (match-beginning 0)))
208 (narrow-to-region start (point))
209 (setq diff-current-difference
210 (int-to-string (+ n (string-to-int
211 diff-current-difference)))))
212 (re-search-backward diff-search-pattern nil)
213 (narrow-to-region (point) (point-max))
214 (message "No following differences.")
215 (setq diff-current-difference diff-total-differences))
216 (goto-char (point-min)))))
217
218(defun diff-previous-difference (n)
219 "Go the the beginning of the previous difference.
220Differences are delimited by `diff-search-pattern'."
221 (interactive "p")
222 (if (< n 0) (diff-next-difference (- n))
223 (if (zerop n) ()
224 (goto-char (point-min))
225 (widen)
226 (if (re-search-backward diff-search-pattern nil 'move n)
227 (setq diff-current-difference
228 (int-to-string (- (string-to-int diff-current-difference) n)))
229 (message "No previous differences.")
230 (setq diff-current-difference "1"))
231 (narrow-to-region (point) (progn
232 (forward-line 1)
233 (re-search-forward diff-search-pattern nil)
234 (goto-char (match-beginning 0))))
235 (goto-char (point-min)))))
236
237(defun diff-show-difference (n)
238 "Show difference number N (prefix argument)."
239 (interactive "p")
240 (let ((cur (string-to-int diff-current-difference)))
241 (cond ((or (= n cur)
242 (zerop n)
243 (not (natnump n))) ; should signal an error perhaps.
244 ;; just redisplay.
245 (goto-char (point-min)))
246 ((< n cur)
247 (diff-previous-difference (- cur n)))
248 ((> n cur)
249 (diff-next-difference (- n cur))))))
250
251(defun diff-beginning-of-diff ()
252 "Go to beginning of current difference."
253 (interactive)
254 (goto-char (point-min)))
255
256;; This function counts up the number of differences in the buffer.
257(defun diff-count-differences ()
258 "Count number of differences in the current buffer."
259 (message "Counting differences...")
260 (save-excursion
261 (save-restriction
262 (widen)
263 (goto-char (point-min))
264 (let ((cnt 0))
265 (while (re-search-forward diff-search-pattern nil t)
266 (setq cnt (1+ cnt)))
267 (message "Counting differences...done (%d)" cnt)
268 cnt))))
269
270;;; diff.el ends here 229;;; diff.el ends here
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index b1f7fa0683e..0dd9f5111b1 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -6,8 +6,6 @@
6;; Maintainer: FSF 6;; Maintainer: FSF
7;; Keyword: tools, processes 7;; Keyword: tools, processes
8 8
9;;;!!! dup removal is broken.
10
11;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
12 10
13;; GNU Emacs is free software; you can redistribute it and/or modify 11;; GNU Emacs is free software; you can redistribute it and/or modify
@@ -36,12 +34,12 @@
36 34
37(defvar compilation-error-list nil 35(defvar compilation-error-list nil
38 "List of error message descriptors for visiting erring functions. 36 "List of error message descriptors for visiting erring functions.
39Each error descriptor is a cons (or nil). 37Each error descriptor is a cons (or nil). Its car is a marker pointing to
40Its car is a marker pointing to an error message. 38an error message. If its cdr is a marker, it points to the text of the
41If its cdr is a marker, it points to the text of the line the message is about. 39line the message is about. If its cdr is a cons, that cons's car is a cons
42If its cdr is a cons, that cons's car is a cons (DIRECTORY . FILE), specifying 40\(DIRECTORY . FILE\), specifying the file the message is about, and its cdr
43file the message is about, and its cdr is the number of the line the message 41is the number of the line the message is about. Or its cdr may be nil if
44is about. Or its cdr may be nil if that error is not interesting. 42that error is not interesting.
45 43
46The value may be t instead of a list; this means that the buffer of 44The value may be t instead of a list; this means that the buffer of
47error messages should be reparsed the next time the list of errors is wanted.") 45error messages should be reparsed the next time the list of errors is wanted.")
@@ -219,7 +217,9 @@ arg REGEXP-ALIST is the error message regexp alist to use (nil means the
219default). Sixth arg NAME-FUNCTION is a function called to name the buffer (nil 217default). Sixth arg NAME-FUNCTION is a function called to name the buffer (nil
220means the default). The defaults for these variables are the global values of 218means the default). The defaults for these variables are the global values of
221\`compilation-parse-errors-function', `compilation-error-regexp-alist', and 219\`compilation-parse-errors-function', `compilation-error-regexp-alist', and
222\`compilation-buffer-name-function', respectively." 220\`compilation-buffer-name-function', respectively.
221
222Returns the compilation buffer created."
223 (let (outbuf) 223 (let (outbuf)
224 (save-excursion 224 (save-excursion
225 (or name-of-mode 225 (or name-of-mode
@@ -303,6 +303,10 @@ means the default). The defaults for these variables are the global values of
303 (let ((map (make-sparse-keymap))) 303 (let ((map (make-sparse-keymap)))
304 (define-key map "\C-c\C-c" 'compile-goto-error) 304 (define-key map "\C-c\C-c" 'compile-goto-error)
305 (define-key map "\C-c\C-k" 'kill-compilation) 305 (define-key map "\C-c\C-k" 'kill-compilation)
306 (define-key map " " 'scroll-up)
307 (define-key map "\^?" 'scroll-down)
308 (define-key map "\M-n" 'compilation-next-error)
309 (define-key map "\M-p" 'compilation-previous-error)
306 map) 310 map)
307 "Keymap for compilation log buffers.") 311 "Keymap for compilation log buffers.")
308 312
@@ -374,6 +378,67 @@ Runs `compilation-mode-hook' with `run-hooks' (which see)."
374 (setq compilation-in-progress (delq proc compilation-in-progress)) 378 (setq compilation-in-progress (delq proc compilation-in-progress))
375 )))) 379 ))))
376 380
381
382(defun compilation-next-error (n)
383 "Move point to the next error in the compilation buffer.
384Does NOT find the source line like \\[next-error]."
385 (interactive "p")
386 (or (compilation-buffer-p (current-buffer))
387 (error "Not in a compilation buffer."))
388 (setq compilation-last-buffer (current-buffer))
389 (let ((p (point))
390 (errors nil)
391 (first t))
392
393 (save-excursion ;save point in case of later error
394 (while (and (if (< n 0)
395 (null errors)
396 (< (length errors) n))
397 (or first (< compilation-parsing-end (point-max))))
398 (setq first nil)
399
400 (if (< compilation-parsing-end (point-max))
401 (progn
402 ;; Move forward a bit and parse.
403 ;; Hopefully we will parse enough to find the one we want.
404 (forward-line n)
405 (compile-reinitialize-errors nil (point))))
406 (setq errors compilation-old-error-list)
407
408 ;; Look for the error containing P (the original point).
409 (if (< n 0)
410 (while (and errors
411 (> p (car (car errors))))
412 (setq errors (cdr errors)))
413 (while (and errors
414 (>= p (car (car errors))))
415 (setq errors (cdr errors))))
416 (ignore))
417
418 ;; Move to the error after the one containing point.
419 (setq p (car (if (< n 0)
420 (let ((i 0)
421 (e compilation-old-error-list))
422 ;; See how many cdrs away ERRORS is from the start.
423 (while (not (eq e errors))
424 (setq i (1+ i)
425 e (cdr e)))
426 (if (> (- n) i)
427 (error "Moved back past first error")
428 (nth (+ i n) compilation-old-error-list)))
429 (if errors
430 (nth (1- n) errors)
431 (error "Moved past last error"))))))
432
433 (goto-char p)))
434
435(defun compilation-previous-error (n)
436 "Move point to the previous error in the compilation buffer.
437Does NOT find the source line like \\[next-error]."
438 (interactive "p")
439 (compilation-next-error (- n)))
440
441
377(defun kill-compilation () 442(defun kill-compilation ()
378 "Kill the process made by the \\[compile] command." 443 "Kill the process made by the \\[compile] command."
379 (interactive) 444 (interactive)
@@ -394,7 +459,7 @@ Runs `compilation-mode-hook' with `run-hooks' (which see)."
394 (consp argp)) 459 (consp argp))
395 (progn (compilation-forget-errors) 460 (progn (compilation-forget-errors)
396 (setq compilation-parsing-end 1))) 461 (setq compilation-parsing-end 1)))
397 (if compilation-error-list 462 (if (and compilation-error-list (not limit-search))
398 ;; Since compilation-error-list is non-nil, it points to a specific 463 ;; Since compilation-error-list is non-nil, it points to a specific
399 ;; error the user wanted. So don't move it around. 464 ;; error the user wanted. So don't move it around.
400 nil 465 nil
@@ -419,24 +484,23 @@ other kinds of prefix arguments are ignored."
419 (error "Not in a compilation buffer.")) 484 (error "Not in a compilation buffer."))
420 (setq compilation-last-buffer (current-buffer)) 485 (setq compilation-last-buffer (current-buffer))
421 (compile-reinitialize-errors argp (point)) 486 (compile-reinitialize-errors argp (point))
422 (save-excursion 487
423 (beginning-of-line) 488 ;; Move compilation-error-list to the elt of compilation-old-error-list
424 ;; Move compilation-error-list to the elt of 489 ;; whose cadr is the error we want.
425 ;; compilation-old-error-list whose car is the error we want. 490 (setq compilation-error-list compilation-old-error-list)
426 (setq compilation-error-list 491 (while (and (cdr compilation-error-list)
427 (memq (let (elt) 492 (> (point) (car (car (cdr compilation-error-list)))))
428 (while (not (or (setq elt (assoc (point-marker) 493 (setq compilation-error-list (cdr compilation-error-list)))
429 compilation-old-error-list)) 494
430 (eobp)))
431 ;; This line doesn't contain an error.
432 ;; Move forward a line and look again.
433 (forward-line 1))
434 elt)
435 compilation-old-error-list)))
436 ;; Move to another window, so that next-error's window changes 495 ;; Move to another window, so that next-error's window changes
437 ;; result in the desired setup. 496 ;; result in the desired setup.
438 (or (one-window-p) 497 (or (one-window-p)
439 (other-window -1)) 498 (progn
499 (other-window -1)
500 ;; other-window changed the selected buffer,
501 ;; but we didn't want to do that.
502 (set-buffer compilation-last-buffer)))
503
440 (next-error 1)) 504 (next-error 1))
441 505
442(defun compilation-buffer-p (buffer) 506(defun compilation-buffer-p (buffer)
@@ -505,11 +569,10 @@ See variables `compilation-parse-errors-function' and
505 (let (next-errors next-error) 569 (let (next-errors next-error)
506 (save-excursion 570 (save-excursion
507 (set-buffer compilation-last-buffer) 571 (set-buffer compilation-last-buffer)
508 (setq next-errors (nthcdr (+ (- (length compilation-old-error-list) 572 ;; This code used to do something bizarre and incomprehensible.
509 (length compilation-error-list) 573 ;; Was there a reason I wrote it like that? --roland
510 1) 574 (setq next-errors (nthcdr (prefix-numeric-value argp)
511 (prefix-numeric-value argp)) 575 compilation-error-list)
512 compilation-old-error-list)
513 next-error (car next-errors)) 576 next-error (car next-errors))
514 (while 577 (while
515 (progn 578 (progn
@@ -650,7 +713,7 @@ See variables `compilation-parse-errors-function' and
650;; Set compilation-error-list to nil, and unchain the markers that point to the 713;; Set compilation-error-list to nil, and unchain the markers that point to the
651;; error messages and their text, so that they no longer slow down gap motion. 714;; error messages and their text, so that they no longer slow down gap motion.
652;; This would happen anyway at the next garbage collection, but it is better to 715;; This would happen anyway at the next garbage collection, but it is better to
653;; do it the right away. 716;; do it right away.
654(defun compilation-forget-errors () 717(defun compilation-forget-errors ()
655 (while compilation-old-error-list 718 (while compilation-old-error-list
656 (let ((next-error (car compilation-old-error-list))) 719 (let ((next-error (car compilation-old-error-list)))
@@ -741,11 +804,11 @@ See variable `compilation-parse-errors-function' for the interface it uses."
741 (setq subexpr (+ subexpr 1 (count-regexp-groupings (car (car alist))))) 804 (setq subexpr (+ subexpr 1 (count-regexp-groupings (car (car alist)))))
742 (setq alist (cdr alist))) 805 (setq alist (cdr alist)))
743 806
744 (while (and (re-search-forward regexp nil t) 807 (while (and (not found-desired)
745 ;; We don't just pass LIMIT-SEARCH to re-search-forward 808 ;; We don't just pass LIMIT-SEARCH to re-search-forward
746 ;; because we want to find matches containing LIMIT-SEARCH 809 ;; because we want to find matches containing LIMIT-SEARCH
747 ;; but which extend past it. 810 ;; but which extend past it.
748 (not found-desired)) 811 (re-search-forward regexp nil t))
749 ;; Figure out which constituent regexp matched. 812 ;; Figure out which constituent regexp matched.
750 (cond ((match-beginning enter-group) 813 (cond ((match-beginning enter-group)
751 ;; The match was the enter-directory regexp. 814 ;; The match was the enter-directory regexp.
@@ -813,16 +876,13 @@ See variable `compilation-parse-errors-function' for the interface it uses."
813 (cons filename linenum)) 876 (cons filename linenum))
814 compilation-error-list))))) 877 compilation-error-list)))))
815 (t 878 (t
816 (error "Impossible regexp match!"))) 879 (error "compilation-parse-errors: impossible regexp match!")))
817 (and limit-search (>= (point) limit-search) 880 (and limit-search (>= (point) limit-search)
818 ;; The user wanted a specific error, and we're past it. 881 ;; The user wanted a specific error, and we're past it.
819 (setq found-desired t))) 882 (setq found-desired t)))
820 (if desired-found 883 (if found-desired
821 (progn 884 (setq compilation-parsing-end (point))
822 (setq compilation-parsing-end (point)) 885 ;; We have searched the whole buffer.
823 (message "Desired error message found."))
824 ;; Set to point-max, not point, so we don't perpetually
825 ;; parse the last bit of text when it isn't an error message.
826 (setq compilation-parsing-end (point-max)) 886 (setq compilation-parsing-end (point-max))
827 (message "Parsing error messages...done"))) 887 (message "Parsing error messages...done")))
828 (setq compilation-error-list (nreverse compilation-error-list))) 888 (setq compilation-error-list (nreverse compilation-error-list)))