-;;; compile.el --- run compiler as inferior of Emacs, parse error messages
+;;; compile.el --- run compiler as inferior of Emacs, parse error messages -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 1993-1999, 2001-2015 Free Software
+;; Copyright (C) 1985-1987, 1993-1999, 2001-2016 Free Software
;; Foundation, Inc.
;; Authors: Roland McGrath <roland@gnu.org>,
;; emacs -batch -l compile-tests.el -f ert-run-tests-batch-and-exit
(defvar compilation-error-regexp-alist-alist
- '((absoft
+ `((absoft
"^\\(?:[Ee]rror on \\|[Ww]arning on\\( \\)\\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
" in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
(ant
- "^[ \t]*\\[[^] \n]+\\][ \t]*\\([^: \n]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\)?\
+ "^[ \t]*\\[[^] \n]+\\][ \t]*\\(\\(?:[A-Za-z]:\\\\\\)?[^: \n]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\)?\
\\( warning\\)?" 1 (2 . 4) (3 . 5) (6))
(bash
(cucumber
"\\(?:^cucumber\\(?: -p [^[:space:]]+\\)?\\|#\\)\
-\\(?: \\)\\([^\(].*\\):\\([1-9][0-9]*\\)" 1 2)
+\\(?: \\)\\([^(].*\\):\\([1-9][0-9]*\\)" 1 2)
(msft
;; Must be before edg-1, so that MSVC's longer messages are
;; due to matching filenames via \\(.*?\\). This might be faster.
(maven
;; Maven is a popular free software build tool for Java.
- "\\([^ \n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\] " 1 2 3)
+ "\\(\\[WARNING\\] *\\)?\\([^ \n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\] " 2 3 4 (1))
(jikes-line
"^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
1 2 3 (4 . 5))
(ruby-Test::Unit
- "^[\t ]*\\[\\([^\(].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:in " 1 2)
+ "^[\t ]*\\[\\([^(].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:in " 1 2)
(gnu
;; The first line matches the program name for
;; 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 -, 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]+\\)\\(?:-\\(?4:[0-9]+\\)\\(?:\\.\\(?5:[0-9]+\\)\\)?\
-\\|[.:]\\(?3:[0-9]+\\)\\(?:-\\(?:\\(?4:[0-9]+\\)\\.\\)?\\(?5:[0-9]+\\)\\)?\\)?:\
-\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
- *\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|\\[ skipping .+ \\]\\|\
-\\(?:instantiated\\|required\\) from\\|[Nn]ote\\)\\|\
- *[Ee]rror\\|[0-9]?\\(?:[^0-9\n]\\|$\\)\\|[0-9][0-9][0-9]\\)"
+ ,(rx
+ bol
+ (? (| (regexp "[[:alpha:]][-[:alnum:].]+: ?")
+ (regexp "[ \t]+\\(?:in \\|from\\)")))
+ (group-n 1 (: (regexp "[0-9]*[^0-9\n]")
+ (*? (| (regexp "[^\n :]")
+ (regexp " [^-/\n]")
+ (regexp ":[^ \n]")))))
+ (regexp ": ?")
+ (group-n 2 (regexp "[0-9]+"))
+ (? (| (: "-"
+ (group-n 4 (regexp "[0-9]+"))
+ (? "." (group-n 5 (regexp "[0-9]+"))))
+ (: (in ".:")
+ (group-n 3 (regexp "[0-9]+"))
+ (? "-"
+ (? (group-n 4 (regexp "[0-9]+")) ".")
+ (group-n 5 (regexp "[0-9]+"))))))
+ ":"
+ (| (: (* " ")
+ (group-n 6 (| "FutureWarning"
+ "RuntimeWarning"
+ "Warning"
+ "warning"
+ "W:")))
+ (: (* " ")
+ (group-n 7 (| (regexp "[Ii]nfo\\(?:\\>\\|rmationa?l?\\)")
+ "I:"
+ (: "[ skipping " (+ ".") " ]")
+ "instantiated from"
+ "required from"
+ (regexp "[Nn]ote"))))
+ (: (* " ")
+ (regexp "[Ee]rror"))
+ (: (regexp "[0-9]?")
+ (| (regexp "[^0-9\n]")
+ eol))
+ (regexp "[0-9][0-9][0-9]")))
1 (2 . 4) (3 . 5) (6 . 7))
(lcc
3 4 5 (1 . 2))
(sun-ada
- "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
+ "^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., (-]" 1 2 3)
(watcom
"^[ \t]*\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
;;
"^\\([^ \t\r\n(]+\\) (\\([0-9]+\\):\\([0-9]+\\)) "
1 2 3)
+
+ ;; Guile compilation yields file-headers in the following format:
+ ;;
+ ;; In sourcefile.scm:
+ ;;
+ ;; We need to catch those, but we also need to be aware that Emacs
+ ;; byte-compilation yields compiler headers in similar form of
+ ;; those:
+ ;;
+ ;; In toplevel form:
+ ;; In end of data:
+ ;;
+ ;; We want to catch the Guile file-headers but not the Emacs
+ ;; byte-compilation headers, because that will cause next-error
+ ;; and prev-error to break, because the files "toplevel form" and
+ ;; "end of data" does not exist.
+ ;;
+ ;; To differentiate between these two cases, we require that the
+ ;; file-match must always contain an extension.
+ ;;
+ ;; We should also only treat this as "info", not "error", because
+ ;; we do not know what lines will follow.
+ (guile-file "^In \\(.+\\..+\\):\n" 1 nil nil 0)
+ (guile-line "^ *\\([0-9]+\\): *\\([0-9]+\\)" nil 1 2)
)
"Alist of values for `compilation-error-regexp-alist'.")
Sometimes it is useful for files to supply local values for this variable.
You might also use mode hooks to specify it in certain modes, like this:
- (add-hook 'c-mode-hook
+ (add-hook \\='c-mode-hook
(lambda ()
(unless (or (file-exists-p \"makefile\")
(file-exists-p \"Makefile\"))
- (set (make-local-variable 'compile-command)
+ (set (make-local-variable \\='compile-command)
(concat \"make -k \"
(if buffer-file-name
(shell-quote-argument
(defvar compilation--previous-directory-cache nil
"A pair (POS . RES) caching the result of previous directory search.
Basically, this pair says that calling
- (previous-single-property-change POS 'compilation-directory)
+ (previous-single-property-change POS \\='compilation-directory)
returned RES, i.e. there is no change of `compilation-directory' between
POS and RES.")
(make-variable-buffer-local 'compilation--previous-directory-cache)
(t (setq compilation--previous-directory-cache nil))))
(defun compilation--previous-directory (pos)
- "Like (previous-single-property-change POS 'compilation-directory), but faster."
+ "Like (previous-single-property-change POS \\='compilation-directory), but faster."
;; This avoids an N² behavior when there's no/few compilation-directory
;; entries, in which case each call to previous-single-property-change
;; ends up having to walk very far back to find the last change.
(cons (copy-marker pos) (if prev (copy-marker prev))))
prev)
((and prev (= prev cache))
- (if cache
- (set-marker (car compilation--previous-directory-cache) pos)
- (setq compilation--previous-directory-cache
- (cons (copy-marker pos) nil)))
+ (set-marker (car compilation--previous-directory-cache) pos)
(cdr compilation--previous-directory-cache))
(t
- (if cache
- (progn
- (set-marker cache pos)
- (setcdr compilation--previous-directory-cache
- (copy-marker prev)))
- (setq compilation--previous-directory-cache
- (cons (copy-marker pos) (if prev (copy-marker prev)))))
+ (set-marker cache pos)
+ (setcdr compilation--previous-directory-cache
+ (copy-marker prev))
prev))))
(if (markerp res) (marker-position res) res))))
just char-counts."
(setq col (- col compilation-first-column))
(if screen
- (move-to-column (max col 0))
+ ;; Presumably, the compilation tool doesn't know about our current
+ ;; `tab-width' setting, so it probably assumed 8-wide TABs (bug#21038).
+ (let ((tab-width 8)) (move-to-column (max col 0)))
(goto-char (min (+ (line-beginning-position) col) (line-end-position)))))
(defun compilation-internal-error-properties (file line end-line col end-col type fmts)
comint mode, i.e. interactive.
To run more than one compilation at once, start one then rename
-the \`*compilation*' buffer to some other name with
+the `*compilation*' buffer to some other name with
\\[rename-buffer]. Then _switch buffers_ and start the new compilation.
-It will create a new \`*compilation*' buffer.
+It will create a new `*compilation*' buffer.
On most systems, termination of the main compilation process
kills its subprocesses.
(list "TERM=emacs"
(format "TERMCAP=emacs:co#%d:tc=unknown:"
(window-width))))
- ;; Set the EMACS variable, but
- ;; don't override users' setting of $EMACS.
- (unless (getenv "EMACS")
- (list "EMACS=t"))
- (list "INSIDE_EMACS=t")
+ (list (format "INSIDE_EMACS=%s,compile" emacs-version))
(copy-sequence process-environment))))
(set (make-local-variable 'compilation-arguments)
(list command mode name-function highlight-regexp))
(if minor
(progn
(font-lock-add-keywords nil (compilation-mode-font-lock-keywords))
- (if font-lock-mode
- (font-lock-fontify-buffer)))
+ (font-lock-flush))
(setq font-lock-defaults '(compilation-mode-font-lock-keywords t))))
(defun compilation--unsetup ()
(remove-hook 'before-change-functions 'compilation--flush-parse t)
(kill-local-variable 'compilation--parsed)
(compilation--remove-properties)
- (if font-lock-mode
- (font-lock-fontify-buffer)))
+ (font-lock-flush))
;;;###autoload
(define-minor-mode compilation-shell-minor-mode
(or (compilation-buffer-p (current-buffer))
(error "Not in a compilation buffer"))
(or pt (setq pt (point)))
+ (compilation--ensure-parse pt)
(let* ((msg (get-text-property pt 'compilation-message))
;; `loc', `msg', and `last' are used by the compilation-loop macro.
(loc (and msg (compilation--message->loc msg)))
(line-beginning-position)))
(unless (setq msg (get-text-property (max (1- pt) (point-min))
'compilation-message))
- (setq pt (next-single-property-change pt 'compilation-message nil
+ (setq pt (compilation-next-single-property-change
+ pt 'compilation-message nil
(line-end-position)))
(or (setq msg (get-text-property pt 'compilation-message))
(setq pt (point)))))
"No more %ss yet"
"Moved past last %s")
(point-max))
- (compilation--ensure-parse pt)
;; Don't move "back" to message at or before point.
;; Pass an explicit (point-min) to make sure pt is non-nil.
(setq pt (previous-single-property-change
(- 1 compilation-context-lines))
(point)))
;; If there is no left fringe.
- (if (equal (car (window-fringes)) 0)
- (set-window-start w (save-excursion
- (goto-char mk)
+ (when (equal (car (window-fringes w)) 0)
+ (set-window-start w (save-excursion
+ (goto-char mk)
(beginning-of-line 1)
(point)))))
(set-window-point w mk))
(goto-char mk)))
(if end-mk
(push-mark end-mk t)
- (if mark-active (setq mark-active)))
+ (if mark-active (setq mark-active nil)))
;; If hideshow got in the way of
;; seeing the right place, open permanently.
(dolist (ov (overlays-at (point)))