(c-electric-paren): Call old-blink-paren only for close-paren.
[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,
034babe1 4;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3a801d0c 5
7837c247
SM
6;; Authors: Roland McGrath <roland@gnu.org>,
7;; Daniel Pfeiffer <occitan@esperanto.org>
d1c7011d 8;; Maintainer: FSF
e9571d2a 9;; Keywords: tools, processes
d1c7011d 10
55dfd2c4
RS
11;; This file is part of GNU Emacs.
12
29add8b9
RM
13;; GNU Emacs is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation; either version 2, or (at your option)
16;; any later version.
17
55dfd2c4 18;; GNU Emacs is distributed in the hope that it will be useful,
29add8b9
RM
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
b578f267 24;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
25;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26;; Boston, MA 02110-1301, USA.
55dfd2c4 27
5cc57841
ER
28;;; Commentary:
29
7837c247
SM
30;; This package provides the compile facilities documented in the Emacs user's
31;; manual.
5cc57841 32
c536bb39 33;; This mode uses some complex data-structures:
7837c247 34
c536bb39 35;; LOC (or location) is a list of (COLUMN LINE FILE-STRUCTURE)
7837c247
SM
36
37;; COLUMN and LINE are numbers parsed from an error message. COLUMN and maybe
38;; LINE will be nil for a message that doesn't contain them. Then the
39;; location refers to a indented beginning of line or beginning of file.
40;; Once any location in some file has been jumped to, the list is extended to
41;; (COLUMN LINE FILE-STRUCTURE MARKER . VISITED) for all LOCs pertaining to
42;; that file.
43;; MARKER initially points to LINE and COLUMN in a buffer visiting that file.
44;; Being a marker it sticks to some text, when the buffer grows or shrinks
45;; before that point. VISITED is t if we have jumped there, else nil.
46
c536bb39
SM
47;; FILE-STRUCTURE is a list of
48;; ((FILENAME . DIRECTORY) FORMATS (LINE LOC ...) ...)
7837c247
SM
49
50;; FILENAME is a string parsed from an error message. DIRECTORY is a string
51;; obtained by following directory change messages. DIRECTORY will be nil for
52;; an absolute filename. FORMATS is a list of formats to apply to FILENAME if
53;; a file of that name can't be found.
54;; The rest of the list is an alist of elements with LINE as key. The keys
55;; are either nil or line numbers. If present, nil comes first, followed by
56;; the numbers in decreasing order. The LOCs for each line are again an alist
57;; ordered the same way. Note that the whole file structure is referenced in
58;; every LOC.
59
c536bb39 60;; MESSAGE is a list of (LOC TYPE END-LOC)
7837c247
SM
61
62;; TYPE is 0 for info or 1 for warning if the message matcher identified it as
63;; such, 2 otherwise (for a real error). END-LOC is a LOC pointing to the
64;; other end, if the parsed message contained a range. If the end of the
65;; range didn't specify a COLUMN, it defaults to -1, meaning end of line.
66;; These are the value of the `message' text-properties in the compilation
67;; buffer.
68
24299582
DP
69;;; Code:
70
583a15bb
SM
71(eval-when-compile (require 'cl))
72
e623859c
JB
73(defvar font-lock-extra-managed-props)
74(defvar font-lock-keywords)
75(defvar font-lock-maximum-size)
76(defvar font-lock-support-mode)
77
78
c5049fa0
RS
79(defgroup compilation nil
80 "Run compiler as inferior of Emacs, parse error messages."
81 :group 'tools
82 :group 'processes)
83
84
7c163413 85;;;###autoload
c5049fa0 86(defcustom compilation-mode-hook nil
2894bd96 87 "*List of hook functions run by `compilation-mode' (see `run-mode-hooks')."
c5049fa0
RS
88 :type 'hook
89 :group 'compilation)
7c163413
RM
90
91;;;###autoload
c5049fa0
RS
92(defcustom compilation-window-height nil
93 "*Number of lines in a compilation window. If nil, use Emacs default."
94 :type '(choice (const :tag "Default" nil)
95 integer)
96 :group 'compilation)
d3cb357b 97
7837c247
SM
98(defvar compilation-first-column 1
99 "*This is how compilers number the first column, usually 1 or 0.")
55dfd2c4 100
e335e194
GM
101(defvar compilation-parse-errors-filename-function nil
102 "Function to call to post-process filenames while parsing error messages.
103It takes one arg FILENAME which is the name of a file as found
104in the compilation output, and should return a transformed file name.")
105
49683a13
EZ
106;;;###autoload
107(defvar compilation-process-setup-function nil
108 "*Function to call to customize the compilation process.
6f5b7627 109This function is called immediately before the compilation process is
49683a13 110started. It can be used to set any variables or functions that are used
9ac57479
KS
111while processing the output of the compilation process. The function
112is called with variables `compilation-buffer' and `compilation-window'
7837c247 113bound to the compilation buffer and window, respectively.")
49683a13 114
aa228418 115;;;###autoload
d3cb357b 116(defvar compilation-buffer-name-function nil
6c43f2f9
RS
117 "Function to compute the name of a compilation buffer.
118The function receives one argument, the name of the major mode of the
119compilation buffer. It should return a string.
120nil means compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
55dfd2c4 121
aa228418 122;;;###autoload
d3cb357b 123(defvar compilation-finish-function nil
c5049fa0 124 "Function to call when a compilation process finishes.
d3cb357b 125It is called with two arguments: the compilation buffer, and a string
620d3304 126describing how the process finished.")
3c9e7f42
RS
127
128(make-obsolete-variable 'compilation-finish-function
129 "Use `compilation-finish-functions', but it works a little differently."
130 "22.1")
55dfd2c4 131
4cc36b17
RS
132;;;###autoload
133(defvar compilation-finish-functions nil
c5049fa0 134 "Functions to call when a compilation process finishes.
4cc36b17
RS
135Each function is called with two arguments: the compilation buffer,
136and a string describing how the process finished.")
137
ebff767c
RM
138(defvar compilation-in-progress nil
139 "List of compilation processes now running.")
140(or (assq 'compilation-in-progress minor-mode-alist)
141 (setq minor-mode-alist (cons '(compilation-in-progress " Compiling")
142 minor-mode-alist)))
143
7837c247
SM
144(defvar compilation-error "error"
145 "Stem of message to print when no matches are found.")
6c43f2f9 146
58856335 147(defvar compilation-arguments nil
7837c247 148 "Arguments that were given to `compilation-start'.")
58856335 149
6c43f2f9 150(defvar compilation-num-errors-found)
d3cb357b 151
7837c247
SM
152(defconst compilation-error-regexp-alist-alist
153 '((absoft
154 "^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
155of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
5dfa3d35 156
7837c247
SM
157 (ada
158 "\\(warning: .*\\)? at \\([^ \n]+\\):\\([0-9]+\\)$" 2 3 nil (1))
c7c5bbc0 159
7837c247
SM
160 (aix
161 " in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
e1f540f2 162
7837c247
SM
163 (ant
164 "^[ \t]*\\[[^] \n]+\\][ \t]*\\([^: \n]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):[0-9]+:[0-9]+:\\)?\
165\\( warning\\)?" 1 2 3 (4))
e1f540f2 166
7837c247
SM
167 (bash
168 "^\\([^: \n\t]+\\): line \\([0-9]+\\):" 1 2)
e1f540f2 169
7837c247
SM
170 (borland
171 "^\\(?:Error\\|Warnin\\(g\\)\\) \\(?:[FEW][0-9]+ \\)?\
172\\([a-zA-Z]?:?[^:( \t\n]+\\)\
173 \\([0-9]+\\)\\(?:[) \t]\\|:[^0-9\n]\\)" 2 3 nil (1))
174
175 (caml
f6164cdd
DP
176 "^ *File \\(\"?\\)\\([^,\" \n\t<>]+\\)\\1, lines? \\([0-9]+\\)-?\\([0-9]+\\)?\\(?:$\\|,\
177\\(?: characters? \\([0-9]+\\)-?\\([0-9]+\\)?:\\)?\\([ \n]Warning:\\)?\\)"
178 2 (3 . 4) (5 . 6) (7))
7837c247
SM
179
180 (comma
181 "^\"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)\
182\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4))
183
c39bf546
DP
184 (edg-1
185 "^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
186 1 2 nil (3 . 4))
187 (edg-2
188 "at line \\([0-9]+\\) of \"\\([^ \n]+\\)\"$"
189 2 1 nil 0)
190
7837c247 191 (epc
c39bf546 192 "^Error [0-9]+ at (\\([0-9]+\\):\\([^)\n]+\\))" 2 1)
7837c247 193
12221c84
DP
194 (ftnchek
195 "\\(^Warning .*\\)? line[ \n]\\([0-9]+\\)[ \n]\\(?:col \\([0-9]+\\)[ \n]\\)?file \\([^ :;\n]+\\)"
196 4 2 3 (1))
9fcabe79 197
7837c247
SM
198 (iar
199 "^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:"
200 1 2 nil (3))
201
202 (ibm
203 "^\\([^( \n\t]+\\)(\\([0-9]+\\):\\([0-9]+\\)) :\
204 \\(?:warnin\\(g\\)\\|informationa\\(l\\)\\)?" 1 2 3 (4 . 5))
205
6f5b7627 206 ;; fixme: should be `mips'
7837c247 207 (irix
9fcabe79
DP
208 "^[-[:alnum:]_/ ]+: \\(?:\\(?:[sS]evere\\|[eE]rror\\|[wW]arnin\\(g\\)\\|[iI]nf\\(o\\)\\)[0-9 ]*: \\)?\
209\\([^,\" \n\t]+\\)\\(?:, line\\|:\\) \\([0-9]+\\):" 3 4 nil (1 . 2))
7837c247
SM
210
211 (java
212 "^\\(?:[ \t]+at \\|==[0-9]+== +\\(?:at\\|b\\(y\\)\\)\\).+(\\([^()\n]+\\):\\([0-9]+\\))$" 2 3 nil (1))
213
214 (jikes-file
215 "^\\(?:Found\\|Issued\\) .* compiling \"\\(.+\\)\":$" 1 nil nil 0)
216 (jikes-line
217 "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
218 nil 1 nil 2 0
219 (2 (compilation-face '(3))))
220
221 (gcc-include
222 "^\\(?:In file included\\| \\) from \
223\\(.+\\):\\([0-9]+\\)\\(?:\\(:\\)\\|\\(,\\)\\)?" 1 2 nil (3 . 4))
224
225 (gnu
6f5b7627 226 "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\)?\
b3ef54c5 227\\([/.]*[a-zA-Z]:?[^ \t\n:]*\\|{standard input}\\): ?\
7837c247
SM
228\\([0-9]+\\)\\([.:]?\\)\\([0-9]+\\)?\
229\\(?:-\\(?:\\([0-9]+\\)\\3\\)?\\.?\\([0-9]+\\)?\\)?:\
230\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
231 *\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\)\\)?"
232 1 (2 . 5) (4 . 6) (7 . 8))
233
234 (lcc
235 "^\\(?:E\\|\\(W\\)\\), \\([^(\n]+\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)"
236 2 3 4 (1))
237
238 (makepp
0cb687c0 239 "^makepp: \\(?:\\(?:warning\\(:\\).*?\\|\\(Scanning\\|[LR]e?l?oading makefile\\) \\|.*?\\)\
3b79dd20 240`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]\\)"
7837c247 241 4 5 nil (1 . 2) 3
3b79dd20 242 ("`\\(\\(\\S +?\\)\\(?::\\([0-9]+\\)\\)?\\)['(]" nil nil
7837c247
SM
243 (2 compilation-info-face)
244 (3 compilation-line-face nil t)
51c8ad03 245 (1 (compilation-error-properties 2 3 nil nil nil 0 nil)
7837c247
SM
246 append)))
247
6f5b7627 248 ;; Should be lint-1, lint-2 (SysV lint)
7837c247
SM
249 (mips-1
250 " (\\([0-9]+\\)) in \\([^ \n]+\\)" 2 1)
251 (mips-2
252 " in \\([^()\n ]+\\)(\\([0-9]+\\))$" 1 2)
253
254 (msft
28547c1f 255 "^\\([0-9]+>\\)?\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \
2a516a73 256: \\(?:error\\|warnin\\(g\\)\\) C[0-9]+:" 2 3 nil (4))
7837c247
SM
257
258 (oracle
b3ef54c5
DP
259 "^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
260\\(?:\\(?:,\\| at\\)? column \\([0-9]+\\)\\)?\
261\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
7837c247 262 3 1 2)
40d63d1f 263
7837c247
SM
264 (perl
265 " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\)" 1 2)
266
267 (rxp
268 "^\\(?:Error\\|Warnin\\(g\\)\\):.*\n.* line \\([0-9]+\\) char\
269 \\([0-9]+\\) of file://\\(.+\\)"
270 4 2 3 (1))
271
272 (sparc-pascal-file
273 "^\\w\\w\\w \\w\\w\\w +[0-3]?[0-9] +[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\
274 [12][09][0-9][0-9] +\\(.*\\):$"
275 1 nil nil 0)
276 (sparc-pascal-line
277 "^\\(\\(?:E\\|\\(w\\)\\) +[0-9]+\\) line \\([0-9]+\\) - "
278 nil 3 nil (2) nil (1 (compilation-face '(2))))
279 (sparc-pascal-example
280 "^ +\\([0-9]+\\) +.*\n\\(\\(?:e\\|\\(w\\)\\) [0-9]+\\)-+"
281 nil 1 nil (3) nil (2 (compilation-face '(3))))
282
283 (sun
6f5b7627 284 ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
7837c247
SM
285File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
286 3 4 5 (1 . 2))
287
288 (sun-ada
289 "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
290
7837c247
SM
291 (4bsd
292 "\\(?:^\\|:: \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
0c9a01ff
MY
293\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))
294
295 (gcov-file
e623859c 296 "^ +-: \\(0\\):Source:\\(.+\\)$" 2 1 nil 0)
0c9a01ff 297 (gcov-bb-file
e623859c 298 "^ +-: \\(0\\):Object:\\(?:.+\\)$" nil 1 nil 0)
0c9a01ff 299 (gcov-never-called-line
e623859c 300 "^ +\\(#####\\): +\\([0-9]+\\):.+$" nil 2 nil 2 nil
0c9a01ff
MY
301 (1 compilation-error-face))
302 (gcov-called-line
303 "^ +[-0-9]+: +\\([1-9]\\|[0-9]\\{2,\\}\\):.*$" nil 1 nil 0)
304)
7837c247
SM
305 "Alist of values for `compilation-error-regexp-alist'.")
306
307(defcustom compilation-error-regexp-alist
308 (mapcar 'car compilation-error-regexp-alist-alist)
6c43f2f9 309 "Alist that specifies how to match errors in compiler output.
7957baea 310On GNU and Unix, any string is a valid filename, so these
7837c247
SM
311matchers must make some common sense assumptions, which catch
312normal cases. A shorter list will be lighter on resource usage.
313
314Instead of an alist element, you can use a symbol, which is
315looked up in `compilation-error-regexp-alist-alist'. You can see
316the predefined symbols and their effects in the file
6f5b7627 317`etc/compilation.txt' (linked below if you are customizing this).
7837c247
SM
318
319Each elt has the form (REGEXP FILE [LINE COLUMN TYPE HYPERLINK
320HIGHLIGHT...]). If REGEXP matches, the FILE'th subexpression
321gives the file name, and the LINE'th subexpression gives the line
322number. The COLUMN'th subexpression gives the column number on
323that line.
324
325If FILE, LINE or COLUMN are nil or that index didn't match, that
326information is not present on the matched line. In that case the
327file name is assumed to be the same as the previous one in the
328buffer, line number defaults to 1 and column defaults to
329beginning of line's indentation.
330
331FILE can also have the form (FILE FORMAT...), where the FORMATs
332\(e.g. \"%s.c\") will be applied in turn to the recognized file
333name, until a file of that name is found. Or FILE can also be a
334function to return the filename.
335
336LINE can also be of the form (LINE . END-LINE) meaning a range
337of lines. COLUMN can also be of the form (COLUMN . END-COLUMN)
338meaning a range of columns starting on LINE and ending on
339END-LINE, if that matched.
340
341TYPE is 2 or nil for a real error or 1 for warning or 0 for info.
342TYPE can also be of the form (WARNING . INFO). In that case this
343will be equivalent to 1 if the WARNING'th subexpression matched
344or else equivalent to 0 if the INFO'th subexpression matched.
345See `compilation-error-face', `compilation-warning-face',
346`compilation-info-face' and `compilation-skip-threshold'.
347
348What matched the HYPERLINK'th subexpression has `mouse-face' and
349`compilation-message-face' applied. If this is nil, the text
350matched by the whole REGEXP becomes the hyperlink.
351
352Additional HIGHLIGHTs as described under `font-lock-keywords' can
353be added."
354 :type `(set :menu-tag "Pick"
355 ,@(mapcar (lambda (elt)
356 (list 'const (car elt)))
357 compilation-error-regexp-alist-alist))
358 :link `(file-link :tag "example file"
eeb3ede4 359 ,(expand-file-name "compilation.txt" data-directory))
7837c247 360 :group 'compilation)
55dfd2c4 361
ebb8cb68
EZ
362(defvar compilation-directory nil
363 "Directory to restore to when doing `recompile'.")
364
7837c247
SM
365(defvar compilation-directory-matcher
366 '("\\(?:Entering\\|Leavin\\(g\\)\\) directory `\\(.+\\)'$" (2 . 1))
367 "A list for tracking when directories are entered or left.
368Nil means not to track directories, e.g. if all file names are absolute. The
369first element is the REGEXP matching these messages. It can match any number
370of variants, e.g. different languages. The remaining elements are all of the
371form (DIR . LEAVE). If for any one of these the DIR'th subexpression
372matches, that is a directory name. If LEAVE is nil or the corresponding
373LEAVE'th subexpression doesn't match, this message is about going into another
374directory. If it does match anything, this message is about going back to the
375directory we were in before the last entering message. If you change this,
376you may also want to change `compilation-page-delimiter'.")
377
378(defvar compilation-page-delimiter
379 "^\\(?:\f\\|.*\\(?:Entering\\|Leaving\\) directory `.+'\n\\)+"
380 "Value of `page-delimiter' in Compilation mode.")
381
382(defvar compilation-mode-font-lock-keywords
383 '(;; configure output lines.
384 ("^[Cc]hecking \\(?:[Ff]or \\|[Ii]f \\|[Ww]hether \\(?:to \\)?\\)?\\(.+\\)\\.\\.\\. *\\(?:(cached) *\\)?\\(\\(yes\\(?: .+\\)?\\)\\|no\\|\\(.*\\)\\)$"
385 (1 font-lock-variable-name-face)
38dbf92b 386 (2 (compilation-face '(4 . 3))))
7837c247 387 ;; Command output lines. Recognize `make[n]:' lines too.
6f5b7627 388 ("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
7837c247
SM
389 (1 font-lock-function-name-face) (3 compilation-line-face nil t))
390 (" --?o\\(?:utfile\\|utput\\)?[= ]?\\(\\S +\\)" . 1)
314b410b
JL
391 ("^Compilation \\(finished\\)"
392 (1 compilation-info-face))
393 ("^Compilation \\(exited abnormally\\|interrupt\\|killed\\|terminated\\)\\(?:.*with code \\([0-9]+\\)\\)?"
394 (1 compilation-error-face)
395 (2 compilation-error-face nil t)))
7837c247
SM
396 "Additional things to highlight in Compilation mode.
397This gets tacked on the end of the generated expressions.")
a24770bc 398
9ac57479
KS
399(defvar compilation-highlight-regexp t
400 "Regexp matching part of visited source lines to highlight temporarily.
401Highlight entire line if t; don't highlight source lines if nil.")
402
403(defvar compilation-highlight-overlay nil
404 "Overlay used to temporarily highlight compilation matches.")
405
f8e03ecb
AS
406(defcustom compilation-error-screen-columns t
407 "*If non-nil, column numbers in error messages are screen columns.
408Otherwise they are interpreted as character positions, with
409each character occupying one column.
410The default is to use screen columns, which requires that the compilation
411program and Emacs agree about the display width of the characters,
412especially the TAB character."
413 :type 'boolean
414 :group 'compilation
415 :version "20.4")
416
c5049fa0 417(defcustom compilation-read-command t
851231e9
DL
418 "*Non-nil means \\[compile] reads the compilation command to use.
419Otherwise, \\[compile] just uses the value of `compile-command'."
c5049fa0
RS
420 :type 'boolean
421 :group 'compilation)
90016295 422
e83be080 423;;;###autoload
c5049fa0 424(defcustom compilation-ask-about-save t
851231e9 425 "*Non-nil means \\[compile] asks which buffers to save before compiling.
c5049fa0
RS
426Otherwise, it saves all modified buffers without asking."
427 :type 'boolean
428 :group 'compilation)
90016295 429
7c163413 430;;;###autoload
c5049fa0 431(defcustom compilation-search-path '(nil)
7c163413 432 "*List of directories to search for source files named in error messages.
d3cb357b 433Elements should be directory names, not file names of directories.
c5049fa0
RS
434nil as an element means to try the default directory."
435 :type '(repeat (choice (const :tag "Default" nil)
436 (string :tag "Directory")))
437 :group 'compilation)
55dfd2c4 438
7957baea 439;;;###autoload
c5049fa0
RS
440(defcustom compile-command "make -k "
441 "*Last shell command used to do a compilation; default for next compilation.
55dfd2c4
RS
442
443Sometimes it is useful for files to supply local values for this variable.
444You might also use mode hooks to specify it in certain modes, like this:
445
61c4aaf8 446 (add-hook 'c-mode-hook
61c4aaf8
RS
447 (lambda ()
448 (unless (or (file-exists-p \"makefile\")
449 (file-exists-p \"Makefile\"))
5b6858da
SM
450 (set (make-local-variable 'compile-command)
451 (concat \"make -k \"
7837c247 452 (file-name-sans-extension buffer-file-name))))))"
c5049fa0
RS
453 :type 'string
454 :group 'compilation)
55dfd2c4 455
7957baea 456;;;###autoload
93ef35e4 457(defcustom compilation-disable-input nil
3fa37cd1
EZ
458 "*If non-nil, send end-of-file as compilation process input.
459This only affects platforms that support asynchronous processes (see
bac3a1c9 460`start-process'); synchronous compilation processes never accept input."
3fa37cd1
EZ
461 :type 'boolean
462 :group 'compilation
463 :version "22.1")
464
7837c247
SM
465;; A weak per-compilation-buffer hash indexed by (FILENAME . DIRECTORY). Each
466;; value is a FILE-STRUCTURE as described above, with the car eq to the hash
467;; key. This holds the tree seen from root, for storing new nodes.
468(defvar compilation-locs ())
469
470(defvar compilation-debug nil
6f5b7627 471 "*Set this to t before creating a *compilation* buffer.
7837c247
SM
472Then every error line will have a debug text property with the matcher that
473fit this line and the match data. Use `describe-text-properties'.")
d3cb357b 474
01f89d11
RM
475(defvar compilation-exit-message-function nil "\
476If non-nil, called when a compilation process dies to return a status message.
fd5e58d7
RM
477This should be a function of three arguments: process status, exit status,
478and exit message; it returns a cons (MESSAGE . MODELINE) of the strings to
479write into the compilation buffer, and to put in its mode line.")
01f89d11 480
c20f961b
JPW
481(defvar compilation-environment nil
482 "*List of environment variables for compilation to inherit.
483Each element should be a string of the form ENVVARNAME=VALUE.
484This list is temporarily prepended to `process-environment' prior to
485starting the compilation process.")
486
770970cb
RS
487;; History of compile commands.
488(defvar compile-history nil)
770970cb 489
fa947ef3
JL
490(defface compilation-error
491 '((t :inherit font-lock-warning-face))
492 "Face used to highlight compiler errors."
493 :group 'font-lock-highlighting-faces
494 :version "22.1")
495
541a6d0d 496(defface compilation-warning
bc3621a0
EZ
497 '((((class color) (min-colors 16)) (:foreground "Orange" :weight bold))
498 (((class color)) (:foreground "cyan" :weight bold))
7837c247
SM
499 (t (:weight bold)))
500 "Face used to highlight compiler warnings."
f6164cdd 501 :group 'font-lock-highlighting-faces
bf247b6e 502 :version "22.1")
7837c247 503
541a6d0d 504(defface compilation-info
e4aa3c94 505 '((((class color) (min-colors 16) (background light))
bc3621a0 506 (:foreground "Green3" :weight bold))
ea81d57e
DN
507 (((class color) (min-colors 88) (background dark))
508 (:foreground "Green1" :weight bold))
e4aa3c94 509 (((class color) (min-colors 16) (background dark))
bc3621a0
EZ
510 (:foreground "Green" :weight bold))
511 (((class color)) (:foreground "green" :weight bold))
7837c247 512 (t (:weight bold)))
fa947ef3 513 "Face used to highlight compiler information."
f6164cdd 514 :group 'font-lock-highlighting-faces
bf247b6e 515 :version "22.1")
7837c247 516
a5f1c37e 517(defface compilation-line-number
38dbf92b 518 '((t :inherit font-lock-variable-name-face))
fa947ef3 519 "Face for displaying line numbers in compiler messages."
a5f1c37e
RS
520 :group 'font-lock-highlighting-faces
521 :version "22.1")
522
523(defface compilation-column-number
38dbf92b 524 '((t :inherit font-lock-type-face))
fa947ef3 525 "Face for displaying column numbers in compiler messages."
a5f1c37e
RS
526 :group 'font-lock-highlighting-faces
527 :version "22.1")
528
38dbf92b 529(defvar compilation-message-face 'underline
7837c247
SM
530 "Face name to use for whole messages.
531Faces `compilation-error-face', `compilation-warning-face',
532`compilation-info-face', `compilation-line-face' and
533`compilation-column-face' get prepended to this, when applicable.")
534
38dbf92b 535(defvar compilation-error-face 'compilation-error
7837c247
SM
536 "Face name to use for file name in error messages.")
537
38dbf92b 538(defvar compilation-warning-face 'compilation-warning
7837c247
SM
539 "Face name to use for file name in warning messages.")
540
38dbf92b 541(defvar compilation-info-face 'compilation-info
7837c247
SM
542 "Face name to use for file name in informational messages.")
543
a5f1c37e 544(defvar compilation-line-face 'compilation-line-number
38dbf92b 545 "Face name to use for line numbers in compiler messages.")
7837c247 546
a5f1c37e 547(defvar compilation-column-face 'compilation-column-number
fa947ef3 548 "Face name to use for column numbers in compiler messages.")
7837c247
SM
549
550;; same faces as dired uses
551(defvar compilation-enter-directory-face 'font-lock-function-name-face
fa947ef3 552 "Face name to use for entering directory messages.")
7837c247
SM
553
554(defvar compilation-leave-directory-face 'font-lock-type-face
fa947ef3 555 "Face name to use for leaving directory messages.")
7837c247
SM
556
557
558
c536bb39 559;; Used for compatibility with the old compile.el.
0ff7f01e 560(defvaralias 'compilation-last-buffer 'next-error-last-buffer)
6f5b7627 561(defvar compilation-parsing-end (make-marker))
c536bb39
SM
562(defvar compilation-parse-errors-function nil)
563(defvar compilation-error-list nil)
564(defvar compilation-old-error-list nil)
565
7837c247
SM
566(defun compilation-face (type)
567 (or (and (car type) (match-end (car type)) compilation-warning-face)
568 (and (cdr type) (match-end (cdr type)) compilation-info-face)
569 compilation-error-face))
570
deda0c65
DP
571;; Internal function for calculating the text properties of a directory
572;; change message. The directory property is important, because it is
573;; the stack of nested enter-messages. Relative filenames on the following
574;; lines are relative to the top of the stack.
7837c247
SM
575(defun compilation-directory-properties (idx leave)
576 (if leave (setq leave (match-end leave)))
577 ;; find previous stack, and push onto it, or if `leave' pop it
578 (let ((dir (previous-single-property-change (point) 'directory)))
579 (setq dir (if dir (or (get-text-property (1- dir) 'directory)
580 (get-text-property dir 'directory))))
581 `(face ,(if leave
582 compilation-leave-directory-face
583 compilation-enter-directory-face)
584 directory ,(if leave
585 (or (cdr dir)
586 '(nil)) ; nil only isn't a property-change
587 (cons (match-string-no-properties idx) dir))
588 mouse-face highlight
6f5b7627 589 keymap compilation-button-map
7837c247
SM
590 help-echo "mouse-2: visit current directory")))
591
592;; Data type `reverse-ordered-alist' retriever. This function retrieves the
593;; KEY element from the ALIST, creating it in the right position if not already
594;; present. ALIST structure is
595;; '(ANCHOR (KEY1 ...) (KEY2 ...)... (KEYn ALIST ...))
596;; ANCHOR is ignored, but necessary so that elements can be inserted. KEY1
597;; may be nil. The other KEYs are ordered backwards so that growing line
598;; numbers can be inserted in front and searching can abort after half the
599;; list on average.
6f5b7627 600(eval-when-compile ;Don't keep it at runtime if not needed.
7837c247
SM
601(defmacro compilation-assq (key alist)
602 `(let* ((l1 ,alist)
603 (l2 (cdr l1)))
604 (car (if (if (null ,key)
605 (if l2 (null (caar l2)))
606 (while (if l2 (if (caar l2) (< ,key (caar l2)) t))
607 (setq l1 l2
608 l2 (cdr l1)))
609 (if l2 (eq ,key (caar l2))))
610 l2
6f5b7627 611 (setcdr l1 (cons (list ,key) l2)))))))
7837c247
SM
612
613
614;; This function is the central driver, called when font-locking to gather
615;; all information needed to later jump to corresponding source code.
616;; Return a property list with all meta information on this error location.
617(defun compilation-error-properties (file line end-line col end-col type fmt)
618 (unless (< (next-single-property-change (match-beginning 0) 'directory nil (point))
619 (point))
620 (if file
621 (if (functionp file)
622 (setq file (funcall file))
623 (let (dir)
624 (setq file (match-string-no-properties file))
625 (unless (file-name-absolute-p file)
626 (setq dir (previous-single-property-change (point) 'directory)
627 dir (if dir (or (get-text-property (1- dir) 'directory)
628 (get-text-property dir 'directory)))))
efb0e677 629 (setq file (cons file (car dir)))))
7837c247
SM
630 ;; This message didn't mention one, get it from previous
631 (setq file (previous-single-property-change (point) 'message)
632 file (or (if file
efb0e677
SM
633 (car (nth 2 (car (or (get-text-property (1- file) 'message)
634 (get-text-property file 'message))))))
635 '("*unknown*"))))
7837c247
SM
636 ;; All of these fields are optional, get them only if we have an index, and
637 ;; it matched some part of the message.
638 (and line
639 (setq line (match-string-no-properties line))
640 (setq line (string-to-number line)))
641 (and end-line
642 (setq end-line (match-string-no-properties end-line))
643 (setq end-line (string-to-number end-line)))
9dc3a46a
JL
644 (if col
645 (if (functionp col)
646 (setq col (funcall col))
647 (and
648 (setq col (match-string-no-properties col))
649 (setq col (- (string-to-number col) compilation-first-column)))))
650 (if (and end-col (functionp end-col))
651 (setq end-col (funcall end-col))
652 (if (and end-col (setq end-col (match-string-no-properties end-col)))
653 (setq end-col (- (string-to-number end-col) compilation-first-column -1))
654 (if end-line (setq end-col -1))))
eb6fb6e2 655 (if (consp type) ; not a static type, check what it is.
7837c247
SM
656 (setq type (or (and (car type) (match-end (car type)) 1)
657 (and (cdr type) (match-end (cdr type)) 0)
658 2)))
efb0e677
SM
659 (compilation-internal-error-properties file line end-line col end-col type fmt)))
660
9c8e6c85
SM
661(defun compilation-move-to-column (col screen)
662 "Go to column COL on the current line.
663If SCREEN is non-nil, columns are screen columns, otherwise, they are
664just char-counts."
665 (if screen
666 (move-to-column col)
667 (goto-char (min (+ (line-beginning-position) col) (line-end-position)))))
668
7957baea 669(defun compilation-internal-error-properties (file line end-line col end-col type fmts)
efb0e677
SM
670 "Get the meta-info that will be added as text-properties.
671LINE, END-LINE, COL, END-COL are integers or nil.
7957baea
RS
672TYPE can be 0, 1, or 2, meaning error, warning, or just info.
673FILE should be (FILENAME) or (RELATIVE-FILENAME . DIRNAME) or nil.
674FMTS is a list of format specs for transforming the file name.
675 (See `compilation-error-regexp-alist'.)"
efb0e677 676 (unless file (setq file '("*unknown*")))
7957baea
RS
677 (let* ((file-struct (compilation-get-file-structure file fmts))
678 ;; Get first already existing marker (if any has one, all have one).
679 ;; Do this first, as the compilation-assq`s may create new nodes.
680 (marker-line (car (cddr file-struct))) ; a line structure
efb0e677
SM
681 (marker (nth 3 (cadr marker-line))) ; its marker
682 (compilation-error-screen-columns compilation-error-screen-columns)
683 end-marker loc end-loc)
684 (if (not (and marker (marker-buffer marker)))
7957baea 685 (setq marker nil) ; no valid marker for this file
dbd97672
DP
686 (setq loc (or line 1)) ; normalize no linenumber to line 1
687 (catch 'marker ; find nearest loc, at least one exists
7957baea 688 (dolist (x (nthcdr 3 file-struct)) ; loop over remaining lines
dbd97672 689 (if (> (car x) loc) ; still bigger
efb0e677 690 (setq marker-line x)
dbd97672
DP
691 (if (> (- (or (car marker-line) 1) loc)
692 (- loc (car x))) ; current line is nearer
efb0e677
SM
693 (setq marker-line x))
694 (throw 'marker t))))
695 (setq marker (nth 3 (cadr marker-line))
dbd97672 696 marker-line (or (car marker-line) 1))
efb0e677
SM
697 (with-current-buffer (marker-buffer marker)
698 (save-restriction
699 (widen)
700 (goto-char (marker-position marker))
701 (when (or end-col end-line)
702 (beginning-of-line (- (or end-line line) marker-line -1))
930a3e46 703 (if (or (null end-col) (< end-col 0))
efb0e677 704 (end-of-line)
9c8e6c85
SM
705 (compilation-move-to-column
706 end-col compilation-error-screen-columns))
efb0e677
SM
707 (setq end-marker (list (point-marker))))
708 (beginning-of-line (if end-line
930a3e46 709 (- line end-line -1)
efb0e677
SM
710 (- loc marker-line -1)))
711 (if col
9c8e6c85
SM
712 (compilation-move-to-column
713 col compilation-error-screen-columns)
efb0e677
SM
714 (forward-to-indentation 0))
715 (setq marker (list (point-marker))))))
716
7957baea 717 (setq loc (compilation-assq line (cdr file-struct)))
efb0e677 718 (if end-line
7957baea 719 (setq end-loc (compilation-assq end-line (cdr file-struct))
efb0e677
SM
720 end-loc (compilation-assq end-col end-loc))
721 (if end-col ; use same line element
722 (setq end-loc (compilation-assq end-col loc))))
723 (setq loc (compilation-assq col loc))
724 ;; If they are new, make the loc(s) reference the file they point to.
7957baea 725 (or (cdr loc) (setcdr loc `(,line ,file-struct ,@marker)))
efb0e677 726 (if end-loc
7957baea
RS
727 (or (cdr end-loc)
728 (setcdr end-loc `(,(or end-line line) ,file-struct ,@end-marker))))
efb0e677
SM
729
730 ;; Must start with face
731 `(face ,compilation-message-face
732 message (,loc ,type ,end-loc)
733 ,@(if compilation-debug
734 `(debug (,(assoc (with-no-warnings matcher) font-lock-keywords)
735 ,@(match-data))))
736 help-echo ,(if col
737 "mouse-2: visit this file, line and column"
738 (if line
739 "mouse-2: visit this file and line"
740 "mouse-2: visit this file"))
741 keymap compilation-button-map
742 mouse-face highlight)))
7837c247 743
e93b2a55
SM
744(defun compilation-mode-font-lock-keywords ()
745 "Return expressions to highlight in Compilation mode."
91fa27cd
SM
746 (if compilation-parse-errors-function
747 ;; An old package! Try the compatibility code.
748 '((compilation-compat-parse-errors))
749 (append
750 ;; make directory tracking
751 (if compilation-directory-matcher
752 `((,(car compilation-directory-matcher)
753 ,@(mapcar (lambda (elt)
754 `(,(car elt)
755 (compilation-directory-properties
756 ,(car elt) ,(cdr elt))
0ea50e43 757 t t))
91fa27cd
SM
758 (cdr compilation-directory-matcher)))))
759
760 ;; Compiler warning/error lines.
761 (mapcar
762 (lambda (item)
763 (if (symbolp item)
764 (setq item (cdr (assq item
765 compilation-error-regexp-alist-alist))))
766 (let ((file (nth 1 item))
767 (line (nth 2 item))
768 (col (nth 3 item))
769 (type (nth 4 item))
770 end-line end-col fmt)
b3a7f48f
DP
771 (if (consp file) (setq fmt (cdr file) file (car file)))
772 (if (consp line) (setq end-line (cdr line) line (car line)))
91fa27cd 773 (if (consp col) (setq end-col (cdr col) col (car col)))
b3a7f48f 774
544dccaa 775 (if (functionp line)
91fa27cd
SM
776 ;; The old compile.el had here an undocumented hook that
777 ;; allowed `line' to be a function that computed the actual
778 ;; error location. Let's do our best.
779 `(,(car item)
0ea50e43
RS
780 (0 (save-match-data
781 (compilation-compat-error-properties
782 (funcall ',line (cons (match-string ,file)
783 (cons default-directory
784 ',(nthcdr 4 item)))
785 ,(if col `(match-string ,col))))))
91fa27cd 786 (,file compilation-error-face t))
b3a7f48f 787
f71d34b0
SM
788 (unless (or (null (nth 5 item)) (integerp (nth 5 item)))
789 (error "HYPERLINK should be an integer: %s" (nth 5 item)))
790
91fa27cd
SM
791 `(,(nth 0 item)
792
793 ,@(when (integerp file)
794 `((,file ,(if (consp type)
795 `(compilation-face ',type)
796 (aref [compilation-info-face
797 compilation-warning-face
798 compilation-error-face]
799 (or type 2))))))
800
801 ,@(when line
802 `((,line compilation-line-face nil t)))
803 ,@(when end-line
804 `((,end-line compilation-line-face nil t)))
805
9dc3a46a 806 ,@(when (integerp col)
91fa27cd 807 `((,col compilation-column-face nil t)))
9dc3a46a 808 ,@(when (integerp end-col)
91fa27cd
SM
809 `((,end-col compilation-column-face nil t)))
810
811 ,@(nthcdr 6 item)
812 (,(or (nth 5 item) 0)
813 (compilation-error-properties ',file ,line ,end-line
814 ,col ,end-col ',(or type 2)
815 ',fmt)
816 append))))) ; for compilation-message-face
817 compilation-error-regexp-alist)
818
819 compilation-mode-font-lock-keywords)))
7837c247 820
01f89d11 821\f
d3cb357b 822;;;###autoload
7837c247 823(defun compile (command &optional comint)
55dfd2c4
RS
824 "Compile the program including the current buffer. Default: run `make'.
825Runs COMMAND, a shell command, in a separate process asynchronously
826with output going to the buffer `*compilation*'.
d3cb357b 827
6f5b7627 828If optional second arg COMINT is t the buffer will be in Comint mode with
7837c247
SM
829`compilation-shell-minor-mode'.
830
55dfd2c4
RS
831You can then use the command \\[next-error] to find the next error message
832and move to the source code that caused it.
833
08b1edf4
RM
834Interactively, prompts for the command if `compilation-read-command' is
835non-nil; otherwise uses `compile-command'. With prefix arg, always prompts.
c39bf546
DP
836Additionally, with universal prefix arg, compilation buffer will be in
837comint mode, i.e. interactive.
08b1edf4 838
c72095b3
RS
839To run more than one compilation at once, start one and rename
840the \`*compilation*' buffer to some other name with
841\\[rename-buffer]. Then start the next one. On most systems,
842termination of the main compilation process kills its
843subprocesses.
d3cb357b
RM
844
845The name used for the buffer is actually whatever is returned by
846the function in `compilation-buffer-name-function', so you can set that
847to a function that generates a unique name."
90016295 848 (interactive
c39bf546 849 (list
20320c65
JL
850 (let ((command (eval compile-command)))
851 (if (or compilation-read-command current-prefix-arg)
852 (read-from-minibuffer "Compile command: "
853 command nil nil
854 (if (equal (car compile-history) command)
855 '(compile-history . 1)
856 'compile-history))
857 command))
c39bf546 858 (consp current-prefix-arg)))
5b6858da
SM
859 (unless (equal command (eval compile-command))
860 (setq compile-command command))
90016295 861 (save-some-buffers (not compilation-ask-about-save) nil)
ebb8cb68 862 (setq compilation-directory default-directory)
7837c247 863 (compilation-start command comint))
55dfd2c4 864
5b6858da 865;; run compile with the default command line
e60476ca 866(defun recompile ()
6867356a 867 "Re-compile the program including the current buffer.
6f5b7627
SM
868If this is run in a Compilation mode buffer, re-use the arguments from the
869original use. Otherwise, recompile using `compile-command'."
e60476ca
RS
870 (interactive)
871 (save-some-buffers (not compilation-ask-about-save) nil)
e4aa3c94
JL
872 (let ((default-directory
873 (or (and (not (eq major-mode (nth 1 compilation-arguments)))
874 compilation-directory)
875 default-directory)))
7837c247
SM
876 (apply 'compilation-start (or compilation-arguments
877 `(,(eval compile-command))))))
09843b4a 878
b5812513
DL
879(defcustom compilation-scroll-output nil
880 "*Non-nil to scroll the *compilation* buffer window as output appears.
881
6f5b7627 882Setting it causes the Compilation mode commands to put point at the
b5812513 883end of their output window so that the end of the output is always
6f5b7627 884visible rather than the beginning."
b5812513 885 :type 'boolean
a46fddeb 886 :version "20.3"
b5812513
DL
887 :group 'compilation)
888
7bdb67b2
GM
889
890(defun compilation-buffer-name (mode-name name-function)
891 "Return the name of a compilation buffer to use.
892If NAME-FUNCTION is non-nil, call it with one argument MODE-NAME
893to determine the buffer name.
894Likewise if `compilation-buffer-name-function' is non-nil.
895If current buffer is in Compilation mode for the same mode name
896return the name of the current buffer, so that it gets reused.
897Otherwise, construct a buffer name from MODE-NAME."
dc2feacf 898 (cond (name-function
7bdb67b2 899 (funcall name-function mode-name))
dc2feacf 900 (compilation-buffer-name-function
7bdb67b2 901 (funcall compilation-buffer-name-function mode-name))
e4aa3c94 902 ((eq major-mode (nth 1 compilation-arguments))
7bdb67b2
GM
903 (buffer-name))
904 (t
905 (concat "*" (downcase mode-name) "*"))))
906
7837c247
SM
907;; This is a rough emulation of the old hack, until the transition to new
908;; compile is complete.
55dfd2c4 909(defun compile-internal (command error-message
a24770bc
RS
910 &optional name-of-mode parser
911 error-regexp-alist name-function
912 enter-regexp-alist leave-regexp-alist
23b0c5fc 913 file-regexp-alist nomessage-regexp-alist
9ac57479 914 no-async highlight-regexp local-map)
7837c247
SM
915 (if parser
916 (error "Compile now works very differently, see `compilation-error-regexp-alist'"))
917 (let ((compilation-error-regexp-alist
918 (append file-regexp-alist (or error-regexp-alist
919 compilation-error-regexp-alist)))
920 (compilation-error (replace-regexp-in-string "^No more \\(.+\\)s\\.?"
921 "\\1" error-message)))
922 (compilation-start command nil name-function highlight-regexp)))
923(make-obsolete 'compile-internal 'compilation-start)
924
a24c45d2 925;;;###autoload
7837c247 926(defun compilation-start (command &optional mode name-function highlight-regexp)
55dfd2c4 927 "Run compilation command COMMAND (low level interface).
489a8034 928If COMMAND starts with a cd command, that becomes the `default-directory'.
9ac57479
KS
929The rest of the arguments are optional; for them, nil means use the default.
930
7837c247 931MODE is the major mode to set in the compilation buffer. Mode
6f5b7627 932may also be t meaning use `compilation-shell-minor-mode' under `comint-mode'.
5b317d74
RF
933If NAME-FUNCTION is non-nil, call it with one argument (the mode name)
934to determine the buffer name.
23b0c5fc 935
9ac57479 936If HIGHLIGHT-REGEXP is non-nil, `next-error' will temporarily highlight
6f5b7627 937the matching section of the visited source line; the default is to use the
9ac57479
KS
938global value of `compilation-highlight-regexp'.
939
646bd331 940Returns the compilation buffer created."
7837c247 941 (or mode (setq mode 'compilation-mode))
489a8034
DP
942 (let* ((name-of-mode
943 (if (eq mode t)
944 (prog1 "compilation" (require 'comint))
945 (replace-regexp-in-string "-mode$" "" (symbol-name mode))))
199143f1 946 (thisdir default-directory)
489a8034 947 outwin outbuf)
c536bb39
SM
948 (with-current-buffer
949 (setq outbuf
950 (get-buffer-create
951 (compilation-buffer-name name-of-mode name-function)))
d3cb357b
RM
952 (let ((comp-proc (get-buffer-process (current-buffer))))
953 (if comp-proc
954 (if (or (not (eq (process-status comp-proc) 'run))
955 (yes-or-no-p
bea1d57a
JB
956 (format "A %s process is running; kill it? "
957 name-of-mode)))
d3cb357b
RM
958 (condition-case ()
959 (progn
960 (interrupt-process comp-proc)
961 (sit-for 1)
962 (delete-process comp-proc))
963 (error nil))
964 (error "Cannot have two processes in `%s' at once"
7837c247 965 (buffer-name)))))
7837c247 966 (buffer-disable-undo (current-buffer))
199143f1
DP
967 ;; first transfer directory from where M-x compile was called
968 (setq default-directory thisdir)
d42c87ab
RS
969 ;; Make compilation buffer read-only. The filter can still write it.
970 ;; Clear out the compilation buffer.
199143f1
DP
971 (let ((inhibit-read-only t)
972 (default-directory thisdir))
973 ;; Then evaluate a cd command if any, but don't perform it yet, else start-command
974 ;; would do it again through the shell: (cd "..") AND sh -c "cd ..; make"
975 (cd (if (string-match "^\\s *cd\\(?:\\s +\\(\\S +?\\)\\)?\\s *[;&\n]" command)
976 (if (match-end 1)
12221c84 977 (substitute-env-vars (match-string 1 command))
199143f1
DP
978 "~")
979 default-directory))
abed5267 980 (erase-buffer)
6d2957c4
RS
981 ;; Select the desired mode.
982 (if (not (eq mode t))
983 (funcall mode)
984 (setq buffer-read-only nil)
985 (with-no-warnings (comint-mode))
986 (compilation-shell-minor-mode))
987 (if highlight-regexp
988 (set (make-local-variable 'compilation-highlight-regexp)
989 highlight-regexp))
6d2957c4 990 ;; Output a mode setter, for saving and later reloading this buffer.
d42c87ab
RS
991 (insert "-*- mode: " name-of-mode
992 "; default-directory: " (prin1-to-string default-directory)
a67e5425 993 " -*-\n"
314b410b
JL
994 (format "%s started at %s\n\n"
995 mode-name
996 (substring (current-time-string) 0 19))
a67e5425 997 command "\n")
abed5267 998 (setq thisdir default-directory))
7837c247
SM
999 (set-buffer-modified-p nil))
1000 ;; If we're already in the compilation buffer, go to the end
1001 ;; of the buffer, so point will track the compilation output.
1002 (if (eq outbuf (current-buffer))
1003 (goto-char (point-max)))
1004 ;; Pop up the compilation buffer.
1005 (setq outwin (display-buffer outbuf nil t))
1006 (with-current-buffer outbuf
577bf5d2
JL
1007 (let ((process-environment
1008 (append
1009 compilation-environment
1010 (if (if (boundp 'system-uses-terminfo) ; `if' for compiler warning
1011 system-uses-terminfo)
1012 (list "TERM=dumb" "TERMCAP="
1013 (format "COLUMNS=%d" (window-width)))
1014 (list "TERM=emacs"
1015 (format "TERMCAP=emacs:co#%d:tc=unknown:"
1016 (window-width))))
1017 ;; Set the EMACS variable, but
1018 ;; don't override users' setting of $EMACS.
1019 (unless (getenv "EMACS") '("EMACS=t"))
1020 (copy-sequence process-environment))))
577bf5d2
JL
1021 (set (make-local-variable 'compilation-arguments)
1022 (list command mode name-function highlight-regexp))
1023 (set (make-local-variable 'revert-buffer-function)
1024 'compilation-revert-buffer)
1025 (set-window-start outwin (point-min))
1026 (or (eq outwin (selected-window))
1027 (set-window-point outwin (if compilation-scroll-output
1028 (point)
1029 (point-min))))
1030 ;; The setup function is called before compilation-set-window-height
1031 ;; so it can set the compilation-window-height buffer locally.
1032 (if compilation-process-setup-function
1033 (funcall compilation-process-setup-function))
1034 (compilation-set-window-height outwin)
1035 ;; Start the compilation.
1036 (if (fboundp 'start-process)
1037 (let ((proc (if (eq mode t)
1038 (get-buffer-process
1039 (with-no-warnings
1040 (comint-exec outbuf (downcase mode-name)
1041 shell-file-name nil `("-c" ,command))))
1042 (start-process-shell-command (downcase mode-name)
1043 outbuf command))))
1044 ;; Make the buffer's mode line show process state.
1045 (setq mode-line-process '(":%s"))
1046 (set-process-sentinel proc 'compilation-sentinel)
1047 (set-process-filter proc 'compilation-filter)
1048 (set-marker (process-mark proc) (point) outbuf)
32eb2c08
SM
1049 (when compilation-disable-input
1050 (condition-case nil
1051 (process-send-eof proc)
1052 ;; The process may have exited already.
1053 (error nil)))
577bf5d2
JL
1054 (setq compilation-in-progress
1055 (cons proc compilation-in-progress)))
1056 ;; No asynchronous processes available.
1057 (message "Executing `%s'..." command)
1058 ;; Fake modeline display as if `start-process' were run.
1059 (setq mode-line-process ":run")
1060 (force-mode-line-update)
1061 (sit-for 0) ; Force redisplay
cf63e6fa
EZ
1062 (let* ((buffer-read-only nil) ; call-process needs to modify outbuf
1063 (status (call-process shell-file-name nil outbuf nil "-c"
1064 command)))
577bf5d2
JL
1065 (cond ((numberp status)
1066 (compilation-handle-exit 'exit status
1067 (if (zerop status)
1068 "finished\n"
1069 (format "\
fd5e58d7 1070exited abnormally with code %d\n"
577bf5d2
JL
1071 status))))
1072 ((stringp status)
1073 (compilation-handle-exit 'signal status
1074 (concat status "\n")))
1075 (t
1076 (compilation-handle-exit 'bizarre status status))))
1077 ;; Without async subprocesses, the buffer is not yet
1078 ;; fontified, so fontify it now.
1079 (let ((font-lock-verbose nil)) ; shut up font-lock messages
1080 (font-lock-fontify-buffer))
cf63e6fa 1081 (set-buffer-modified-p nil)
199143f1
DP
1082 (message "Executing `%s'...done" command)))
1083 ;; Now finally cd to where the shell started make/grep/...
1084 (setq default-directory thisdir))
7837c247
SM
1085 (if (buffer-local-value 'compilation-scroll-output outbuf)
1086 (save-selected-window
1087 (select-window outwin)
043442b4
KS
1088 (goto-char (point-max))))
1089 ;; Make it so the next C-x ` will use this buffer.
5d9f0de2 1090 (setq next-error-last-buffer outbuf)))
55dfd2c4 1091
c94b02d6 1092(defun compilation-set-window-height (window)
851231e9 1093 "Set the height of WINDOW according to `compilation-window-height'."
9ac57479
KS
1094 (let ((height (buffer-local-value 'compilation-window-height (window-buffer window))))
1095 (and height
1096 (= (window-width window) (frame-width (window-frame window)))
1097 ;; If window is alone in its frame, aside from a minibuffer,
1098 ;; don't change its height.
1099 (not (eq window (frame-root-window (window-frame window))))
b3ef54c5
DP
1100 ;; Stef said that doing the saves in this order is safer:
1101 (save-excursion
9ac57479 1102 (save-selected-window
b3ef54c5
DP
1103 (select-window window)
1104 (enlarge-window (- height (window-height))))))))
c94b02d6 1105
4282eba1
SM
1106(defvar compilation-menu-map
1107 (let ((map (make-sparse-keymap "Errors")))
1108 (define-key map [stop-subjob]
37bf89ab 1109 '("Stop Compilation" . kill-compilation))
4282eba1
SM
1110 (define-key map [compilation-mode-separator2]
1111 '("----" . nil))
9ac57479 1112 (define-key map [compilation-first-error]
4282eba1 1113 '("First Error" . first-error))
9ac57479 1114 (define-key map [compilation-previous-error]
4282eba1 1115 '("Previous Error" . previous-error))
9ac57479 1116 (define-key map [compilation-next-error]
4282eba1
SM
1117 '("Next Error" . next-error))
1118 map))
1119
0b18a8f6 1120(defvar compilation-minor-mode-map
55dfd2c4 1121 (let ((map (make-sparse-keymap)))
9da85ee5 1122 (define-key map [mouse-2] 'compile-goto-error)
0ac804df 1123 (define-key map [follow-link] 'mouse-face)
55dfd2c4 1124 (define-key map "\C-c\C-c" 'compile-goto-error)
4e7ce12e 1125 (define-key map "\C-m" 'compile-goto-error)
d3cb357b 1126 (define-key map "\C-c\C-k" 'kill-compilation)
646bd331
RM
1127 (define-key map "\M-n" 'compilation-next-error)
1128 (define-key map "\M-p" 'compilation-previous-error)
d1ed4475
RM
1129 (define-key map "\M-{" 'compilation-previous-file)
1130 (define-key map "\M-}" 'compilation-next-file)
4282eba1
SM
1131 ;; Set up the menu-bar
1132 (define-key map [menu-bar compilation]
1133 (cons "Errors" compilation-menu-map))
55dfd2c4 1134 map)
4f6e4ad6 1135 "Keymap for `compilation-minor-mode'.")
0b18a8f6 1136
a24770bc
RS
1137(defvar compilation-shell-minor-mode-map
1138 (let ((map (make-sparse-keymap)))
a24770bc
RS
1139 (define-key map "\M-\C-m" 'compile-goto-error)
1140 (define-key map "\M-\C-n" 'compilation-next-error)
1141 (define-key map "\M-\C-p" 'compilation-previous-error)
1142 (define-key map "\M-{" 'compilation-previous-file)
1143 (define-key map "\M-}" 'compilation-next-file)
1144 ;; Set up the menu-bar
4282eba1
SM
1145 (define-key map [menu-bar compilation]
1146 (cons "Errors" compilation-menu-map))
a24770bc
RS
1147 map)
1148 "Keymap for `compilation-shell-minor-mode'.")
1149
60470fd2
SM
1150(defvar compilation-button-map
1151 (let ((map (make-sparse-keymap)))
1152 (define-key map [mouse-2] 'compile-goto-error)
0ac804df 1153 (define-key map [follow-link] 'mouse-face)
60470fd2
SM
1154 (define-key map "\C-m" 'compile-goto-error)
1155 map)
1156 "Keymap for compilation-message buttons.")
1157(fset 'compilation-button-map compilation-button-map)
1158
0b18a8f6 1159(defvar compilation-mode-map
4282eba1 1160 (let ((map (make-sparse-keymap)))
261b01c6
RS
1161 ;; Don't inherit from compilation-minor-mode-map,
1162 ;; because that introduces a menu bar item we don't want.
1163 ;; That confuses C-down-mouse-3.
5988691b 1164 (define-key map [mouse-2] 'compile-goto-error)
0ac804df 1165 (define-key map [follow-link] 'mouse-face)
5988691b
RS
1166 (define-key map "\C-c\C-c" 'compile-goto-error)
1167 (define-key map "\C-m" 'compile-goto-error)
1168 (define-key map "\C-c\C-k" 'kill-compilation)
1169 (define-key map "\M-n" 'compilation-next-error)
1170 (define-key map "\M-p" 'compilation-previous-error)
1171 (define-key map "\M-{" 'compilation-previous-file)
1172 (define-key map "\M-}" 'compilation-next-file)
70fec115
JL
1173 (define-key map "\t" 'compilation-next-error)
1174 (define-key map [backtab] 'compilation-previous-error)
5988691b 1175
0b18a8f6
RM
1176 (define-key map " " 'scroll-up)
1177 (define-key map "\^?" 'scroll-down)
221206e3 1178 (define-key map "\C-c\C-f" 'next-error-follow-minor-mode)
9ac57479 1179
e60476ca 1180 ;; Set up the menu-bar
5988691b
RS
1181 (let ((submap (make-sparse-keymap "Compile")))
1182 (define-key map [menu-bar compilation]
1183 (cons "Compile" submap))
1184 (set-keymap-parent submap compilation-menu-map))
4282eba1 1185 (define-key map [menu-bar compilation compilation-separator2]
e60476ca 1186 '("----" . nil))
9ac57479 1187 (define-key map [menu-bar compilation compilation-grep]
314b410b 1188 '("Search Files (grep)..." . grep))
9ac57479 1189 (define-key map [menu-bar compilation compilation-recompile]
e60476ca 1190 '("Recompile" . recompile))
9ac57479 1191 (define-key map [menu-bar compilation compilation-compile]
32f4ab17 1192 '("Compile..." . compile))
0b18a8f6
RM
1193 map)
1194 "Keymap for compilation log buffers.
4282eba1 1195`compilation-minor-mode-map' is a parent of this.")
55dfd2c4 1196
0a35bd79
RS
1197(put 'compilation-mode 'mode-class 'special)
1198
c536bb39
SM
1199(defvar compilation-skip-to-next-location t
1200 "*If non-nil, skip multiple error messages for the same source location.")
1201
1202(defcustom compilation-skip-threshold 1
1203 "*Compilation motion commands skip less important messages.
1204The value can be either 2 -- skip anything less than error, 1 --
1205skip anything less than warning or 0 -- don't skip any messages.
1206Note that all messages not positively identified as warning or
1207info, are considered errors."
1208 :type '(choice (const :tag "Warnings and info" 2)
1209 (const :tag "Info" 1)
1210 (const :tag "None" 0))
f6164cdd 1211 :group 'compilation
bf247b6e 1212 :version "22.1")
c536bb39
SM
1213
1214(defcustom compilation-skip-visited nil
1215 "*Compilation motion commands skip visited messages if this is t.
1216Visited messages are ones for which the file, line and column have been jumped
1217to from the current content in the current compilation buffer, even if it was
1218from a different message."
1219 :type 'boolean
f6164cdd 1220 :group 'compilation
bf247b6e 1221 :version "22.1")
c536bb39 1222
501cf428 1223;;;###autoload
d42c87ab 1224(defun compilation-mode (&optional name-of-mode)
55dfd2c4
RS
1225 "Major mode for compilation log buffers.
1226\\<compilation-mode-map>To visit the source for a line-numbered error,
d3cb357b 1227move point to the error message line and type \\[compile-goto-error].
7c163413
RM
1228To kill the compilation, type \\[kill-compilation].
1229
2894bd96 1230Runs `compilation-mode-hook' with `run-mode-hooks' (which see).
8ff2ed52
RS
1231
1232\\{compilation-mode-map}"
55dfd2c4 1233 (interactive)
9af0d309 1234 (kill-all-local-variables)
55dfd2c4 1235 (use-local-map compilation-mode-map)
0b18a8f6 1236 (setq major-mode 'compilation-mode
d42c87ab 1237 mode-name (or name-of-mode "Compilation"))
7837c247
SM
1238 (set (make-local-variable 'page-delimiter)
1239 compilation-page-delimiter)
0b18a8f6 1240 (compilation-setup)
bd8c6db5 1241 (setq buffer-read-only t)
7837c247
SM
1242 (run-mode-hooks 'compilation-mode-hook))
1243
1244(defmacro define-compilation-mode (mode name doc &rest body)
1245 "This is like `define-derived-mode' without the PARENT argument.
1246The parent is always `compilation-mode' and the customizable `compilation-...'
bac3a1c9
JL
1247variables are also set from the name of the mode you have chosen,
1248by replacing the first word, e.g `compilation-scroll-output' from
1249`grep-scroll-output' if that variable exists."
7837c247
SM
1250 (let ((mode-name (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
1251 `(define-derived-mode ,mode compilation-mode ,name
1252 ,doc
1253 ,@(mapcar (lambda (v)
1254 (setq v (cons v
1255 (intern-soft (replace-regexp-in-string
1256 "^compilation" mode-name
1257 (symbol-name v)))))
1258 (and (cdr v)
1259 (or (boundp (cdr v))
1260 (if (boundp 'byte-compile-bound-variables)
1261 (memq (cdr v) byte-compile-bound-variables)))
1262 `(set (make-local-variable ',(car v)) ,(cdr v))))
1263 '(compilation-buffer-name-function
1264 compilation-directory-matcher
1265 compilation-error
1266 compilation-error-regexp-alist
1267 compilation-error-regexp-alist-alist
1268 compilation-error-screen-columns
1269 compilation-finish-function
1270 compilation-finish-functions
1271 compilation-first-column
1272 compilation-mode-font-lock-keywords
1273 compilation-page-delimiter
1274 compilation-parse-errors-filename-function
1275 compilation-process-setup-function
1276 compilation-scroll-output
1277 compilation-search-path
1278 compilation-skip-threshold
1279 compilation-window-height))
1280 ,@body)))
0b18a8f6 1281
58856335 1282(defun compilation-revert-buffer (ignore-auto noconfirm)
9ed2ab9f
RS
1283 (if buffer-file-name
1284 (let (revert-buffer-function)
9ac57479 1285 (revert-buffer ignore-auto noconfirm))
9ed2ab9f 1286 (if (or noconfirm (yes-or-no-p (format "Restart compilation? ")))
7837c247
SM
1287 (apply 'compilation-start compilation-arguments))))
1288
c536bb39
SM
1289(defvar compilation-current-error nil
1290 "Marker to the location from where the next error will be found.
1291The global commands next/previous/first-error/goto-error use this.")
51c8ad03 1292
9b7b51a2
SM
1293(defvar compilation-messages-start nil
1294 "Buffer position of the beginning of the compilation messages.
1295If nil, use the beginning of buffer.")
1296
7837c247
SM
1297;; A function name can't be a hook, must be something with a value.
1298(defconst compilation-turn-on-font-lock 'turn-on-font-lock)
58856335 1299
7837c247 1300(defun compilation-setup (&optional minor)
6f5b7627
SM
1301 "Prepare the buffer for the compilation parsing commands to work.
1302Optional argument MINOR indicates this is called from
1303`compilation-minor-mode'."
51c8ad03 1304 (make-local-variable 'compilation-current-error)
9b7b51a2 1305 (make-local-variable 'compilation-messages-start)
18aac618 1306 (make-local-variable 'compilation-error-screen-columns)
b3a7f48f 1307 (make-local-variable 'overlay-arrow-position)
8b71e4d1 1308 (set (make-local-variable 'overlay-arrow-string) "")
6a1cdc5b
JL
1309 (setq next-error-overlay-arrow-position nil)
1310 (add-hook 'kill-buffer-hook
1311 (lambda () (setq next-error-overlay-arrow-position nil)) nil t)
9b7b51a2
SM
1312 ;; Note that compilation-next-error-function is for interfacing
1313 ;; with the next-error function in simple.el, and it's only
1314 ;; coincidentally named similarly to compilation-next-error.
1315 (setq next-error-function 'compilation-next-error-function)
7837c247
SM
1316 (set (make-local-variable 'font-lock-extra-managed-props)
1317 '(directory message help-echo mouse-face debug))
1318 (set (make-local-variable 'compilation-locs)
1319 (make-hash-table :test 'equal :weakness 'value))
6f5b7627 1320 ;; lazy-lock would never find the message unless it's scrolled to.
c536bb39
SM
1321 ;; jit-lock might fontify some things too late.
1322 (set (make-local-variable 'font-lock-support-mode) nil)
7837c247 1323 (set (make-local-variable 'font-lock-maximum-size) nil)
f6164cdd
DP
1324 (let ((fld font-lock-defaults))
1325 (if (and minor fld)
1326 (font-lock-add-keywords nil (compilation-mode-font-lock-keywords))
1327 (setq font-lock-defaults '(compilation-mode-font-lock-keywords t)))
1328 (if minor
1329 (if font-lock-mode
1330 (if fld
1331 (font-lock-fontify-buffer)
1332 (font-lock-change-mode)
1333 (turn-on-font-lock))
1334 (turn-on-font-lock))
1335 ;; maybe defer font-lock till after derived mode is set up
1336 (run-mode-hooks 'compilation-turn-on-font-lock))))
0b18a8f6 1337
7052680b 1338;;;###autoload
4282eba1 1339(define-minor-mode compilation-shell-minor-mode
7052680b
RS
1340 "Toggle compilation shell minor mode.
1341With arg, turn compilation mode on if and only if arg is positive.
4282eba1
SM
1342In this minor mode, all the error-parsing commands of the
1343Compilation major mode are available but bound to keys that don't
1344collide with Shell mode. See `compilation-mode'.
7052680b 1345Turning the mode on runs the normal hook `compilation-shell-minor-mode-hook'."
7837c247 1346 nil " Shell-Compile"
d408fed8 1347 :group 'compilation
7837c247
SM
1348 (if compilation-shell-minor-mode
1349 (compilation-setup t)
1350 (font-lock-remove-keywords nil (compilation-mode-font-lock-keywords))
1351 (font-lock-fontify-buffer)))
7052680b 1352
d6bd8dca 1353;;;###autoload
4282eba1 1354(define-minor-mode compilation-minor-mode
0b18a8f6
RM
1355 "Toggle compilation minor mode.
1356With arg, turn compilation mode on if and only if arg is positive.
4282eba1
SM
1357In this minor mode, all the error-parsing commands of the
1358Compilation major mode are available. See `compilation-mode'.
fee3f63a 1359Turning the mode on runs the normal hook `compilation-minor-mode-hook'."
7837c247 1360 nil " Compilation"
d408fed8 1361 :group 'compilation
7837c247
SM
1362 (if compilation-minor-mode
1363 (compilation-setup t)
1364 (font-lock-remove-keywords nil (compilation-mode-font-lock-keywords))
1365 (font-lock-fontify-buffer)))
55dfd2c4 1366
fd5e58d7 1367(defun compilation-handle-exit (process-status exit-status msg)
6f5b7627 1368 "Write MSG in the current buffer and hack its mode-line-process."
d42c87ab 1369 (let ((inhibit-read-only t)
fd5e58d7
RM
1370 (status (if compilation-exit-message-function
1371 (funcall compilation-exit-message-function
1372 process-status exit-status msg)
1373 (cons msg exit-status)))
1374 (omax (point-max))
1375 (opoint (point)))
b3a7f48f 1376 ;; Record where we put the message, so we can ignore it later on.
fd5e58d7
RM
1377 (goto-char omax)
1378 (insert ?\n mode-name " " (car status))
0eac1faa 1379 (if (and (numberp compilation-window-height)
7837c247
SM
1380 (zerop compilation-window-height))
1381 (message "%s" (cdr status)))
01c50447
RS
1382 (if (bolp)
1383 (forward-char -1))
fd5e58d7 1384 (insert " at " (substring (current-time-string) 0 19))
01c50447 1385 (goto-char (point-max))
47092737
RS
1386 ;; Prevent that message from being recognized as a compilation error.
1387 (add-text-properties omax (point)
1388 (append '(compilation-handle-exit t) nil))
52f84622 1389 (setq mode-line-process (format ":%s [%s]" process-status (cdr status)))
fd5e58d7
RM
1390 ;; Force mode line redisplay soon.
1391 (force-mode-line-update)
1392 (if (and opoint (< opoint omax))
1393 (goto-char opoint))
a5f1c37e
RS
1394 (with-no-warnings
1395 (if compilation-finish-function
1396 (funcall compilation-finish-function (current-buffer) msg)))
4cc36b17
RS
1397 (let ((functions compilation-finish-functions))
1398 (while functions
1399 (funcall (car functions) (current-buffer) msg)
1400 (setq functions (cdr functions))))))
fd5e58d7 1401
55dfd2c4 1402;; Called when compilation process changes state.
55dfd2c4 1403(defun compilation-sentinel (proc msg)
d3cb357b 1404 "Sentinel for compilation buffers."
b3a7f48f
DP
1405 (if (memq (process-status proc) '(exit signal))
1406 (let ((buffer (process-buffer proc)))
1407 (if (null (buffer-name buffer))
1408 ;; buffer killed
1409 (set-process-buffer proc nil)
1410 (with-current-buffer buffer
1411 ;; Write something in the compilation buffer
1412 ;; and hack its mode line.
1413 (compilation-handle-exit (process-status proc)
1414 (process-exit-status proc)
1415 msg)
1416 ;; Since the buffer and mode line will show that the
1417 ;; process is dead, we can delete it now. Otherwise it
1418 ;; will stay around until M-x list-processes.
1419 (delete-process proc)))
1420 (setq compilation-in-progress (delq proc compilation-in-progress)))))
55dfd2c4 1421
ad62b7f1
RM
1422(defun compilation-filter (proc string)
1423 "Process filter for compilation buffers.
4f6e4ad6 1424Just inserts the text, but uses `insert-before-markers'."
991c70f8 1425 (if (buffer-name (process-buffer proc))
c536bb39
SM
1426 (with-current-buffer (process-buffer proc)
1427 (let ((inhibit-read-only t))
991c70f8
RS
1428 (save-excursion
1429 (goto-char (process-mark proc))
1430 (insert-before-markers string)
7837c247 1431 (run-hooks 'compilation-filter-hook))))))
b5bb472e 1432
5d9f0de2
KS
1433;;; test if a buffer is a compilation buffer, assuming we're in the buffer
1434(defsubst compilation-buffer-internal-p ()
1435 "Test if inside a compilation buffer."
1436 (local-variable-p 'compilation-locs))
1437
1438;;; test if a buffer is a compilation buffer, using compilation-buffer-internal-p
51ba27e7 1439(defsubst compilation-buffer-p (buffer)
5d9f0de2
KS
1440 "Test if BUFFER is a compilation buffer."
1441 (with-current-buffer buffer
1442 (compilation-buffer-internal-p)))
7837c247
SM
1443
1444(defmacro compilation-loop (< property-change 1+ error)
1445 `(while (,< n 0)
1446 (or (setq pt (,property-change pt 'message))
1447 (error ,error compilation-error))
1448 ;; prop 'message usually has 2 changes, on and off, so re-search if off
1449 (or (setq msg (get-text-property pt 'message))
1450 (if (setq pt (,property-change pt 'message))
1451 (setq msg (get-text-property pt 'message)))
1452 (error ,error compilation-error))
1453 (or (< (cadr msg) compilation-skip-threshold)
1454 (if different-file
1455 (eq (prog1 last (setq last (nth 2 (car msg))))
1456 last))
1457 (if compilation-skip-visited
1458 (nthcdr 4 (car msg)))
1459 (if compilation-skip-to-next-location
1460 (eq (car msg) loc))
1461 ;; count this message only if none of the above are true
1462 (setq n (,1+ n)))))
1463
51c8ad03 1464(defun compilation-next-error (n &optional different-file pt)
646bd331 1465 "Move point to the next error in the compilation buffer.
851231e9
DL
1466Prefix arg N says how many error messages to move forwards (or
1467backwards, if negative).
646bd331
RM
1468Does NOT find the source line like \\[next-error]."
1469 (interactive "p")
1470 (or (compilation-buffer-p (current-buffer))
851231e9 1471 (error "Not in a compilation buffer"))
51c8ad03 1472 (or pt (setq pt (point)))
51c8ad03
DP
1473 (let* ((msg (get-text-property pt 'message))
1474 (loc (car msg))
1475 last)
7837c247
SM
1476 (if (zerop n)
1477 (unless (or msg ; find message near here
c536bb39
SM
1478 (setq msg (get-text-property (max (1- pt) (point-min))
1479 'message)))
7837c247 1480 (setq pt (previous-single-property-change pt 'message nil
c536bb39 1481 (line-beginning-position)))
b3a7f48f 1482 (unless (setq msg (get-text-property (max (1- pt) (point-min)) 'message))
7837c247 1483 (setq pt (next-single-property-change pt 'message nil
c536bb39 1484 (line-end-position)))
b3a7f48f
DP
1485 (or (setq msg (get-text-property pt 'message))
1486 (setq pt (point)))))
7837c247 1487 (setq last (nth 2 (car msg)))
51c8ad03
DP
1488 (if (>= n 0)
1489 (compilation-loop > next-single-property-change 1-
1490 (if (get-buffer-process (current-buffer))
1491 "No more %ss yet"
1492 "Moved past last %s"))
c536bb39
SM
1493 ;; Don't move "back" to message at or before point.
1494 ;; Pass an explicit (point-min) to make sure pt is non-nil.
1495 (setq pt (previous-single-property-change pt 'message nil (point-min)))
51c8ad03
DP
1496 (compilation-loop < previous-single-property-change 1+
1497 "Moved back before first %s")))
7837c247
SM
1498 (goto-char pt)
1499 (or msg
1500 (error "No %s here" compilation-error))))
646bd331
RM
1501
1502(defun compilation-previous-error (n)
1503 "Move point to the previous error in the compilation buffer.
851231e9
DL
1504Prefix arg N says how many error messages to move backwards (or
1505forwards, if negative).
7837c247 1506Does NOT find the source line like \\[previous-error]."
646bd331
RM
1507 (interactive "p")
1508 (compilation-next-error (- n)))
1509
b5bb472e 1510(defun compilation-next-file (n)
24299582
DP
1511 "Move point to the next error for a different file than the current one.
1512Prefix arg N says how many files to move forwards (or backwards, if negative)."
b5bb472e 1513 (interactive "p")
7837c247 1514 (compilation-next-error n t))
b5bb472e
RM
1515
1516(defun compilation-previous-file (n)
24299582
DP
1517 "Move point to the previous error for a different file than the current one.
1518Prefix arg N says how many files to move backwards (or forwards, if negative)."
b5bb472e
RM
1519 (interactive "p")
1520 (compilation-next-file (- n)))
1521
55dfd2c4 1522(defun kill-compilation ()
b765ba64 1523 "Kill the process made by the \\[compile] or \\[grep] commands."
55dfd2c4 1524 (interactive)
d3cb357b 1525 (let ((buffer (compilation-find-buffer)))
55dfd2c4 1526 (if (get-buffer-process buffer)
d3cb357b 1527 (interrupt-process (get-buffer-process buffer))
bac3a1c9 1528 (error "The %s process is not running" (downcase mode-name)))))
d3cb357b 1529
9da85ee5 1530(defalias 'compile-mouse-goto-error 'compile-goto-error)
c536bb39 1531
9da85ee5
SM
1532(defun compile-goto-error (&optional event)
1533 "Visit the source for the error message at point.
7837c247 1534Use this command in a compilation log buffer. Sets the mark at point there."
9da85ee5 1535 (interactive (list last-input-event))
a6cd3f65 1536 (if event (posn-set-point (event-end event)))
d3cb357b 1537 (or (compilation-buffer-p (current-buffer))
851231e9 1538 (error "Not in a compilation buffer"))
b3a7f48f
DP
1539 (if (get-text-property (point) 'directory)
1540 (dired-other-window (car (get-text-property (point) 'directory)))
1541 (push-mark)
1542 (setq compilation-current-error (point))
bfd271b5 1543 (next-error 0)))
55dfd2c4 1544
d3cb357b
RM
1545;; Return a compilation buffer.
1546;; If the current buffer is a compilation buffer, return it.
d3cb357b
RM
1547;; Otherwise, look for a compilation buffer and signal an error
1548;; if there are none.
749354f0
RS
1549(defun compilation-find-buffer (&optional avoid-current)
1550 (next-error-find-buffer avoid-current 'compilation-buffer-internal-p))
d3cb357b
RM
1551
1552;;;###autoload
5d9f0de2 1553(defun compilation-next-error-function (n &optional reset)
a5f1c37e
RS
1554 "Advance to the next error message and visit the file where the error was.
1555This is the value of `next-error-function' in Compilation buffers."
7837c247 1556 (interactive "p")
5d9f0de2
KS
1557 (when reset
1558 (setq compilation-current-error nil))
7837c247
SM
1559 (let* ((columns compilation-error-screen-columns) ; buffer's local value
1560 (last 1)
51c8ad03 1561 (loc (compilation-next-error (or n 1) nil
9b7b51a2
SM
1562 (or compilation-current-error
1563 compilation-messages-start
1564 (point-min))))
7837c247
SM
1565 (end-loc (nth 2 loc))
1566 (marker (point-marker)))
51c8ad03 1567 (setq compilation-current-error (point-marker)
b3a7f48f
DP
1568 overlay-arrow-position
1569 (if (bolp)
1570 compilation-current-error
9b7b51a2 1571 (copy-marker (line-beginning-position)))
51c8ad03 1572 loc (car loc))
7837c247
SM
1573 ;; If loc contains no marker, no error in that file has been visited. If
1574 ;; the marker is invalid the buffer has been killed. So, recalculate all
1575 ;; markers for that file.
eb6fb6e2 1576 (unless (and (nth 3 loc) (marker-buffer (nth 3 loc)))
c536bb39 1577 (with-current-buffer (compilation-find-file marker (caar (nth 2 loc))
7957baea 1578 (cadr (car (nth 2 loc))))
7837c247
SM
1579 (save-restriction
1580 (widen)
c536bb39 1581 (goto-char (point-min))
7837c247
SM
1582 ;; Treat file's found lines in forward order, 1 by 1.
1583 (dolist (line (reverse (cddr (nth 2 loc))))
1584 (when (car line) ; else this is a filename w/o a line#
1585 (beginning-of-line (- (car line) last -1))
1586 (setq last (car line)))
1587 ;; Treat line's found columns and store/update a marker for each.
1588 (dolist (col (cdr line))
1589 (if (car col)
1590 (if (eq (car col) -1) ; special case for range end
1591 (end-of-line)
9c8e6c85 1592 (compilation-move-to-column (car col) columns))
7837c247
SM
1593 (beginning-of-line)
1594 (skip-chars-forward " \t"))
eb6fb6e2 1595 (if (nth 3 col)
7837c247
SM
1596 (set-marker (nth 3 col) (point))
1597 (setcdr (nthcdr 2 col) `(,(point-marker)))))))))
1598 (compilation-goto-locus marker (nth 3 loc) (nth 3 end-loc))
1599 (setcdr (nthcdr 3 loc) t))) ; Set this one as visited.
1600
e3bef839
SM
1601(defvar compilation-gcpro nil
1602 "Internal variable used to keep some values from being GC'd.")
1603(make-variable-buffer-local 'compilation-gcpro)
1604
eb6fb6e2
DP
1605(defun compilation-fake-loc (marker file &optional line col)
1606 "Preassociate MARKER with FILE.
dbd97672 1607FILE should be ABSOLUTE-FILENAME or (RELATIVE-FILENAME . DIRNAME).
eb6fb6e2
DP
1608This is useful when you compile temporary files, but want
1609automatic translation of the messages to the real buffer from
1610which the temporary file came. This only works if done before a
1611message about FILE appears!
1612
1613Optional args LINE and COL default to 1 and beginning of
1614indentation respectively. The marker is expected to reflect
1615this. In the simplest case the marker points to the first line
1616of the region that was saved to the temp file.
1617
1618If you concatenate several regions into the temp file (e.g. a
1619header with variable assignments and a code region), you must
1620call this several times, once each for the last line of one
1621region and the first line of the next region."
1622 (or (consp file) (setq file (list file)))
dbd97672 1623 (setq file (compilation-get-file-structure file))
e3bef839
SM
1624 ;; Between the current call to compilation-fake-loc and the first occurrence
1625 ;; of an error message referring to `file', the data is only kept is the
1626 ;; weak hash-table compilation-locs, so we need to prevent this entry
1627 ;; in compilation-locs from being GC'd away. --Stef
1628 (push file compilation-gcpro)
eb6fb6e2
DP
1629 (let ((loc (compilation-assq (or line 1) (cdr file))))
1630 (setq loc (compilation-assq col loc))
1631 (if (cdr loc)
1632 (setcdr (cddr loc) (list marker))
dbd97672 1633 (setcdr loc (list line file marker)))
eb6fb6e2
DP
1634 loc))
1635
8b71e4d1
NR
1636(defcustom compilation-context-lines nil
1637 "Display this many lines of leading context before the current message.
1638If nil and the left fringe is displayed, don't scroll the
1639compilation output window; an arrow in the left fringe points to
1640the current message. If nil and there is no left fringe, the message
1641displays at the top of the window; there is no arrow."
a3a9c080 1642 :type '(choice integer (const :tag "No window scrolling" nil))
f6164cdd 1643 :group 'compilation
bf247b6e 1644 :version "22.1")
7837c247
SM
1645
1646(defsubst compilation-set-window (w mk)
6f5b7627 1647 "Align the compilation output window W with marker MK near top."
a3a9c080
JL
1648 (if (integerp compilation-context-lines)
1649 (set-window-start w (save-excursion
8b71e4d1
NR
1650 (goto-char mk)
1651 (beginning-of-line
1652 (- 1 compilation-context-lines))
1653 (point)))
3c9e7f42
RS
1654 ;; If there is no left fringe.
1655 (if (equal (car (window-fringes)) 0)
8b71e4d1
NR
1656 (set-window-start w (save-excursion
1657 (goto-char mk)
1658 (beginning-of-line 1)
1659 (point)))))
1660 (set-window-point w mk))
7837c247 1661
0ea50e43
RS
1662(defvar next-error-highlight-timer)
1663
7837c247 1664(defun compilation-goto-locus (msg mk end-mk)
6f5b7627 1665 "Jump to an error corresponding to MSG at MK.
9dc3a46a
JL
1666All arguments are markers. If END-MK is non-nil, mark is set there
1667and overlay is highlighted between MK and END-MK."
d28701c7 1668 (if (eq (window-buffer (selected-window))
7837c247 1669 (marker-buffer msg))
d28701c7
RS
1670 ;; If the compilation buffer window is selected,
1671 ;; keep the compilation buffer in this window;
1672 ;; display the source in another window.
1673 (let ((pop-up-windows t))
7837c247 1674 (pop-to-buffer (marker-buffer mk)))
8f36a284 1675 (if (window-dedicated-p (selected-window))
7837c247
SM
1676 (pop-to-buffer (marker-buffer mk))
1677 (switch-to-buffer (marker-buffer mk))))
1678 ;; If narrowing gets in the way of going to the right place, widen.
1679 (unless (eq (goto-char mk) (point))
1680 (widen)
1681 (goto-char mk))
1682 (if end-mk
9dc3a46a 1683 (push-mark end-mk t)
7837c247 1684 (if mark-active (setq mark-active)))
721cfafe
TTN
1685 ;; If hideshow got in the way of
1686 ;; seeing the right place, open permanently.
7837c247
SM
1687 (dolist (ov (overlays-at (point)))
1688 (when (eq 'hs (overlay-get ov 'invisible))
1689 (delete-overlay ov)
1690 (goto-char mk)))
eaa3cac5
RM
1691
1692 ;; Show compilation buffer in other window, scrolled to this error.
1693 (let* ((pop-up-windows t)
eae2c972 1694 ;; Use an existing window if it is in a visible frame.
7bbbd31f
SM
1695 (pre-existing (get-buffer-window (marker-buffer msg) 0))
1696 (w (let ((display-buffer-reuse-frames t))
1697 ;; Pop up a window.
1698 (display-buffer (marker-buffer msg))))
7837c247
SM
1699 (highlight-regexp (with-current-buffer (marker-buffer msg)
1700 ;; also do this while we change buffer
1701 (compilation-set-window w msg)
9ac57479 1702 compilation-highlight-regexp)))
7bbbd31f
SM
1703 ;; Ideally, the window-size should be passed to `display-buffer' (via
1704 ;; something like special-display-buffer) so it's only used when
1705 ;; creating a new window.
1706 (unless pre-existing (compilation-set-window-height w))
9ac57479 1707
9dc3a46a 1708 (when highlight-regexp
073fcaf6
JL
1709 (if (timerp next-error-highlight-timer)
1710 (cancel-timer next-error-highlight-timer))
9ac57479 1711 (unless compilation-highlight-overlay
c536bb39
SM
1712 (setq compilation-highlight-overlay
1713 (make-overlay (point-min) (point-min)))
2beb6aa0 1714 (overlay-put compilation-highlight-overlay 'face 'next-error))
7837c247 1715 (with-current-buffer (marker-buffer mk)
9ac57479 1716 (save-excursion
9dc3a46a 1717 (if end-mk (goto-char end-mk) (end-of-line))
c536bb39 1718 (let ((end (point)))
9dc3a46a 1719 (if mk (goto-char mk) (beginning-of-line))
9ac57479 1720 (if (and (stringp highlight-regexp)
7837c247 1721 (re-search-forward highlight-regexp end t))
9ac57479
KS
1722 (progn
1723 (goto-char (match-beginning 0))
2beb6aa0
JL
1724 (move-overlay compilation-highlight-overlay
1725 (match-beginning 0) (match-end 0)
1726 (current-buffer)))
1727 (move-overlay compilation-highlight-overlay
1728 (point) end (current-buffer)))
1729 (if (numberp next-error-highlight)
073fcaf6
JL
1730 (setq next-error-highlight-timer
1731 (run-at-time next-error-highlight nil 'delete-overlay
1732 compilation-highlight-overlay)))
1733 (if (not (or (eq next-error-highlight t)
1734 (numberp next-error-highlight)))
2beb6aa0
JL
1735 (delete-overlay compilation-highlight-overlay))))))
1736 (when (and (eq next-error-highlight 'fringe-arrow))
6a1cdc5b
JL
1737 (setq next-error-overlay-arrow-position
1738 (copy-marker (line-beginning-position))))))
1739
eaa3cac5 1740\f
7957baea 1741(defun compilation-find-file (marker filename directory &rest formats)
851231e9 1742 "Find a buffer for file FILENAME.
ffb4b7a1
SM
1743Search the directories in `compilation-search-path'.
1744A nil in `compilation-search-path' means to try the
7957baea
RS
1745\"current\" directory, which is passed in DIRECTORY.
1746If DIRECTORY. is relative, it is combined with `default-directory'.
1747If DIRECTORY. is nil, that means use `default-directory'.
851231e9
DL
1748If FILENAME is not found at all, ask the user where to find it.
1749Pop up the buffer containing MARKER and scroll to MARKER if we ask the user."
20c1daec 1750 (or formats (setq formats '("%s")))
721cfafe
TTN
1751 (save-excursion
1752 (let ((dirs compilation-search-path)
7957baea
RS
1753 (spec-dir (if directory
1754 (expand-file-name directory)
1755 default-directory))
721cfafe
TTN
1756 buffer thisdir fmts name)
1757 (if (file-name-absolute-p filename)
5b6858da
SM
1758 ;; The file name is absolute. Use its explicit directory as
1759 ;; the first in the search path, and strip it from FILENAME.
1760 (setq filename (abbreviate-file-name (expand-file-name filename))
1761 dirs (cons (file-name-directory filename) dirs)
1762 filename (file-name-nondirectory filename)))
721cfafe
TTN
1763 ;; Now search the path.
1764 (while (and dirs (null buffer))
7957baea 1765 (setq thisdir (or (car dirs) spec-dir)
721cfafe
TTN
1766 fmts formats)
1767 ;; For each directory, try each format string.
1768 (while (and fmts (null buffer))
1769 (setq name (expand-file-name (format (car fmts) filename) thisdir)
1770 buffer (and (file-exists-p name)
ffb4b7a1 1771 (find-file-noselect name))
721cfafe
TTN
1772 fmts (cdr fmts)))
1773 (setq dirs (cdr dirs)))
1774 (or buffer
7837c247
SM
1775 ;; The file doesn't exist. Ask the user where to find it.
1776 (let ((pop-up-windows t))
1777 (compilation-set-window (display-buffer (marker-buffer marker))
1778 marker)
721cfafe
TTN
1779 (let ((name (expand-file-name
1780 (read-file-name
5b76833f 1781 (format "Find this %s in (default %s): "
bac3a1c9 1782 compilation-error filename)
7957baea 1783 spec-dir filename t))))
721cfafe
TTN
1784 (if (file-directory-p name)
1785 (setq name (expand-file-name filename name)))
1786 (setq buffer (and (file-exists-p name)
1787 (find-file name))))))
1788 ;; Make intangible overlays tangible.
1789 (mapcar (function (lambda (ov)
1790 (when (overlay-get ov 'intangible)
1791 (overlay-put ov 'intangible nil))))
1792 (overlays-in (point-min) (point-max)))
1793 buffer)))
1794
dbd97672
DP
1795(defun compilation-get-file-structure (file &optional fmt)
1796 "Retrieve FILE's file-structure or create a new one.
7957baea
RS
1797FILE should be (FILENAME) or (RELATIVE-FILENAME . DIRNAME).
1798In the former case, FILENAME may be relative or absolute.
dbd97672 1799
7957baea
RS
1800The file-structure looks like this:
1801 (list (list FILENAME [DIR-FROM-PREV-MSG]) FMT LINE-STRUCT...)
1802"
dbd97672
DP
1803 (or (gethash file compilation-locs)
1804 ;; File was not previously encountered, at least not in the form passed.
1805 ;; Let's normalize it and look again.
1806 (let ((filename (car file))
7957baea
RS
1807 ;; Get the specified directory from FILE.
1808 (spec-directory (if (cdr file)
1809 (file-truename (cdr file)))))
dbd97672
DP
1810
1811 ;; Check for a comint-file-name-prefix and prepend it if appropriate.
1812 ;; (This is very useful for compilation-minor-mode in an rlogin-mode
1813 ;; buffer.)
7957baea
RS
1814 (when (and (boundp 'comint-file-name-prefix)
1815 (not (equal comint-file-name-prefix "")))
1816 (if (file-name-absolute-p filename)
1817 (setq filename
1818 (concat comint-file-name-prefix filename))
1819 (if spec-directory
1820 (setq spec-directory
1821 (file-truename
1822 (concat comint-file-name-prefix spec-directory))))))
dbd97672
DP
1823
1824 ;; If compilation-parse-errors-filename-function is
1825 ;; defined, use it to process the filename.
1826 (when compilation-parse-errors-filename-function
1827 (setq filename
1828 (funcall compilation-parse-errors-filename-function
1829 filename)))
1830
1831 ;; Some compilers (e.g. Sun's java compiler, reportedly) produce bogus
1832 ;; file names like "./bar//foo.c" for file "bar/foo.c";
1833 ;; expand-file-name will collapse these into "/foo.c" and fail to find
1834 ;; the appropriate file. So we look for doubled slashes in the file
1835 ;; name and fix them.
1836 (setq filename (command-line-normalize-file-name filename))
1837
dbd97672
DP
1838 ;; Store it for the possibly unnormalized name
1839 (puthash file
1840 ;; Retrieve or create file-structure for normalized name
7957baea
RS
1841 (or (gethash (list filename) compilation-locs)
1842 (puthash (list filename)
1843 (list (list filename spec-directory) fmt)
1844 compilation-locs))
dbd97672 1845 compilation-locs))))
51501e54 1846
7837c247 1847(add-to-list 'debug-ignored-errors "^No more [-a-z ]+s yet$")
f1ed9461 1848
c536bb39
SM
1849;;; Compatibility with the old compile.el.
1850
1851(defun compile-buffer-substring (n) (if n (match-string n)))
1852
1853(defun compilation-compat-error-properties (err)
6f5b7627 1854 "Map old-style error ERR to new-style message."
efb0e677
SM
1855 ;; Old-style structure is (MARKER (FILE DIR) LINE COL) or
1856 ;; (MARKER . MARKER).
1857 (let ((dst (cdr err)))
1858 (if (markerp dst)
1859 ;; Must start with a face, for font-lock.
1860 `(face nil
1861 message ,(list (list nil nil nil dst) 2)
1862 help-echo "mouse-2: visit the source location"
1863 keymap compilation-button-map
1864 mouse-face highlight)
1865 ;; Too difficult to do it by hand: dispatch to the normal code.
1866 (let* ((file (pop dst))
1867 (line (pop dst))
1868 (col (pop dst))
1869 (filename (pop file))
1870 (dirname (pop file))
1871 (fmt (pop file)))
1872 (compilation-internal-error-properties
1873 (cons filename dirname) line nil col nil 2 fmt)))))
c536bb39
SM
1874
1875(defun compilation-compat-parse-errors (limit)
1876 (when compilation-parse-errors-function
1877 ;; FIXME: We should remove the rest of the compilation keywords
1878 ;; but we can't do that from here because font-lock is using
1879 ;; the value right now. --stef
1880 (save-excursion
1881 (setq compilation-error-list nil)
1882 ;; Reset compilation-parsing-end each time because font-lock
1883 ;; might force us the re-parse many times (typically because
1884 ;; some code adds some text-property to the output that we
1885 ;; already parsed). You might say "why reparse", well:
1886 ;; because font-lock has just removed the `message' property so
1887 ;; have to do it all over again.
1888 (if compilation-parsing-end
1889 (set-marker compilation-parsing-end (point))
1890 (setq compilation-parsing-end (point-marker)))
1891 (condition-case nil
1892 ;; Ignore any error: we're calling this function earlier than
1893 ;; in the old compile.el so things might not all be setup yet.
1894 (funcall compilation-parse-errors-function limit nil)
1895 (error nil))
1896 (dolist (err (if (listp compilation-error-list) compilation-error-list))
1897 (let* ((src (car err))
1898 (dst (cdr err))
1899 (loc (cond ((markerp dst) (list nil nil nil dst))
1900 ((consp dst)
1901 (list (nth 2 dst) (nth 1 dst)
1902 (cons (cdar dst) (caar dst)))))))
1903 (when loc
1904 (goto-char src)
1905 ;; (put-text-property src (line-end-position) 'font-lock-face 'font-lock-warning-face)
1906 (put-text-property src (line-end-position)
1907 'message (list loc 2)))))))
1908 (goto-char limit)
1909 nil)
1910
9b7b51a2 1911;; Beware: this is not only compatiblity code. New code stil uses it. --Stef
c536bb39
SM
1912(defun compilation-forget-errors ()
1913 ;; In case we hit the same file/line specs, we want to recompute a new
1914 ;; marker for them, so flush our cache.
b3a7f48f 1915 (setq compilation-locs (make-hash-table :test 'equal :weakness 'value))
e3bef839 1916 (setq compilation-gcpro nil)
c536bb39
SM
1917 ;; FIXME: the old code reset the directory-stack, so maybe we should
1918 ;; put a `directory change' marker of some sort, but where? -stef
b3a7f48f 1919 ;;
c536bb39
SM
1920 ;; FIXME: The old code moved compilation-current-error (which was
1921 ;; virtually represented by a mix of compilation-parsing-end and
1922 ;; compilation-error-list) to point-min, but that was only meaningful for
1923 ;; the internal uses of compilation-forget-errors: all calls from external
1924 ;; packages seem to be followed by a move of compilation-parsing-end to
1925 ;; something equivalent to point-max. So we speculatively move
1926 ;; compilation-current-error to point-max (since the external package
1927 ;; won't know that it should do it). --stef
9b7b51a2
SM
1928 (setq compilation-current-error nil)
1929 (let* ((proc (get-buffer-process (current-buffer)))
1930 (mark (if proc (process-mark proc)))
1931 (pos (or mark (point-max))))
1932 (setq compilation-messages-start
1933 ;; In the future, ignore the text already present in the buffer.
1934 ;; Since many process filter functions insert before markers,
1935 ;; we need to put ours just before the insertion point rather
1936 ;; than at the insertion point. If that's not possible, then
1937 ;; don't use a marker. --Stef
1938 (if (> pos (point-min)) (copy-marker (1- pos)) pos))))
c536bb39 1939
0c9a01ff
MY
1940;;;###autoload
1941(add-to-list 'auto-mode-alist '("\\.gcov\\'" . compilation-mode))
1942
4746118a 1943(provide 'compile)
fad160d5 1944
822001db 1945;; arch-tag: 12465727-7382-4f72-b234-79855a00dd8c
fad160d5 1946;;; compile.el ends here