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