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