;;; compile.el --- run compiler as inferior of Emacs, parse error messages
;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; Free Software Foundation, Inc.
;; Authors: Roland McGrath <roland@gnu.org>,
;; using the same *compilation* buffer. this necessitates re-parsing markers.
;; FILE-STRUCTURE is a list of
-;; ((FILENAME . DIRECTORY) FORMATS (LINE LOC ...) ...)
+;; ((FILENAME DIRECTORY) FORMATS (LINE LOC ...) ...)
;; FILENAME is a string parsed from an error message. DIRECTORY is a string
;; obtained by following directory change messages. DIRECTORY will be nil for
(defvar compilation-num-errors-found)
-(defconst compilation-error-regexp-alist-alist
+(defvar compilation-error-regexp-alist-alist
'((absoft
"^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
"^\"\\([^,\" \n\t]+\\)\", line \\([0-9]+\\)\
\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4))
+ (cucumber
+ "\\(?:^cucumber\\(?: -p [^[:space:]]+\\)?\\|#\\)\
+\\(?: \\)\\([^\(].*\\):\\([1-9][0-9]*\\)" 1 2)
+
(edg-1
"^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
1 2 nil (3 . 4))
nil 1 nil 2 0
(2 (compilation-face '(3))))
+ (gcc-include
+ "^\\(?:In file included \\| \\|\t\\)from \
+\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\
+\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?\\(?:\\(:\\)\\|\\(,\\|$\\)\\)?"
+ 1 2 3 (4 . 5))
+
(gnu
;; The first line matches the program name for
;; The core of the regexp is the one with *?. It says that a file name
;; can be composed of any non-newline char, but it also rules out some
;; valid but unlikely cases, such as a trailing space or a space
- ;; followed by a -.
- "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\)?\
-\\([0-9]*[^0-9\n]\\(?:[^\n ]\\| [^-/\n]\\)*?\\): ?\
-\\([0-9]+\\)\\(?:\\([.:]\\)\\([0-9]+\\)\\)?\
+ ;; followed by a -, or a colon followed by a space.
+
+ ;; The "in \\|from " exception was added to handle messages from Ruby.
+ "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\|[ \t]+\\(?:in \\|from \\)\\)?\
+\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\): ?\
+\\([0-9]+\\)\\(?:[.:]\\([0-9]+\\)\\)?\
\\(?:-\\([0-9]+\\)?\\(?:\\.\\([0-9]+\\)\\)?\\)?:\
\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
*\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|instantiated from\\|[Nn]ote\\)\\|\
\[0-9]?\\(?:[^0-9\n]\\|$\\)\\|[0-9][0-9][0-9]\\)"
- 1 (2 . 5) (4 . 6) (7 . 8))
-
- ;; The `gnu' style above can incorrectly match gcc's "In file
- ;; included from" message, so we process that first. -- cyd
- (gcc-include
- "^\\(?:In file included\\| \\) from \
-\\(.+\\):\\([0-9]+\\)\\(?:\\(:\\)\\|\\(,\\)\\)?" 1 2 nil (3 . 4))
+ 1 (2 . 4) (3 . 5) (6 . 7))
(lcc
"^\\(?:E\\|\\(W\\)\\), \\([^(\n]+\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)"
"\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
2 3 nil nil)
+ (ruby-Test::Unit
+ "[\t ]*\\[\\([^\(].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:$" 1 2)
+
(rxp
"^\\(?:Error\\|Warnin\\(g\\)\\):.*\n.* line \\([0-9]+\\) char\
\\([0-9]+\\) of file://\\(.+\\)"
"^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
(watcom
- "\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
+ "^[ \t]*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
\\(?:\\(Error! E[0-9]+\\)\\|\\(Warning! W[0-9]+\\)\\):"
1 2 nil (4))
Additional HIGHLIGHTs as described under `font-lock-keywords' can
be added."
- :type `(set :menu-tag "Pick"
- ,@(mapcar (lambda (elt)
- (list 'const (car elt)))
- compilation-error-regexp-alist-alist))
+ :type '(repeat (choice (symbol :tag "Predefined symbol")
+ (sexp :tag "Error specification")))
:link `(file-link :tag "example file"
,(expand-file-name "compilation.txt" data-directory))
:group 'compilation)
;; Command output lines. Recognize `make[n]:' lines too.
("^\\([[:alnum:]_/.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:"
(1 font-lock-function-name-face) (3 compilation-line-face nil t))
- (" --?o\\(?:utfile\\|utput\\)?[= ]?\\(\\S +\\)" . 1)
+ (" -\\(?:o[= ]?\\|-\\(?:outfile\\|output\\)[= ]\\)\\(\\S +\\)" . 1)
("^Compilation \\(finished\\).*"
(0 '(face nil message nil help-echo nil mouse-face nil) t)
(1 compilation-info-face))
:type 'boolean
:group 'compilation)
+(defcustom compilation-save-buffers-predicate nil
+ "The second argument (PRED) passed to `save-some-buffers' before compiling.
+E.g., one can set this to
+ (lambda ()
+ (string-prefix-p my-compilation-root (file-truename (buffer-file-name))))
+to limit saving to files located under `my-compilation-root'.
+Note, that, in general, `compilation-directory' cannot be used instead
+of `my-compilation-root' here."
+ :type '(choice
+ (const :tag "Default (save all file-visiting buffers)" nil)
+ (const :tag "Save all buffers" t)
+ function)
+ :group 'compilation
+ :version "24.1")
+
;;;###autoload
(defcustom compilation-search-path '(nil)
"List of directories to search for source files named in error messages.
"If non-nil, automatically jump to the next error encountered.")
(make-variable-buffer-local 'compilation-auto-jump-to-next)
+(defvar compilation-buffer-modtime nil
+ "The buffer modification time, for buffers not associated with files.")
+(make-variable-buffer-local 'compilation-buffer-modtime)
(defvar compilation-skip-to-next-location t
"*If non-nil, skip multiple error messages for the same source location.")
skip anything less than warning or 0 -- don't skip any messages.
Note that all messages not positively identified as warning or
info, are considered errors."
- :type '(choice (const :tag "Warnings and info" 2)
- (const :tag "Info" 1)
- (const :tag "None" 0))
+ :type '(choice (const :tag "Skip warnings and info" 2)
+ (const :tag "Skip info" 1)
+ (const :tag "No skip" 0))
:group 'compilation
:version "22.1")
+(defun compilation-set-skip-threshold (level)
+ "Switch the `compilation-skip-threshold' level."
+ (interactive
+ (list
+ (mod (if current-prefix-arg
+ (prefix-numeric-value current-prefix-arg)
+ (1+ compilation-skip-threshold))
+ 3)))
+ (setq compilation-skip-threshold level)
+ (message "Skipping %s"
+ (case compilation-skip-threshold
+ (0 "Nothing")
+ (1 "Info messages")
+ (2 "Warnings and info"))))
+
(defcustom compilation-skip-visited nil
"Compilation motion commands skip visited messages if this is t.
Visited messages are ones for which the file, line and column have been jumped
(consp current-prefix-arg)))
(unless (equal command (eval compile-command))
(setq compile-command command))
- (save-some-buffers (not compilation-ask-about-save) nil)
+ (save-some-buffers (not compilation-ask-about-save)
+ compilation-save-buffers-predicate)
(setq-default compilation-directory default-directory)
(compilation-start command comint))
original use. Otherwise, recompile using `compile-command'.
If the optional argument `edit-command' is non-nil, the command can be edited."
(interactive "P")
- (save-some-buffers (not compilation-ask-about-save) nil)
+ (save-some-buffers (not compilation-ask-about-save)
+ compilation-save-buffers-predicate)
(let ((default-directory (or compilation-directory default-directory)))
(when edit-command
(setcar compilation-arguments
(let* ((name-of-mode
(if (eq mode t)
"compilation"
- (replace-regexp-in-string "-mode$" "" (symbol-name mode))))
+ (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
(thisdir default-directory)
outwin outbuf)
(with-current-buffer
;; Then evaluate a cd command if any, but don't perform it yet, else
;; start-command would do it again through the shell: (cd "..") AND
;; sh -c "cd ..; make"
- (cd (if (string-match "^\\s *cd\\(?:\\s +\\(\\S +?\\)\\)?\\s *[;&\n]" command)
+ (cd (if (string-match "\\`\\s *cd\\(?:\\s +\\(\\S +?\\)\\)?\\s *[;&\n]"
+ command)
(if (match-end 1)
(substitute-env-vars (match-string 1 command))
"~")
(set (make-local-variable 'compilation-auto-jump-to-next) t))
;; Output a mode setter, for saving and later reloading this buffer.
(insert "-*- mode: " name-of-mode
- "; default-directory: " (prin1-to-string default-directory)
+ "; default-directory: "
+ (prin1-to-string (abbreviate-file-name default-directory))
" -*-\n"
(format "%s started at %s\n\n"
mode-name
(defvar compilation-mode-tool-bar-map
;; When bootstrapping, tool-bar-map is not properly initialized yet,
;; so don't do anything.
- (when (keymapp (butlast tool-bar-map))
- (let ((map (butlast (copy-keymap tool-bar-map)))
- (help (last tool-bar-map))) ;; Keep Help last in tool bar
+ (when (keymapp tool-bar-map)
+ (let ((map (copy-keymap tool-bar-map)))
+ (define-key map [undo] nil)
+ (define-key map [separator-2] nil)
+ (define-key-after map [separator-compile] menu-bar-separator)
(tool-bar-local-item
"left-arrow" 'previous-error-no-select 'previous-error-no-select map
:rtl "right-arrow"
(tool-bar-local-item
"refresh" 'recompile 'recompile map
:help "Restart compilation")
- (append map help))))
+ map)))
(put 'compilation-mode 'mode-class 'special)
;; Let windows scroll along with the output.
(set (make-local-variable 'window-point-insertion-type) t)
(set (make-local-variable 'tool-bar-map) compilation-mode-tool-bar-map)
- (setq major-mode 'compilation-mode
+ (setq major-mode 'compilation-mode ; FIXME: Use define-derived-mode.
mode-name (or name-of-mode "Compilation"))
(set (make-local-variable 'page-delimiter)
compilation-page-delimiter)
+ (set (make-local-variable 'compilation-buffer-modtime) nil)
(compilation-setup)
(setq buffer-read-only t)
(run-mode-hooks 'compilation-mode-hook))
(unless comint-inhibit-carriage-motion
(comint-carriage-motion (process-mark proc) (point)))
(set-marker (process-mark proc) (point))
+ (set (make-local-variable 'compilation-buffer-modtime) (current-time))
(run-hooks 'compilation-filter-hook))
(goto-char pos)
(narrow-to-region min max)
;; There may be no timestamp info if the loc is a `fake-loc',
;; but we just checked that the file has been visited before!
(equal (nth 4 loc)
- (setq timestamp
- (with-current-buffer (marker-buffer (nth 3 loc))
- (visited-file-modtime)))))
+ (setq timestamp compilation-buffer-modtime)))
(with-current-buffer (compilation-find-file marker (caar (nth 2 loc))
(cadr (car (nth 2 loc))))
(save-restriction
pre-existing
(let ((display-buffer-reuse-frames t)
(pop-up-windows t))
- ;; Pop up a window.
+ ;; Pop up a window.
(display-buffer (marker-buffer msg)))))
(highlight-regexp (with-current-buffer (marker-buffer msg)
;; also do this while we change buffer
(defun compilation-forget-errors ()
;; In case we hit the same file/line specs, we want to recompute a new
;; marker for them, so flush our cache.
- (setq compilation-locs (make-hash-table :test 'equal :weakness 'value))
+ (clrhash compilation-locs)
(setq compilation-gcpro nil)
;; FIXME: the old code reset the directory-stack, so maybe we should
;; put a `directory change' marker of some sort, but where? -stef
(or compilation-auto-jump-to-first-error
(eq compilation-scroll-output 'first-error))))
-;;;###autoload
-(add-to-list 'auto-mode-alist (cons (purecopy "\\.gcov\\'") 'compilation-mode))
-
(provide 'compile)
-;; arch-tag: 12465727-7382-4f72-b234-79855a00dd8c
;;; compile.el ends here