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