* progmodes/compile.el (compilation-start): Move setting of
[bpt/emacs.git] / lisp / progmodes / compile.el
CommitLineData
55535639 1;;; compile.el --- run compiler as inferior of Emacs, parse error messages
fad160d5 2
930a3e46 3;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
049dcb6f
GM
4;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
5;; Free Software Foundation, Inc.
3a801d0c 6
7837c247
SM
7;; Authors: Roland McGrath <roland@gnu.org>,
8;; Daniel Pfeiffer <occitan@esperanto.org>
d1c7011d 9;; Maintainer: FSF
e9571d2a 10;; Keywords: tools, processes
d1c7011d 11
55dfd2c4
RS
12;; This file is part of GNU Emacs.
13
29add8b9
RM
14;; GNU Emacs is free software; you can redistribute it and/or modify
15;; it under the terms of the GNU General Public License as published by
1a484753 16;; the Free Software Foundation; either version 3, or (at your option)
29add8b9
RM
17;; any later version.
18
55dfd2c4 19;; GNU Emacs is distributed in the hope that it will be useful,
29add8b9
RM
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
b578f267 25;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
26;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27;; Boston, MA 02110-1301, USA.
55dfd2c4 28
5cc57841
ER
29;;; Commentary:
30
7837c247
SM
31;; This package provides the compile facilities documented in the Emacs user's
32;; manual.
5cc57841 33
c536bb39 34;; This mode uses some complex data-structures:
7837c247 35
c536bb39 36;; LOC (or location) is a list of (COLUMN LINE FILE-STRUCTURE)
7837c247
SM
37
38;; COLUMN and LINE are numbers parsed from an error message. COLUMN and maybe
39;; LINE will be nil for a message that doesn't contain them. Then the
40;; location refers to a indented beginning of line or beginning of file.
41;; Once any location in some file has been jumped to, the list is extended to
b84acff6
SS
42;; (COLUMN LINE FILE-STRUCTURE MARKER TIMESTAMP . VISITED)
43;; for all LOCs pertaining to that file.
7837c247
SM
44;; MARKER initially points to LINE and COLUMN in a buffer visiting that file.
45;; Being a marker it sticks to some text, when the buffer grows or shrinks
46;; before that point. VISITED is t if we have jumped there, else nil.
b84acff6
SS
47;; TIMESTAMP is necessary because of "incremental compilation": `omake -P'
48;; polls filesystem for changes and recompiles when a file is modified
49;; using the same *compilation* buffer. this necessitates re-parsing markers.
7837c247 50
c536bb39
SM
51;; FILE-STRUCTURE is a list of
52;; ((FILENAME . DIRECTORY) FORMATS (LINE LOC ...) ...)
7837c247
SM
53
54;; FILENAME is a string parsed from an error message. DIRECTORY is a string
55;; obtained by following directory change messages. DIRECTORY will be nil for
56;; an absolute filename. FORMATS is a list of formats to apply to FILENAME if
57;; a file of that name can't be found.
58;; The rest of the list is an alist of elements with LINE as key. The keys
59;; are either nil or line numbers. If present, nil comes first, followed by
60;; the numbers in decreasing order. The LOCs for each line are again an alist
61;; ordered the same way. Note that the whole file structure is referenced in
62;; every LOC.
63
c536bb39 64;; MESSAGE is a list of (LOC TYPE END-LOC)
7837c247
SM
65
66;; TYPE is 0 for info or 1 for warning if the message matcher identified it as
67;; such, 2 otherwise (for a real error). END-LOC is a LOC pointing to the
4fffd73b 68;; other end, if the parsed message contained a range. If the end of the
7837c247
SM
69;; range didn't specify a COLUMN, it defaults to -1, meaning end of line.
70;; These are the value of the `message' text-properties in the compilation
71;; buffer.
72
24299582
DP
73;;; Code:
74
583a15bb 75(eval-when-compile (require 'cl))
c45e48d2 76(require 'tool-bar)
583a15bb 77
e623859c
JB
78(defvar font-lock-extra-managed-props)
79(defvar font-lock-keywords)
80(defvar font-lock-maximum-size)
81(defvar font-lock-support-mode)
82
83
c5049fa0
RS
84(defgroup compilation nil
85 "Run compiler as inferior of Emacs, parse error messages."
86 :group 'tools
87 :group 'processes)
88
89
7c163413 90;;;###autoload
c5049fa0 91(defcustom compilation-mode-hook nil
813fb3fe 92 "List of hook functions run by `compilation-mode' (see `run-mode-hooks')."
c5049fa0
RS
93 :type 'hook
94 :group 'compilation)
7c163413
RM
95
96;;;###autoload
c5049fa0 97(defcustom compilation-window-height nil
813fb3fe 98 "Number of lines in a compilation window. If nil, use Emacs default."
c5049fa0
RS
99 :type '(choice (const :tag "Default" nil)
100 integer)
101 :group 'compilation)
d3cb357b 102
7837c247
SM
103(defvar compilation-first-column 1
104 "*This is how compilers number the first column, usually 1 or 0.")
55dfd2c4 105
e335e194
GM
106(defvar compilation-parse-errors-filename-function nil
107 "Function to call to post-process filenames while parsing error messages.
108It takes one arg FILENAME which is the name of a file as found
109in the compilation output, and should return a transformed file name.")
110
49683a13
EZ
111;;;###autoload
112(defvar compilation-process-setup-function nil
113 "*Function to call to customize the compilation process.
6f5b7627 114This function is called immediately before the compilation process is
49683a13 115started. It can be used to set any variables or functions that are used
9ac57479
KS
116while processing the output of the compilation process. The function
117is called with variables `compilation-buffer' and `compilation-window'
7837c247 118bound to the compilation buffer and window, respectively.")
49683a13 119
aa228418 120;;;###autoload
d3cb357b 121(defvar compilation-buffer-name-function nil
6c43f2f9
RS
122 "Function to compute the name of a compilation buffer.
123The function receives one argument, the name of the major mode of the
124compilation buffer. It should return a string.
f441be5b 125If nil, compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
55dfd2c4 126
aa228418 127;;;###autoload
d3cb357b 128(defvar compilation-finish-function nil
c5049fa0 129 "Function to call when a compilation process finishes.
d3cb357b 130It is called with two arguments: the compilation buffer, and a string
620d3304 131describing how the process finished.")
3c9e7f42
RS
132
133(make-obsolete-variable 'compilation-finish-function
f441be5b 134 "use `compilation-finish-functions', but it works a little differently."
3c9e7f42 135 "22.1")
55dfd2c4 136
4cc36b17
RS
137;;;###autoload
138(defvar compilation-finish-functions nil
c5049fa0 139 "Functions to call when a compilation process finishes.
4cc36b17
RS
140Each function is called with two arguments: the compilation buffer,
141and a string describing how the process finished.")
142
ebff767c
RM
143(defvar compilation-in-progress nil
144 "List of compilation processes now running.")
145(or (assq 'compilation-in-progress minor-mode-alist)
146 (setq minor-mode-alist (cons '(compilation-in-progress " Compiling")
147 minor-mode-alist)))
148
7837c247
SM
149(defvar compilation-error "error"
150 "Stem of message to print when no matches are found.")
6c43f2f9 151
58856335 152(defvar compilation-arguments nil
7837c247 153 "Arguments that were given to `compilation-start'.")
58856335 154
6c43f2f9 155(defvar compilation-num-errors-found)
d3cb357b 156
7837c247
SM
157(defconst compilation-error-regexp-alist-alist
158 '((absoft
159 "^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
160of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
5dfa3d35 161
7837c247
SM
162 (ada
163 "\\(warning: .*\\)? at \\([^ \n]+\\):\\([0-9]+\\)$" 2 3 nil (1))
c7c5bbc0 164
7837c247
SM
165 (aix
166 " in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
e1f540f2 167
7837c247
SM
168 (ant
169 "^[ \t]*\\[[^] \n]+\\][ \t]*\\([^: \n]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):[0-9]+:[0-9]+:\\)?\
170\\( warning\\)?" 1 2 3 (4))
e1f540f2 171
bffa7817
SM
172 (maven
173 ;; Maven is a popular build tool for Java. Maven is Free Software.
174 "\\(.*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\]" 1 2 3)
c94d5f81 175
7837c247
SM
176 (bash
177 "^\\([^: \n\t]+\\): line \\([0-9]+\\):" 1 2)
e1f540f2 178
7837c247
SM
179 (borland
180 "^\\(?:Error\\|Warnin\\(g\\)\\) \\(?:[FEW][0-9]+ \\)?\
181\\([a-zA-Z]?:?[^:( \t\n]+\\)\
182 \\([0-9]+\\)\\(?:[) \t]\\|:[^0-9\n]\\)" 2 3 nil (1))
183
184 (caml
f6164cdd
DP
185 "^ *File \\(\"?\\)\\([^,\" \n\t<>]+\\)\\1, lines? \\([0-9]+\\)-?\\([0-9]+\\)?\\(?:$\\|,\
186\\(?: characters? \\([0-9]+\\)-?\\([0-9]+\\)?:\\)?\\([ \n]Warning:\\)?\\)"
187 2 (3 . 4) (5 . 6) (7))
7837c247
SM
188
189 (comma
190 "^\"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)\
191\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4))
192
c39bf546
DP
193 (edg-1
194 "^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
195 1 2 nil (3 . 4))
196 (edg-2
197 "at line \\([0-9]+\\) of \"\\([^ \n]+\\)\"$"
198 2 1 nil 0)
199
7837c247 200 (epc
c39bf546 201 "^Error [0-9]+ at (\\([0-9]+\\):\\([^)\n]+\\))" 2 1)
7837c247 202
12221c84
DP
203 (ftnchek
204 "\\(^Warning .*\\)? line[ \n]\\([0-9]+\\)[ \n]\\(?:col \\([0-9]+\\)[ \n]\\)?file \\([^ :;\n]+\\)"
205 4 2 3 (1))
9fcabe79 206
7837c247
SM
207 (iar
208 "^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:"
209 1 2 nil (3))
210
211 (ibm
212 "^\\([^( \n\t]+\\)(\\([0-9]+\\):\\([0-9]+\\)) :\
213 \\(?:warnin\\(g\\)\\|informationa\\(l\\)\\)?" 1 2 3 (4 . 5))
214
6f5b7627 215 ;; fixme: should be `mips'
7837c247 216 (irix
9fcabe79
DP
217 "^[-[:alnum:]_/ ]+: \\(?:\\(?:[sS]evere\\|[eE]rror\\|[wW]arnin\\(g\\)\\|[iI]nf\\(o\\)\\)[0-9 ]*: \\)?\
218\\([^,\" \n\t]+\\)\\(?:, line\\|:\\) \\([0-9]+\\):" 3 4 nil (1 . 2))
7837c247
SM
219
220 (java
221 "^\\(?:[ \t]+at \\|==[0-9]+== +\\(?:at\\|b\\(y\\)\\)\\).+(\\([^()\n]+\\):\\([0-9]+\\))$" 2 3 nil (1))
222
223 (jikes-file
224 "^\\(?:Found\\|Issued\\) .* compiling \"\\(.+\\)\":$" 1 nil nil 0)
225 (jikes-line
226 "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
227 nil 1 nil 2 0
228 (2 (compilation-face '(3))))
229
7837c247 230 (gnu
b8fa0ffd
SM
231 ;; I have no idea what this first line is supposed to match, but it
232 ;; makes things ambiguous with output such as "foo:344:50:blabla" since
233 ;; the "foo" part can match this first line (in which case the file
0ab31e4a
SM
234 ;; name as "344"). To avoid this, the second line disallows filenames
235 ;; exclusively composed of digits. --Stef
236 ;; Similarly, we get lots of false positives with messages including
237 ;; times of the form "HH:MM:SS" where MM is taken as a line number, so
238 ;; the last line tries to rule out message where the info after the
239 ;; line number starts with "SS". --Stef
bb6da2f8
SM
240
241 ;; The core of the regexp is the one with *?. It says that a file name
242 ;; can be composed of any non-newline char, but it also rules out some
243 ;; valid but unlikely cases, such as a trailing space or a space
244 ;; followed by a -.
6f5b7627 245 "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\)?\
bb6da2f8 246\\([0-9]*[^0-9\n]\\(?:[^\n ]\\| [^-/\n]\\)*?\\): ?\
8decc87f
SM
247\\([0-9]+\\)\\(?:\\([.:]\\)\\([0-9]+\\)\\)?\
248\\(?:-\\([0-9]+\\)?\\(?:\\3\\([0-9]+\\)\\)?\\)?:\
7837c247 249\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
d40a86f9 250 *\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|instantiated from\\|[Nn]ote\\)\\|\
0ab31e4a 251\[0-9]?\\(?:[^0-9\n]\\|$\\)\\|[0-9][0-9][0-9]\\)"
7837c247
SM
252 1 (2 . 5) (4 . 6) (7 . 8))
253
6e1a9597
CY
254 ;; The `gnu' style above can incorrectly match gcc's "In file
255 ;; included from" message, so we process that first. -- cyd
256 (gcc-include
257 "^\\(?:In file included\\| \\) from \
258\\(.+\\):\\([0-9]+\\)\\(?:\\(:\\)\\|\\(,\\)\\)?" 1 2 nil (3 . 4))
259
7837c247
SM
260 (lcc
261 "^\\(?:E\\|\\(W\\)\\), \\([^(\n]+\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)"
262 2 3 4 (1))
263
264 (makepp
250540cd 265 "^makepp\\(?:\\(?:: warning\\(:\\).*?\\|\\(: Scanning\\|: [LR]e?l?oading makefile\\|: Imported\\|log:.*?\\) \\|: .*?\\)\
3b79dd20 266`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]\\)"
7837c247 267 4 5 nil (1 . 2) 3
3b79dd20 268 ("`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]" nil nil
7837c247
SM
269 (2 compilation-info-face)
270 (3 compilation-line-face nil t)
51c8ad03 271 (1 (compilation-error-properties 2 3 nil nil nil 0 nil)
7837c247
SM
272 append)))
273
6f5b7627 274 ;; Should be lint-1, lint-2 (SysV lint)
7837c247
SM
275 (mips-1
276 " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
277 (mips-2
278 " in \\([^()\n ]+\\)(\\([0-9]+\\))$" 1 2)
279
280 (msft
db0095e0 281 ;; AFAWK, The message may be a "warning", "error", or "fatal error".
28547c1f 282 "^\\([0-9]+>\\)?\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \
db0095e0 283: \\(?:warnin\\(g\\)\\|[a-z ]+\\) C[0-9]+:" 2 3 nil (4))
7837c247
SM
284
285 (oracle
b3ef54c5
DP
286 "^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
287\\(?:\\(?:,\\| at\\)? column \\([0-9]+\\)\\)?\
288\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
7837c247 289 3 1 2)
40d63d1f 290
049dcb6f
GM
291 ;; "during global destruction": This comes out under "use
292 ;; warnings" in recent perl when breaking circular references
293 ;; during program or thread exit.
7837c247 294 (perl
049dcb6f
GM
295 " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\| \
296during global destruction\\.$\\)" 1 2)
7837c247 297
fa2a4e7d
MH
298 (php
299 "\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
300 2 3 nil nil)
301
7837c247
SM
302 (rxp
303 "^\\(?:Error\\|Warnin\\(g\\)\\):.*\n.* line \\([0-9]+\\) char\
304 \\([0-9]+\\) of file://\\(.+\\)"
305 4 2 3 (1))
306
307 (sparc-pascal-file
308 "^\\w\\w\\w \\w\\w\\w +[0-3]?[0-9] +[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\
309 [12][09][0-9][0-9] +\\(.*\\):$"
310 1 nil nil 0)
311 (sparc-pascal-line
312 "^\\(\\(?:E\\|\\(w\\)\\) +[0-9]+\\) line \\([0-9]+\\) - "
313 nil 3 nil (2) nil (1 (compilation-face '(2))))
314 (sparc-pascal-example
315 "^ +\\([0-9]+\\) +.*\n\\(\\(?:e\\|\\(w\\)\\) [0-9]+\\)-+"
316 nil 1 nil (3) nil (2 (compilation-face '(3))))
317
318 (sun
6f5b7627 319 ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
7837c247
SM
320File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
321 3 4 5 (1 . 2))
322
323 (sun-ada
324 "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
325
7837c247
SM
326 (4bsd
327 "\\(?:^\\|:: \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
0c9a01ff
MY
328\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))
329
330 (gcov-file
b8fa0ffd 331 "^ *-: *\\(0\\):Source:\\(.+\\)$"
eb3d9609
MY
332 2 1 nil 0 nil
333 (1 compilation-line-face prepend) (2 compilation-info-face prepend))
334 (gcov-header
335 "^ *-: *\\(0\\):\\(?:Object\\|Graph\\|Data\\|Runs\\|Programs\\):.+$"
336 nil 1 nil 0 nil
337 (1 compilation-line-face prepend))
338 ;; Underlines over all lines of gcov output are too uncomfortable to read.
339 ;; However, hyperlinks embedded in the lines are useful.
340 ;; So I put default face on the lines; and then put
341 ;; compilation-*-face by manually to eliminate the underlines.
342 ;; The hyperlinks are still effective.
343 (gcov-nomark
344 "^ *-: *\\([1-9]\\|[0-9]\\{2,\\}\\):.*$"
345 nil 1 nil 0 nil
346 (0 'default t)
347 (1 compilation-line-face prepend))
0c9a01ff 348 (gcov-called-line
eb3d9609 349 "^ *\\([0-9]+\\): *\\([0-9]+\\):.*$"
b8fa0ffd 350 nil 2 nil 0 nil
eb3d9609
MY
351 (0 'default t)
352 (1 compilation-info-face prepend) (2 compilation-line-face prepend))
353 (gcov-never-called
b8fa0ffd 354 "^ *\\(#####\\): *\\([0-9]+\\):.*$"
eb3d9609
MY
355 nil 2 nil 2 nil
356 (0 'default t)
357 (1 compilation-error-face prepend) (2 compilation-line-face prepend))
ddab7705 358
3dc4febd 359 (perl--Pod::Checker
ddab7705
VJL
360 ;; podchecker error messages, per Pod::Checker.
361 ;; The style is from the Pod::Checker::poderror() function, eg.
362 ;; *** ERROR: Spurious text after =cut at line 193 in file foo.pm
363 ;;
364 ;; Plus end_pod() can give "at line EOF" instead of a
365 ;; number, so for that match "on line N" which is the
366 ;; originating spot, eg.
367 ;; *** ERROR: =over on line 37 without closing =back at line EOF in file bar.pm
368 ;;
369 ;; Plus command() can give both "on line N" and "at line N";
370 ;; the latter is desired and is matched because the .* is
371 ;; greedy.
372 ;; *** ERROR: =over on line 1 without closing =back (at head1) at line 3 in file x.pod
373 ;;
374 "^\\*\\*\\* \\(?:ERROR\\|\\(WARNING\\)\\).* \\(?:at\\|on\\) line \
375\\([0-9]+\\) \\(?:.* \\)?in file \\([^ \t\n]+\\)"
376 3 2 nil (1))
3dc4febd 377 (perl--Test
ddab7705
VJL
378 ;; perl Test module error messages.
379 ;; Style per the ok() function "$context", eg.
380 ;; # Failed test 1 in foo.t at line 6
381 ;;
382 "^# Failed test [0-9]+ in \\([^ \t\r\n]+\\) at line \\([0-9]+\\)"
383 1 2)
3dc4febd 384 (perl--Test2
01f179de
GM
385 ;; Or when comparing got/want values,
386 ;; # Test 2 got: "xx" (t-compilation-perl-2.t at line 10)
387 ;;
388 ;; And under Test::Harness they're preceded by progress stuff with
389 ;; \r and "NOK",
390 ;; ... NOK 1# Test 1 got: "1234" (t/foo.t at line 46)
391 ;;
392 "^\\(.*NOK.*\\)?# Test [0-9]+ got:.* (\\([^ \t\r\n]+\\) at line \
393\\([0-9]+\\))"
394 2 3)
3dc4febd 395 (perl--Test::Harness
ddab7705
VJL
396 ;; perl Test::Harness output, eg.
397 ;; NOK 1# Test 1 got: "1234" (t/foo.t at line 46)
398 ;;
399 ;; Test::Harness is slightly designed for tty output, since
400 ;; it prints CRs to overwrite progress messages, but if you
401 ;; run it in with M-x compile this pattern can at least step
402 ;; through the failures.
403 ;;
404 "^.*NOK.* \\([^ \t\r\n]+\\) at line \\([0-9]+\\)"
405 1 2)
3dc4febd 406 (weblint
ddab7705
VJL
407 ;; The style comes from HTML::Lint::Error::as_string(), eg.
408 ;; index.html (13:1) Unknown element <fdjsk>
409 ;;
410 ;; The pattern only matches filenames without spaces, since that
411 ;; should be usual and should help reduce the chance of a false
412 ;; match of a message from some unrelated program.
413 ;;
414 ;; This message style is quite close to the "ibm" entry which is
415 ;; for IBM C, though that ibm bit doesn't put a space after the
416 ;; filename.
417 ;;
418 "^\\([^ \t\r\n(]+\\) (\\([0-9]+\\):\\([0-9]+\\)) "
419 1 2 3)
eb3d9609 420 )
7837c247
SM
421 "Alist of values for `compilation-error-regexp-alist'.")
422
423(defcustom compilation-error-regexp-alist
424 (mapcar 'car compilation-error-regexp-alist-alist)
6c43f2f9 425 "Alist that specifies how to match errors in compiler output.
7957baea 426On GNU and Unix, any string is a valid filename, so these
7837c247
SM
427matchers must make some common sense assumptions, which catch
428normal cases. A shorter list will be lighter on resource usage.
429
430Instead of an alist element, you can use a symbol, which is
431looked up in `compilation-error-regexp-alist-alist'. You can see
432the predefined symbols and their effects in the file
6f5b7627 433`etc/compilation.txt' (linked below if you are customizing this).
7837c247
SM
434
435Each elt has the form (REGEXP FILE [LINE COLUMN TYPE HYPERLINK
436HIGHLIGHT...]). If REGEXP matches, the FILE'th subexpression
437gives the file name, and the LINE'th subexpression gives the line
438number. The COLUMN'th subexpression gives the column number on
439that line.
440
441If FILE, LINE or COLUMN are nil or that index didn't match, that
442information is not present on the matched line. In that case the
443file name is assumed to be the same as the previous one in the
444buffer, line number defaults to 1 and column defaults to
445beginning of line's indentation.
446
447FILE can also have the form (FILE FORMAT...), where the FORMATs
448\(e.g. \"%s.c\") will be applied in turn to the recognized file
449name, until a file of that name is found. Or FILE can also be a
4aede2f2
RS
450function that returns (FILENAME) or (RELATIVE-FILENAME . DIRNAME).
451In the former case, FILENAME may be relative or absolute.
7837c247
SM
452
453LINE can also be of the form (LINE . END-LINE) meaning a range
454of lines. COLUMN can also be of the form (COLUMN . END-COLUMN)
455meaning a range of columns starting on LINE and ending on
456END-LINE, if that matched.
457
458TYPE is 2 or nil for a real error or 1 for warning or 0 for info.
459TYPE can also be of the form (WARNING . INFO). In that case this
460will be equivalent to 1 if the WARNING'th subexpression matched
461or else equivalent to 0 if the INFO'th subexpression matched.
462See `compilation-error-face', `compilation-warning-face',
463`compilation-info-face' and `compilation-skip-threshold'.
464
465What matched the HYPERLINK'th subexpression has `mouse-face' and
466`compilation-message-face' applied. If this is nil, the text
467matched by the whole REGEXP becomes the hyperlink.
468
469Additional HIGHLIGHTs as described under `font-lock-keywords' can
470be added."
471 :type `(set :menu-tag "Pick"
472 ,@(mapcar (lambda (elt)
473 (list 'const (car elt)))
474 compilation-error-regexp-alist-alist))
475 :link `(file-link :tag "example file"
eeb3ede4 476 ,(expand-file-name "compilation.txt" data-directory))
7837c247 477 :group 'compilation)
55dfd2c4 478
98d4c36f 479;;;###autoload(put 'compilation-directory 'safe-local-variable 'stringp)
ebb8cb68
EZ
480(defvar compilation-directory nil
481 "Directory to restore to when doing `recompile'.")
482
7837c247
SM
483(defvar compilation-directory-matcher
484 '("\\(?:Entering\\|Leavin\\(g\\)\\) directory `\\(.+\\)'$" (2 . 1))
485 "A list for tracking when directories are entered or left.
434520fa 486If nil, do not track directories, e.g. if all file names are absolute. The
7837c247
SM
487first element is the REGEXP matching these messages. It can match any number
488of variants, e.g. different languages. The remaining elements are all of the
489form (DIR . LEAVE). If for any one of these the DIR'th subexpression
490matches, that is a directory name. If LEAVE is nil or the corresponding
491LEAVE'th subexpression doesn't match, this message is about going into another
492directory. If it does match anything, this message is about going back to the
493directory we were in before the last entering message. If you change this,
494you may also want to change `compilation-page-delimiter'.")
495
496(defvar compilation-page-delimiter
497 "^\\(?:\f\\|.*\\(?:Entering\\|Leaving\\) directory `.+'\n\\)+"
498 "Value of `page-delimiter' in Compilation mode.")
499
500(defvar compilation-mode-font-lock-keywords
0ab31e4a 501 '(;; configure output lines.
7837c247
SM
502 ("^[Cc]hecking \\(?:[Ff]or \\|[Ii]f \\|[Ww]hether \\(?:to \\)?\\)?\\(.+\\)\\.\\.\\. *\\(?:(cached) *\\)?\\(\\(yes\\(?: .+\\)?\\)\\|no\\|\\(.*\\)\\)$"
503 (1 font-lock-variable-name-face)
38dbf92b 504 (2 (compilation-face '(4 . 3))))
7837c247 505 ;; Command output lines. Recognize `make[n]:' lines too.
6f5b7627 506 ("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
7837c247
SM
507 (1 font-lock-function-name-face) (3 compilation-line-face nil t))
508 (" --?o\\(?:utfile\\|utput\\)?[= ]?\\(\\S +\\)" . 1)
47f97084
RF
509 ("^Compilation \\(finished\\).*"
510 (0 '(face nil message nil help-echo nil mouse-face nil) t)
314b410b 511 (1 compilation-info-face))
0ab31e4a 512 ("^Compilation \\(exited abnormally\\|interrupt\\|killed\\|terminated\\|segmentation fault\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
47f97084 513 (0 '(face nil message nil help-echo nil mouse-face nil) t)
314b410b
JL
514 (1 compilation-error-face)
515 (2 compilation-error-face nil t)))
7837c247
SM
516 "Additional things to highlight in Compilation mode.
517This gets tacked on the end of the generated expressions.")
a24770bc 518
9ac57479
KS
519(defvar compilation-highlight-regexp t
520 "Regexp matching part of visited source lines to highlight temporarily.
521Highlight entire line if t; don't highlight source lines if nil.")
522
523(defvar compilation-highlight-overlay nil
524 "Overlay used to temporarily highlight compilation matches.")
525
f8e03ecb 526(defcustom compilation-error-screen-columns t
813fb3fe 527 "If non-nil, column numbers in error messages are screen columns.
f8e03ecb
AS
528Otherwise they are interpreted as character positions, with
529each character occupying one column.
530The default is to use screen columns, which requires that the compilation
531program and Emacs agree about the display width of the characters,
532especially the TAB character."
533 :type 'boolean
534 :group 'compilation
535 :version "20.4")
536
c5049fa0 537(defcustom compilation-read-command t
813fb3fe 538 "Non-nil means \\[compile] reads the compilation command to use.
851231e9 539Otherwise, \\[compile] just uses the value of `compile-command'."
c5049fa0
RS
540 :type 'boolean
541 :group 'compilation)
90016295 542
e83be080 543;;;###autoload
c5049fa0 544(defcustom compilation-ask-about-save t
813fb3fe 545 "Non-nil means \\[compile] asks which buffers to save before compiling.
c5049fa0
RS
546Otherwise, it saves all modified buffers without asking."
547 :type 'boolean
548 :group 'compilation)
90016295 549
7c163413 550;;;###autoload
c5049fa0 551(defcustom compilation-search-path '(nil)
813fb3fe 552 "List of directories to search for source files named in error messages.
d3cb357b 553Elements should be directory names, not file names of directories.
f441be5b 554The value nil as an element means to try the default directory."
c5049fa0
RS
555 :type '(repeat (choice (const :tag "Default" nil)
556 (string :tag "Directory")))
557 :group 'compilation)
55dfd2c4 558
7957baea 559;;;###autoload
c5049fa0 560(defcustom compile-command "make -k "
813fb3fe 561 "Last shell command used to do a compilation; default for next compilation.
55dfd2c4
RS
562
563Sometimes it is useful for files to supply local values for this variable.
564You might also use mode hooks to specify it in certain modes, like this:
565
61c4aaf8 566 (add-hook 'c-mode-hook
61c4aaf8
RS
567 (lambda ()
568 (unless (or (file-exists-p \"makefile\")
569 (file-exists-p \"Makefile\"))
5b6858da
SM
570 (set (make-local-variable 'compile-command)
571 (concat \"make -k \"
7837c247 572 (file-name-sans-extension buffer-file-name))))))"
c5049fa0
RS
573 :type 'string
574 :group 'compilation)
631c8020 575;;;###autoload(put 'compile-command 'safe-local-variable 'stringp)
55dfd2c4 576
7957baea 577;;;###autoload
93ef35e4 578(defcustom compilation-disable-input nil
813fb3fe 579 "If non-nil, send end-of-file as compilation process input.
3fa37cd1 580This only affects platforms that support asynchronous processes (see
bac3a1c9 581`start-process'); synchronous compilation processes never accept input."
3fa37cd1
EZ
582 :type 'boolean
583 :group 'compilation
584 :version "22.1")
585
7837c247
SM
586;; A weak per-compilation-buffer hash indexed by (FILENAME . DIRECTORY). Each
587;; value is a FILE-STRUCTURE as described above, with the car eq to the hash
4fffd73b 588;; key. This holds the tree seen from root, for storing new nodes.
7837c247
SM
589(defvar compilation-locs ())
590
591(defvar compilation-debug nil
6f5b7627 592 "*Set this to t before creating a *compilation* buffer.
7837c247
SM
593Then every error line will have a debug text property with the matcher that
594fit this line and the match data. Use `describe-text-properties'.")
d3cb357b 595
01f89d11
RM
596(defvar compilation-exit-message-function nil "\
597If non-nil, called when a compilation process dies to return a status message.
fd5e58d7
RM
598This should be a function of three arguments: process status, exit status,
599and exit message; it returns a cons (MESSAGE . MODELINE) of the strings to
600write into the compilation buffer, and to put in its mode line.")
01f89d11 601
c20f961b
JPW
602(defvar compilation-environment nil
603 "*List of environment variables for compilation to inherit.
604Each element should be a string of the form ENVVARNAME=VALUE.
605This list is temporarily prepended to `process-environment' prior to
606starting the compilation process.")
607
770970cb
RS
608;; History of compile commands.
609(defvar compile-history nil)
770970cb 610
fa947ef3
JL
611(defface compilation-error
612 '((t :inherit font-lock-warning-face))
613 "Face used to highlight compiler errors."
da742205 614 :group 'compilation
fa947ef3
JL
615 :version "22.1")
616
541a6d0d 617(defface compilation-warning
bc3621a0
EZ
618 '((((class color) (min-colors 16)) (:foreground "Orange" :weight bold))
619 (((class color)) (:foreground "cyan" :weight bold))
7837c247
SM
620 (t (:weight bold)))
621 "Face used to highlight compiler warnings."
da742205 622 :group 'compilation
bf247b6e 623 :version "22.1")
7837c247 624
541a6d0d 625(defface compilation-info
e4aa3c94 626 '((((class color) (min-colors 16) (background light))
bc3621a0 627 (:foreground "Green3" :weight bold))
ea81d57e
DN
628 (((class color) (min-colors 88) (background dark))
629 (:foreground "Green1" :weight bold))
e4aa3c94 630 (((class color) (min-colors 16) (background dark))
bc3621a0
EZ
631 (:foreground "Green" :weight bold))
632 (((class color)) (:foreground "green" :weight bold))
7837c247 633 (t (:weight bold)))
fa947ef3 634 "Face used to highlight compiler information."
da742205 635 :group 'compilation
bf247b6e 636 :version "22.1")
7837c247 637
a5f1c37e 638(defface compilation-line-number
38dbf92b 639 '((t :inherit font-lock-variable-name-face))
fa947ef3 640 "Face for displaying line numbers in compiler messages."
da742205 641 :group 'compilation
a5f1c37e
RS
642 :version "22.1")
643
644(defface compilation-column-number
38dbf92b 645 '((t :inherit font-lock-type-face))
fa947ef3 646 "Face for displaying column numbers in compiler messages."
da742205 647 :group 'compilation
a5f1c37e
RS
648 :version "22.1")
649
f4beca06 650(defcustom compilation-message-face 'underline
7837c247
SM
651 "Face name to use for whole messages.
652Faces `compilation-error-face', `compilation-warning-face',
653`compilation-info-face', `compilation-line-face' and
f4beca06
RS
654`compilation-column-face' get prepended to this, when applicable."
655 :type 'face
656 :group 'compilation
657 :version "22.1")
7837c247 658
38dbf92b 659(defvar compilation-error-face 'compilation-error
7837c247
SM
660 "Face name to use for file name in error messages.")
661
38dbf92b 662(defvar compilation-warning-face 'compilation-warning
7837c247
SM
663 "Face name to use for file name in warning messages.")
664
38dbf92b 665(defvar compilation-info-face 'compilation-info
7837c247
SM
666 "Face name to use for file name in informational messages.")
667
a5f1c37e 668(defvar compilation-line-face 'compilation-line-number
38dbf92b 669 "Face name to use for line numbers in compiler messages.")
7837c247 670
a5f1c37e 671(defvar compilation-column-face 'compilation-column-number
fa947ef3 672 "Face name to use for column numbers in compiler messages.")
7837c247
SM
673
674;; same faces as dired uses
675(defvar compilation-enter-directory-face 'font-lock-function-name-face
fa947ef3 676 "Face name to use for entering directory messages.")
7837c247
SM
677
678(defvar compilation-leave-directory-face 'font-lock-type-face
fa947ef3 679 "Face name to use for leaving directory messages.")
7837c247
SM
680
681
682
c536bb39 683;; Used for compatibility with the old compile.el.
0ff7f01e 684(defvaralias 'compilation-last-buffer 'next-error-last-buffer)
6f5b7627 685(defvar compilation-parsing-end (make-marker))
c536bb39
SM
686(defvar compilation-parse-errors-function nil)
687(defvar compilation-error-list nil)
688(defvar compilation-old-error-list nil)
689
813fb3fe
SM
690(defcustom compilation-auto-jump-to-first-error nil
691 "If non-nil, automatically jump to the first error after `compile'."
765831a0
DN
692 :type 'boolean
693 :group 'compilation
694 :version "23.1")
813fb3fe
SM
695
696(defvar compilation-auto-jump-to-next nil
697 "If non-nil, automatically jump to the next error encountered.")
698(make-variable-buffer-local 'compilation-auto-jump-to-next)
699
97546017
DN
700
701(defvar compilation-skip-to-next-location t
702 "*If non-nil, skip multiple error messages for the same source location.")
703
704(defcustom compilation-skip-threshold 1
705 "Compilation motion commands skip less important messages.
706The value can be either 2 -- skip anything less than error, 1 --
707skip anything less than warning or 0 -- don't skip any messages.
708Note that all messages not positively identified as warning or
709info, are considered errors."
710 :type '(choice (const :tag "Warnings and info" 2)
711 (const :tag "Info" 1)
712 (const :tag "None" 0))
713 :group 'compilation
714 :version "22.1")
715
716(defcustom compilation-skip-visited nil
717 "Compilation motion commands skip visited messages if this is t.
718Visited messages are ones for which the file, line and column have been jumped
719to from the current content in the current compilation buffer, even if it was
720from a different message."
721 :type 'boolean
722 :group 'compilation
723 :version "22.1")
724
7837c247
SM
725(defun compilation-face (type)
726 (or (and (car type) (match-end (car type)) compilation-warning-face)
727 (and (cdr type) (match-end (cdr type)) compilation-info-face)
728 compilation-error-face))
729
deda0c65
DP
730;; Internal function for calculating the text properties of a directory
731;; change message. The directory property is important, because it is
732;; the stack of nested enter-messages. Relative filenames on the following
733;; lines are relative to the top of the stack.
7837c247
SM
734(defun compilation-directory-properties (idx leave)
735 (if leave (setq leave (match-end leave)))
736 ;; find previous stack, and push onto it, or if `leave' pop it
737 (let ((dir (previous-single-property-change (point) 'directory)))
738 (setq dir (if dir (or (get-text-property (1- dir) 'directory)
739 (get-text-property dir 'directory))))
740 `(face ,(if leave
741 compilation-leave-directory-face
742 compilation-enter-directory-face)
743 directory ,(if leave
744 (or (cdr dir)
745 '(nil)) ; nil only isn't a property-change
746 (cons (match-string-no-properties idx) dir))
747 mouse-face highlight
6f5b7627 748 keymap compilation-button-map
5ae48997 749 help-echo "mouse-2: visit destination directory")))
7837c247 750
4fffd73b 751;; Data type `reverse-ordered-alist' retriever. This function retrieves the
7837c247
SM
752;; KEY element from the ALIST, creating it in the right position if not already
753;; present. ALIST structure is
754;; '(ANCHOR (KEY1 ...) (KEY2 ...)... (KEYn ALIST ...))
755;; ANCHOR is ignored, but necessary so that elements can be inserted. KEY1
4fffd73b 756;; may be nil. The other KEYs are ordered backwards so that growing line
7837c247
SM
757;; numbers can be inserted in front and searching can abort after half the
758;; list on average.
6f5b7627 759(eval-when-compile ;Don't keep it at runtime if not needed.
7837c247
SM
760(defmacro compilation-assq (key alist)
761 `(let* ((l1 ,alist)
762 (l2 (cdr l1)))
763 (car (if (if (null ,key)
764 (if l2 (null (caar l2)))
765 (while (if l2 (if (caar l2) (< ,key (caar l2)) t))
766 (setq l1 l2
767 l2 (cdr l1)))
768 (if l2 (eq ,key (caar l2))))
769 l2
6f5b7627 770 (setcdr l1 (cons (list ,key) l2)))))))
7837c247 771
813fb3fe
SM
772(defun compilation-auto-jump (buffer pos)
773 (with-current-buffer buffer
774 (goto-char pos)
93c0985f
JL
775 (let ((win (get-buffer-window buffer 0)))
776 (if win (set-window-point win pos)))
78dc87a2
JL
777 (if compilation-auto-jump-to-first-error
778 (compile-goto-error))))
7837c247
SM
779
780;; This function is the central driver, called when font-locking to gather
781;; all information needed to later jump to corresponding source code.
782;; Return a property list with all meta information on this error location.
f0685ed1 783
7837c247 784(defun compilation-error-properties (file line end-line col end-col type fmt)
813fb3fe
SM
785 (unless (< (next-single-property-change (match-beginning 0)
786 'directory nil (point))
7837c247
SM
787 (point))
788 (if file
789 (if (functionp file)
790 (setq file (funcall file))
791 (let (dir)
792 (setq file (match-string-no-properties file))
793 (unless (file-name-absolute-p file)
794 (setq dir (previous-single-property-change (point) 'directory)
795 dir (if dir (or (get-text-property (1- dir) 'directory)
796 (get-text-property dir 'directory)))))
efb0e677 797 (setq file (cons file (car dir)))))
7837c247 798 ;; This message didn't mention one, get it from previous
f0685ed1
RS
799 (let ((prev-pos
800 ;; Find the previous message.
801 (previous-single-property-change (point) 'message)))
802 (if prev-pos
803 ;; Get the file structure that belongs to it.
804 (let* ((prev
805 (or (get-text-property (1- prev-pos) 'message)
806 (get-text-property prev-pos 'message)))
807 (prev-struct
808 (car (nth 2 (car prev)))))
809 ;; Construct FILE . DIR from that.
810 (if prev-struct
811 (setq file (cons (car prev-struct)
812 (cadr prev-struct))))))
813 (unless file
814 (setq file '("*unknown*")))))
7837c247
SM
815 ;; All of these fields are optional, get them only if we have an index, and
816 ;; it matched some part of the message.
817 (and line
818 (setq line (match-string-no-properties line))
819 (setq line (string-to-number line)))
820 (and end-line
821 (setq end-line (match-string-no-properties end-line))
822 (setq end-line (string-to-number end-line)))
9dc3a46a
JL
823 (if col
824 (if (functionp col)
825 (setq col (funcall col))
826 (and
827 (setq col (match-string-no-properties col))
828 (setq col (- (string-to-number col) compilation-first-column)))))
829 (if (and end-col (functionp end-col))
830 (setq end-col (funcall end-col))
831 (if (and end-col (setq end-col (match-string-no-properties end-col)))
832 (setq end-col (- (string-to-number end-col) compilation-first-column -1))
833 (if end-line (setq end-col -1))))
eb6fb6e2 834 (if (consp type) ; not a static type, check what it is.
7837c247
SM
835 (setq type (or (and (car type) (match-end (car type)) 1)
836 (and (cdr type) (match-end (cdr type)) 0)
837 2)))
813fb3fe
SM
838
839 (when (and compilation-auto-jump-to-next
840 (>= type compilation-skip-threshold))
841 (kill-local-variable 'compilation-auto-jump-to-next)
842 (run-with-timer 0 nil 'compilation-auto-jump
843 (current-buffer) (match-beginning 0)))
844
efb0e677
SM
845 (compilation-internal-error-properties file line end-line col end-col type fmt)))
846
9c8e6c85
SM
847(defun compilation-move-to-column (col screen)
848 "Go to column COL on the current line.
849If SCREEN is non-nil, columns are screen columns, otherwise, they are
850just char-counts."
851 (if screen
852 (move-to-column col)
853 (goto-char (min (+ (line-beginning-position) col) (line-end-position)))))
854
7957baea 855(defun compilation-internal-error-properties (file line end-line col end-col type fmts)
efb0e677
SM
856 "Get the meta-info that will be added as text-properties.
857LINE, END-LINE, COL, END-COL are integers or nil.
7957baea
RS
858TYPE can be 0, 1, or 2, meaning error, warning, or just info.
859FILE should be (FILENAME) or (RELATIVE-FILENAME . DIRNAME) or nil.
860FMTS is a list of format specs for transforming the file name.
861 (See `compilation-error-regexp-alist'.)"
efb0e677 862 (unless file (setq file '("*unknown*")))
7957baea
RS
863 (let* ((file-struct (compilation-get-file-structure file fmts))
864 ;; Get first already existing marker (if any has one, all have one).
865 ;; Do this first, as the compilation-assq`s may create new nodes.
866 (marker-line (car (cddr file-struct))) ; a line structure
efb0e677
SM
867 (marker (nth 3 (cadr marker-line))) ; its marker
868 (compilation-error-screen-columns compilation-error-screen-columns)
869 end-marker loc end-loc)
870 (if (not (and marker (marker-buffer marker)))
7957baea 871 (setq marker nil) ; no valid marker for this file
dbd97672
DP
872 (setq loc (or line 1)) ; normalize no linenumber to line 1
873 (catch 'marker ; find nearest loc, at least one exists
7957baea 874 (dolist (x (nthcdr 3 file-struct)) ; loop over remaining lines
dbd97672 875 (if (> (car x) loc) ; still bigger
efb0e677 876 (setq marker-line x)
dbd97672
DP
877 (if (> (- (or (car marker-line) 1) loc)
878 (- loc (car x))) ; current line is nearer
efb0e677
SM
879 (setq marker-line x))
880 (throw 'marker t))))
881 (setq marker (nth 3 (cadr marker-line))
dbd97672 882 marker-line (or (car marker-line) 1))
efb0e677 883 (with-current-buffer (marker-buffer marker)
8dfb3e16
RS
884 (save-excursion
885 (save-restriction
886 (widen)
887 (goto-char (marker-position marker))
888 (when (or end-col end-line)
889 (beginning-of-line (- (or end-line line) marker-line -1))
890 (if (or (null end-col) (< end-col 0))
891 (end-of-line)
892 (compilation-move-to-column
893 end-col compilation-error-screen-columns))
894 (setq end-marker (list (point-marker))))
895 (beginning-of-line (if end-line
896 (- line end-line -1)
897 (- loc marker-line -1)))
898 (if col
899 (compilation-move-to-column
900 col compilation-error-screen-columns)
901 (forward-to-indentation 0))
902 (setq marker (list (point-marker)))))))
efb0e677 903
7957baea 904 (setq loc (compilation-assq line (cdr file-struct)))
efb0e677 905 (if end-line
7957baea 906 (setq end-loc (compilation-assq end-line (cdr file-struct))
efb0e677
SM
907 end-loc (compilation-assq end-col end-loc))
908 (if end-col ; use same line element
909 (setq end-loc (compilation-assq end-col loc))))
910 (setq loc (compilation-assq col loc))
911 ;; If they are new, make the loc(s) reference the file they point to.
7957baea 912 (or (cdr loc) (setcdr loc `(,line ,file-struct ,@marker)))
efb0e677 913 (if end-loc
7957baea
RS
914 (or (cdr end-loc)
915 (setcdr end-loc `(,(or end-line line) ,file-struct ,@end-marker))))
efb0e677
SM
916
917 ;; Must start with face
918 `(face ,compilation-message-face
919 message (,loc ,type ,end-loc)
920 ,@(if compilation-debug
921 `(debug (,(assoc (with-no-warnings matcher) font-lock-keywords)
922 ,@(match-data))))
923 help-echo ,(if col
924 "mouse-2: visit this file, line and column"
925 (if line
926 "mouse-2: visit this file and line"
927 "mouse-2: visit this file"))
928 keymap compilation-button-map
929 mouse-face highlight)))
7837c247 930
e93b2a55
SM
931(defun compilation-mode-font-lock-keywords ()
932 "Return expressions to highlight in Compilation mode."
91fa27cd
SM
933 (if compilation-parse-errors-function
934 ;; An old package! Try the compatibility code.
935 '((compilation-compat-parse-errors))
936 (append
937 ;; make directory tracking
938 (if compilation-directory-matcher
939 `((,(car compilation-directory-matcher)
940 ,@(mapcar (lambda (elt)
941 `(,(car elt)
942 (compilation-directory-properties
943 ,(car elt) ,(cdr elt))
0ea50e43 944 t t))
91fa27cd
SM
945 (cdr compilation-directory-matcher)))))
946
947 ;; Compiler warning/error lines.
948 (mapcar
949 (lambda (item)
950 (if (symbolp item)
951 (setq item (cdr (assq item
952 compilation-error-regexp-alist-alist))))
953 (let ((file (nth 1 item))
954 (line (nth 2 item))
955 (col (nth 3 item))
956 (type (nth 4 item))
957 end-line end-col fmt)
b3a7f48f
DP
958 (if (consp file) (setq fmt (cdr file) file (car file)))
959 (if (consp line) (setq end-line (cdr line) line (car line)))
91fa27cd 960 (if (consp col) (setq end-col (cdr col) col (car col)))
b3a7f48f 961
544dccaa 962 (if (functionp line)
91fa27cd
SM
963 ;; The old compile.el had here an undocumented hook that
964 ;; allowed `line' to be a function that computed the actual
965 ;; error location. Let's do our best.
966 `(,(car item)
0ea50e43
RS
967 (0 (save-match-data
968 (compilation-compat-error-properties
969 (funcall ',line (cons (match-string ,file)
970 (cons default-directory
971 ',(nthcdr 4 item)))
972 ,(if col `(match-string ,col))))))
91fa27cd 973 (,file compilation-error-face t))
b3a7f48f 974
f71d34b0
SM
975 (unless (or (null (nth 5 item)) (integerp (nth 5 item)))
976 (error "HYPERLINK should be an integer: %s" (nth 5 item)))
977
91fa27cd
SM
978 `(,(nth 0 item)
979
980 ,@(when (integerp file)
981 `((,file ,(if (consp type)
982 `(compilation-face ',type)
983 (aref [compilation-info-face
984 compilation-warning-face
985 compilation-error-face]
986 (or type 2))))))
987
988 ,@(when line
989 `((,line compilation-line-face nil t)))
990 ,@(when end-line
991 `((,end-line compilation-line-face nil t)))
992
9dc3a46a 993 ,@(when (integerp col)
91fa27cd 994 `((,col compilation-column-face nil t)))
9dc3a46a 995 ,@(when (integerp end-col)
91fa27cd
SM
996 `((,end-col compilation-column-face nil t)))
997
998 ,@(nthcdr 6 item)
999 (,(or (nth 5 item) 0)
1000 (compilation-error-properties ',file ,line ,end-line
1001 ,col ,end-col ',(or type 2)
1002 ',fmt)
1003 append))))) ; for compilation-message-face
1004 compilation-error-regexp-alist)
1005
1006 compilation-mode-font-lock-keywords)))
7837c247 1007
01f89d11 1008\f
d3cb357b 1009;;;###autoload
7837c247 1010(defun compile (command &optional comint)
55dfd2c4
RS
1011 "Compile the program including the current buffer. Default: run `make'.
1012Runs COMMAND, a shell command, in a separate process asynchronously
1013with output going to the buffer `*compilation*'.
d3cb357b 1014
55dfd2c4
RS
1015You can then use the command \\[next-error] to find the next error message
1016and move to the source code that caused it.
1017
8f72171b
RS
1018If optional second arg COMINT is t the buffer will be in Comint mode with
1019`compilation-shell-minor-mode'.
1020
08b1edf4
RM
1021Interactively, prompts for the command if `compilation-read-command' is
1022non-nil; otherwise uses `compile-command'. With prefix arg, always prompts.
c39bf546
DP
1023Additionally, with universal prefix arg, compilation buffer will be in
1024comint mode, i.e. interactive.
08b1edf4 1025
7d1dad0c 1026To run more than one compilation at once, start one then rename
c72095b3 1027the \`*compilation*' buffer to some other name with
7d1dad0c
RS
1028\\[rename-buffer]. Then _switch buffers_ and start the new compilation.
1029It will create a new \`*compilation*' buffer.
1030
1031On most systems, termination of the main compilation process
1032kills its subprocesses.
d3cb357b
RM
1033
1034The name used for the buffer is actually whatever is returned by
1035the function in `compilation-buffer-name-function', so you can set that
1036to a function that generates a unique name."
90016295 1037 (interactive
c39bf546 1038 (list
20320c65
JL
1039 (let ((command (eval compile-command)))
1040 (if (or compilation-read-command current-prefix-arg)
286d4b3b
SM
1041 (read-shell-command "Compile command: " command
1042 (if (equal (car compile-history) command)
1043 '(compile-history . 1)
1044 'compile-history))
20320c65 1045 command))
c39bf546 1046 (consp current-prefix-arg)))
5b6858da
SM
1047 (unless (equal command (eval compile-command))
1048 (setq compile-command command))
90016295 1049 (save-some-buffers (not compilation-ask-about-save) nil)
091525d5 1050 (setq-default compilation-directory default-directory)
7837c247 1051 (compilation-start command comint))
55dfd2c4 1052
5b6858da 1053;; run compile with the default command line
e60476ca 1054(defun recompile ()
6867356a 1055 "Re-compile the program including the current buffer.
6f5b7627
SM
1056If this is run in a Compilation mode buffer, re-use the arguments from the
1057original use. Otherwise, recompile using `compile-command'."
e60476ca
RS
1058 (interactive)
1059 (save-some-buffers (not compilation-ask-about-save) nil)
091525d5 1060 (let ((default-directory (or compilation-directory default-directory)))
7837c247
SM
1061 (apply 'compilation-start (or compilation-arguments
1062 `(,(eval compile-command))))))
09843b4a 1063
b5812513 1064(defcustom compilation-scroll-output nil
813fb3fe 1065 "Non-nil to scroll the *compilation* buffer window as output appears.
b5812513 1066
6f5b7627 1067Setting it causes the Compilation mode commands to put point at the
b5812513 1068end of their output window so that the end of the output is always
78dc87a2
JL
1069visible rather than the beginning.
1070
1071The value `first-error' stops scrolling at the first error, and leaves
1072point on its location in the *compilation* buffer."
1073 :type '(choice (const :tag "No scrolling" nil)
1074 (const :tag "Scroll compilation output" t)
1075 (const :tag "Stop scrolling at the first error" first-error))
a46fddeb 1076 :version "20.3"
b5812513
DL
1077 :group 'compilation)
1078
7bdb67b2 1079
ae0cc840 1080(defun compilation-buffer-name (mode-name mode-command name-function)
7bdb67b2
GM
1081 "Return the name of a compilation buffer to use.
1082If NAME-FUNCTION is non-nil, call it with one argument MODE-NAME
1083to determine the buffer name.
1084Likewise if `compilation-buffer-name-function' is non-nil.
7d1dad0c 1085If current buffer has the major mode MODE-COMMAND,
7bdb67b2
GM
1086return the name of the current buffer, so that it gets reused.
1087Otherwise, construct a buffer name from MODE-NAME."
dc2feacf 1088 (cond (name-function
7bdb67b2 1089 (funcall name-function mode-name))
dc2feacf 1090 (compilation-buffer-name-function
7bdb67b2 1091 (funcall compilation-buffer-name-function mode-name))
be947101 1092 ((eq mode-command major-mode)
7bdb67b2
GM
1093 (buffer-name))
1094 (t
1095 (concat "*" (downcase mode-name) "*"))))
1096
7837c247
SM
1097;; This is a rough emulation of the old hack, until the transition to new
1098;; compile is complete.
55dfd2c4 1099(defun compile-internal (command error-message
a24770bc
RS
1100 &optional name-of-mode parser
1101 error-regexp-alist name-function
1102 enter-regexp-alist leave-regexp-alist
23b0c5fc 1103 file-regexp-alist nomessage-regexp-alist
9ac57479 1104 no-async highlight-regexp local-map)
7837c247
SM
1105 (if parser
1106 (error "Compile now works very differently, see `compilation-error-regexp-alist'"))
1107 (let ((compilation-error-regexp-alist
1108 (append file-regexp-alist (or error-regexp-alist
1109 compilation-error-regexp-alist)))
1110 (compilation-error (replace-regexp-in-string "^No more \\(.+\\)s\\.?"
1111 "\\1" error-message)))
1112 (compilation-start command nil name-function highlight-regexp)))
ddb1f2e3 1113(make-obsolete 'compile-internal 'compilation-start "22.1")
7837c247 1114
a24c45d2 1115;;;###autoload
7837c247 1116(defun compilation-start (command &optional mode name-function highlight-regexp)
55dfd2c4 1117 "Run compilation command COMMAND (low level interface).
489a8034 1118If COMMAND starts with a cd command, that becomes the `default-directory'.
9ac57479
KS
1119The rest of the arguments are optional; for them, nil means use the default.
1120
7837c247 1121MODE is the major mode to set in the compilation buffer. Mode
6f5b7627 1122may also be t meaning use `compilation-shell-minor-mode' under `comint-mode'.
7d1dad0c 1123
5b317d74 1124If NAME-FUNCTION is non-nil, call it with one argument (the mode name)
7d1dad0c
RS
1125to determine the buffer name. Otherwise, the default is to
1126reuses the current buffer if it has the proper major mode,
1127else use or create a buffer with name based on the major mode.
23b0c5fc 1128
9ac57479 1129If HIGHLIGHT-REGEXP is non-nil, `next-error' will temporarily highlight
6f5b7627 1130the matching section of the visited source line; the default is to use the
9ac57479
KS
1131global value of `compilation-highlight-regexp'.
1132
646bd331 1133Returns the compilation buffer created."
7837c247 1134 (or mode (setq mode 'compilation-mode))
489a8034
DP
1135 (let* ((name-of-mode
1136 (if (eq mode t)
1137 (prog1 "compilation" (require 'comint))
1138 (replace-regexp-in-string "-mode$" "" (symbol-name mode))))
199143f1 1139 (thisdir default-directory)
489a8034 1140 outwin outbuf)
c536bb39
SM
1141 (with-current-buffer
1142 (setq outbuf
1143 (get-buffer-create
be947101 1144 (compilation-buffer-name name-of-mode mode name-function)))
d3cb357b
RM
1145 (let ((comp-proc (get-buffer-process (current-buffer))))
1146 (if comp-proc
1147 (if (or (not (eq (process-status comp-proc) 'run))
1148 (yes-or-no-p
bea1d57a
JB
1149 (format "A %s process is running; kill it? "
1150 name-of-mode)))
d3cb357b
RM
1151 (condition-case ()
1152 (progn
1153 (interrupt-process comp-proc)
1154 (sit-for 1)
1155 (delete-process comp-proc))
1156 (error nil))
1157 (error "Cannot have two processes in `%s' at once"
7837c247 1158 (buffer-name)))))
7837c247 1159 (buffer-disable-undo (current-buffer))
199143f1
DP
1160 ;; first transfer directory from where M-x compile was called
1161 (setq default-directory thisdir)
d42c87ab
RS
1162 ;; Make compilation buffer read-only. The filter can still write it.
1163 ;; Clear out the compilation buffer.
199143f1
DP
1164 (let ((inhibit-read-only t)
1165 (default-directory thisdir))
813fb3fe
SM
1166 ;; Then evaluate a cd command if any, but don't perform it yet, else
1167 ;; start-command would do it again through the shell: (cd "..") AND
1168 ;; sh -c "cd ..; make"
199143f1
DP
1169 (cd (if (string-match "^\\s *cd\\(?:\\s +\\(\\S +?\\)\\)?\\s *[;&\n]" command)
1170 (if (match-end 1)
12221c84 1171 (substitute-env-vars (match-string 1 command))
199143f1
DP
1172 "~")
1173 default-directory))
abed5267 1174 (erase-buffer)
6d2957c4
RS
1175 ;; Select the desired mode.
1176 (if (not (eq mode t))
1177 (funcall mode)
1178 (setq buffer-read-only nil)
1179 (with-no-warnings (comint-mode))
1180 (compilation-shell-minor-mode))
5f3ca1ba
SS
1181 ;; Remember the original dir, so we can use it when we recompile.
1182 ;; default-directory' can't be used reliably for that because it may be
1183 ;; affected by the special handling of "cd ...;".
1184 ;; NB: must be fone after (funcall mode) as that resets local variables
1185 (set (make-local-variable 'compilation-directory) thisdir)
6d2957c4
RS
1186 (if highlight-regexp
1187 (set (make-local-variable 'compilation-highlight-regexp)
1188 highlight-regexp))
78dc87a2
JL
1189 (if (or compilation-auto-jump-to-first-error
1190 (eq compilation-scroll-output 'first-error))
813fb3fe 1191 (set (make-local-variable 'compilation-auto-jump-to-next) t))
6d2957c4 1192 ;; Output a mode setter, for saving and later reloading this buffer.
d42c87ab 1193 (insert "-*- mode: " name-of-mode
4b025f47 1194 "; default-directory: " (prin1-to-string default-directory)
a67e5425 1195 " -*-\n"
314b410b
JL
1196 (format "%s started at %s\n\n"
1197 mode-name
1198 (substring (current-time-string) 0 19))
a67e5425 1199 command "\n")
abed5267 1200 (setq thisdir default-directory))
7837c247 1201 (set-buffer-modified-p nil))
7837c247 1202 ;; Pop up the compilation buffer.
c34dc850
GM
1203 ;; http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01638.html
1204 (setq outwin (display-buffer outbuf))
7837c247 1205 (with-current-buffer outbuf
577bf5d2
JL
1206 (let ((process-environment
1207 (append
1208 compilation-environment
1209 (if (if (boundp 'system-uses-terminfo) ; `if' for compiler warning
1210 system-uses-terminfo)
1211 (list "TERM=dumb" "TERMCAP="
1212 (format "COLUMNS=%d" (window-width)))
1213 (list "TERM=emacs"
1214 (format "TERMCAP=emacs:co#%d:tc=unknown:"
1215 (window-width))))
1216 ;; Set the EMACS variable, but
1217 ;; don't override users' setting of $EMACS.
4b1aaa8b 1218 (unless (getenv "EMACS")
e725507a
CY
1219 (list "EMACS=t"))
1220 (list "INSIDE_EMACS=t")
a9e11582 1221 (copy-sequence process-environment))))
577bf5d2
JL
1222 (set (make-local-variable 'compilation-arguments)
1223 (list command mode name-function highlight-regexp))
1224 (set (make-local-variable 'revert-buffer-function)
1225 'compilation-revert-buffer)
1226 (set-window-start outwin (point-min))
2d0a22f8
RS
1227
1228 ;; Position point as the user will see it.
1229 (let ((desired-visible-point
1230 ;; Put it at the end if `compilation-scroll-output' is set.
1231 (if compilation-scroll-output
1232 (point-max)
1233 ;; Normally put it at the top.
1234 (point-min))))
1235 (if (eq outwin (selected-window))
1236 (goto-char desired-visible-point)
1237 (set-window-point outwin desired-visible-point)))
1238
577bf5d2
JL
1239 ;; The setup function is called before compilation-set-window-height
1240 ;; so it can set the compilation-window-height buffer locally.
1241 (if compilation-process-setup-function
1242 (funcall compilation-process-setup-function))
1243 (compilation-set-window-height outwin)
1244 ;; Start the compilation.
db8af973
MA
1245 (let ((proc
1246 (if (eq mode t)
1247 ;; comint uses `start-file-process'.
1248 (get-buffer-process
1249 (with-no-warnings
a9e11582
MA
1250 (comint-exec
1251 outbuf (downcase mode-name)
1252 (if (file-remote-p default-directory)
1253 "/bin/sh"
1254 shell-file-name)
c94d5f81 1255 nil `("-c" ,command))))
a9e11582
MA
1256 (start-file-process-shell-command (downcase mode-name)
1257 outbuf command))))
4b29e550 1258 ;; Make the buffer's mode line show process state.
ddb1f2e3 1259 (setq mode-line-process
a8bdd228 1260 (list (propertize ":%s" 'face 'compilation-warning)))
4b29e550
MA
1261 (set-process-sentinel proc 'compilation-sentinel)
1262 (set-process-filter proc 'compilation-filter)
b17f53ab
MB
1263 ;; Use (point-max) here so that output comes in
1264 ;; after the initial text,
1265 ;; regardless of where the user sees point.
1266 (set-marker (process-mark proc) (point-max) outbuf)
4b29e550
MA
1267 (when compilation-disable-input
1268 (condition-case nil
1269 (process-send-eof proc)
1270 ;; The process may have exited already.
1271 (error nil)))
1272 (setq compilation-in-progress
1273 (cons proc compilation-in-progress))))
199143f1
DP
1274 ;; Now finally cd to where the shell started make/grep/...
1275 (setq default-directory thisdir))
7837c247
SM
1276 (if (buffer-local-value 'compilation-scroll-output outbuf)
1277 (save-selected-window
1278 (select-window outwin)
043442b4
KS
1279 (goto-char (point-max))))
1280 ;; Make it so the next C-x ` will use this buffer.
5d9f0de2 1281 (setq next-error-last-buffer outbuf)))
55dfd2c4 1282
c94b02d6 1283(defun compilation-set-window-height (window)
851231e9 1284 "Set the height of WINDOW according to `compilation-window-height'."
9ac57479
KS
1285 (let ((height (buffer-local-value 'compilation-window-height (window-buffer window))))
1286 (and height
0dad3dfe 1287 (window-full-width-p window)
9ac57479
KS
1288 ;; If window is alone in its frame, aside from a minibuffer,
1289 ;; don't change its height.
1290 (not (eq window (frame-root-window (window-frame window))))
b3ef54c5
DP
1291 ;; Stef said that doing the saves in this order is safer:
1292 (save-excursion
9ac57479 1293 (save-selected-window
b3ef54c5
DP
1294 (select-window window)
1295 (enlarge-window (- height (window-height))))))))
c94b02d6 1296
4282eba1 1297(defvar compilation-menu-map
93260283
DN
1298 (let ((map (make-sparse-keymap "Errors"))
1299 (opt-map (make-sparse-keymap "Skip")))
4282eba1 1300 (define-key map [stop-subjob]
38805987
DN
1301 '(menu-item "Stop Compilation" kill-compilation
1302 :help "Kill the process made by the M-x compile or M-x grep commands"))
93260283
DN
1303 (define-key map [compilation-mode-separator3]
1304 '("----" . nil))
1305 (define-key map [compilation-next-error-follow-minor-mode]
1306 '(menu-item
1307 "Auto Error Display" next-error-follow-minor-mode
1308 :help "Display the error under cursor when moving the cursor"
1309 :button (:toggle . next-error-follow-minor-mode)))
1310 (define-key map [compilation-skip]
1311 (cons "Skip Less Important Messages" opt-map))
1312 (define-key opt-map [compilation-skip-none]
1313 '(menu-item "Don't Skip Any Messages"
1314 (lambda ()
1315 (interactive)
1316 (customize-set-variable 'compilation-skip-threshold 0))
1317 :help "Do not skip any type of messages"
1318 :button (:radio . (eq compilation-skip-threshold 0))))
1319 (define-key opt-map [compilation-skip-info]
1320 '(menu-item "Skip Info"
1321 (lambda ()
1322 (interactive)
1323 (customize-set-variable 'compilation-skip-threshold 1))
1324 :help "Skip anything less than warning"
1325 :button (:radio . (eq compilation-skip-threshold 1))))
1326 (define-key opt-map [compilation-skip-warning-and-info]
1327 '(menu-item "Skip Warnings and Info"
1328 (lambda ()
1329 (interactive)
1330 (customize-set-variable 'compilation-skip-threshold 2))
1331 :help "Skip over Warnings and Info, stop for errors"
1332 :button (:radio . (eq compilation-skip-threshold 2))))
4282eba1
SM
1333 (define-key map [compilation-mode-separator2]
1334 '("----" . nil))
9ac57479 1335 (define-key map [compilation-first-error]
38805987
DN
1336 '(menu-item "First Error" first-error
1337 :help "Restart at the first error, visit corresponding source code"))
9ac57479 1338 (define-key map [compilation-previous-error]
38805987
DN
1339 '(menu-item "Previous Error" previous-error
1340 :help "Visit previous `next-error' message and corresponding source code"))
9ac57479 1341 (define-key map [compilation-next-error]
38805987
DN
1342 '(menu-item "Next Error" next-error
1343 :help "Visit next `next-error' message and corresponding source code"))
4282eba1
SM
1344 map))
1345
0b18a8f6 1346(defvar compilation-minor-mode-map
55dfd2c4 1347 (let ((map (make-sparse-keymap)))
9da85ee5 1348 (define-key map [mouse-2] 'compile-goto-error)
0ac804df 1349 (define-key map [follow-link] 'mouse-face)
55dfd2c4 1350 (define-key map "\C-c\C-c" 'compile-goto-error)
4e7ce12e 1351 (define-key map "\C-m" 'compile-goto-error)
d3cb357b 1352 (define-key map "\C-c\C-k" 'kill-compilation)
646bd331
RM
1353 (define-key map "\M-n" 'compilation-next-error)
1354 (define-key map "\M-p" 'compilation-previous-error)
d1ed4475
RM
1355 (define-key map "\M-{" 'compilation-previous-file)
1356 (define-key map "\M-}" 'compilation-next-file)
4282eba1
SM
1357 ;; Set up the menu-bar
1358 (define-key map [menu-bar compilation]
1359 (cons "Errors" compilation-menu-map))
55dfd2c4 1360 map)
4f6e4ad6 1361 "Keymap for `compilation-minor-mode'.")
0b18a8f6 1362
a24770bc
RS
1363(defvar compilation-shell-minor-mode-map
1364 (let ((map (make-sparse-keymap)))
a24770bc
RS
1365 (define-key map "\M-\C-m" 'compile-goto-error)
1366 (define-key map "\M-\C-n" 'compilation-next-error)
1367 (define-key map "\M-\C-p" 'compilation-previous-error)
1368 (define-key map "\M-{" 'compilation-previous-file)
1369 (define-key map "\M-}" 'compilation-next-file)
1370 ;; Set up the menu-bar
4282eba1
SM
1371 (define-key map [menu-bar compilation]
1372 (cons "Errors" compilation-menu-map))
a24770bc
RS
1373 map)
1374 "Keymap for `compilation-shell-minor-mode'.")
1375
60470fd2
SM
1376(defvar compilation-button-map
1377 (let ((map (make-sparse-keymap)))
1378 (define-key map [mouse-2] 'compile-goto-error)
0ac804df 1379 (define-key map [follow-link] 'mouse-face)
60470fd2
SM
1380 (define-key map "\C-m" 'compile-goto-error)
1381 map)
1382 "Keymap for compilation-message buttons.")
1383(fset 'compilation-button-map compilation-button-map)
1384
0b18a8f6 1385(defvar compilation-mode-map
4282eba1 1386 (let ((map (make-sparse-keymap)))
261b01c6
RS
1387 ;; Don't inherit from compilation-minor-mode-map,
1388 ;; because that introduces a menu bar item we don't want.
1389 ;; That confuses C-down-mouse-3.
5988691b 1390 (define-key map [mouse-2] 'compile-goto-error)
0ac804df 1391 (define-key map [follow-link] 'mouse-face)
5988691b
RS
1392 (define-key map "\C-c\C-c" 'compile-goto-error)
1393 (define-key map "\C-m" 'compile-goto-error)
1394 (define-key map "\C-c\C-k" 'kill-compilation)
1395 (define-key map "\M-n" 'compilation-next-error)
1396 (define-key map "\M-p" 'compilation-previous-error)
1397 (define-key map "\M-{" 'compilation-previous-file)
1398 (define-key map "\M-}" 'compilation-next-file)
70fec115
JL
1399 (define-key map "\t" 'compilation-next-error)
1400 (define-key map [backtab] 'compilation-previous-error)
5988691b 1401
0b18a8f6
RM
1402 (define-key map " " 'scroll-up)
1403 (define-key map "\^?" 'scroll-down)
221206e3 1404 (define-key map "\C-c\C-f" 'next-error-follow-minor-mode)
9ac57479 1405
e60476ca 1406 ;; Set up the menu-bar
5988691b
RS
1407 (let ((submap (make-sparse-keymap "Compile")))
1408 (define-key map [menu-bar compilation]
1409 (cons "Compile" submap))
1410 (set-keymap-parent submap compilation-menu-map))
4282eba1 1411 (define-key map [menu-bar compilation compilation-separator2]
e60476ca 1412 '("----" . nil))
9ac57479 1413 (define-key map [menu-bar compilation compilation-grep]
38805987
DN
1414 '(menu-item "Search Files (grep)..." grep
1415 :help "Run grep, with user-specified args, and collect output in a buffer"))
9ac57479 1416 (define-key map [menu-bar compilation compilation-recompile]
38805987
DN
1417 '(menu-item "Recompile" recompile
1418 :help "Re-compile the program including the current buffer"))
9ac57479 1419 (define-key map [menu-bar compilation compilation-compile]
38805987
DN
1420 '(menu-item "Compile..." compile
1421 :help "Compile the program including the current buffer. Default: run `make'"))
0b18a8f6
RM
1422 map)
1423 "Keymap for compilation log buffers.
4282eba1 1424`compilation-minor-mode-map' is a parent of this.")
55dfd2c4 1425
c45e48d2
JD
1426(defvar compilation-mode-tool-bar-map
1427 (if (display-graphic-p)
1428 (let ((map (butlast (copy-keymap tool-bar-map)))
1429 (help (last tool-bar-map))) ;; Keep Help last in tool bar
ddb1f2e3 1430 (tool-bar-local-item
c45e48d2
JD
1431 "left-arrow" 'previous-error-no-select 'previous-error-no-select map
1432 :rtl "right-arrow"
1433 :help "Goto previous error")
df1a5d7d
JD
1434 (tool-bar-local-item
1435 "right-arrow" 'next-error-no-select 'next-error-no-select map
1436 :rtl "left-arrow"
1437 :help "Goto next error")
ddb1f2e3 1438 (tool-bar-local-item
c45e48d2 1439 "cancel" 'kill-compilation 'kill-compilation map
5af370ab
JD
1440 :enable '(let ((buffer (compilation-find-buffer)))
1441 (get-buffer-process buffer))
c45e48d2 1442 :help "Stop compilation")
ddb1f2e3 1443 (tool-bar-local-item
c45e48d2
JD
1444 "refresh" 'recompile 'recompile map
1445 :help "Restart compilation")
1446 (append map help))))
1447
0a35bd79
RS
1448(put 'compilation-mode 'mode-class 'special)
1449
501cf428 1450;;;###autoload
d42c87ab 1451(defun compilation-mode (&optional name-of-mode)
55dfd2c4
RS
1452 "Major mode for compilation log buffers.
1453\\<compilation-mode-map>To visit the source for a line-numbered error,
d3cb357b 1454move point to the error message line and type \\[compile-goto-error].
7c163413
RM
1455To kill the compilation, type \\[kill-compilation].
1456
2894bd96 1457Runs `compilation-mode-hook' with `run-mode-hooks' (which see).
8ff2ed52
RS
1458
1459\\{compilation-mode-map}"
55dfd2c4 1460 (interactive)
9af0d309 1461 (kill-all-local-variables)
55dfd2c4 1462 (use-local-map compilation-mode-map)
c45e48d2 1463 (set (make-local-variable 'tool-bar-map) compilation-mode-tool-bar-map)
0b18a8f6 1464 (setq major-mode 'compilation-mode
d42c87ab 1465 mode-name (or name-of-mode "Compilation"))
7837c247
SM
1466 (set (make-local-variable 'page-delimiter)
1467 compilation-page-delimiter)
0b18a8f6 1468 (compilation-setup)
bd8c6db5 1469 (setq buffer-read-only t)
7837c247
SM
1470 (run-mode-hooks 'compilation-mode-hook))
1471
1472(defmacro define-compilation-mode (mode name doc &rest body)
1473 "This is like `define-derived-mode' without the PARENT argument.
1474The parent is always `compilation-mode' and the customizable `compilation-...'
bac3a1c9
JL
1475variables are also set from the name of the mode you have chosen,
1476by replacing the first word, e.g `compilation-scroll-output' from
1477`grep-scroll-output' if that variable exists."
7837c247
SM
1478 (let ((mode-name (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
1479 `(define-derived-mode ,mode compilation-mode ,name
1480 ,doc
1481 ,@(mapcar (lambda (v)
1482 (setq v (cons v
1483 (intern-soft (replace-regexp-in-string
1484 "^compilation" mode-name
1485 (symbol-name v)))))
1486 (and (cdr v)
1487 (or (boundp (cdr v))
1488 (if (boundp 'byte-compile-bound-variables)
1489 (memq (cdr v) byte-compile-bound-variables)))
1490 `(set (make-local-variable ',(car v)) ,(cdr v))))
1491 '(compilation-buffer-name-function
1492 compilation-directory-matcher
1493 compilation-error
1494 compilation-error-regexp-alist
1495 compilation-error-regexp-alist-alist
1496 compilation-error-screen-columns
1497 compilation-finish-function
1498 compilation-finish-functions
1499 compilation-first-column
1500 compilation-mode-font-lock-keywords
1501 compilation-page-delimiter
1502 compilation-parse-errors-filename-function
1503 compilation-process-setup-function
1504 compilation-scroll-output
1505 compilation-search-path
1506 compilation-skip-threshold
1507 compilation-window-height))
1508 ,@body)))
0b18a8f6 1509
58856335 1510(defun compilation-revert-buffer (ignore-auto noconfirm)
9ed2ab9f
RS
1511 (if buffer-file-name
1512 (let (revert-buffer-function)
9ac57479 1513 (revert-buffer ignore-auto noconfirm))
9ed2ab9f 1514 (if (or noconfirm (yes-or-no-p (format "Restart compilation? ")))
7837c247
SM
1515 (apply 'compilation-start compilation-arguments))))
1516
c536bb39
SM
1517(defvar compilation-current-error nil
1518 "Marker to the location from where the next error will be found.
1519The global commands next/previous/first-error/goto-error use this.")
51c8ad03 1520
9b7b51a2
SM
1521(defvar compilation-messages-start nil
1522 "Buffer position of the beginning of the compilation messages.
1523If nil, use the beginning of buffer.")
1524
7837c247
SM
1525;; A function name can't be a hook, must be something with a value.
1526(defconst compilation-turn-on-font-lock 'turn-on-font-lock)
58856335 1527
7837c247 1528(defun compilation-setup (&optional minor)
6f5b7627
SM
1529 "Prepare the buffer for the compilation parsing commands to work.
1530Optional argument MINOR indicates this is called from
1531`compilation-minor-mode'."
51c8ad03 1532 (make-local-variable 'compilation-current-error)
9b7b51a2 1533 (make-local-variable 'compilation-messages-start)
18aac618 1534 (make-local-variable 'compilation-error-screen-columns)
b3a7f48f 1535 (make-local-variable 'overlay-arrow-position)
8b71e4d1 1536 (set (make-local-variable 'overlay-arrow-string) "")
6a1cdc5b
JL
1537 (setq next-error-overlay-arrow-position nil)
1538 (add-hook 'kill-buffer-hook
1539 (lambda () (setq next-error-overlay-arrow-position nil)) nil t)
9b7b51a2
SM
1540 ;; Note that compilation-next-error-function is for interfacing
1541 ;; with the next-error function in simple.el, and it's only
1542 ;; coincidentally named similarly to compilation-next-error.
1543 (setq next-error-function 'compilation-next-error-function)
00d6fd04
MA
1544 (set (make-local-variable 'comint-file-name-prefix)
1545 (or (file-remote-p default-directory) ""))
7837c247
SM
1546 (set (make-local-variable 'font-lock-extra-managed-props)
1547 '(directory message help-echo mouse-face debug))
1548 (set (make-local-variable 'compilation-locs)
1549 (make-hash-table :test 'equal :weakness 'value))
6f5b7627 1550 ;; lazy-lock would never find the message unless it's scrolled to.
c536bb39
SM
1551 ;; jit-lock might fontify some things too late.
1552 (set (make-local-variable 'font-lock-support-mode) nil)
7837c247 1553 (set (make-local-variable 'font-lock-maximum-size) nil)
963b2040
CY
1554 (if minor
1555 (let ((fld font-lock-defaults))
f6164cdd 1556 (font-lock-add-keywords nil (compilation-mode-font-lock-keywords))
f6164cdd
DP
1557 (if font-lock-mode
1558 (if fld
1559 (font-lock-fontify-buffer)
1560 (font-lock-change-mode)
1561 (turn-on-font-lock))
963b2040 1562 (turn-on-font-lock)))
49d11c49 1563 (setq font-lock-defaults '(compilation-mode-font-lock-keywords t))
963b2040
CY
1564 ;; maybe defer font-lock till after derived mode is set up
1565 (run-mode-hooks 'compilation-turn-on-font-lock)))
0b18a8f6 1566
7052680b 1567;;;###autoload
4282eba1 1568(define-minor-mode compilation-shell-minor-mode
7052680b
RS
1569 "Toggle compilation shell minor mode.
1570With arg, turn compilation mode on if and only if arg is positive.
4282eba1
SM
1571In this minor mode, all the error-parsing commands of the
1572Compilation major mode are available but bound to keys that don't
1573collide with Shell mode. See `compilation-mode'.
7052680b 1574Turning the mode on runs the normal hook `compilation-shell-minor-mode-hook'."
7837c247 1575 nil " Shell-Compile"
d408fed8 1576 :group 'compilation
7837c247
SM
1577 (if compilation-shell-minor-mode
1578 (compilation-setup t)
1579 (font-lock-remove-keywords nil (compilation-mode-font-lock-keywords))
1580 (font-lock-fontify-buffer)))
7052680b 1581
d6bd8dca 1582;;;###autoload
4282eba1 1583(define-minor-mode compilation-minor-mode
0b18a8f6
RM
1584 "Toggle compilation minor mode.
1585With arg, turn compilation mode on if and only if arg is positive.
4282eba1
SM
1586In this minor mode, all the error-parsing commands of the
1587Compilation major mode are available. See `compilation-mode'.
fee3f63a 1588Turning the mode on runs the normal hook `compilation-minor-mode-hook'."
7837c247 1589 nil " Compilation"
d408fed8 1590 :group 'compilation
7837c247
SM
1591 (if compilation-minor-mode
1592 (compilation-setup t)
1593 (font-lock-remove-keywords nil (compilation-mode-font-lock-keywords))
1594 (font-lock-fontify-buffer)))
55dfd2c4 1595
fd5e58d7 1596(defun compilation-handle-exit (process-status exit-status msg)
f441be5b 1597 "Write MSG in the current buffer and hack its `mode-line-process'."
d42c87ab 1598 (let ((inhibit-read-only t)
fd5e58d7
RM
1599 (status (if compilation-exit-message-function
1600 (funcall compilation-exit-message-function
1601 process-status exit-status msg)
1602 (cons msg exit-status)))
1603 (omax (point-max))
c96e025a
GM
1604 (opoint (point))
1605 (cur-buffer (current-buffer)))
b3a7f48f 1606 ;; Record where we put the message, so we can ignore it later on.
fd5e58d7
RM
1607 (goto-char omax)
1608 (insert ?\n mode-name " " (car status))
0eac1faa 1609 (if (and (numberp compilation-window-height)
7837c247
SM
1610 (zerop compilation-window-height))
1611 (message "%s" (cdr status)))
01c50447
RS
1612 (if (bolp)
1613 (forward-char -1))
fd5e58d7 1614 (insert " at " (substring (current-time-string) 0 19))
01c50447 1615 (goto-char (point-max))
47092737
RS
1616 ;; Prevent that message from being recognized as a compilation error.
1617 (add-text-properties omax (point)
1618 (append '(compilation-handle-exit t) nil))
a8bdd228
DN
1619 (setq mode-line-process
1620 (let ((out-string (format ":%s [%s]" process-status (cdr status)))
a46b95a8
JL
1621 (msg (format "%s %s" mode-name
1622 (replace-regexp-in-string "\n?$" "" (car status)))))
1623 (message "%s" msg)
1624 (propertize out-string
1625 'help-echo msg 'face (if (> exit-status 0)
1626 'compilation-error
1627 'compilation-info))))
fd5e58d7
RM
1628 ;; Force mode line redisplay soon.
1629 (force-mode-line-update)
1630 (if (and opoint (< opoint omax))
1631 (goto-char opoint))
a5f1c37e
RS
1632 (with-no-warnings
1633 (if compilation-finish-function
c96e025a
GM
1634 (funcall compilation-finish-function cur-buffer msg)))
1635 (run-hook-with-args 'compilation-finish-functions cur-buffer msg)))
fd5e58d7 1636
55dfd2c4 1637;; Called when compilation process changes state.
55dfd2c4 1638(defun compilation-sentinel (proc msg)
d3cb357b 1639 "Sentinel for compilation buffers."
b3a7f48f
DP
1640 (if (memq (process-status proc) '(exit signal))
1641 (let ((buffer (process-buffer proc)))
1642 (if (null (buffer-name buffer))
1643 ;; buffer killed
1644 (set-process-buffer proc nil)
1645 (with-current-buffer buffer
1646 ;; Write something in the compilation buffer
1647 ;; and hack its mode line.
1648 (compilation-handle-exit (process-status proc)
1649 (process-exit-status proc)
1650 msg)
1651 ;; Since the buffer and mode line will show that the
1652 ;; process is dead, we can delete it now. Otherwise it
1653 ;; will stay around until M-x list-processes.
1654 (delete-process proc)))
1655 (setq compilation-in-progress (delq proc compilation-in-progress)))))
55dfd2c4 1656
ad62b7f1
RM
1657(defun compilation-filter (proc string)
1658 "Process filter for compilation buffers.
4f6e4ad6 1659Just inserts the text, but uses `insert-before-markers'."
991c70f8 1660 (if (buffer-name (process-buffer proc))
c536bb39
SM
1661 (with-current-buffer (process-buffer proc)
1662 (let ((inhibit-read-only t))
991c70f8
RS
1663 (save-excursion
1664 (goto-char (process-mark proc))
1665 (insert-before-markers string)
7837c247 1666 (run-hooks 'compilation-filter-hook))))))
b5bb472e 1667
5d9f0de2
KS
1668;;; test if a buffer is a compilation buffer, assuming we're in the buffer
1669(defsubst compilation-buffer-internal-p ()
1670 "Test if inside a compilation buffer."
1671 (local-variable-p 'compilation-locs))
1672
1673;;; test if a buffer is a compilation buffer, using compilation-buffer-internal-p
51ba27e7 1674(defsubst compilation-buffer-p (buffer)
5d9f0de2
KS
1675 "Test if BUFFER is a compilation buffer."
1676 (with-current-buffer buffer
1677 (compilation-buffer-internal-p)))
7837c247 1678
060d5dc1
CY
1679(defmacro compilation-loop (< property-change 1+ error limit)
1680 `(let (opt)
1681 (while (,< n 0)
1682 (setq opt pt)
1683 (or (setq pt (,property-change pt 'message))
1684 ;; Handle the case where where the first error message is
1685 ;; at the start of the buffer, and n < 0.
1686 (if (or (eq (get-text-property ,limit 'message)
1687 (get-text-property opt 'message))
1688 (eq pt opt))
1689 (error ,error compilation-error)
1690 (setq pt ,limit)))
1691 ;; prop 'message usually has 2 changes, on and off, so
1692 ;; re-search if off
1693 (or (setq msg (get-text-property pt 'message))
1694 (if (setq pt (,property-change pt 'message nil ,limit))
1695 (setq msg (get-text-property pt 'message)))
1696 (error ,error compilation-error))
1697 (or (< (cadr msg) compilation-skip-threshold)
1698 (if different-file
1699 (eq (prog1 last (setq last (nth 2 (car msg))))
1700 last))
1701 (if compilation-skip-visited
b84acff6 1702 (nthcdr 5 (car msg)))
060d5dc1
CY
1703 (if compilation-skip-to-next-location
1704 (eq (car msg) loc))
1705 ;; count this message only if none of the above are true
1706 (setq n (,1+ n))))))
7837c247 1707
51c8ad03 1708(defun compilation-next-error (n &optional different-file pt)
646bd331 1709 "Move point to the next error in the compilation buffer.
d0048c60 1710This function does NOT find the source line like \\[next-error].
851231e9
DL
1711Prefix arg N says how many error messages to move forwards (or
1712backwards, if negative).
d0048c60
EZ
1713Optional arg DIFFERENT-FILE, if non-nil, means find next error for a
1714file that is different from the current one.
1715Optional arg PT, if non-nil, specifies the value of point to start
1716looking for the next message."
646bd331
RM
1717 (interactive "p")
1718 (or (compilation-buffer-p (current-buffer))
851231e9 1719 (error "Not in a compilation buffer"))
51c8ad03 1720 (or pt (setq pt (point)))
51c8ad03 1721 (let* ((msg (get-text-property pt 'message))
250962b3 1722 ;; `loc' is used by the compilation-loop macro.
51c8ad03
DP
1723 (loc (car msg))
1724 last)
7837c247
SM
1725 (if (zerop n)
1726 (unless (or msg ; find message near here
c536bb39
SM
1727 (setq msg (get-text-property (max (1- pt) (point-min))
1728 'message)))
7837c247 1729 (setq pt (previous-single-property-change pt 'message nil
c536bb39 1730 (line-beginning-position)))
b3a7f48f 1731 (unless (setq msg (get-text-property (max (1- pt) (point-min)) 'message))
7837c247 1732 (setq pt (next-single-property-change pt 'message nil
c536bb39 1733 (line-end-position)))
b3a7f48f
DP
1734 (or (setq msg (get-text-property pt 'message))
1735 (setq pt (point)))))
7837c247 1736 (setq last (nth 2 (car msg)))
51c8ad03
DP
1737 (if (>= n 0)
1738 (compilation-loop > next-single-property-change 1-
1739 (if (get-buffer-process (current-buffer))
1740 "No more %ss yet"
060d5dc1
CY
1741 "Moved past last %s")
1742 (point-max))
c536bb39
SM
1743 ;; Don't move "back" to message at or before point.
1744 ;; Pass an explicit (point-min) to make sure pt is non-nil.
1745 (setq pt (previous-single-property-change pt 'message nil (point-min)))
51c8ad03 1746 (compilation-loop < previous-single-property-change 1+
060d5dc1 1747 "Moved back before first %s" (point-min))))
7837c247
SM
1748 (goto-char pt)
1749 (or msg
1750 (error "No %s here" compilation-error))))
646bd331
RM
1751
1752(defun compilation-previous-error (n)
1753 "Move point to the previous error in the compilation buffer.
851231e9
DL
1754Prefix arg N says how many error messages to move backwards (or
1755forwards, if negative).
7837c247 1756Does NOT find the source line like \\[previous-error]."
646bd331
RM
1757 (interactive "p")
1758 (compilation-next-error (- n)))
1759
b5bb472e 1760(defun compilation-next-file (n)
24299582
DP
1761 "Move point to the next error for a different file than the current one.
1762Prefix arg N says how many files to move forwards (or backwards, if negative)."
b5bb472e 1763 (interactive "p")
7837c247 1764 (compilation-next-error n t))
b5bb472e
RM
1765
1766(defun compilation-previous-file (n)
24299582
DP
1767 "Move point to the previous error for a different file than the current one.
1768Prefix arg N says how many files to move backwards (or forwards, if negative)."
b5bb472e
RM
1769 (interactive "p")
1770 (compilation-next-file (- n)))
1771
55dfd2c4 1772(defun kill-compilation ()
b765ba64 1773 "Kill the process made by the \\[compile] or \\[grep] commands."
55dfd2c4 1774 (interactive)
d3cb357b 1775 (let ((buffer (compilation-find-buffer)))
55dfd2c4 1776 (if (get-buffer-process buffer)
d3cb357b 1777 (interrupt-process (get-buffer-process buffer))
bac3a1c9 1778 (error "The %s process is not running" (downcase mode-name)))))
d3cb357b 1779
9da85ee5 1780(defalias 'compile-mouse-goto-error 'compile-goto-error)
c536bb39 1781
9da85ee5
SM
1782(defun compile-goto-error (&optional event)
1783 "Visit the source for the error message at point.
7837c247 1784Use this command in a compilation log buffer. Sets the mark at point there."
9da85ee5 1785 (interactive (list last-input-event))
a6cd3f65 1786 (if event (posn-set-point (event-end event)))
d3cb357b 1787 (or (compilation-buffer-p (current-buffer))
851231e9 1788 (error "Not in a compilation buffer"))
b3a7f48f
DP
1789 (if (get-text-property (point) 'directory)
1790 (dired-other-window (car (get-text-property (point) 'directory)))
1791 (push-mark)
1792 (setq compilation-current-error (point))
942c40e3 1793 (next-error-internal)))
55dfd2c4 1794
749354f0 1795(defun compilation-find-buffer (&optional avoid-current)
7d1dad0c 1796 "Return a compilation buffer.
0dad3dfe
MR
1797If AVOID-CURRENT is nil, and the current buffer is a compilation buffer,
1798return it. If AVOID-CURRENT is non-nil, return the current buffer only
1799as a last resort."
1800 (if (and (compilation-buffer-internal-p) (not avoid-current))
7d1dad0c
RS
1801 (current-buffer)
1802 (next-error-find-buffer avoid-current 'compilation-buffer-internal-p)))
d3cb357b
RM
1803
1804;;;###autoload
5d9f0de2 1805(defun compilation-next-error-function (n &optional reset)
a5f1c37e
RS
1806 "Advance to the next error message and visit the file where the error was.
1807This is the value of `next-error-function' in Compilation buffers."
7837c247 1808 (interactive "p")
5d9f0de2
KS
1809 (when reset
1810 (setq compilation-current-error nil))
7837c247 1811 (let* ((columns compilation-error-screen-columns) ; buffer's local value
b84acff6 1812 (last 1) timestamp
51c8ad03 1813 (loc (compilation-next-error (or n 1) nil
9b7b51a2
SM
1814 (or compilation-current-error
1815 compilation-messages-start
1816 (point-min))))
7837c247
SM
1817 (end-loc (nth 2 loc))
1818 (marker (point-marker)))
51c8ad03 1819 (setq compilation-current-error (point-marker)
b3a7f48f
DP
1820 overlay-arrow-position
1821 (if (bolp)
1822 compilation-current-error
9b7b51a2 1823 (copy-marker (line-beginning-position)))
51c8ad03 1824 loc (car loc))
b84acff6
SS
1825 ;; If loc contains no marker, no error in that file has been visited.
1826 ;; If the marker is invalid the buffer has been killed.
1827 ;; If the file is newer than the timestamp, it has been modified
1828 ;; (`omake -P' polls filesystem for changes and recompiles when needed
1829 ;; in the same process and buffer).
1830 ;; So, recalculate all markers for that file.
1831 (unless (and (nth 3 loc) (marker-buffer (nth 3 loc))
77041513
SM
1832 ;; There may be no timestamp info if the loc is a `fake-loc'.
1833 ;; So we skip the time-check here, although we should maybe
1834 ;; change `compilation-fake-loc' to add timestamp info.
1835 (or (null (nth 4 loc))
1836 (equal (nth 4 loc)
1837 (setq timestamp
1838 (with-current-buffer
1839 (marker-buffer (nth 3 loc))
1840 (visited-file-modtime))))))
c536bb39 1841 (with-current-buffer (compilation-find-file marker (caar (nth 2 loc))
7957baea 1842 (cadr (car (nth 2 loc))))
7837c247
SM
1843 (save-restriction
1844 (widen)
c536bb39 1845 (goto-char (point-min))
7837c247
SM
1846 ;; Treat file's found lines in forward order, 1 by 1.
1847 (dolist (line (reverse (cddr (nth 2 loc))))
1848 (when (car line) ; else this is a filename w/o a line#
1849 (beginning-of-line (- (car line) last -1))
1850 (setq last (car line)))
1851 ;; Treat line's found columns and store/update a marker for each.
1852 (dolist (col (cdr line))
1853 (if (car col)
1854 (if (eq (car col) -1) ; special case for range end
1855 (end-of-line)
9c8e6c85 1856 (compilation-move-to-column (car col) columns))
7837c247
SM
1857 (beginning-of-line)
1858 (skip-chars-forward " \t"))
eb6fb6e2 1859 (if (nth 3 col)
7837c247
SM
1860 (set-marker (nth 3 col) (point))
1861 (setcdr (nthcdr 2 col) `(,(point-marker)))))))))
1862 (compilation-goto-locus marker (nth 3 loc) (nth 3 end-loc))
b84acff6
SS
1863 (setcdr (nthcdr 3 loc) (list timestamp))
1864 (setcdr (nthcdr 4 loc) t))) ; Set this one as visited.
7837c247 1865
e3bef839
SM
1866(defvar compilation-gcpro nil
1867 "Internal variable used to keep some values from being GC'd.")
1868(make-variable-buffer-local 'compilation-gcpro)
1869
eb6fb6e2
DP
1870(defun compilation-fake-loc (marker file &optional line col)
1871 "Preassociate MARKER with FILE.
dbd97672 1872FILE should be ABSOLUTE-FILENAME or (RELATIVE-FILENAME . DIRNAME).
eb6fb6e2
DP
1873This is useful when you compile temporary files, but want
1874automatic translation of the messages to the real buffer from
1875which the temporary file came. This only works if done before a
1876message about FILE appears!
1877
1878Optional args LINE and COL default to 1 and beginning of
1879indentation respectively. The marker is expected to reflect
1880this. In the simplest case the marker points to the first line
1881of the region that was saved to the temp file.
1882
1883If you concatenate several regions into the temp file (e.g. a
1884header with variable assignments and a code region), you must
1885call this several times, once each for the last line of one
1886region and the first line of the next region."
1887 (or (consp file) (setq file (list file)))
dbd97672 1888 (setq file (compilation-get-file-structure file))
e3bef839 1889 ;; Between the current call to compilation-fake-loc and the first occurrence
77041513 1890 ;; of an error message referring to `file', the data is only kept in the
e3bef839
SM
1891 ;; weak hash-table compilation-locs, so we need to prevent this entry
1892 ;; in compilation-locs from being GC'd away. --Stef
1893 (push file compilation-gcpro)
eb6fb6e2
DP
1894 (let ((loc (compilation-assq (or line 1) (cdr file))))
1895 (setq loc (compilation-assq col loc))
1896 (if (cdr loc)
1897 (setcdr (cddr loc) (list marker))
dbd97672 1898 (setcdr loc (list line file marker)))
eb6fb6e2
DP
1899 loc))
1900
8b71e4d1
NR
1901(defcustom compilation-context-lines nil
1902 "Display this many lines of leading context before the current message.
1903If nil and the left fringe is displayed, don't scroll the
1904compilation output window; an arrow in the left fringe points to
1905the current message. If nil and there is no left fringe, the message
1906displays at the top of the window; there is no arrow."
a3a9c080 1907 :type '(choice integer (const :tag "No window scrolling" nil))
f6164cdd 1908 :group 'compilation
bf247b6e 1909 :version "22.1")
7837c247
SM
1910
1911(defsubst compilation-set-window (w mk)
6f5b7627 1912 "Align the compilation output window W with marker MK near top."
a3a9c080
JL
1913 (if (integerp compilation-context-lines)
1914 (set-window-start w (save-excursion
8b71e4d1
NR
1915 (goto-char mk)
1916 (beginning-of-line
1917 (- 1 compilation-context-lines))
1918 (point)))
3c9e7f42
RS
1919 ;; If there is no left fringe.
1920 (if (equal (car (window-fringes)) 0)
8b71e4d1
NR
1921 (set-window-start w (save-excursion
1922 (goto-char mk)
1923 (beginning-of-line 1)
1924 (point)))))
1925 (set-window-point w mk))
7837c247 1926
0ea50e43
RS
1927(defvar next-error-highlight-timer)
1928
7837c247 1929(defun compilation-goto-locus (msg mk end-mk)
6f5b7627 1930 "Jump to an error corresponding to MSG at MK.
9dc3a46a
JL
1931All arguments are markers. If END-MK is non-nil, mark is set there
1932and overlay is highlighted between MK and END-MK."
eaa3cac5 1933 ;; Show compilation buffer in other window, scrolled to this error.
e5456e73
SM
1934 (let* ((from-compilation-buffer (eq (window-buffer (selected-window))
1935 (marker-buffer msg)))
1936 ;; Use an existing window if it is in a visible frame.
7bbbd31f 1937 (pre-existing (get-buffer-window (marker-buffer msg) 0))
e5456e73
SM
1938 (w (if (and from-compilation-buffer pre-existing)
1939 ;; Calling display-buffer here may end up (partly) hiding
1940 ;; the error location if the two buffers are in two
1941 ;; different frames. So don't do it if it's not necessary.
1942 pre-existing
1943 (let ((display-buffer-reuse-frames t)
1944 (pop-up-windows t))
1945 ;; Pop up a window.
1946 (display-buffer (marker-buffer msg)))))
7837c247
SM
1947 (highlight-regexp (with-current-buffer (marker-buffer msg)
1948 ;; also do this while we change buffer
1949 (compilation-set-window w msg)
9ac57479 1950 compilation-highlight-regexp)))
7bbbd31f
SM
1951 ;; Ideally, the window-size should be passed to `display-buffer' (via
1952 ;; something like special-display-buffer) so it's only used when
1953 ;; creating a new window.
1954 (unless pre-existing (compilation-set-window-height w))
9ac57479 1955
e5456e73
SM
1956 (if from-compilation-buffer
1957 ;; If the compilation buffer window was selected,
1958 ;; keep the compilation buffer in this window;
1959 ;; display the source in another window.
1960 (let ((pop-up-windows t))
1961 (pop-to-buffer (marker-buffer mk) 'other-window))
1962 (if (window-dedicated-p (selected-window))
1963 (pop-to-buffer (marker-buffer mk))
1964 (switch-to-buffer (marker-buffer mk))))
1965 ;; If narrowing gets in the way of going to the right place, widen.
1966 (unless (eq (goto-char mk) (point))
1967 (widen)
1968 (goto-char mk))
1969 (if end-mk
1970 (push-mark end-mk t)
1971 (if mark-active (setq mark-active)))
1972 ;; If hideshow got in the way of
1973 ;; seeing the right place, open permanently.
1974 (dolist (ov (overlays-at (point)))
1975 (when (eq 'hs (overlay-get ov 'invisible))
1976 (delete-overlay ov)
1977 (goto-char mk)))
1978
9dc3a46a 1979 (when highlight-regexp
073fcaf6
JL
1980 (if (timerp next-error-highlight-timer)
1981 (cancel-timer next-error-highlight-timer))
9ac57479 1982 (unless compilation-highlight-overlay
c536bb39
SM
1983 (setq compilation-highlight-overlay
1984 (make-overlay (point-min) (point-min)))
2beb6aa0 1985 (overlay-put compilation-highlight-overlay 'face 'next-error))
7837c247 1986 (with-current-buffer (marker-buffer mk)
9ac57479 1987 (save-excursion
9dc3a46a 1988 (if end-mk (goto-char end-mk) (end-of-line))
c536bb39 1989 (let ((end (point)))
9dc3a46a 1990 (if mk (goto-char mk) (beginning-of-line))
9ac57479 1991 (if (and (stringp highlight-regexp)
7837c247 1992 (re-search-forward highlight-regexp end t))
9ac57479
KS
1993 (progn
1994 (goto-char (match-beginning 0))
2beb6aa0
JL
1995 (move-overlay compilation-highlight-overlay
1996 (match-beginning 0) (match-end 0)
1997 (current-buffer)))
1998 (move-overlay compilation-highlight-overlay
1999 (point) end (current-buffer)))
63522e3a
RS
2000 (if (or (eq next-error-highlight t)
2001 (numberp next-error-highlight))
2002 ;; We want highlighting: delete overlay on next input.
2003 (add-hook 'pre-command-hook
2004 'compilation-goto-locus-delete-o)
2005 ;; We don't want highlighting: delete overlay now.
2006 (delete-overlay compilation-highlight-overlay))
2007 ;; We want highlighting for a limited time:
2008 ;; set up a timer to delete it.
2009 (when (numberp next-error-highlight)
2010 (setq next-error-highlight-timer
2011 (run-at-time next-error-highlight nil
2012 'compilation-goto-locus-delete-o)))))))
2beb6aa0 2013 (when (and (eq next-error-highlight 'fringe-arrow))
63522e3a 2014 ;; We want a fringe arrow (instead of highlighting).
6a1cdc5b
JL
2015 (setq next-error-overlay-arrow-position
2016 (copy-marker (line-beginning-position))))))
2017
63522e3a
RS
2018(defun compilation-goto-locus-delete-o ()
2019 (delete-overlay compilation-highlight-overlay)
2020 ;; Get rid of timer and hook that would try to do this again.
2021 (if (timerp next-error-highlight-timer)
2022 (cancel-timer next-error-highlight-timer))
2023 (remove-hook 'pre-command-hook
2024 'compilation-goto-locus-delete-o))
eaa3cac5 2025\f
7957baea 2026(defun compilation-find-file (marker filename directory &rest formats)
851231e9 2027 "Find a buffer for file FILENAME.
5099d512
EZ
2028If FILENAME is not found at all, ask the user where to find it.
2029Pop up the buffer containing MARKER and scroll to MARKER if we ask
2030the user where to find the file.
ffb4b7a1
SM
2031Search the directories in `compilation-search-path'.
2032A nil in `compilation-search-path' means to try the
7957baea 2033\"current\" directory, which is passed in DIRECTORY.
f441be5b
JB
2034If DIRECTORY is relative, it is combined with `default-directory'.
2035If DIRECTORY is nil, that means use `default-directory'.
5099d512
EZ
2036FORMATS, if given, is a list of formats to reformat FILENAME when
2037looking for it: for each element FMT in FORMATS, this function
2038attempts to find a file whose name is produced by (format FMT FILENAME)."
20c1daec 2039 (or formats (setq formats '("%s")))
b8fa0ffd
SM
2040 (let ((dirs compilation-search-path)
2041 (spec-dir (if directory
2042 (expand-file-name directory)
2043 default-directory))
2044 buffer thisdir fmts name)
2045 (if (file-name-absolute-p filename)
2046 ;; The file name is absolute. Use its explicit directory as
2047 ;; the first in the search path, and strip it from FILENAME.
2048 (setq filename (abbreviate-file-name (expand-file-name filename))
2049 dirs (cons (file-name-directory filename) dirs)
2050 filename (file-name-nondirectory filename)))
2051 ;; Now search the path.
2052 (while (and dirs (null buffer))
2053 (setq thisdir (or (car dirs) spec-dir)
2054 fmts formats)
2055 ;; For each directory, try each format string.
2056 (while (and fmts (null buffer))
2057 (setq name (expand-file-name (format (car fmts) filename) thisdir)
2058 buffer (and (file-exists-p name)
2059 (find-file-noselect name))
2060 fmts (cdr fmts)))
2061 (setq dirs (cdr dirs)))
f65b9df2
SM
2062 (while (null buffer) ;Repeat until the user selects an existing file.
2063 ;; The file doesn't exist. Ask the user where to find it.
2064 (save-excursion ;This save-excursion is probably not right.
2065 (let ((pop-up-windows t))
2066 (compilation-set-window (display-buffer (marker-buffer marker))
2067 marker)
2068 (let* ((name (read-file-name
2069 (format "Find this %s in (default %s): "
2070 compilation-error filename)
44038dc8
SM
2071 spec-dir filename t nil
2072 ;; The predicate below is fine when called from
2073 ;; minibuffer-complete-and-exit, but it's too
2074 ;; restrictive otherwise, since it also prevents the
2075 ;; user from completing "fo" to "foo/" when she
2076 ;; wants to enter "foo/bar".
f441be5b 2077 ;;
44038dc8
SM
2078 ;; Try to make sure the user can only select
2079 ;; a valid answer. This predicate may be ignored,
2080 ;; tho, so we still have to double-check afterwards.
2081 ;; TODO: We should probably fix read-file-name so
2082 ;; that it never ignores this predicate, even when
2083 ;; using popup dialog boxes.
2084 ;; (lambda (name)
2085 ;; (if (file-directory-p name)
2086 ;; (setq name (expand-file-name filename name)))
2087 ;; (file-exists-p name))
2088 ))
f65b9df2
SM
2089 (origname name))
2090 (cond
2091 ((not (file-exists-p name))
2092 (message "Cannot find file `%s'" name)
2093 (ding) (sit-for 2))
2094 ((and (file-directory-p name)
2095 (not (file-exists-p
2096 (setq name (expand-file-name filename name)))))
2097 (message "No `%s' in directory %s" filename origname)
2098 (ding) (sit-for 2))
2099 (t
2100 (setq buffer (find-file-noselect name))))))))
b8fa0ffd 2101 ;; Make intangible overlays tangible.
f65b9df2
SM
2102 ;; This is weird: it's not even clear which is the current buffer,
2103 ;; so the code below can't be expected to DTRT here. -- Stef
2104 (dolist (ov (overlays-in (point-min) (point-max)))
2105 (when (overlay-get ov 'intangible)
2106 (overlay-put ov 'intangible nil)))
b8fa0ffd 2107 buffer))
721cfafe 2108
dbd97672
DP
2109(defun compilation-get-file-structure (file &optional fmt)
2110 "Retrieve FILE's file-structure or create a new one.
7957baea
RS
2111FILE should be (FILENAME) or (RELATIVE-FILENAME . DIRNAME).
2112In the former case, FILENAME may be relative or absolute.
dbd97672 2113
7957baea 2114The file-structure looks like this:
34a9bf20 2115 (list (list FILENAME [DIR-FROM-PREV-MSG]) FMT LINE-STRUCT...)"
dbd97672
DP
2116 (or (gethash file compilation-locs)
2117 ;; File was not previously encountered, at least not in the form passed.
2118 ;; Let's normalize it and look again.
2119 (let ((filename (car file))
7957baea
RS
2120 ;; Get the specified directory from FILE.
2121 (spec-directory (if (cdr file)
2122 (file-truename (cdr file)))))
dbd97672
DP
2123
2124 ;; Check for a comint-file-name-prefix and prepend it if appropriate.
2125 ;; (This is very useful for compilation-minor-mode in an rlogin-mode
2126 ;; buffer.)
7957baea
RS
2127 (when (and (boundp 'comint-file-name-prefix)
2128 (not (equal comint-file-name-prefix "")))
2129 (if (file-name-absolute-p filename)
2130 (setq filename
2131 (concat comint-file-name-prefix filename))
2132 (if spec-directory
2133 (setq spec-directory
2134 (file-truename
2135 (concat comint-file-name-prefix spec-directory))))))
dbd97672
DP
2136
2137 ;; If compilation-parse-errors-filename-function is
2138 ;; defined, use it to process the filename.
2139 (when compilation-parse-errors-filename-function
2140 (setq filename
2141 (funcall compilation-parse-errors-filename-function
2142 filename)))
2143
2144 ;; Some compilers (e.g. Sun's java compiler, reportedly) produce bogus
2145 ;; file names like "./bar//foo.c" for file "bar/foo.c";
2146 ;; expand-file-name will collapse these into "/foo.c" and fail to find
2147 ;; the appropriate file. So we look for doubled slashes in the file
2148 ;; name and fix them.
2149 (setq filename (command-line-normalize-file-name filename))
2150
dbd97672
DP
2151 ;; Store it for the possibly unnormalized name
2152 (puthash file
2153 ;; Retrieve or create file-structure for normalized name
e68b1841
GM
2154 ;; The gethash used to not use spec-directory, but
2155 ;; this leads to errors when files in different
2156 ;; directories have the same name:
2157 ;; http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00463.html
2158 (or (gethash (cons filename spec-directory) compilation-locs)
34a9bf20 2159 (puthash (cons filename spec-directory)
7957baea
RS
2160 (list (list filename spec-directory) fmt)
2161 compilation-locs))
dbd97672 2162 compilation-locs))))
51501e54 2163
7837c247 2164(add-to-list 'debug-ignored-errors "^No more [-a-z ]+s yet$")
f1ed9461 2165
c536bb39
SM
2166;;; Compatibility with the old compile.el.
2167
2168(defun compile-buffer-substring (n) (if n (match-string n)))
2169
2170(defun compilation-compat-error-properties (err)
6f5b7627 2171 "Map old-style error ERR to new-style message."
efb0e677
SM
2172 ;; Old-style structure is (MARKER (FILE DIR) LINE COL) or
2173 ;; (MARKER . MARKER).
2174 (let ((dst (cdr err)))
2175 (if (markerp dst)
2176 ;; Must start with a face, for font-lock.
2177 `(face nil
2178 message ,(list (list nil nil nil dst) 2)
2179 help-echo "mouse-2: visit the source location"
2180 keymap compilation-button-map
2181 mouse-face highlight)
2182 ;; Too difficult to do it by hand: dispatch to the normal code.
2183 (let* ((file (pop dst))
2184 (line (pop dst))
2185 (col (pop dst))
2186 (filename (pop file))
2187 (dirname (pop file))
2188 (fmt (pop file)))
2189 (compilation-internal-error-properties
2190 (cons filename dirname) line nil col nil 2 fmt)))))
c536bb39
SM
2191
2192(defun compilation-compat-parse-errors (limit)
2193 (when compilation-parse-errors-function
2194 ;; FIXME: We should remove the rest of the compilation keywords
2195 ;; but we can't do that from here because font-lock is using
2196 ;; the value right now. --stef
2197 (save-excursion
2198 (setq compilation-error-list nil)
2199 ;; Reset compilation-parsing-end each time because font-lock
2200 ;; might force us the re-parse many times (typically because
2201 ;; some code adds some text-property to the output that we
2202 ;; already parsed). You might say "why reparse", well:
2203 ;; because font-lock has just removed the `message' property so
2204 ;; have to do it all over again.
2205 (if compilation-parsing-end
2206 (set-marker compilation-parsing-end (point))
2207 (setq compilation-parsing-end (point-marker)))
2208 (condition-case nil
2209 ;; Ignore any error: we're calling this function earlier than
2210 ;; in the old compile.el so things might not all be setup yet.
2211 (funcall compilation-parse-errors-function limit nil)
2212 (error nil))
2213 (dolist (err (if (listp compilation-error-list) compilation-error-list))
2214 (let* ((src (car err))
2215 (dst (cdr err))
2216 (loc (cond ((markerp dst) (list nil nil nil dst))
2217 ((consp dst)
2218 (list (nth 2 dst) (nth 1 dst)
2219 (cons (cdar dst) (caar dst)))))))
2220 (when loc
2221 (goto-char src)
2222 ;; (put-text-property src (line-end-position) 'font-lock-face 'font-lock-warning-face)
2223 (put-text-property src (line-end-position)
2224 'message (list loc 2)))))))
2225 (goto-char limit)
2226 nil)
2227
9b7b51a2 2228;; Beware: this is not only compatiblity code. New code stil uses it. --Stef
c536bb39
SM
2229(defun compilation-forget-errors ()
2230 ;; In case we hit the same file/line specs, we want to recompute a new
2231 ;; marker for them, so flush our cache.
b3a7f48f 2232 (setq compilation-locs (make-hash-table :test 'equal :weakness 'value))
e3bef839 2233 (setq compilation-gcpro nil)
c536bb39
SM
2234 ;; FIXME: the old code reset the directory-stack, so maybe we should
2235 ;; put a `directory change' marker of some sort, but where? -stef
b3a7f48f 2236 ;;
c536bb39
SM
2237 ;; FIXME: The old code moved compilation-current-error (which was
2238 ;; virtually represented by a mix of compilation-parsing-end and
2239 ;; compilation-error-list) to point-min, but that was only meaningful for
2240 ;; the internal uses of compilation-forget-errors: all calls from external
2241 ;; packages seem to be followed by a move of compilation-parsing-end to
b956d64f 2242 ;; something equivalent to point-max. So we heuristically move
c536bb39 2243 ;; compilation-current-error to point-max (since the external package
b956d64f 2244 ;; won't know that it should do it). --Stef
9b7b51a2
SM
2245 (setq compilation-current-error nil)
2246 (let* ((proc (get-buffer-process (current-buffer)))
2247 (mark (if proc (process-mark proc)))
2248 (pos (or mark (point-max))))
2249 (setq compilation-messages-start
2250 ;; In the future, ignore the text already present in the buffer.
2251 ;; Since many process filter functions insert before markers,
2252 ;; we need to put ours just before the insertion point rather
2253 ;; than at the insertion point. If that's not possible, then
2254 ;; don't use a marker. --Stef
b956d64f
SM
2255 (if (> pos (point-min)) (copy-marker (1- pos)) pos)))
2256 ;; Again, since this command is used in buffers that contain several
2257 ;; compilations, to set the beginning of "this compilation", it's a good
2258 ;; place to reset compilation-auto-jump-to-next.
2259 (set (make-local-variable 'compilation-auto-jump-to-next)
78dc87a2
JL
2260 (or compilation-auto-jump-to-first-error
2261 (eq compilation-scroll-output 'first-error))))
c536bb39 2262
0c9a01ff
MY
2263;;;###autoload
2264(add-to-list 'auto-mode-alist '("\\.gcov\\'" . compilation-mode))
2265
4746118a 2266(provide 'compile)
fad160d5 2267
822001db 2268;; arch-tag: 12465727-7382-4f72-b234-79855a00dd8c
fad160d5 2269;;; compile.el ends here