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