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