]> code.delx.au - gnu-emacs/blob - lisp/progmodes/compile.el
(menu-bar-make-mm-toggle): Don't put a quote befor FNAME
[gnu-emacs] / lisp / progmodes / compile.el
1 ;;; compile.el --- run compiler as inferior of Emacs, parse error messages
2
3 ;; Copyright (C) 1985, 86, 87, 93, 94, 95, 96, 97, 98, 1999, 2001
4 ;; Free Software Foundation, Inc.
5
6 ;; Author: Roland McGrath <roland@gnu.org>
7 ;; Maintainer: FSF
8 ;; Keywords: tools, processes
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
16
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
26
27 ;;; Commentary:
28
29 ;; This package provides the compile and grep facilities documented in
30 ;; the Emacs user's manual.
31
32 ;;; Code:
33
34 (defgroup compilation nil
35 "Run compiler as inferior of Emacs, parse error messages."
36 :group 'tools
37 :group 'processes)
38
39
40 ;;;###autoload
41 (defcustom compilation-mode-hook nil
42 "*List of hook functions run by `compilation-mode' (see `run-hooks')."
43 :type 'hook
44 :group 'compilation)
45
46 ;;;###autoload
47 (defcustom compilation-window-height nil
48 "*Number of lines in a compilation window. If nil, use Emacs default."
49 :type '(choice (const :tag "Default" nil)
50 integer)
51 :group 'compilation)
52
53 (defcustom compile-auto-highlight nil
54 "*Specify how many compiler errors to highlight (and parse) initially.
55 \(Highlighting applies to an error message when the mouse is over it.)
56 If this is a number N, all compiler error messages in the first N lines
57 are highlighted and parsed as soon as they arrive in Emacs.
58 If t, highlight and parse the whole compilation output as soon as it arrives.
59 If nil, don't highlight or parse any of the buffer until you try to
60 move to the error messages.
61
62 Those messages which are not parsed and highlighted initially
63 will be parsed and highlighted as soon as you try to move to them."
64 :type '(choice (const :tag "All" t)
65 (const :tag "None" nil)
66 (integer :tag "First N lines"))
67 :group 'compilation)
68
69 ;;; This has to be here so it can be called
70 ;;; by the following defcustoms.
71 (defun grep-compute-defaults ()
72 (unless (or (not grep-use-null-device) (eq grep-use-null-device t))
73 (setq grep-use-null-device
74 (with-temp-buffer
75 (let ((hello-file (expand-file-name "HELLO" data-directory)))
76 (not
77 (and (equal (condition-case nil
78 (if grep-command
79 ;; `grep-command' is already set, so
80 ;; use that for testing.
81 (call-process-shell-command
82 grep-command nil t nil
83 "^English" hello-file)
84 ;; otherwise use `grep-program'
85 (call-process grep-program nil t nil
86 "-nH" "^English" hello-file))
87 (error nil))
88 0)
89 (progn
90 (goto-char (point-min))
91 (looking-at
92 (concat (regexp-quote hello-file)
93 ":[0-9]+:English")))))))))
94 (unless grep-command
95 (setq grep-command
96 (let ((required-options (if grep-use-null-device "-n" "-nH")))
97 (if (equal (condition-case nil ; in case "grep" isn't in exec-path
98 (call-process grep-program nil nil nil
99 "-e" "foo" null-device)
100 (error nil))
101 1)
102 (format "%s %s -e " grep-program required-options)
103 (format "%s %s " grep-program required-options)))))
104 (unless grep-find-use-xargs
105 (setq grep-find-use-xargs
106 (if (and
107 (equal (call-process "find" nil nil nil
108 null-device "-print0")
109 0)
110 (equal (call-process "xargs" nil nil nil
111 "-0" "-e" "echo")
112 0))
113 'gnu)))
114 (unless grep-find-command
115 (setq grep-find-command
116 (cond ((eq grep-find-use-xargs 'gnu)
117 (format "%s . -type f -print0 | xargs -0 -e %s"
118 find-program grep-command))
119 (grep-find-use-xargs
120 (format "%s . -type f -print | xargs %s"
121 find-program grep-command))
122 (t (cons (format "%s . -type f -exec %s {} %s \\;"
123 find-program grep-command null-device)
124 (+ 22 (length grep-command)))))))
125 (unless grep-tree-command
126 (setq grep-tree-command
127 (let* ((glen (length grep-program))
128 (gcmd (concat grep-program " <C>" (substring grep-command glen))))
129 (cond ((eq grep-find-use-xargs 'gnu)
130 (format "%s <D> <X> -type f <F> -print0 | xargs -0 -e %s <R>"
131 find-program gcmd))
132 (grep-find-use-xargs
133 (format "%s <D> <X> -type f <F> -print | xargs %s <R>"
134 find-program gcmd))
135 (t (format "%s <D> <X> -type f <F> -exec %s <R> {} %s \\;"
136 find-program gcmd null-device)))))))
137
138 (defcustom grep-command nil
139 "The default grep command for \\[grep].
140 If the grep program used supports an option to always include file names
141 in its output (such as the `-H' option to GNU grep), it's a good idea to
142 include it when specifying `grep-command'.
143
144 The default value of this variable is set up by `grep-compute-defaults';
145 call that function before using this variable in your program."
146 :type 'string
147 :get '(lambda (symbol)
148 (or grep-command
149 (progn (grep-compute-defaults) grep-command)))
150 :group 'compilation)
151
152 (defcustom grep-use-null-device 'auto-detect
153 "If non-nil, append the value of `null-device' to grep commands.
154 This is done to ensure that the output of grep includes the filename of
155 any match in the case where only a single file is searched, and is not
156 necessary if the grep program used supports the `-H' option.
157
158 The default value of this variable is set up by `grep-compute-defaults';
159 call that function before using this variable in your program."
160 :type 'boolean
161 :get '(lambda (symbol)
162 (if (and grep-use-null-device (not (eq grep-use-null-device t)))
163 (progn (grep-compute-defaults) grep-use-null-device)
164 grep-use-null-device))
165 :group 'compilation)
166
167 (defcustom grep-find-command nil
168 "The default find command for \\[grep-find].
169 The default value of this variable is set up by `grep-compute-defaults';
170 call that function before using this variable in your program."
171 :type 'string
172 :get (lambda (symbol)
173 (or grep-find-command
174 (progn (grep-compute-defaults) grep-find-command)))
175 :group 'compilation)
176
177 (defcustom grep-tree-command nil
178 "The default find command for \\[grep-tree].
179 The default value of this variable is set up by `grep-compute-defaults';
180 call that function before using this variable in your program.
181 The following place holders should be present in the string:
182 <D> - base directory for find
183 <X> - find options to restrict or expand the directory list
184 <F> - find options to limit the files matched
185 <C> - place to put -i if case insensitive grep
186 <R> - the regular expression searched for."
187 :type 'string
188 :version "21.4"
189 :get (lambda (symbol)
190 (or grep-tree-command
191 (progn (grep-compute-defaults) grep-tree-command)))
192 :group 'compilation)
193
194 (defcustom grep-tree-files-aliases '(
195 ("ch" . "*.[ch]")
196 ("c" . "*.c")
197 ("h" . "*.h")
198 ("m" . "[Mm]akefile*")
199 ("asm" . "*.[sS]")
200 ("all" . "*")
201 ("el" . "*.el")
202 )
203 "*Alist of aliases for the FILES argument to `grep-tree'."
204 :type 'alist
205 :group 'compilation)
206
207 (defcustom grep-tree-ignore-case t
208 "*If non-nil, `grep-tree' ignores case in matches."
209 :type 'boolean
210 :group 'compilation)
211
212 (defcustom grep-tree-ignore-CVS-directories t
213 "*If non-nil, `grep-tree' does no recurse into CVS directories."
214 :type 'boolean
215 :group 'compilation)
216
217 (defvar compilation-error-list nil
218 "List of error message descriptors for visiting erring functions.
219 Each error descriptor is a cons (or nil). Its car is a marker pointing to
220 an error message. If its cdr is a marker, it points to the text of the
221 line the message is about. If its cdr is a cons, it is a list
222 \(\(DIRECTORY . FILE\) LINE [COLUMN]\). Or its cdr may be nil if that
223 error is not interesting.
224
225 The value may be t instead of a list; this means that the buffer of
226 error messages should be reparsed the next time the list of errors is wanted.
227
228 Some other commands (like `diff') use this list to control the error
229 message tracking facilities; if you change its structure, you should make
230 sure you also change those packages. Perhaps it is better not to change
231 it at all.")
232
233 (defvar compilation-old-error-list nil
234 "Value of `compilation-error-list' after errors were parsed.")
235
236 (defvar compilation-parse-errors-function 'compilation-parse-errors
237 "Function to call to parse error messages from a compilation.
238 It takes args LIMIT-SEARCH and FIND-AT-LEAST.
239 If LIMIT-SEARCH is non-nil, don't bother parsing past that location.
240 If FIND-AT-LEAST is non-nil, don't bother parsing after finding that
241 many new errors.
242 It should read in the source files which have errors and set
243 `compilation-error-list' to a list with an element for each error message
244 found. See that variable for more info.")
245
246 (defvar compilation-parse-errors-filename-function nil
247 "Function to call to post-process filenames while parsing error messages.
248 It takes one arg FILENAME which is the name of a file as found
249 in the compilation output, and should return a transformed file name.")
250
251 ;;;###autoload
252 (defvar compilation-process-setup-function nil
253 "*Function to call to customize the compilation process.
254 This functions is called immediately before the compilation process is
255 started. It can be used to set any variables or functions that are used
256 while processing the output of the compilation process.")
257
258 ;;;###autoload
259 (defvar compilation-buffer-name-function nil
260 "Function to compute the name of a compilation buffer.
261 The function receives one argument, the name of the major mode of the
262 compilation buffer. It should return a string.
263 nil means compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
264
265 ;;;###autoload
266 (defvar compilation-finish-function nil
267 "Function to call when a compilation process finishes.
268 It is called with two arguments: the compilation buffer, and a string
269 describing how the process finished.")
270
271 ;;;###autoload
272 (defvar compilation-finish-functions nil
273 "Functions to call when a compilation process finishes.
274 Each function is called with two arguments: the compilation buffer,
275 and a string describing how the process finished.")
276
277 (defvar compilation-last-buffer nil
278 "The most recent compilation buffer.
279 A buffer becomes most recent when its compilation is started
280 or when it is used with \\[next-error] or \\[compile-goto-error].")
281
282 (defvar compilation-in-progress nil
283 "List of compilation processes now running.")
284 (or (assq 'compilation-in-progress minor-mode-alist)
285 (setq minor-mode-alist (cons '(compilation-in-progress " Compiling")
286 minor-mode-alist)))
287
288 (defvar compilation-parsing-end nil
289 "Marker position of end of buffer when last error messages were parsed.")
290
291 (defvar compilation-error-message "No more errors"
292 "Message to print when no more matches are found.")
293
294 (defvar compilation-arguments nil
295 "Arguments that were given to `compile-internal'.")
296
297 (defvar compilation-num-errors-found)
298
299 (defvar compilation-error-regexp-alist
300 '(
301 ;; NOTE! See also grep-regexp-alist, below.
302
303 ;; 4.3BSD grep, cc, lint pass 1:
304 ;; /usr/src/foo/foo.c(8): warning: w may be used before set
305 ;; or GNU utilities:
306 ;; foo.c:8: error message
307 ;; or HP-UX 7.0 fc:
308 ;; foo.f :16 some horrible error message
309 ;; or GNU utilities with column (GNAT 1.82):
310 ;; foo.adb:2:1: Unit name does not match file name
311 ;; or with column and program name:
312 ;; jade:dbcommon.dsl:133:17:E: missing argument for function call
313 ;;
314 ;; We'll insist that the number be followed by a colon or closing
315 ;; paren, because otherwise this matches just about anything
316 ;; containing a number with spaces around it.
317
318 ;; We insist on a non-digit in the file name
319 ;; so that we don't mistake the file name for a command name
320 ;; and take the line number as the file name.
321 ("\\([a-zA-Z][-a-zA-Z._0-9]+: ?\\)?\
322 \\([a-zA-Z]?:?[^:( \t\n]*[^:( \t\n0-9][^:( \t\n]*\\)[:(][ \t]*\\([0-9]+\\)\
323 \\([) \t]\\|:\\(\\([0-9]+:\\)\\|[0-9]*[^:0-9]\\)\\)" 2 3 6)
324
325 ;; GNU utilities with precise locations (line and columns),
326 ;; possibly ranges:
327 ;; foo.c:8.23-9.1: error message
328 ("\\([a-zA-Z][-a-zA-Z._0-9]+: ?\\)\
329 \\([0-9]+\\)\\.\\([0-9]+\\)\
330 -\\([0-9]+\\)\\.\\([0-9]+\\)\
331 :" 1 2 3) ;; When ending points are supported, add line = 4 and col = 5.
332 ;; foo.c:8.23-45: error message
333 ("\\([a-zA-Z][-a-zA-Z._0-9]+: ?\\)\
334 \\([0-9]+\\)\\.\\([0-9]+\\)\
335 -\\([0-9]+\\)\
336 :" 1 2 3) ;; When ending points are supported, add line = 2 and col = 4.
337 ;; foo.c:8-45.3: error message
338 ("\\([a-zA-Z][-a-zA-Z._0-9]+: ?\\)\
339 \\([0-9]+\\)\
340 -\\([0-9]+\\)\\.\\([0-9]+\\)\
341 :" 1 2 nil) ;; When ending points are supported, add line = 2 and col = 4.
342 ;; foo.c:8.23: error message
343 ("\\([a-zA-Z][-a-zA-Z._0-9]+: ?\\)\
344 \\([0-9]+\\)\\.\\([0-9]+\\)\
345 :" 1 2 3)
346 ;; foo.c:8-23: error message
347 ("\\([a-zA-Z][-a-zA-Z._0-9]+: ?\\)\
348 \\([0-9]+\\)\
349 -\\([0-9]+\\)\
350 :" 1 2 nil);; When ending points are supported, add line = 3.
351
352 ;; Microsoft C/C++:
353 ;; keyboard.c(537) : warning C4005: 'min' : macro redefinition
354 ;; d:\tmp\test.c(23) : error C2143: syntax error : missing ';' before 'if'
355 ;; This used to be less selective and allow characters other than
356 ;; parens around the line number, but that caused confusion for
357 ;; GNU-style error messages.
358 ;; This used to reject spaces and dashes in file names,
359 ;; but they are valid now; so I made it more strict about the error
360 ;; message that follows.
361 ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \
362 : \\(error\\|warning\\) C[0-9]+:" 1 3)
363
364 ;; Borland C++, C++Builder:
365 ;; Error ping.c 15: Unable to open include file 'sys/types.h'
366 ;; Warning ping.c 68: Call to function 'func' with no prototype
367 ;; Error E2010 ping.c 15: Unable to open include file 'sys/types.h'
368 ;; Warning W1022 ping.c 68: Call to function 'func' with no prototype
369 ("\\(Error\\|Warning\\) \\(\\([FEW][0-9]+\\) \\)?\
370 \\([a-zA-Z]?:?[^:( \t\n]+\\)\
371 \\([0-9]+\\)\\([) \t]\\|:[^0-9\n]\\)" 4 5)
372
373 ;; Valgrind (memory debugger for x86 GNU/Linux):
374 ;; ==1332== at 0x8008621: main (vtest.c:180)
375 ;; Currently this regexp only matches the first error.
376 ;; Thanks to Hans Petter Jansson <hpj@ximian.com> for his regexp wisdom.
377 ("^==[0-9]+==[^(]+\(([^:]+):([0-9]+)" 1 2)
378
379 ;; 4.3BSD lint pass 2
380 ;; strcmp: variable # of args. llib-lc(359) :: /usr/src/foo/foo.c(8)
381 (".*[ \t:]\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(](+[ \t]*\\([0-9]+\\))[:) \t]*$"
382 1 2)
383
384 ;; 4.3BSD lint pass 3
385 ;; bloofle defined( /users/wolfgang/foo.c(4) ), but never used
386 ;; This used to be
387 ;; ("[ \t(]+\\([a-zA-Z]?:?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]+" 1 2)
388 ;; which is regexp Impressionism - it matches almost anything!
389 (".*([ \t]*\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\))" 1 2)
390
391 ;; MIPS lint pass<n>; looks good for SunPro lint also
392 ;; TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) in solomon.c due to truncation
393 ("[^\n ]+ (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
394 ;; name defined but never used: LinInt in cmap_calc.c(199)
395 (".*in \\([^(\n]+\\)(\\([0-9]+\\))$" 1 2)
396
397 ;; Ultrix 3.0 f77:
398 ;; fort: Severe: addstf.f, line 82: Missing operator or delimiter symbol
399 ;; Some SGI cc version:
400 ;; cfe: Warning 835: foo.c, line 2: something
401 ("\\(cfe\\|fort\\): [^:\n]*: \\([^ \n]*\\), line \\([0-9]+\\):" 2 3)
402 ;; Error on line 3 of t.f: Execution error unclassifiable statement
403 ;; Unknown who does this:
404 ;; Line 45 of "foo.c": bloofle undefined
405 ;; Absoft FORTRAN 77 Compiler 3.1.3
406 ;; error on line 19 of fplot.f: spelling error?
407 ;; warning on line 17 of fplot.f: data type is undefined for variable d
408 ("\\(.* on \\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
409 of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2)
410
411 ;; Apollo cc, 4.3BSD fc:
412 ;; "foo.f", line 3: Error: syntax error near end of statement
413 ;; IBM RS6000:
414 ;; "vvouch.c", line 19.5: 1506-046 (S) Syntax error.
415 ;; Microtec mcc68k:
416 ;; "foo.c", line 32 pos 1; (E) syntax error; unexpected symbol: "lossage"
417 ;; GNAT (as of July 94):
418 ;; "foo.adb", line 2(11): warning: file name does not match ...
419 ;; IBM AIX xlc compiler:
420 ;; "src/swapping.c", line 30.34: 1506-342 (W) "/*" detected in comment.
421 (".*\"\\([^,\" \n\t]+\\)\", lines? \
422 \\([0-9]+\\)\\([\(.]\\([0-9]+\\)\)?\\)?[:., (-]" 1 2 4)
423
424 ;; Python:
425 ;; File "foobar.py", line 5, blah blah
426 ("^File \"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)," 1 2)
427
428 ;; Caml compiler:
429 ;; File "foobar.ml", lines 5-8, characters 20-155: blah blah
430 ("^File \"\\([^,\" \n\t]+\\)\", lines? \\([0-9]+\\)[-0-9]*, characters? \\([0-9]+\\)" 1 2 3)
431
432 ;; MIPS RISC CC - the one distributed with Ultrix:
433 ;; ccom: Error: foo.c, line 2: syntax error
434 ;; DEC AXP OSF/1 cc
435 ;; /usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah
436 ("[a-z0-9/]+: \\([eE]rror\\|[wW]arning\\): \\([^,\" \n\t]+\\)[,:] \\(line \\)?\\([0-9]+\\):" 2 4)
437
438 ;; IBM AIX PS/2 C version 1.1:
439 ;; ****** Error number 140 in line 8 of file errors.c ******
440 (".*in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
441 ;; IBM AIX lint is too painful to do right this way. File name
442 ;; prefixes entire sections rather than being on each line.
443
444 ;; SPARCcompiler Pascal:
445 ;; 20 linjer : array[1..4] of linje;
446 ;; e 18480-----------^--- Inserted ';'
447 ;; and
448 ;; E 18520 line 61 - 0 is undefined
449 ;; These messages don't contain a file name. Instead the compiler gives
450 ;; a message whenever the file being compiled is changed.
451 (" +\\([0-9]+\\) +.*\n[ew] [0-9]+-+" nil 1)
452 ("[Ew] +[0-9]+ line \\([0-9]+\\) - " nil 1)
453
454 ;; Lucid Compiler, lcc 3.x
455 ;; E, file.cc(35,52) Illegal operation on pointers
456 ("[EW], \\([^(\n]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3)
457
458 ;; This seems to be superfluous because the first pattern matches it.
459 ;; ;; GNU messages with program name and optional column number.
460 ;; ("[a-zA-Z]?:?[^0-9 \n\t:]+[^ \n\t:]*:[ \t]*\\([^ \n\t:]+\\):\
461 ;;\\([0-9]+\\):\\(\\([0-9]+\\)[: \t]\\)?" 1 2 4)
462
463 ;; Cray C compiler error messages
464 ("\\(cc\\| cft\\)-[0-9]+ c\\(c\\|f77\\): ERROR \\([^,\n]+, \\)* File = \
465 \\([^,\n]+\\), Line = \\([0-9]+\\)" 4 5)
466
467 ;; IBM C/C++ Tools 2.01:
468 ;; foo.c(2:0) : informational EDC0804: Function foo is not referenced.
469 ;; foo.c(3:8) : warning EDC0833: Implicit return statement encountered.
470 ;; foo.c(5:5) : error EDC0350: Syntax error.
471 ("\\([^( \n\t]+\\)(\\([0-9]+\\):\\([0-9]+\\)) : " 1 2 3)
472
473 ;; IAR Systems C Compiler:
474 ;; "foo.c",3 Error[32]: Error message
475 ;; "foo.c",3 Warning[32]: Error message
476 ("\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(Error\\|Warning\\)\\[[0-9]+\\]:" 1 2)
477
478 ;; Sun ada (VADS, Solaris):
479 ;; /home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: "," inserted
480 ("\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
481
482 ;; Perl -w:
483 ;; syntax error at automake line 922, near "':'"
484 ;; Perl debugging traces
485 ;; store::odrecall('File_A', 'x2') called at store.pm line 90
486 (".* at \\([^ \n]+\\) line \\([0-9]+\\)[,.\n]" 1 2)
487
488 ;; Oracle pro*c:
489 ;; Semantic error at line 528, column 5, file erosacqdb.pc:
490 ("Semantic error at line \\([0-9]+\\), column \\([0-9]+\\), file \\(.*\\):"
491 3 1 2)
492
493 ;; EPC F90 compiler:
494 ;; Error 24 at (2:progran.f90) : syntax error
495 ("Error [0-9]+ at (\\([0-9]*\\):\\([^)\n]+\\))" 2 1)
496
497 ;; SGI IRIX MipsPro 7.3 compilers:
498 ;; cc-1070 cc: ERROR File = linkl.c, Line = 38
499 (".*: ERROR File = \\(.+\\), Line = \\([0-9]+\\)" 1 2)
500 (".*: WARNING File = \\(.+\\), Line = \\([0-9]+\\)" 1 2)
501
502 ;; Sun F90 error messages:
503 ;; cf90-113 f90comp: ERROR NSE, File = Hoved.f90, Line = 16, Column = 3
504 (".* ERROR [a-zA-Z0-9 ]+, File = \\(.+\\), Line = \\([0-9]+\\), Column = \\([0-9]+\\)"
505 1 2 3)
506
507 ;; RXP - GPL XML validator at http://www.cogsci.ed.ac.uk/~richard/rxp.html:
508 ;; Error: Mismatched end tag: expected </geroup>, got </group>
509 ;; in unnamed entity at line 71 char 8 of file:///home/reto/test/group.xml
510 ("Error:.*\n.* line \\([0-9]+\\) char \\([0-9]+\\) of file://\\(.+\\)"
511 3 1 2)
512 ;; Warning: Start tag for undeclared element geroup
513 ;; in unnamed entity at line 4 char 8 of file:///home/reto/test/group.xml
514 ("Warning:.*\n.* line \\([0-9]+\\) char \\([0-9]+\\) of file://\\(.+\\)"
515 3 1 2)
516 )
517
518 "Alist that specifies how to match errors in compiler output.
519 Each elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX FILE-FORMAT...])
520 If REGEXP matches, the FILE-IDX'th subexpression gives the file name, and
521 the LINE-IDX'th subexpression gives the line number. If COLUMN-IDX is
522 given, the COLUMN-IDX'th subexpression gives the column number on that line.
523 If any FILE-FORMAT is given, each is a format string to produce a file name to
524 try; %s in the string is replaced by the text matching the FILE-IDX'th
525 subexpression.")
526
527 (defvar compilation-enter-directory-regexp-alist
528 '(
529 ;; Matches lines printed by the `-w' option of GNU Make.
530 (".*: Entering directory `\\(.*\\)'$" 1)
531 )
532 "Alist specifying how to match lines that indicate a new current directory.
533 Note that the match is done at the beginning of lines.
534 Each elt has the form (REGEXP IDX).
535 If REGEXP matches, the IDX'th subexpression gives the directory name.
536
537 The default value matches lines printed by the `-w' option of GNU Make.")
538
539 (defvar compilation-leave-directory-regexp-alist
540 '(
541 ;; Matches lines printed by the `-w' option of GNU Make.
542 (".*: Leaving directory `\\(.*\\)'$" 1)
543 )
544 "Alist specifying how to match lines that indicate restoring current directory.
545 Note that the match is done at the beginning of lines.
546 Each elt has the form (REGEXP IDX).
547 If REGEXP matches, the IDX'th subexpression gives the name of the directory
548 being moved from. If IDX is nil, the last directory entered \(by a line
549 matching `compilation-enter-directory-regexp-alist'\) is assumed.
550
551 The default value matches lines printed by the `-w' option of GNU Make.")
552
553 (defvar compilation-file-regexp-alist
554 '(
555 ;; This matches entries with date time year file-name: like
556 ;; Thu May 14 10:46:12 1992 mom3.p:
557 ("\\w\\w\\w \\w\\w\\w +[0-9]+ [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9] \\(.*\\):$" 1)
558 )
559 "Alist specifying how to match lines that indicate a new current file.
560 Note that the match is done at the beginning of lines.
561 Each elt has the form (REGEXP IDX).
562 If REGEXP matches, the IDX'th subexpression gives the file name. This is
563 used with compilers that don't indicate file name in every error message.")
564
565 ;; There is no generally useful regexp that will match non messages, but
566 ;; in special cases there might be one. The lines that are not matched by
567 ;; a regexp take much longer time than the ones that are recognized so if
568 ;; you have same regexeps here, parsing is faster.
569 (defvar compilation-nomessage-regexp-alist
570 '(
571 )
572 "Alist specifying how to match lines that have no message.
573 Note that the match is done at the beginning of lines.
574 Each elt has the form (REGEXP). This alist is by default empty, but if
575 you have some good regexps here, the parsing of messages will be faster.")
576
577 (defcustom compilation-error-screen-columns t
578 "*If non-nil, column numbers in error messages are screen columns.
579 Otherwise they are interpreted as character positions, with
580 each character occupying one column.
581 The default is to use screen columns, which requires that the compilation
582 program and Emacs agree about the display width of the characters,
583 especially the TAB character."
584 :type 'boolean
585 :group 'compilation
586 :version "20.4")
587
588 (defcustom compilation-read-command t
589 "*Non-nil means \\[compile] reads the compilation command to use.
590 Otherwise, \\[compile] just uses the value of `compile-command'."
591 :type 'boolean
592 :group 'compilation)
593
594 ;;;###autoload
595 (defcustom compilation-ask-about-save t
596 "*Non-nil means \\[compile] asks which buffers to save before compiling.
597 Otherwise, it saves all modified buffers without asking."
598 :type 'boolean
599 :group 'compilation)
600
601 ;; Note: the character class after the optional drive letter does not
602 ;; include a space to support file names with blanks.
603 (defvar grep-regexp-alist
604 '(("\\([a-zA-Z]?:?[^:(\t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2))
605 "Regexp used to match grep hits. See `compilation-error-regexp-alist'.")
606
607 (defvar grep-program
608 ;; Currently zgrep has trouble. It runs egrep instead of grep,
609 ;; and it doesn't pass along long options right.
610 "grep"
611 ;; (if (equal (condition-case nil ; in case "zgrep" isn't in exec-path
612 ;; (call-process "zgrep" nil nil nil
613 ;; "foo" null-device)
614 ;; (error nil))
615 ;; 1)
616 ;; "zgrep"
617 ;; "grep")
618 "The default grep program for `grep-command' and `grep-find-command'.
619 This variable's value takes effect when `grep-compute-defaults' is called.")
620
621 (defvar find-program "find"
622 "The default find program for `grep-find-command'.
623 This variable's value takes effect when `grep-compute-defaults' is called.")
624
625 (defvar grep-find-use-xargs nil
626 "Whether \\[grep-find] uses the `xargs' utility by default.
627
628 If nil, it uses `grep -exec'; if `gnu', it uses `find -print0' and `xargs -0';
629 if not nil and not `gnu', it uses `find -print' and `xargs'.
630
631 This variable's value takes effect when `grep-compute-defaults' is called.")
632
633 ;;;###autoload
634 (defcustom compilation-search-path '(nil)
635 "*List of directories to search for source files named in error messages.
636 Elements should be directory names, not file names of directories.
637 nil as an element means to try the default directory."
638 :type '(repeat (choice (const :tag "Default" nil)
639 (string :tag "Directory")))
640 :group 'compilation)
641
642 (defcustom compile-command "make -k "
643 "*Last shell command used to do a compilation; default for next compilation.
644
645 Sometimes it is useful for files to supply local values for this variable.
646 You might also use mode hooks to specify it in certain modes, like this:
647
648 (add-hook 'c-mode-hook
649 (lambda ()
650 (unless (or (file-exists-p \"makefile\")
651 (file-exists-p \"Makefile\"))
652 (set (make-local-variable 'compile-command)
653 (concat \"make -k \"
654 (file-name-sans-extension buffer-file-name))))))"
655 :type 'string
656 :group 'compilation)
657
658 (defvar compilation-directory-stack nil
659 "Stack of previous directories for `compilation-leave-directory-regexp'.
660 The last element is the directory the compilation was started in.")
661
662 (defvar compilation-exit-message-function nil "\
663 If non-nil, called when a compilation process dies to return a status message.
664 This should be a function of three arguments: process status, exit status,
665 and exit message; it returns a cons (MESSAGE . MODELINE) of the strings to
666 write into the compilation buffer, and to put in its mode line.")
667
668 ;; History of compile commands.
669 (defvar compile-history nil)
670 ;; History of grep commands.
671 (defvar grep-history nil)
672 (defvar grep-find-history nil)
673
674 (defun compilation-mode-font-lock-keywords ()
675 "Return expressions to highlight in Compilation mode."
676 (nconc
677 ;;
678 ;; Compiler warning/error lines.
679 (mapcar (function
680 (lambda (item)
681 ;; Prepend "^", adjusting FILE-IDX and LINE-IDX accordingly.
682 (let ((file-idx (nth 1 item))
683 (line-idx (nth 2 item))
684 (col-idx (nth 3 item))
685 keyword)
686 (when (numberp col-idx)
687 (setq keyword
688 (cons (list (1+ col-idx) 'font-lock-type-face nil t)
689 keyword)))
690 (when (numberp line-idx)
691 (setq keyword
692 (cons (list (1+ line-idx) 'font-lock-variable-name-face)
693 keyword)))
694 (when (numberp file-idx)
695 (setq keyword
696 (cons (list (1+ file-idx) 'font-lock-warning-face)
697 keyword)))
698 (cons (concat "^\\(" (nth 0 item) "\\)") keyword))))
699 compilation-error-regexp-alist)
700 (list
701 ;;
702 ;; Compiler output lines. Recognize `make[n]:' lines too.
703 '("^\\([A-Za-z_0-9/\.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
704 (1 font-lock-function-name-face) (3 font-lock-comment-face nil t)))
705 ))
706 \f
707 ;;;###autoload
708 (defun compile (command)
709 "Compile the program including the current buffer. Default: run `make'.
710 Runs COMMAND, a shell command, in a separate process asynchronously
711 with output going to the buffer `*compilation*'.
712
713 You can then use the command \\[next-error] to find the next error message
714 and move to the source code that caused it.
715
716 Interactively, prompts for the command if `compilation-read-command' is
717 non-nil; otherwise uses `compile-command'. With prefix arg, always prompts.
718
719 To run more than one compilation at once, start one and rename the
720 \`*compilation*' buffer to some other name with \\[rename-buffer].
721 Then start the next one.
722
723 The name used for the buffer is actually whatever is returned by
724 the function in `compilation-buffer-name-function', so you can set that
725 to a function that generates a unique name."
726 (interactive
727 (if (or compilation-read-command current-prefix-arg)
728 (list (read-from-minibuffer "Compile command: "
729 (eval compile-command) nil nil
730 '(compile-history . 1)))
731 (list (eval compile-command))))
732 (unless (equal command (eval compile-command))
733 (setq compile-command command))
734 (save-some-buffers (not compilation-ask-about-save) nil)
735 (compile-internal command "No more errors"))
736
737 ;; run compile with the default command line
738 (defun recompile ()
739 "Re-compile the program including the current buffer.
740 If this is run in a compilation-mode buffer, re-use the arguments from the
741 original use. Otherwise, it recompiles using `compile-command'."
742 (interactive)
743 (save-some-buffers (not compilation-ask-about-save) nil)
744 (apply 'compile-internal (or compilation-arguments
745 `(,(eval compile-command) "No more errors"))))
746
747 (defun grep-process-setup ()
748 "Set up `compilation-exit-message-function' for `grep'."
749 (set (make-local-variable 'compilation-exit-message-function)
750 (lambda (status code msg)
751 (if (eq status 'exit)
752 (cond ((zerop code)
753 '("finished (matches found)\n" . "matched"))
754 ((= code 1)
755 '("finished with no matches found\n" . "no match"))
756 (t
757 (cons msg code)))
758 (cons msg code)))))
759
760 ;;;###autoload
761 (defun grep (command-args)
762 "Run grep, with user-specified args, and collect output in a buffer.
763 While grep runs asynchronously, you can use \\[next-error] (M-x next-error),
764 or \\<compilation-minor-mode-map>\\[compile-goto-error] in the grep \
765 output buffer, to go to the lines
766 where grep found matches.
767
768 This command uses a special history list for its COMMAND-ARGS, so you can
769 easily repeat a grep command.
770
771 A prefix argument says to default the argument based upon the current
772 tag the cursor is over, substituting it into the last grep command
773 in the grep command history (or into `grep-command'
774 if that history list is empty)."
775 (interactive
776 (let (grep-default (arg current-prefix-arg))
777 (unless (and grep-command
778 (or (not grep-use-null-device) (eq grep-use-null-device t)))
779 (grep-compute-defaults))
780 (when arg
781 (let ((tag-default
782 (funcall (or find-tag-default-function
783 (get major-mode 'find-tag-default-function)
784 ;; We use grep-tag-default instead of
785 ;; find-tag-default, to avoid loading etags.
786 'grep-tag-default))))
787 (setq grep-default (or (car grep-history) grep-command))
788 ;; Replace the thing matching for with that around cursor
789 (when (string-match "[^ ]+\\s +\\(-[^ ]+\\s +\\)*\\(\"[^\"]+\"\\|[^ ]+\\)\\(\\s-+\\S-+\\)?" grep-default)
790 (unless (or (match-beginning 3) (not (stringp buffer-file-name)))
791 (setq grep-default (concat grep-default "*."
792 (file-name-extension buffer-file-name))))
793 (setq grep-default (replace-match (or tag-default "")
794 t t grep-default 2)))))
795 (list (read-from-minibuffer "Run grep (like this): "
796 (or grep-default grep-command)
797 nil nil 'grep-history))))
798
799 ;; Setting process-setup-function makes exit-message-function work
800 ;; even when async processes aren't supported.
801 (let* ((compilation-process-setup-function 'grep-process-setup)
802 (buf (compile-internal (if (and grep-use-null-device null-device)
803 (concat command-args " " null-device)
804 command-args)
805 "No more grep hits" "grep"
806 ;; Give it a simpler regexp to match.
807 nil grep-regexp-alist)))))
808
809 ;; This is a copy of find-tag-default from etags.el.
810 (defun grep-tag-default ()
811 (save-excursion
812 (while (looking-at "\\sw\\|\\s_")
813 (forward-char 1))
814 (when (or (re-search-backward "\\sw\\|\\s_"
815 (save-excursion (beginning-of-line) (point))
816 t)
817 (re-search-forward "\\(\\sw\\|\\s_\\)+"
818 (save-excursion (end-of-line) (point))
819 t))
820 (goto-char (match-end 0))
821 (buffer-substring (point)
822 (progn (forward-sexp -1)
823 (while (looking-at "\\s'")
824 (forward-char 1))
825 (point))))))
826
827 ;;;###autoload
828 (defun grep-find (command-args)
829 "Run grep via find, with user-specified args COMMAND-ARGS.
830 Collect output in a buffer.
831 While find runs asynchronously, you can use the \\[next-error] command
832 to find the text that grep hits refer to.
833
834 This command uses a special history list for its arguments, so you can
835 easily repeat a find command."
836 (interactive
837 (progn
838 (unless grep-find-command
839 (grep-compute-defaults))
840 (list (read-from-minibuffer "Run find (like this): "
841 grep-find-command nil nil
842 'grep-find-history))))
843 (let ((null-device nil)) ; see grep
844 (grep command-args)))
845
846 (defun grep-expand-command-macros (command &optional regexp files dir excl case-fold)
847 "Patch grep COMMAND replacing <D>, etc."
848 (setq command
849 (replace-regexp-in-string "<D>"
850 (or dir ".") command t t))
851 (setq command
852 (replace-regexp-in-string "<X>"
853 (or excl "") command t t))
854 (setq command
855 (replace-regexp-in-string "<F>"
856 (or files "") command t t))
857 (setq command
858 (replace-regexp-in-string "<C>"
859 (if case-fold "-i" "") command t t))
860 (setq command
861 (replace-regexp-in-string "<R>"
862 (or regexp "") command t t))
863 command)
864
865 (defvar grep-tree-last-regexp "")
866 (defvar grep-tree-last-files (car (car grep-tree-files-aliases)))
867
868 ;;;###autoload
869 (defun grep-tree (regexp files dir &optional subdirs)
870 "Grep for REGEXP in FILES in directory tree rooted at DIR.
871 Collect output in a buffer.
872 Interactively, prompt separately for each search parameter.
873 With prefix arg, reuse previous REGEXP.
874 The search is limited to file names matching shell pattern FILES.
875 FILES may use abbreviations defined in `grep-tree-files-aliases', e.g.
876 entering `ch' is equivalent to `*.[ch]'.
877
878 While find runs asynchronously, you can use the \\[next-error] command
879 to find the text that grep hits refer to.
880
881 This command uses a special history list for its arguments, so you can
882 easily repeat a find command.
883
884 When used non-interactively, optional arg SUBDIRS limits the search to
885 those sub directories of DIR."
886 (interactive
887 (let* ((regexp
888 (if current-prefix-arg
889 grep-tree-last-regexp
890 (let* ((default (current-word))
891 (spec (read-string
892 (concat "Search for"
893 (if (and default (> (length default) 0))
894 (format " (default %s): " default) ": ")))))
895 (if (equal spec "") default spec))))
896 (files
897 (read-string (concat "Search for \"" regexp "\" in files (default " grep-tree-last-files "): ")))
898 (dir
899 (read-directory-name "Base directory: " nil default-directory t)))
900 (list regexp files dir)))
901 (unless grep-tree-command
902 (grep-compute-defaults))
903 (unless (and (stringp files) (> (length files) 0))
904 (setq files grep-tree-last-files))
905 (when files
906 (setq grep-tree-last-files files)
907 (let ((mf (assoc files grep-tree-files-aliases)))
908 (if mf
909 (setq files (cdr mf)))))
910 (let ((command-args (grep-expand-command-macros
911 grep-tree-command
912 (setq grep-tree-last-regexp regexp)
913 (and files (concat "-name '" files "'"))
914 (if subdirs
915 (if (stringp subdirs)
916 subdirs
917 (mapconcat 'identity subdirs " "))
918 nil) ;; we change default-directory to dir
919 (and grep-tree-ignore-CVS-directories "-path '*/CVS' -prune -o ")
920 grep-tree-ignore-case))
921 (default-directory dir)
922 (null-device nil)) ; see grep
923 (grep command-args)))
924
925 (defcustom compilation-scroll-output nil
926 "*Non-nil to scroll the *compilation* buffer window as output appears.
927
928 Setting it causes the compilation-mode commands to put point at the
929 end of their output window so that the end of the output is always
930 visible rather than the begining."
931 :type 'boolean
932 :version "20.3"
933 :group 'compilation)
934
935
936 (defun compilation-buffer-name (mode-name name-function)
937 "Return the name of a compilation buffer to use.
938 If NAME-FUNCTION is non-nil, call it with one argument MODE-NAME
939 to determine the buffer name.
940 Likewise if `compilation-buffer-name-function' is non-nil.
941 If current buffer is in Compilation mode for the same mode name
942 return the name of the current buffer, so that it gets reused.
943 Otherwise, construct a buffer name from MODE-NAME."
944 (cond (name-function
945 (funcall name-function mode-name))
946 (compilation-buffer-name-function
947 (funcall compilation-buffer-name-function mode-name))
948 ((and (eq major-mode 'compilation-mode)
949 (equal mode-name (nth 2 compilation-arguments)))
950 (buffer-name))
951 (t
952 (concat "*" (downcase mode-name) "*"))))
953
954
955 (defun compile-internal (command error-message
956 &optional name-of-mode parser
957 error-regexp-alist name-function
958 enter-regexp-alist leave-regexp-alist
959 file-regexp-alist nomessage-regexp-alist
960 no-async)
961 "Run compilation command COMMAND (low level interface).
962 ERROR-MESSAGE is a string to print if the user asks to see another error
963 and there are no more errors. The rest of the arguments, 3-10 are optional.
964 For them nil means use the default.
965 NAME-OF-MODE is the name to display as the major mode in the compilation
966 buffer. PARSER is the error parser function. ERROR-REGEXP-ALIST is the error
967 message regexp alist to use. NAME-FUNCTION is a function called to name the
968 buffer. ENTER-REGEXP-ALIST is the enter directory message regexp alist to use.
969 LEAVE-REGEXP-ALIST is the leave directory message regexp alist to use.
970 FILE-REGEXP-ALIST is the change current file message regexp alist to use.
971 NOMESSAGE-REGEXP-ALIST is the nomessage regexp alist to use.
972 The defaults for these variables are the global values of
973 \`compilation-parse-errors-function', `compilation-error-regexp-alist',
974 \`compilation-buffer-name-function', `compilation-enter-directory-regexp-alist',
975 \`compilation-leave-directory-regexp-alist', `compilation-file-regexp-alist',
976 \ and `compilation-nomessage-regexp-alist', respectively.
977 For arg 7-10 a value `t' means an empty alist.
978
979 If NO-ASYNC is non-nil, start the compilation process synchronously.
980
981 Returns the compilation buffer created."
982 (unless no-async
983 (setq no-async (not (fboundp 'start-process))))
984 (let (outbuf)
985 (save-excursion
986 (or name-of-mode
987 (setq name-of-mode "Compilation"))
988 (setq outbuf
989 (get-buffer-create (compilation-buffer-name name-of-mode
990 name-function)))
991 (set-buffer outbuf)
992 (let ((comp-proc (get-buffer-process (current-buffer))))
993 (if comp-proc
994 (if (or (not (eq (process-status comp-proc) 'run))
995 (yes-or-no-p
996 (format "A %s process is running; kill it? "
997 name-of-mode)))
998 (condition-case ()
999 (progn
1000 (interrupt-process comp-proc)
1001 (sit-for 1)
1002 (delete-process comp-proc))
1003 (error nil))
1004 (error "Cannot have two processes in `%s' at once"
1005 (buffer-name))
1006 )))
1007 ;; In case the compilation buffer is current, make sure we get the global
1008 ;; values of compilation-error-regexp-alist, etc.
1009 (kill-all-local-variables))
1010 (or error-regexp-alist
1011 (setq error-regexp-alist compilation-error-regexp-alist))
1012 (or enter-regexp-alist
1013 (setq enter-regexp-alist compilation-enter-directory-regexp-alist))
1014 (or leave-regexp-alist
1015 (setq leave-regexp-alist compilation-leave-directory-regexp-alist))
1016 (or file-regexp-alist
1017 (setq file-regexp-alist compilation-file-regexp-alist))
1018 (or nomessage-regexp-alist
1019 (setq nomessage-regexp-alist compilation-nomessage-regexp-alist))
1020 (or parser (setq parser compilation-parse-errors-function))
1021 (let ((thisdir default-directory)
1022 outwin)
1023 (save-excursion
1024 ;; Clear out the compilation buffer and make it writable.
1025 ;; Change its default-directory to the directory where the compilation
1026 ;; will happen, and insert a `cd' command to indicate this.
1027 (set-buffer outbuf)
1028 (setq buffer-read-only nil)
1029 (buffer-disable-undo (current-buffer))
1030 (erase-buffer)
1031 (buffer-enable-undo (current-buffer))
1032 (setq default-directory thisdir)
1033 (insert "cd " thisdir "\n" command "\n")
1034 (set-buffer-modified-p nil))
1035 ;; If we're already in the compilation buffer, go to the end
1036 ;; of the buffer, so point will track the compilation output.
1037 (if (eq outbuf (current-buffer))
1038 (goto-char (point-max)))
1039 ;; Pop up the compilation buffer.
1040 (setq outwin (display-buffer outbuf nil t))
1041 (save-excursion
1042 (set-buffer outbuf)
1043 (compilation-mode name-of-mode)
1044 ;; In what way is it non-ergonomic ? -stef
1045 ;; (toggle-read-only 1) ;;; Non-ergonomic.
1046 (set (make-local-variable 'compilation-parse-errors-function) parser)
1047 (set (make-local-variable 'compilation-error-message) error-message)
1048 (set (make-local-variable 'compilation-error-regexp-alist)
1049 error-regexp-alist)
1050 (set (make-local-variable 'compilation-enter-directory-regexp-alist)
1051 enter-regexp-alist)
1052 (set (make-local-variable 'compilation-leave-directory-regexp-alist)
1053 leave-regexp-alist)
1054 (set (make-local-variable 'compilation-file-regexp-alist)
1055 file-regexp-alist)
1056 (set (make-local-variable 'compilation-nomessage-regexp-alist)
1057 nomessage-regexp-alist)
1058 (set (make-local-variable 'compilation-arguments)
1059 (list command error-message
1060 name-of-mode parser
1061 error-regexp-alist name-function
1062 enter-regexp-alist leave-regexp-alist
1063 file-regexp-alist nomessage-regexp-alist))
1064 ;; This proves a good idea if the buffer's going to scroll
1065 ;; with lazy-lock on.
1066 (set (make-local-variable 'lazy-lock-defer-on-scrolling) t)
1067 (setq default-directory thisdir
1068 compilation-directory-stack (list default-directory))
1069 (set-window-start outwin (point-min))
1070 (or (eq outwin (selected-window))
1071 (set-window-point outwin (point-min)))
1072 (compilation-set-window-height outwin)
1073 (if compilation-process-setup-function
1074 (funcall compilation-process-setup-function))
1075 ;; Start the compilation.
1076 (if (not no-async)
1077 (let* ((process-environment
1078 (append
1079 (if (and (boundp 'system-uses-terminfo)
1080 system-uses-terminfo)
1081 (list "TERM=dumb" "TERMCAP="
1082 (format "COLUMNS=%d" (window-width)))
1083 (list "TERM=emacs"
1084 (format "TERMCAP=emacs:co#%d:tc=unknown:"
1085 (window-width))))
1086 ;; Set the EMACS variable, but
1087 ;; don't override users' setting of $EMACS.
1088 (if (getenv "EMACS")
1089 process-environment
1090 (cons "EMACS=t" process-environment))))
1091 (proc (start-process-shell-command (downcase mode-name)
1092 outbuf
1093 command)))
1094 (set-process-sentinel proc 'compilation-sentinel)
1095 (set-process-filter proc 'compilation-filter)
1096 (set-marker (process-mark proc) (point) outbuf)
1097 (setq compilation-in-progress
1098 (cons proc compilation-in-progress)))
1099 ;; No asynchronous processes available.
1100 (message "Executing `%s'..." command)
1101 ;; Fake modeline display as if `start-process' were run.
1102 (setq mode-line-process ":run")
1103 (force-mode-line-update)
1104 (sit-for 0) ; Force redisplay
1105 (let ((status (call-process shell-file-name nil outbuf nil "-c"
1106 command)))
1107 (cond ((numberp status)
1108 (compilation-handle-exit 'exit status
1109 (if (zerop status)
1110 "finished\n"
1111 (format "\
1112 exited abnormally with code %d\n"
1113 status))))
1114 ((stringp status)
1115 (compilation-handle-exit 'signal status
1116 (concat status "\n")))
1117 (t
1118 (compilation-handle-exit 'bizarre status status))))
1119 (message "Executing `%s'...done" command)))
1120 (if compilation-scroll-output
1121 (save-selected-window
1122 (select-window outwin)
1123 (goto-char (point-max)))))
1124 ;; Make it so the next C-x ` will use this buffer.
1125 (setq compilation-last-buffer outbuf)))
1126
1127 (defun compilation-set-window-height (window)
1128 "Set the height of WINDOW according to `compilation-window-height'."
1129 (and compilation-window-height
1130 (= (window-width window) (frame-width (window-frame window)))
1131 ;; If window is alone in its frame, aside from a minibuffer,
1132 ;; don't change its height.
1133 (not (eq window (frame-root-window (window-frame window))))
1134 ;; This save-excursion prevents us from changing the current buffer,
1135 ;; which might not be the same as the selected window's buffer.
1136 (save-excursion
1137 (let ((w (selected-window)))
1138 (unwind-protect
1139 (progn
1140 (select-window window)
1141 (enlarge-window (- compilation-window-height
1142 (window-height))))
1143 ;; The enlarge-window above may have deleted W, if
1144 ;; compilation-window-height is large enough.
1145 (when (window-live-p w)
1146 (select-window w)))))))
1147
1148 (defvar compilation-minor-mode-map
1149 (let ((map (make-sparse-keymap)))
1150 (define-key map [mouse-2] 'compile-mouse-goto-error)
1151 (define-key map "\C-c\C-c" 'compile-goto-error)
1152 (define-key map "\C-m" 'compile-goto-error)
1153 (define-key map "\C-c\C-k" 'kill-compilation)
1154 (define-key map "\M-n" 'compilation-next-error)
1155 (define-key map "\M-p" 'compilation-previous-error)
1156 (define-key map "\M-{" 'compilation-previous-file)
1157 (define-key map "\M-}" 'compilation-next-file)
1158 map)
1159 "Keymap for `compilation-minor-mode'.")
1160
1161 (defvar compilation-shell-minor-mode-map
1162 (let ((map (make-sparse-keymap)))
1163 (define-key map [mouse-2] 'compile-mouse-goto-error)
1164 (define-key map "\M-\C-m" 'compile-goto-error)
1165 (define-key map "\M-\C-n" 'compilation-next-error)
1166 (define-key map "\M-\C-p" 'compilation-previous-error)
1167 (define-key map "\M-{" 'compilation-previous-file)
1168 (define-key map "\M-}" 'compilation-next-file)
1169 ;; Set up the menu-bar
1170 (define-key map [menu-bar errors-menu]
1171 (cons "Errors" (make-sparse-keymap "Errors")))
1172 (define-key map [menu-bar errors-menu stop-subjob]
1173 '("Stop" . comint-interrupt-subjob))
1174 (define-key map [menu-bar errors-menu compilation-mode-separator2]
1175 '("----" . nil))
1176 (define-key map [menu-bar errors-menu compilation-mode-first-error]
1177 '("First Error" . first-error))
1178 (define-key map [menu-bar errors-menu compilation-mode-previous-error]
1179 '("Previous Error" . previous-error))
1180 (define-key map [menu-bar errors-menu compilation-mode-next-error]
1181 '("Next Error" . next-error))
1182 map)
1183 "Keymap for `compilation-shell-minor-mode'.")
1184
1185 (defvar compilation-mode-map
1186 (let ((map (cons 'keymap compilation-minor-mode-map)))
1187 (define-key map " " 'scroll-up)
1188 (define-key map "\^?" 'scroll-down)
1189 ;; Set up the menu-bar
1190 (define-key map [menu-bar compilation-menu]
1191 (cons "Compile" (make-sparse-keymap "Compile")))
1192
1193 (define-key map [menu-bar compilation-menu compilation-mode-kill-compilation]
1194 '("Stop Compilation" . kill-compilation))
1195 (define-key map [menu-bar compilation-menu compilation-mode-separator2]
1196 '("----" . nil))
1197 (define-key map [menu-bar compilation-menu compilation-mode-first-error]
1198 '("First Error" . first-error))
1199 (define-key map [menu-bar compilation-menu compilation-mode-previous-error]
1200 '("Previous Error" . previous-error))
1201 (define-key map [menu-bar compilation-menu compilation-mode-next-error]
1202 '("Next Error" . next-error))
1203 (define-key map [menu-bar compilation-menu compilation-separator2]
1204 '("----" . nil))
1205 (define-key map [menu-bar compilation-menu compilation-mode-grep]
1206 '("Search Files (grep)" . grep))
1207 (define-key map [menu-bar compilation-menu compilation-mode-recompile]
1208 '("Recompile" . recompile))
1209 (define-key map [menu-bar compilation-menu compilation-mode-compile]
1210 '("Compile..." . compile))
1211 map)
1212 "Keymap for compilation log buffers.
1213 `compilation-minor-mode-map' is a cdr of this.")
1214
1215 (put 'compilation-mode 'mode-class 'special)
1216
1217 ;;;###autoload
1218 (defun compilation-mode (&optional name-of-mode)
1219 "Major mode for compilation log buffers.
1220 \\<compilation-mode-map>To visit the source for a line-numbered error,
1221 move point to the error message line and type \\[compile-goto-error].
1222 To kill the compilation, type \\[kill-compilation].
1223
1224 Runs `compilation-mode-hook' with `run-hooks' (which see)."
1225 (interactive)
1226 (kill-all-local-variables)
1227 (use-local-map compilation-mode-map)
1228 (setq major-mode 'compilation-mode
1229 mode-name (or name-of-mode "Compilation"))
1230 (compilation-setup)
1231 (set (make-local-variable 'font-lock-defaults)
1232 '(compilation-mode-font-lock-keywords t))
1233 (set (make-local-variable 'revert-buffer-function)
1234 'compilation-revert-buffer)
1235 (run-hooks 'compilation-mode-hook))
1236
1237 (defun compilation-revert-buffer (ignore-auto noconfirm)
1238 (if (or noconfirm (yes-or-no-p (format "Restart compilation? ")))
1239 (apply 'compile-internal compilation-arguments)))
1240
1241 (defun compilation-setup ()
1242 "Prepare the buffer for the compilation parsing commands to work."
1243 ;; Make the buffer's mode line show process state.
1244 (setq mode-line-process '(":%s"))
1245 (set (make-local-variable 'compilation-error-list) nil)
1246 (set (make-local-variable 'compilation-old-error-list) nil)
1247 (set (make-local-variable 'compilation-parsing-end) (copy-marker 1))
1248 (set (make-local-variable 'compilation-directory-stack)
1249 (list default-directory))
1250 (make-local-variable 'compilation-error-screen-columns)
1251 (setq compilation-last-buffer (current-buffer)))
1252
1253 (defvar compilation-shell-minor-mode nil
1254 "Non-nil when in `compilation-shell-minor-mode'.
1255 In this minor mode, all the error-parsing commands of the
1256 Compilation major mode are available but bound to keys that don't
1257 collide with Shell mode.")
1258 (make-variable-buffer-local 'compilation-shell-minor-mode)
1259
1260 (or (assq 'compilation-shell-minor-mode minor-mode-alist)
1261 (setq minor-mode-alist
1262 (cons '(compilation-shell-minor-mode " Shell-Compile")
1263 minor-mode-alist)))
1264 (or (assq 'compilation-shell-minor-mode minor-mode-map-alist)
1265 (setq minor-mode-map-alist (cons (cons 'compilation-shell-minor-mode
1266 compilation-shell-minor-mode-map)
1267 minor-mode-map-alist)))
1268
1269 (defvar compilation-minor-mode nil
1270 "Non-nil when in `compilation-minor-mode'.
1271 In this minor mode, all the error-parsing commands of the
1272 Compilation major mode are available.")
1273 (make-variable-buffer-local 'compilation-minor-mode)
1274
1275 (or (assq 'compilation-minor-mode minor-mode-alist)
1276 (setq minor-mode-alist (cons '(compilation-minor-mode " Compilation")
1277 minor-mode-alist)))
1278 (or (assq 'compilation-minor-mode minor-mode-map-alist)
1279 (setq minor-mode-map-alist (cons (cons 'compilation-minor-mode
1280 compilation-minor-mode-map)
1281 minor-mode-map-alist)))
1282
1283 ;;;###autoload
1284 (defun compilation-shell-minor-mode (&optional arg)
1285 "Toggle compilation shell minor mode.
1286 With arg, turn compilation mode on if and only if arg is positive.
1287 See `compilation-mode'.
1288 Turning the mode on runs the normal hook `compilation-shell-minor-mode-hook'."
1289 (interactive "P")
1290 (if (setq compilation-shell-minor-mode (if (null arg)
1291 (null compilation-shell-minor-mode)
1292 (> (prefix-numeric-value arg) 0)))
1293 (let ((mode-line-process))
1294 (compilation-setup)
1295 (run-hooks 'compilation-shell-minor-mode-hook))))
1296
1297 ;;;###autoload
1298 (defun compilation-minor-mode (&optional arg)
1299 "Toggle compilation minor mode.
1300 With arg, turn compilation mode on if and only if arg is positive.
1301 See `compilation-mode'.
1302 Turning the mode on runs the normal hook `compilation-minor-mode-hook'."
1303 (interactive "P")
1304 (if (setq compilation-minor-mode (if (null arg)
1305 (null compilation-minor-mode)
1306 (> (prefix-numeric-value arg) 0)))
1307 (let ((mode-line-process))
1308 (compilation-setup)
1309 (run-hooks 'compilation-minor-mode-hook))))
1310
1311 (defun compilation-handle-exit (process-status exit-status msg)
1312 "Write msg in the current buffer and hack its mode-line-process."
1313 (let ((buffer-read-only nil)
1314 (status (if compilation-exit-message-function
1315 (funcall compilation-exit-message-function
1316 process-status exit-status msg)
1317 (cons msg exit-status)))
1318 (omax (point-max))
1319 (opoint (point)))
1320 ;; Record where we put the message, so we can ignore it
1321 ;; later on.
1322 (goto-char omax)
1323 (insert ?\n mode-name " " (car status))
1324 (if (and (numberp compilation-window-height)
1325 (zerop compilation-window-height))
1326 (message "%s" (cdr status)))
1327 (if (bolp)
1328 (forward-char -1))
1329 (insert " at " (substring (current-time-string) 0 19))
1330 (goto-char (point-max))
1331 ;; Prevent that message from being recognized as a compilation error.
1332 (add-text-properties omax (point)
1333 (append '(compilation-handle-exit t) nil))
1334 (setq mode-line-process (format ":%s [%s]" process-status (cdr status)))
1335 ;; Force mode line redisplay soon.
1336 (force-mode-line-update)
1337 (if (and opoint (< opoint omax))
1338 (goto-char opoint))
1339 ;; Automatically parse (and mouse-highlight) error messages:
1340 (cond ((eq compile-auto-highlight t)
1341 (compile-reinitialize-errors nil (point-max)))
1342 ((numberp compile-auto-highlight)
1343 (compile-reinitialize-errors nil
1344 (save-excursion
1345 (goto-line compile-auto-highlight)
1346 (point)))))
1347 (if compilation-finish-function
1348 (funcall compilation-finish-function (current-buffer) msg))
1349 (let ((functions compilation-finish-functions))
1350 (while functions
1351 (funcall (car functions) (current-buffer) msg)
1352 (setq functions (cdr functions))))))
1353
1354 ;; Called when compilation process changes state.
1355 (defun compilation-sentinel (proc msg)
1356 "Sentinel for compilation buffers."
1357 (let ((buffer (process-buffer proc)))
1358 (if (memq (process-status proc) '(signal exit))
1359 (progn
1360 (if (null (buffer-name buffer))
1361 ;; buffer killed
1362 (set-process-buffer proc nil)
1363 (let ((obuf (current-buffer)))
1364 ;; save-excursion isn't the right thing if
1365 ;; process-buffer is current-buffer
1366 (unwind-protect
1367 (progn
1368 ;; Write something in the compilation buffer
1369 ;; and hack its mode line.
1370 (set-buffer buffer)
1371 (compilation-handle-exit (process-status proc)
1372 (process-exit-status proc)
1373 msg)
1374 ;; Since the buffer and mode line will show that the
1375 ;; process is dead, we can delete it now. Otherwise it
1376 ;; will stay around until M-x list-processes.
1377 (delete-process proc))
1378 (set-buffer obuf))))
1379 (setq compilation-in-progress (delq proc compilation-in-progress))
1380 ))))
1381
1382 (defun compilation-filter (proc string)
1383 "Process filter for compilation buffers.
1384 Just inserts the text, but uses `insert-before-markers'."
1385 (if (buffer-name (process-buffer proc))
1386 (save-excursion
1387 (set-buffer (process-buffer proc))
1388 (let ((buffer-read-only nil)
1389 (end (marker-position compilation-parsing-end)))
1390 (save-excursion
1391 (goto-char (process-mark proc))
1392 (insert-before-markers string)
1393 (set-marker compilation-parsing-end end) ;don't move it
1394 (run-hooks 'compilation-filter-hook)
1395 ;; this seems redundant since we insert-before-marks -stefan
1396 ;;(set-marker (process-mark proc) (point))
1397 )))))
1398
1399 (defun compile-error-at-point ()
1400 "Return the cdr of `compilation-old-error-list' for error containing point."
1401 (compile-reinitialize-errors nil (point))
1402 (let ((errors compilation-old-error-list))
1403 (while (and errors
1404 (> (point) (car (car errors))))
1405 (setq errors (cdr errors)))
1406 errors))
1407
1408 (defsubst compilation-buffer-p (buffer)
1409 (save-excursion
1410 (set-buffer buffer)
1411 (or compilation-shell-minor-mode compilation-minor-mode
1412 (eq major-mode 'compilation-mode))))
1413
1414 (defun compilation-next-error (n)
1415 "Move point to the next error in the compilation buffer.
1416 Prefix arg N says how many error messages to move forwards (or
1417 backwards, if negative).
1418 Does NOT find the source line like \\[next-error]."
1419 (interactive "p")
1420 (or (compilation-buffer-p (current-buffer))
1421 (error "Not in a compilation buffer"))
1422 (setq compilation-last-buffer (current-buffer))
1423
1424 (let ((errors (compile-error-at-point)))
1425
1426 ;; Move to the error after the one containing point.
1427 (goto-char (car (if (< n 0)
1428 (let ((i 0)
1429 (e compilation-old-error-list))
1430 ;; See how many cdrs away ERRORS is from the start.
1431 (while (not (eq e errors))
1432 (setq i (1+ i)
1433 e (cdr e)))
1434 (if (> (- n) i)
1435 (error "Moved back past first error")
1436 (nth (+ i n) compilation-old-error-list)))
1437 (let ((compilation-error-list (cdr errors)))
1438 (compile-reinitialize-errors nil nil n)
1439 (if compilation-error-list
1440 (nth (1- n) compilation-error-list)
1441 (error "Moved past last error"))))))))
1442
1443 (defun compilation-previous-error (n)
1444 "Move point to the previous error in the compilation buffer.
1445 Prefix arg N says how many error messages to move backwards (or
1446 forwards, if negative).
1447 Does NOT find the source line like \\[next-error]."
1448 (interactive "p")
1449 (compilation-next-error (- n)))
1450
1451
1452 ;; Given an elt of `compilation-error-list', return an object representing
1453 ;; the referenced file which is equal to (but not necessarily eq to) what
1454 ;; this function would return for another error in the same file.
1455 (defsubst compilation-error-filedata (data)
1456 (setq data (cdr data))
1457 (if (markerp data)
1458 (marker-buffer data)
1459 (car data)))
1460
1461 ;; Return a string describing a value from compilation-error-filedata.
1462 ;; This value is not necessarily useful as a file name, but should be
1463 ;; indicative to the user of what file's errors are being referred to.
1464 (defsubst compilation-error-filedata-file-name (filedata)
1465 (if (bufferp filedata)
1466 (buffer-file-name filedata)
1467 (car filedata)))
1468
1469 (defun compilation-next-file (n)
1470 "Move point to the next error for a different file than the current one."
1471 (interactive "p")
1472 (or (compilation-buffer-p (current-buffer))
1473 (error "Not in a compilation buffer"))
1474 (setq compilation-last-buffer (current-buffer))
1475
1476 (let ((reversed (< n 0))
1477 errors filedata)
1478
1479 (if (not reversed)
1480 (setq errors (or (compile-error-at-point)
1481 (error "Moved past last error")))
1482
1483 ;; Get a reversed list of the errors up through the one containing point.
1484 (compile-reinitialize-errors nil (point))
1485 (setq errors (reverse compilation-old-error-list)
1486 n (- n))
1487
1488 ;; Ignore errors after point. (car ERRORS) will be the error
1489 ;; containing point, (cadr ERRORS) the one before it.
1490 (while (and errors
1491 (< (point) (car (car errors))))
1492 (setq errors (cdr errors))))
1493
1494 (while (> n 0)
1495 (setq filedata (compilation-error-filedata (car errors)))
1496
1497 ;; Skip past the following errors for this file.
1498 (while (equal filedata
1499 (compilation-error-filedata
1500 (car (or errors
1501 (if reversed
1502 (error "%s the first erring file"
1503 (compilation-error-filedata-file-name
1504 filedata))
1505 (let ((compilation-error-list nil))
1506 ;; Parse some more.
1507 (compile-reinitialize-errors nil nil 2)
1508 (setq errors compilation-error-list)))
1509 (error "%s is the last erring file"
1510 (compilation-error-filedata-file-name
1511 filedata))))))
1512 (setq errors (cdr errors)))
1513
1514 (setq n (1- n)))
1515
1516 ;; Move to the following error.
1517 (goto-char (car (car (or errors
1518 (if reversed
1519 (error "This is the first erring file")
1520 (let ((compilation-error-list nil))
1521 ;; Parse the last one.
1522 (compile-reinitialize-errors nil nil 1)
1523 compilation-error-list))))))))
1524
1525 (defun compilation-previous-file (n)
1526 "Move point to the previous error for a different file than the current one."
1527 (interactive "p")
1528 (compilation-next-file (- n)))
1529
1530 (defun kill-compilation ()
1531 "Kill the process made by the \\[compile] or \\[grep] commands."
1532 (interactive)
1533 (let ((buffer (compilation-find-buffer)))
1534 (if (get-buffer-process buffer)
1535 (interrupt-process (get-buffer-process buffer))
1536 (error "The compilation process is not running"))))
1537
1538 (defalias 'kill-grep 'kill-compilation)
1539
1540 ;; Parse any new errors in the compilation buffer,
1541 ;; or reparse from the beginning if the user has asked for that.
1542 (defun compile-reinitialize-errors (reparse
1543 &optional limit-search find-at-least)
1544 (save-excursion
1545 (set-buffer compilation-last-buffer)
1546 ;; If we are out of errors, or if user says "reparse",
1547 ;; discard the info we have, to force reparsing.
1548 (if (or (eq compilation-error-list t)
1549 reparse)
1550 (compilation-forget-errors))
1551 (if (and compilation-error-list
1552 (or (not limit-search)
1553 (> compilation-parsing-end limit-search))
1554 (or (not find-at-least)
1555 (>= (length compilation-error-list) find-at-least)))
1556 ;; Since compilation-error-list is non-nil, it points to a specific
1557 ;; error the user wanted. So don't move it around.
1558 nil
1559 ;; This was here for a long time (before my rewrite); why? --roland
1560 ;;(switch-to-buffer compilation-last-buffer)
1561 (set-buffer-modified-p nil)
1562 (if (< compilation-parsing-end (point-max))
1563 ;; compilation-error-list might be non-nil if we have a non-nil
1564 ;; LIMIT-SEARCH or FIND-AT-LEAST arg. In that case its value
1565 ;; records the current position in the error list, and we must
1566 ;; preserve that after reparsing.
1567 (let ((error-list-pos compilation-error-list))
1568 (funcall compilation-parse-errors-function
1569 limit-search
1570 (and find-at-least
1571 ;; We only need enough new parsed errors to reach
1572 ;; FIND-AT-LEAST errors past the current
1573 ;; position.
1574 (- find-at-least (length compilation-error-list))))
1575 ;; Remember the entire list for compilation-forget-errors. If
1576 ;; this is an incremental parse, append to previous list. If
1577 ;; we are parsing anew, compilation-forget-errors cleared
1578 ;; compilation-old-error-list above.
1579 (setq compilation-old-error-list
1580 (nconc compilation-old-error-list compilation-error-list))
1581 (if error-list-pos
1582 ;; We started in the middle of an existing list of parsed
1583 ;; errors before parsing more; restore that position.
1584 (setq compilation-error-list error-list-pos))
1585 ;; Mouse-Highlight (the first line of) each error message when the
1586 ;; mouse pointer moves over it:
1587 (let ((inhibit-read-only t)
1588 (buffer-undo-list t)
1589 deactivate-mark
1590 (error-list compilation-error-list))
1591 (while error-list
1592 (save-excursion
1593 (add-text-properties (goto-char (car (car error-list)))
1594 (progn (end-of-line) (point))
1595 '(mouse-face highlight help-echo "\
1596 mouse-2: visit this file and line")))
1597 (setq error-list (cdr error-list))))
1598 )))))
1599
1600 (defun compile-mouse-goto-error (event)
1601 "Visit the source for the error message the mouse is pointing at.
1602 This is like `compile-goto-error' called without prefix arg
1603 at the end of the line."
1604 (interactive "e")
1605 (save-excursion
1606 (set-buffer (window-buffer (posn-window (event-end event))))
1607 (goto-char (posn-point (event-end event)))
1608
1609 (or (compilation-buffer-p (current-buffer))
1610 (error "Not in a compilation buffer"))
1611 (setq compilation-last-buffer (current-buffer))
1612 ;; `compile-reinitialize-errors' needs to see the complete filename
1613 ;; on the line where they clicked the mouse. Since it only looks
1614 ;; up to point, moving point to eol makes sure the filename is
1615 ;; visible to `compile-reinitialize-errors'.
1616 (end-of-line)
1617 (compile-reinitialize-errors nil (point))
1618
1619 ;; Move to bol; the marker for the error on this line will point there.
1620 (beginning-of-line)
1621
1622 ;; Move compilation-error-list to the elt of compilation-old-error-list
1623 ;; we want.
1624 (setq compilation-error-list compilation-old-error-list)
1625 (while (and compilation-error-list
1626 ;; The marker can point nowhere if we previously
1627 ;; failed to find the relevant file. See
1628 ;; compilation-next-error-locus.
1629 (or (null (marker-buffer (caar compilation-error-list)))
1630 (and (> (point) (caar compilation-error-list))
1631 (>= (point)
1632 ;; Don't skip too far: the text between
1633 ;; two errors belongs to the first. This
1634 ;; in-between text might be other errors
1635 ;; on the same line (see
1636 ;; compilation-skip-to-next-location).
1637 (if (null (cdr compilation-error-list))
1638 compilation-parsing-end
1639 (caar (cdr compilation-error-list)))))))
1640 (setq compilation-error-list (cdr compilation-error-list)))
1641 (or compilation-error-list
1642 (error "No error to go to")))
1643 (select-window (posn-window (event-end event)))
1644
1645 (push-mark)
1646 (next-error 1))
1647
1648 (defun compile-goto-error (&optional argp)
1649 "Visit the source for the error message point is on.
1650 Use this command in a compilation log buffer. Sets the mark at point there.
1651 \\[universal-argument] as a prefix arg means to reparse the buffer's error messages first;
1652 other kinds of prefix arguments are ignored."
1653 (interactive "P")
1654 (or (compilation-buffer-p (current-buffer))
1655 (error "Not in a compilation buffer"))
1656 (setq compilation-last-buffer (current-buffer))
1657 (compile-reinitialize-errors (consp argp) (point))
1658
1659 ;; Move to bol; the marker for the error on this line will point there.
1660 (beginning-of-line)
1661
1662 ;; Move compilation-error-list to the elt of compilation-old-error-list
1663 ;; we want.
1664 (setq compilation-error-list compilation-old-error-list)
1665 (while (and compilation-error-list
1666 ;; The marker can point nowhere if we previously
1667 ;; failed to find the relevant file. See
1668 ;; compilation-next-error-locus.
1669 (or (null (marker-buffer (caar compilation-error-list)))
1670 (and (> (point) (caar compilation-error-list))
1671 (>= (point)
1672 ;; Don't skip too far: the text between
1673 ;; two errors belongs to the first. This
1674 ;; in-between text might be other errors
1675 ;; on the same line (see
1676 ;; compilation-skip-to-next-location).
1677 (if (null (cdr compilation-error-list))
1678 compilation-parsing-end
1679 (caar (cdr compilation-error-list)))))))
1680 (setq compilation-error-list (cdr compilation-error-list)))
1681
1682 (push-mark)
1683 (next-error 1))
1684
1685 ;; Return a compilation buffer.
1686 ;; If the current buffer is a compilation buffer, return it.
1687 ;; If compilation-last-buffer is set to a live buffer, use that.
1688 ;; Otherwise, look for a compilation buffer and signal an error
1689 ;; if there are none.
1690 (defun compilation-find-buffer (&optional other-buffer)
1691 (if (and (not other-buffer)
1692 (compilation-buffer-p (current-buffer)))
1693 ;; The current buffer is a compilation buffer.
1694 (current-buffer)
1695 (if (and compilation-last-buffer (buffer-name compilation-last-buffer)
1696 (compilation-buffer-p compilation-last-buffer)
1697 (or (not other-buffer) (not (eq compilation-last-buffer
1698 (current-buffer)))))
1699 compilation-last-buffer
1700 (let ((buffers (buffer-list)))
1701 (while (and buffers (or (not (compilation-buffer-p (car buffers)))
1702 (and other-buffer
1703 (eq (car buffers) (current-buffer)))))
1704 (setq buffers (cdr buffers)))
1705 (if buffers
1706 (car buffers)
1707 (or (and other-buffer
1708 (compilation-buffer-p (current-buffer))
1709 ;; The current buffer is a compilation buffer.
1710 (progn
1711 (if other-buffer
1712 (message "This is the only compilation buffer."))
1713 (current-buffer)))
1714 (error "No compilation started!")))))))
1715
1716 ;;;###autoload
1717 (defun next-error (&optional argp)
1718 "Visit next compilation error message and corresponding source code.
1719
1720 If all the error messages parsed so far have been processed already,
1721 the message buffer is checked for new ones.
1722
1723 A prefix ARGP specifies how many error messages to move;
1724 negative means move back to previous error messages.
1725 Just \\[universal-argument] as a prefix means reparse the error message buffer
1726 and start at the first error.
1727
1728 \\[next-error] normally uses the most recently started compilation or
1729 grep buffer. However, it can operate on any buffer with output from
1730 the \\[compile] and \\[grep] commands, or, more generally, on any
1731 buffer in Compilation mode or with Compilation Minor mode enabled. To
1732 specify use of a particular buffer for error messages, type
1733 \\[next-error] in that buffer.
1734
1735 Once \\[next-error] has chosen the buffer for error messages,
1736 it stays with that buffer until you use it in some other buffer which
1737 uses Compilation mode or Compilation Minor mode.
1738
1739 See variables `compilation-parse-errors-function' and
1740 \`compilation-error-regexp-alist' for customization ideas."
1741 (interactive "P")
1742 (setq compilation-last-buffer (compilation-find-buffer))
1743 (compilation-goto-locus (compilation-next-error-locus
1744 ;; We want to pass a number here only if
1745 ;; we got a numeric prefix arg, not just C-u.
1746 (and (not (consp argp))
1747 (prefix-numeric-value argp))
1748 (consp argp))))
1749 ;;;###autoload (define-key ctl-x-map "`" 'next-error)
1750
1751 (defun previous-error ()
1752 "Visit previous compilation error message and corresponding source code.
1753 This operates on the output from the \\[compile] command."
1754 (interactive)
1755 (next-error -1))
1756
1757 (defun first-error ()
1758 "Reparse the error message buffer and start at the first error.
1759 Visit corresponding source code.
1760 This operates on the output from the \\[compile] command."
1761 (interactive)
1762 (next-error '(4)))
1763
1764 (defvar compilation-skip-to-next-location nil
1765 "*If non-nil, skip multiple error messages for the same source location.")
1766
1767 (defun compilation-next-error-locus (&optional move reparse silent)
1768 "Visit next compilation error and return locus in corresponding source code.
1769 This operates on the output from the \\[compile] command.
1770 If all preparsed error messages have been processed,
1771 the error message buffer is checked for new ones.
1772
1773 Returns a cons (ERROR . SOURCE) of two markers: ERROR is a marker at the
1774 location of the error message in the compilation buffer, and SOURCE is a
1775 marker at the location in the source code indicated by the error message.
1776
1777 Optional first arg MOVE says how many error messages to move forwards (or
1778 backwards, if negative); default is 1. Optional second arg REPARSE, if
1779 non-nil, says to reparse the error message buffer and reset to the first
1780 error (plus MOVE - 1). If optional third argument SILENT is non-nil, return
1781 nil instead of raising an error if there are no more errors.
1782
1783 The current buffer should be the desired compilation output buffer."
1784 (or move (setq move 1))
1785 (compile-reinitialize-errors reparse nil (and (not reparse) (max 0 move)))
1786 (let (next-errors next-error)
1787 (catch 'no-next-error
1788 (save-excursion
1789 (set-buffer compilation-last-buffer)
1790 ;; compilation-error-list points to the "current" error.
1791 (setq next-errors
1792 (if (> move 0)
1793 (nthcdr (1- move)
1794 compilation-error-list)
1795 ;; Zero or negative arg; we need to move back in the list.
1796 (let ((n (1- move))
1797 (i 0)
1798 (e compilation-old-error-list))
1799 ;; See how many cdrs away the current error is from the start.
1800 (while (not (eq e compilation-error-list))
1801 (setq i (1+ i)
1802 e (cdr e)))
1803 (if (> (- n) i)
1804 (error "Moved back past first error")
1805 (nthcdr (+ i n) compilation-old-error-list))))
1806 next-error (car next-errors))
1807 (while
1808 (if (null next-error)
1809 (progn
1810 (and move (/= move 1)
1811 (error (if (> move 0)
1812 "Moved past last error")
1813 "Moved back past first error"))
1814 ;; Forget existing error messages if compilation has finished.
1815 (if (not (and (get-buffer-process (current-buffer))
1816 (eq (process-status
1817 (get-buffer-process
1818 (current-buffer)))
1819 'run)))
1820 (compilation-forget-errors))
1821 (if silent
1822 (throw 'no-next-error nil)
1823 (error (concat compilation-error-message
1824 (and (get-buffer-process (current-buffer))
1825 (eq (process-status
1826 (get-buffer-process
1827 (current-buffer)))
1828 'run)
1829 " yet")))))
1830 (setq compilation-error-list (cdr next-errors))
1831 (if (null (cdr next-error))
1832 ;; This error is boring. Go to the next.
1833 t
1834 (or (markerp (cdr next-error))
1835 ;; This error has a filename/lineno pair.
1836 ;; Find the file and turn it into a marker.
1837 (let* ((fileinfo (car (cdr next-error)))
1838 (buffer (apply 'compilation-find-file
1839 (car next-error) fileinfo)))
1840 (if (null buffer)
1841 ;; We can't find this error's file.
1842 ;; Remove all errors in the same file.
1843 (progn
1844 (setq next-errors compilation-old-error-list)
1845 (while next-errors
1846 (and (consp (cdr (car next-errors)))
1847 (equal (car (cdr (car next-errors)))
1848 fileinfo)
1849 (progn
1850 (set-marker (car (car next-errors)) nil)
1851 (setcdr (car next-errors) nil)))
1852 (setq next-errors (cdr next-errors)))
1853 ;; Look for the next error.
1854 t)
1855 ;; We found the file. Get a marker for this error.
1856 ;; compilation-old-error-list and
1857 ;; compilation-error-screen-columns are buffer-local
1858 ;; so we must be careful to extract their value
1859 ;; before switching to the source file buffer.
1860 (let ((errors compilation-old-error-list)
1861 (columns compilation-error-screen-columns)
1862 (last-line (nth 1 (cdr next-error)))
1863 (column (nth 2 (cdr next-error))))
1864 (set-buffer buffer)
1865 (save-excursion
1866 (save-restriction
1867 (widen)
1868 (goto-line last-line)
1869 (if (and column (> column 0))
1870 ;; Columns in error msgs are 1-origin.
1871 (if columns
1872 (move-to-column (1- column))
1873 (forward-char (1- column)))
1874 (beginning-of-line))
1875 (setcdr next-error (point-marker))
1876 ;; Make all the other error messages referring
1877 ;; to the same file have markers into the buffer.
1878 (while errors
1879 (and (consp (cdr (car errors)))
1880 (equal (car (cdr (car errors))) fileinfo)
1881 (let* ((this (nth 1 (cdr (car errors))))
1882 (column (nth 2 (cdr (car errors))))
1883 (lines (- this last-line)))
1884 (if (eq selective-display t)
1885 ;; When selective-display is t,
1886 ;; each C-m is a line boundary,
1887 ;; as well as each newline.
1888 (if (< lines 0)
1889 (re-search-backward "[\n\C-m]"
1890 nil 'end
1891 (- lines))
1892 (re-search-forward "[\n\C-m]"
1893 nil 'end
1894 lines))
1895 (forward-line lines))
1896 (if (and column (> column 1))
1897 (if columns
1898 (move-to-column (1- column))
1899 (forward-char (1- column)))
1900 (beginning-of-line))
1901 (setq last-line this)
1902 (setcdr (car errors) (point-marker))))
1903 (setq errors (cdr errors)))))))))
1904 ;; If we didn't get a marker for this error, or this
1905 ;; marker's buffer was killed, go on to the next one.
1906 (or (not (markerp (cdr next-error)))
1907 (not (marker-buffer (cdr next-error))))))
1908 (setq next-errors compilation-error-list
1909 next-error (car next-errors)))))
1910
1911 (if compilation-skip-to-next-location
1912 ;; Skip over multiple error messages for the same source location,
1913 ;; so the next C-x ` won't go to an error in the same place.
1914 (while (and compilation-error-list
1915 (equal (cdr (car compilation-error-list))
1916 (cdr next-error)))
1917 (setq compilation-error-list (cdr compilation-error-list))))
1918
1919 ;; We now have a marker for the position of the error source code.
1920 ;; NEXT-ERROR is a cons (ERROR . SOURCE) of two markers.
1921 next-error))
1922
1923 (defun compilation-goto-locus (next-error)
1924 "Jump to an error locus returned by `compilation-next-error-locus'.
1925 Takes one argument, a cons (ERROR . SOURCE) of two markers.
1926 Selects a window with point at SOURCE, with another window displaying ERROR."
1927 (if (eq (window-buffer (selected-window))
1928 (marker-buffer (car next-error)))
1929 ;; If the compilation buffer window is selected,
1930 ;; keep the compilation buffer in this window;
1931 ;; display the source in another window.
1932 (let ((pop-up-windows t))
1933 (pop-to-buffer (marker-buffer (cdr next-error))))
1934 (if (window-dedicated-p (selected-window))
1935 (pop-to-buffer (marker-buffer (cdr next-error)))
1936 (switch-to-buffer (marker-buffer (cdr next-error)))))
1937 (goto-char (cdr next-error))
1938 ;; If narrowing got in the way of
1939 ;; going to the right place, widen.
1940 (or (= (point) (marker-position (cdr next-error)))
1941 (progn
1942 (widen)
1943 (goto-char (cdr next-error))))
1944 ;; If hideshow got in the way of
1945 ;; seeing the right place, open permanently.
1946 (mapcar (function (lambda (ov)
1947 (when (eq 'hs (overlay-get ov 'invisible))
1948 (delete-overlay ov)
1949 (goto-char (cdr next-error)))))
1950 (overlays-at (point)))
1951
1952 ;; Show compilation buffer in other window, scrolled to this error.
1953 (let* ((pop-up-windows t)
1954 ;; Use an existing window if it is in a visible frame.
1955 (w (or (get-buffer-window (marker-buffer (car next-error)) 'visible)
1956 ;; Pop up a window.
1957 (display-buffer (marker-buffer (car next-error))))))
1958 (set-window-point w (car next-error))
1959 (set-window-start w (car next-error))
1960 (compilation-set-window-height w)))
1961 \f
1962 (defun compilation-find-file (marker filename dir &rest formats)
1963 "Find a buffer for file FILENAME.
1964 Search the directories in `compilation-search-path'.
1965 A nil in `compilation-search-path' means to try the
1966 current directory, which is passed in DIR.
1967 If FILENAME is not found at all, ask the user where to find it.
1968 Pop up the buffer containing MARKER and scroll to MARKER if we ask the user."
1969 (or formats (setq formats '("%s")))
1970 (save-excursion
1971 (let ((dirs compilation-search-path)
1972 buffer thisdir fmts name)
1973 (if (file-name-absolute-p filename)
1974 ;; The file name is absolute. Use its explicit directory as
1975 ;; the first in the search path, and strip it from FILENAME.
1976 (setq filename (abbreviate-file-name (expand-file-name filename))
1977 dirs (cons (file-name-directory filename) dirs)
1978 filename (file-name-nondirectory filename)))
1979 ;; Now search the path.
1980 (while (and dirs (null buffer))
1981 (setq thisdir (or (car dirs) dir)
1982 fmts formats)
1983 ;; For each directory, try each format string.
1984 (while (and fmts (null buffer))
1985 (setq name (expand-file-name (format (car fmts) filename) thisdir)
1986 buffer (and (file-exists-p name)
1987 (find-file-noselect name))
1988 fmts (cdr fmts)))
1989 (setq dirs (cdr dirs)))
1990 (or buffer
1991 ;; The file doesn't exist.
1992 ;; Ask the user where to find it.
1993 ;; If he hits C-g, then the next time he does
1994 ;; next-error, he'll skip past it.
1995 (let* ((pop-up-windows t)
1996 (w (display-buffer (marker-buffer marker))))
1997 (set-window-point w marker)
1998 (set-window-start w marker)
1999 (let ((name (expand-file-name
2000 (read-file-name
2001 (format "Find this error in: (default %s) "
2002 filename)
2003 dir filename t))))
2004 (if (file-directory-p name)
2005 (setq name (expand-file-name filename name)))
2006 (setq buffer (and (file-exists-p name)
2007 (find-file name))))))
2008 ;; Make intangible overlays tangible.
2009 (mapcar (function (lambda (ov)
2010 (when (overlay-get ov 'intangible)
2011 (overlay-put ov 'intangible nil))))
2012 (overlays-in (point-min) (point-max)))
2013 buffer)))
2014
2015 (defun compilation-normalize-filename (filename)
2016 "Convert a filename string found in an error message to make it usable."
2017
2018 ;; Check for a comint-file-name-prefix and prepend it if
2019 ;; appropriate. (This is very useful for
2020 ;; compilation-minor-mode in an rlogin-mode buffer.)
2021 (and (boundp 'comint-file-name-prefix)
2022 ;; If file name is relative, default-directory will
2023 ;; already contain the comint-file-name-prefix (done
2024 ;; by compile-abbreviate-directory).
2025 (file-name-absolute-p filename)
2026 (setq filename
2027 (concat comint-file-name-prefix filename)))
2028
2029 ;; If compilation-parse-errors-filename-function is
2030 ;; defined, use it to process the filename.
2031 (when compilation-parse-errors-filename-function
2032 (setq filename
2033 (funcall compilation-parse-errors-filename-function
2034 filename)))
2035
2036 ;; Some compilers (e.g. Sun's java compiler, reportedly)
2037 ;; produce bogus file names like "./bar//foo.c" for file
2038 ;; "bar/foo.c"; expand-file-name will collapse these into
2039 ;; "/foo.c" and fail to find the appropriate file. So we
2040 ;; look for doubled slashes in the file name and fix them
2041 ;; up in the buffer.
2042 (setq filename (command-line-normalize-file-name filename)))
2043
2044 ;; Set compilation-error-list to nil, and unchain the markers that point to the
2045 ;; error messages and their text, so that they no longer slow down gap motion.
2046 ;; This would happen anyway at the next garbage collection, but it is better to
2047 ;; do it right away.
2048 (defun compilation-forget-errors ()
2049 (while compilation-old-error-list
2050 (let ((next-error (car compilation-old-error-list)))
2051 (set-marker (car next-error) nil)
2052 (if (markerp (cdr next-error))
2053 (set-marker (cdr next-error) nil)))
2054 (setq compilation-old-error-list (cdr compilation-old-error-list)))
2055 (setq compilation-error-list nil
2056 compilation-directory-stack (list default-directory))
2057 (if compilation-parsing-end
2058 (set-marker compilation-parsing-end 1))
2059 ;; Remove the highlighting added by compile-reinitialize-errors:
2060 (let ((inhibit-read-only t)
2061 (buffer-undo-list t)
2062 deactivate-mark)
2063 (remove-text-properties (point-min) (point-max)
2064 '(mouse-face highlight help-echo nil))))
2065
2066
2067 ;; This function is not needed any more by compilation mode.
2068 ;; Does anyone else need it or can it be deleted?
2069 (defun count-regexp-groupings (regexp)
2070 "Return the number of \\( ... \\) groupings in REGEXP (a string)."
2071 (let ((groupings 0)
2072 (len (length regexp))
2073 (i 0)
2074 c)
2075 (while (< i len)
2076 (setq c (aref regexp i)
2077 i (1+ i))
2078 (cond ((= c ?\[)
2079 ;; Find the end of this [...].
2080 (while (and (< i len)
2081 (not (= (aref regexp i) ?\])))
2082 (setq i (1+ i))))
2083 ((= c ?\\)
2084 (if (< i len)
2085 (progn
2086 (setq c (aref regexp i)
2087 i (1+ i))
2088 (if (= c ?\))
2089 ;; We found the end of a grouping,
2090 ;; so bump our counter.
2091 (setq groupings (1+ groupings))))))))
2092 groupings))
2093
2094 (defvar compilation-current-file nil
2095 "Used by `compilation-parse-errors' to store filename for file being compiled.")
2096
2097 ;; This variable is not used as a global variable. It's defined here just to
2098 ;; shut up the byte compiler. It's bound and used by compilation-parse-errors
2099 ;; and set by compile-collect-regexps.
2100 (defvar compilation-regexps nil)
2101
2102 (defun compilation-parse-errors (limit-search find-at-least)
2103 "Parse the current buffer as grep, cc, lint or other error messages.
2104 See variable `compilation-parse-errors-function' for the interface it uses."
2105 (setq compilation-error-list nil)
2106 (message "Parsing error messages...")
2107 (if (null compilation-error-regexp-alist)
2108 (error "compilation-error-regexp-alist is empty!"))
2109 (let* ((compilation-regexps nil) ; Variable set by compile-collect-regexps.
2110 (default-directory (car compilation-directory-stack))
2111 (found-desired nil)
2112 (compilation-num-errors-found 0)
2113 ;; Set up now the expanded, abbreviated directory variables
2114 ;; that compile-abbreviate-directory will need, so we can
2115 ;; compute them just once here.
2116 (orig (abbreviate-file-name default-directory))
2117 (orig-expanded (abbreviate-file-name
2118 (file-truename default-directory)))
2119 (parent-expanded (abbreviate-file-name
2120 (expand-file-name "../" orig-expanded))))
2121
2122 ;; Make a list of all the regexps. Each element has the form
2123 ;; (REGEXP TYPE IDX1 IDX2 ...)
2124 ;; where TYPE is one of leave, enter, file, error or nomessage.
2125 (compile-collect-regexps 'leave compilation-leave-directory-regexp-alist)
2126 (compile-collect-regexps 'enter compilation-enter-directory-regexp-alist)
2127 (compile-collect-regexps 'file compilation-file-regexp-alist)
2128 (compile-collect-regexps 'error compilation-error-regexp-alist)
2129 (compile-collect-regexps 'nomessage compilation-nomessage-regexp-alist)
2130
2131 ;; Don't reparse messages already seen at last parse.
2132 (goto-char compilation-parsing-end)
2133 (when (and (bobp)
2134 (compilation-buffer-p (current-buffer)))
2135 (setq compilation-current-file nil) ; No current file at start.
2136 ;; Don't parse the first two lines as error messages.
2137 ;; This matters for grep.
2138 (forward-line 2))
2139
2140 ;; Parse messages.
2141 (while (not (or found-desired (eobp)
2142 ;; Don't parse the "compilation finished" message
2143 ;; as a compilation error.
2144 (get-text-property (point) 'compilation-handle-exit)))
2145 (let ((this compilation-regexps) (prev nil) (alist nil) type)
2146 ;; Go through the regular expressions. If a match is found,
2147 ;; variable alist is set to the corresponding alist and the
2148 ;; matching regexp is moved to the front of compilation-regexps
2149 ;; to make it match faster next time.
2150 (while (and this (null alist))
2151 (if (not (looking-at (car (car this))))
2152 (progn (setq prev this) ; No match, go to next.
2153 (setq this (cdr this)))
2154 (setq alist (cdr (car this))) ; Got a match.
2155 ;;; (if prev ; If not the first regexp,
2156 ;;; (progn ; move it to the front.
2157 ;;; (setcdr prev (cdr this))
2158 ;;; (setcdr this compilation-regexps)
2159 ;;; (setq compilation-regexps this)))
2160 ))
2161 (if (and alist ; Seen a match and not to
2162 (not (eq (setq type (car alist)) 'nomessage))) ; be ignored.
2163 (let* ((end-of-match (match-end 0))
2164 (filename
2165 (compile-buffer-substring (car (setq alist (cdr alist)))))
2166 stack)
2167 (if (eq type 'error) ; error message
2168 (let* ((linenum (if (numberp (car (setq alist (cdr alist))))
2169 (string-to-int
2170 (compile-buffer-substring (car alist)))
2171 ;; (car alist) is not a number, must be a
2172 ;; function that is called below to return
2173 ;; an error position descriptor.
2174 (car alist)))
2175 ;; Convert to integer later if linenum not a function.
2176 (column (compile-buffer-substring
2177 (car (setq alist (cdr alist)))))
2178 this-error)
2179
2180 ;; Check that we have a file name.
2181 (or filename
2182 ;; No file name in message, we must have seen it before
2183 (setq filename compilation-current-file)
2184 (error "\
2185 An error message with no file name and no file name has been seen earlier"))
2186
2187 ;; Clean up the file name string in several ways.
2188 (setq filename (compilation-normalize-filename filename))
2189
2190 (setq filename
2191 (cons filename (cons default-directory (cdr alist))))
2192
2193 ;; Locate the erring file and line.
2194 ;; Make this-error a new elt for compilation-error-list,
2195 ;; giving a marker for the current compilation buffer
2196 ;; location, and the file and line number of the error.
2197 ;; Save, as the start of the error, the beginning of the
2198 ;; line containing the match.
2199 (setq this-error
2200 (if (numberp linenum)
2201 (list (point-marker) filename linenum
2202 (and column (string-to-int column)))
2203 ;; If linenum is not a number then it must be
2204 ;; a function returning an error position
2205 ;; descriptor or nil (meaning no position).
2206 (save-excursion
2207 (funcall linenum filename column))))
2208
2209 ;; We have an error position descriptor.
2210 ;; If we have found as many new errors as the user
2211 ;; wants, or if we are past the buffer position he
2212 ;; indicated, then we continue to parse until we have
2213 ;; seen all consecutive errors in the same file. This
2214 ;; means that all the errors of a source file will be
2215 ;; seen in one parsing run, so that the error positions
2216 ;; will be recorded as markers in the source file
2217 ;; buffer that will move when the buffer is changed.
2218 (if (and this-error
2219 compilation-error-list ; At least one previous.
2220 (or (and find-at-least
2221 (>= compilation-num-errors-found
2222 find-at-least))
2223 (and limit-search
2224 (>= end-of-match limit-search)))
2225 ;; `this-error' could contain a pair of
2226 ;; markers already.
2227 (let ((thispos (cdr this-error))
2228 (lastpos (cdar compilation-error-list)))
2229 (not (equal
2230 (if (markerp thispos)
2231 (marker-buffer thispos)
2232 (car thispos))
2233 (if (markerp lastpos)
2234 (marker-buffer lastpos)
2235 (car lastpos))))))
2236 ;; We are past the limits and the last error
2237 ;; parsed, didn't belong to the same source file
2238 ;; as the earlier ones i.e. we have seen all the
2239 ;; errors belonging to the earlier file. We don't
2240 ;; add the error just parsed so that the next
2241 ;; parsing run can get it and the following errors
2242 ;; in the same file all at once.
2243 (setq found-desired t)
2244
2245 (goto-char end-of-match) ; Prepare for next message.
2246 ;; Don't add the same source line more than once.
2247 (and this-error
2248 (not (and
2249 compilation-error-list
2250 (equal (cdr (car compilation-error-list))
2251 (cdr this-error))))
2252 (setq compilation-error-list
2253 (cons this-error compilation-error-list)
2254 compilation-num-errors-found
2255 (1+ compilation-num-errors-found)))))
2256
2257 ;; Not an error message.
2258 (if (eq type `file) ; Change current file.
2259 (when filename
2260 (setq compilation-current-file
2261 ;; Clean up the file name string in several ways.
2262 (compilation-normalize-filename filename)))
2263 ;; Enter or leave directory.
2264 (setq stack compilation-directory-stack)
2265 ;; Don't check if it is really a directory.
2266 ;; Let the code to search and clean up file names
2267 ;; try to use it in any case.
2268 (when filename
2269 ;; Clean up the directory name string in several ways.
2270 (setq filename (compilation-normalize-filename filename))
2271 (setq filename
2272 ;; The directory name in the message
2273 ;; is a truename. Try to convert it to a form
2274 ;; like what the user typed in.
2275 (compile-abbreviate-directory
2276 (file-name-as-directory
2277 (expand-file-name filename))
2278 orig orig-expanded parent-expanded))
2279 (if (eq type 'leave)
2280 ;; If we are leaving a specific directory,
2281 ;; as preparation, pop out of all other directories
2282 ;; that we entered nested within it.
2283 (while (and stack
2284 (not (string-equal (car stack)
2285 filename)))
2286 (setq stack (cdr stack)))
2287 (setq compilation-directory-stack
2288 (cons filename compilation-directory-stack)
2289 default-directory filename)))
2290 (and (eq type 'leave)
2291 stack
2292 (setq compilation-directory-stack (cdr stack))
2293 (setq stack (car compilation-directory-stack))
2294 (setq default-directory stack)))
2295 (goto-char end-of-match) ; Prepare to look at next message.
2296 (and limit-search (>= end-of-match limit-search)
2297 ;; The user wanted a specific error, and we're past it.
2298 ;; We do this check here rather than at the end of the
2299 ;; loop because if the last thing seen is an error
2300 ;; message, we must carefully discard the last error
2301 ;; when it is the first in a new file (see above in
2302 ;; the error-message case)
2303 (setq found-desired t)))
2304
2305 ;; Go to before the last character in the message so that we will
2306 ;; see the next line also when the message ended at end of line.
2307 ;; When we ignore the last error message above, this will
2308 ;; cancel the effect of forward-line below so that point
2309 ;; doesn't move.
2310 (forward-char -1)
2311
2312 ;; Is this message necessary any more? Parsing is now so fast
2313 ;; that you might not need to know how it proceeds.
2314 (message
2315 "Parsing error messages...%d found. %.0f%% of buffer seen."
2316 compilation-num-errors-found
2317 ;; Use floating-point because (* 100 (point)) frequently
2318 ;; exceeds the range of Emacs Lisp integers.
2319 (/ (* 100.0 (point)) (point-max)))
2320 )))
2321
2322 (forward-line 1)) ; End of while loop. Look at next line.
2323
2324 (set-marker compilation-parsing-end (point))
2325 (setq compilation-error-list (nreverse compilation-error-list))
2326 ;; (message "Parsing error messages...done. %d found. %.0f%% of buffer seen."
2327 ;; compilation-num-errors-found
2328 ;; (/ (* 100.0 (point)) (point-max)))
2329 (message "Parsing error messages...done.")))
2330
2331 (defun compile-collect-regexps (type this)
2332 ;; Add elements to variable compilation-regexps that is bound in
2333 ;; compilation-parse-errors.
2334 (and (not (eq this t))
2335 (dolist (el this)
2336 (push (cons (car el) (cons type (cdr el))) compilation-regexps))))
2337
2338 (defun compile-buffer-substring (index)
2339 "Get substring matched by INDEXth subexpression."
2340 (if index
2341 (let ((beg (match-beginning index)))
2342 (if beg (buffer-substring beg (match-end index))))))
2343
2344 ;; If directory DIR is a subdir of ORIG or of ORIG's parent,
2345 ;; return a relative name for it starting from ORIG or its parent.
2346 ;; ORIG-EXPANDED is an expanded version of ORIG.
2347 ;; PARENT-EXPANDED is an expanded version of ORIG's parent.
2348 ;; Those two args could be computed here, but we run faster by
2349 ;; having the caller compute them just once.
2350 (defun compile-abbreviate-directory (dir orig orig-expanded parent-expanded)
2351 ;; Apply canonical abbreviations to DIR first thing.
2352 ;; Those abbreviations are already done in the other arguments passed.
2353 (setq dir (abbreviate-file-name dir))
2354
2355 ;; Check for a comint-file-name-prefix and prepend it if appropriate.
2356 ;; (This is very useful for compilation-minor-mode in an rlogin-mode
2357 ;; buffer.)
2358 (if (boundp 'comint-file-name-prefix)
2359 (setq dir (concat comint-file-name-prefix dir)))
2360
2361 (if (and (> (length dir) (length orig-expanded))
2362 (string= orig-expanded
2363 (substring dir 0 (length orig-expanded))))
2364 (setq dir
2365 (concat orig
2366 (substring dir (length orig-expanded)))))
2367 (if (and (> (length dir) (length parent-expanded))
2368 (string= parent-expanded
2369 (substring dir 0 (length parent-expanded))))
2370 (setq dir
2371 (concat (file-name-directory
2372 (directory-file-name orig))
2373 (substring dir (length parent-expanded)))))
2374 dir)
2375
2376 (add-to-list 'debug-ignored-errors "^No more errors\\( yet\\|\\)$")
2377
2378 (provide 'compile)
2379
2380 ;;; compile.el ends here