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