;;; 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 Free Software Foundation, Inc.
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+;; Free Software Foundation, Inc.
;; Authors: Roland McGrath <roland@gnu.org>,
;; Daniel Pfeiffer <occitan@esperanto.org>
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(eval-when-compile (require 'cl))
+(require 'tool-bar)
(defvar font-lock-extra-managed-props)
(defvar font-lock-keywords)
;; times of the form "HH:MM:SS" where MM is taken as a line number, so
;; the last line tries to rule out message where the info after the
;; line number starts with "SS". --Stef
+
+ ;; 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\n]\\(?:[^\n ]\\| [^-/\n]\\)*?\\): ?\
\\([0-9]+\\)\\(?:\\([.:]\\)\\([0-9]+\\)\\)?\
\\(?:-\\([0-9]+\\)?\\(?:\\3\\([0-9]+\\)\\)?\\)?:\
\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
" in \\([^()\n ]+\\)(\\([0-9]+\\))$" 1 2)
(msft
+ ;; AFAWK, The message may be a "warning", "error", or "fatal error".
"^\\([0-9]+>\\)?\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \
-: \\(?:error\\|warnin\\(g\\)\\) C[0-9]+:" 2 3 nil (4))
+: \\(?:warnin\\(g\\)\\|[a-z ]+\\) C[0-9]+:" 2 3 nil (4))
(oracle
"^\\(?:Semantic error\\|Error\\|PCC-[0-9]+:\\).* line \\([0-9]+\\)\
\\(?:,\\| in\\| of\\)? file \\(.*?\\):?$"
3 1 2)
+ ;; "during global destruction": This comes out under "use
+ ;; warnings" in recent perl when breaking circular references
+ ;; during program or thread exit.
(perl
- " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\)" 1 2)
+ " at \\([^ \n]+\\) line \\([0-9]+\\)\\(?:[,.]\\|$\\| \
+during global destruction\\.$\\)" 1 2)
+
+ (php
+ "\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)"
+ 2 3 nil nil)
(rxp
"^\\(?:Error\\|Warnin\\(g\\)\\):.*\n.* line \\([0-9]+\\) char\
(sun-ada
"^\\([^, \n\t]+\\), line \\([0-9]+\\), char \\([0-9]+\\)[:., \(-]" 1 2 3)
+ (watcom
+ "\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)): ?\
+\\(?:\\(Error! E[0-9]+\\)\\|\\(Warning! W[0-9]+\\)\\):"
+ 1 2 nil (4))
+
(4bsd
"\\(?:^\\|:: \\|\\S ( \\)\\(/[^ \n\t()]+\\)(\\([0-9]+\\))\
\\(?:: \\(warning:\\)?\\|$\\| ),\\)" 1 2 nil (3))
nil 2 nil 2 nil
(0 'default t)
(1 compilation-error-face prepend) (2 compilation-line-face prepend))
+
+ (perl--Pod::Checker
+ ;; podchecker error messages, per Pod::Checker.
+ ;; The style is from the Pod::Checker::poderror() function, eg.
+ ;; *** ERROR: Spurious text after =cut at line 193 in file foo.pm
+ ;;
+ ;; Plus end_pod() can give "at line EOF" instead of a
+ ;; number, so for that match "on line N" which is the
+ ;; originating spot, eg.
+ ;; *** ERROR: =over on line 37 without closing =back at line EOF in file bar.pm
+ ;;
+ ;; Plus command() can give both "on line N" and "at line N";
+ ;; the latter is desired and is matched because the .* is
+ ;; greedy.
+ ;; *** ERROR: =over on line 1 without closing =back (at head1) at line 3 in file x.pod
+ ;;
+ "^\\*\\*\\* \\(?:ERROR\\|\\(WARNING\\)\\).* \\(?:at\\|on\\) line \
+\\([0-9]+\\) \\(?:.* \\)?in file \\([^ \t\n]+\\)"
+ 3 2 nil (1))
+ (perl--Test
+ ;; perl Test module error messages.
+ ;; Style per the ok() function "$context", eg.
+ ;; # Failed test 1 in foo.t at line 6
+ ;;
+ "^# Failed test [0-9]+ in \\([^ \t\r\n]+\\) at line \\([0-9]+\\)"
+ 1 2)
+ (perl--Test2
+ ;; Or when comparing got/want values,
+ ;; # Test 2 got: "xx" (t-compilation-perl-2.t at line 10)
+ ;;
+ ;; And under Test::Harness they're preceded by progress stuff with
+ ;; \r and "NOK",
+ ;; ... NOK 1# Test 1 got: "1234" (t/foo.t at line 46)
+ ;;
+ "^\\(.*NOK.*\\)?# Test [0-9]+ got:.* (\\([^ \t\r\n]+\\) at line \
+\\([0-9]+\\))"
+ 2 3)
+ (perl--Test::Harness
+ ;; perl Test::Harness output, eg.
+ ;; NOK 1# Test 1 got: "1234" (t/foo.t at line 46)
+ ;;
+ ;; Test::Harness is slightly designed for tty output, since
+ ;; it prints CRs to overwrite progress messages, but if you
+ ;; run it in with M-x compile this pattern can at least step
+ ;; through the failures.
+ ;;
+ "^.*NOK.* \\([^ \t\r\n]+\\) at line \\([0-9]+\\)"
+ 1 2)
+ (weblint
+ ;; The style comes from HTML::Lint::Error::as_string(), eg.
+ ;; index.html (13:1) Unknown element <fdjsk>
+ ;;
+ ;; The pattern only matches filenames without spaces, since that
+ ;; should be usual and should help reduce the chance of a false
+ ;; match of a message from some unrelated program.
+ ;;
+ ;; This message style is quite close to the "ibm" entry which is
+ ;; for IBM C, though that ibm bit doesn't put a space after the
+ ;; filename.
+ ;;
+ "^\\([^ \t\r\n(]+\\) (\\([0-9]+\\):\\([0-9]+\\)) "
+ 1 2 3)
)
"Alist of values for `compilation-error-regexp-alist'.")
(defun compilation-auto-jump (buffer pos)
(with-current-buffer buffer
(goto-char pos)
- (compile-goto-error)))
+ (let ((win (get-buffer-window buffer 0)))
+ (if win (set-window-point win pos)))
+ (if compilation-auto-jump-to-first-error
+ (compile-goto-error))))
;; This function is the central driver, called when font-locking to gather
;; all information needed to later jump to corresponding source code.
(list
(let ((command (eval compile-command)))
(if (or compilation-read-command current-prefix-arg)
- (read-from-minibuffer "Compile command: "
- command nil nil
- (if (equal (car compile-history) command)
- '(compile-history . 1)
- 'compile-history))
+ (read-shell-command "Compile command: " command
+ (if (equal (car compile-history) command)
+ '(compile-history . 1)
+ 'compile-history))
command))
(consp current-prefix-arg)))
(unless (equal command (eval compile-command))
Setting it causes the Compilation mode commands to put point at the
end of their output window so that the end of the output is always
-visible rather than the beginning."
- :type 'boolean
+visible rather than the beginning.
+
+The value `first-error' stops scrolling at the first error, and leaves
+point on its location in the *compilation* buffer."
+ :type '(choice (const :tag "No scrolling" nil)
+ (const :tag "Scroll compilation output" t)
+ (const :tag "Stop scrolling at the first error" first-error))
:version "20.3"
:group 'compilation)
(compilation-error (replace-regexp-in-string "^No more \\(.+\\)s\\.?"
"\\1" error-message)))
(compilation-start command nil name-function highlight-regexp)))
-(make-obsolete 'compile-internal 'compilation-start)
+(make-obsolete 'compile-internal 'compilation-start "22.1")
;;;###autoload
(defun compilation-start (command &optional mode name-function highlight-regexp)
(error nil))
(error "Cannot have two processes in `%s' at once"
(buffer-name)))))
- (buffer-disable-undo (current-buffer))
;; first transfer directory from where M-x compile was called
(setq default-directory thisdir)
- ;; Remember the original dir, so we can use it when we recompile.
- ;; default-directory' can't be used reliably for that because it may be
- ;; affected by the special handling of "cd ...;".
- (set (make-local-variable 'compilation-directory) thisdir)
;; Make compilation buffer read-only. The filter can still write it.
;; Clear out the compilation buffer.
(let ((inhibit-read-only t)
(erase-buffer)
;; Select the desired mode.
(if (not (eq mode t))
- (funcall mode)
+ (progn
+ (buffer-disable-undo)
+ (funcall mode))
(setq buffer-read-only nil)
(with-no-warnings (comint-mode))
(compilation-shell-minor-mode))
+ ;; Remember the original dir, so we can use it when we recompile.
+ ;; default-directory' can't be used reliably for that because it may be
+ ;; affected by the special handling of "cd ...;".
+ ;; NB: must be fone after (funcall mode) as that resets local variables
+ (set (make-local-variable 'compilation-directory) thisdir)
(if highlight-regexp
(set (make-local-variable 'compilation-highlight-regexp)
highlight-regexp))
- (if compilation-auto-jump-to-first-error
+ (if (or compilation-auto-jump-to-first-error
+ (eq compilation-scroll-output 'first-error))
(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
command "\n")
(setq thisdir default-directory))
(set-buffer-modified-p nil))
- ;; If we're already in the compilation buffer, go to the end
- ;; of the buffer, so point will track the compilation output.
- (if (eq outbuf (current-buffer))
- (goto-char (point-max)))
;; Pop up the compilation buffer.
- (setq outwin (display-buffer outbuf nil t))
+ ;; http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01638.html
+ (setq outwin (display-buffer outbuf))
(with-current-buffer outbuf
(let ((process-environment
(append
(set (make-local-variable 'revert-buffer-function)
'compilation-revert-buffer)
(set-window-start outwin (point-min))
- (or (eq outwin (selected-window))
- (set-window-point outwin (if compilation-scroll-output
- (point)
- (point-min))))
+
+ ;; Position point as the user will see it.
+ (let ((desired-visible-point
+ ;; Put it at the end if `compilation-scroll-output' is set.
+ (if compilation-scroll-output
+ (point-max)
+ ;; Normally put it at the top.
+ (point-min))))
+ (if (eq outwin (selected-window))
+ (goto-char desired-visible-point)
+ (set-window-point outwin desired-visible-point)))
+
;; The setup function is called before compilation-set-window-height
;; so it can set the compilation-window-height buffer locally.
(if compilation-process-setup-function
(funcall compilation-process-setup-function))
(compilation-set-window-height outwin)
;; Start the compilation.
- (let ((proc
- (if (eq mode t)
- ;; comint uses `start-file-process'.
- (get-buffer-process
- (with-no-warnings
- (comint-exec
- outbuf (downcase mode-name)
- (if (file-remote-p default-directory)
- "/bin/sh"
- shell-file-name)
- nil `("-c" ,command))))
- (start-file-process-shell-command (downcase mode-name)
- outbuf command))))
- ;; Make the buffer's mode line show process state.
- (setq mode-line-process '(":%s"))
- (set-process-sentinel proc 'compilation-sentinel)
- (set-process-filter proc 'compilation-filter)
- (set-marker (process-mark proc) (point) outbuf)
- (when compilation-disable-input
- (condition-case nil
- (process-send-eof proc)
- ;; The process may have exited already.
- (error nil)))
- (setq compilation-in-progress
- (cons proc compilation-in-progress))))
+ (if (fboundp 'start-process)
+ (let ((proc
+ (if (eq mode t)
+ ;; comint uses `start-file-process'.
+ (get-buffer-process
+ (with-no-warnings
+ (comint-exec
+ outbuf (downcase mode-name)
+ (if (file-remote-p default-directory)
+ "/bin/sh"
+ shell-file-name)
+ nil `("-c" ,command))))
+ (start-file-process-shell-command (downcase mode-name)
+ outbuf command))))
+ ;; Make the buffer's mode line show process state.
+ (setq mode-line-process
+ (list (propertize ":%s" 'face 'compilation-warning)))
+ (set-process-sentinel proc 'compilation-sentinel)
+ (unless (eq mode t)
+ ;; Keep the comint filter, since it's needed for proper handling
+ ;; of the prompts.
+ (set-process-filter proc 'compilation-filter))
+ ;; Use (point-max) here so that output comes in
+ ;; after the initial text,
+ ;; regardless of where the user sees point.
+ (set-marker (process-mark proc) (point-max) outbuf)
+ (when compilation-disable-input
+ (condition-case nil
+ (process-send-eof proc)
+ ;; The process may have exited already.
+ (error nil)))
+ (setq compilation-in-progress
+ (cons proc compilation-in-progress)))
+ ;; No asynchronous processes available.
+ (message "Executing `%s'..." command)
+ ;; Fake modeline display as if `start-process' were run.
+ (setq mode-line-process
+ (list (propertize ":run" 'face 'compilation-warning)))
+ (force-mode-line-update)
+ (sit-for 0) ; Force redisplay
+ (save-excursion
+ ;; Insert the output at the end, after the initial text,
+ ;; regardless of where the user sees point.
+ (goto-char (point-max))
+ (let* ((buffer-read-only nil) ; call-process needs to modify outbuf
+ (status (call-process shell-file-name nil outbuf nil "-c"
+ command)))
+ (cond ((numberp status)
+ (compilation-handle-exit
+ 'exit status
+ (if (zerop status)
+ "finished\n"
+ (format "exited abnormally with code %d\n" status))))
+ ((stringp status)
+ (compilation-handle-exit 'signal status
+ (concat status "\n")))
+ (t
+ (compilation-handle-exit 'bizarre status status)))))
+ ;; Without async subprocesses, the buffer is not yet
+ ;; fontified, so fontify it now.
+ (let ((font-lock-verbose nil)) ; shut up font-lock messages
+ (font-lock-fontify-buffer))
+ (set-buffer-modified-p nil)
+ (message "Executing `%s'...done" command)))
;; Now finally cd to where the shell started make/grep/...
- (setq default-directory thisdir))
- (if (buffer-local-value 'compilation-scroll-output outbuf)
- (save-selected-window
- (select-window outwin)
- (goto-char (point-max))))
+ (setq default-directory thisdir)
+ ;; The following form selected outwin ever since revision 1.183,
+ ;; so possibly messing up point in some other window (bug#1073).
+ ;; Moved into the scope of with-current-buffer, though still with
+ ;; complete disregard for the case when compilation-scroll-output
+ ;; equals 'first-error (martin 2008-10-04).
+ (when compilation-scroll-output
+ (goto-char (point-max))))
+
;; Make it so the next C-x ` will use this buffer.
(setq next-error-last-buffer outbuf)))
(enlarge-window (- height (window-height))))))))
(defvar compilation-menu-map
- (let ((map (make-sparse-keymap "Errors")))
+ (let ((map (make-sparse-keymap "Errors"))
+ (opt-map (make-sparse-keymap "Skip")))
(define-key map [stop-subjob]
- '("Stop Compilation" . kill-compilation))
+ '(menu-item "Stop Compilation" kill-compilation
+ :help "Kill the process made by the M-x compile or M-x grep commands"))
+ (define-key map [compilation-mode-separator3]
+ '("----" . nil))
+ (define-key map [compilation-next-error-follow-minor-mode]
+ '(menu-item
+ "Auto Error Display" next-error-follow-minor-mode
+ :help "Display the error under cursor when moving the cursor"
+ :button (:toggle . next-error-follow-minor-mode)))
+ (define-key map [compilation-skip]
+ (cons "Skip Less Important Messages" opt-map))
+ (define-key opt-map [compilation-skip-none]
+ '(menu-item "Don't Skip Any Messages"
+ (lambda ()
+ (interactive)
+ (customize-set-variable 'compilation-skip-threshold 0))
+ :help "Do not skip any type of messages"
+ :button (:radio . (eq compilation-skip-threshold 0))))
+ (define-key opt-map [compilation-skip-info]
+ '(menu-item "Skip Info"
+ (lambda ()
+ (interactive)
+ (customize-set-variable 'compilation-skip-threshold 1))
+ :help "Skip anything less than warning"
+ :button (:radio . (eq compilation-skip-threshold 1))))
+ (define-key opt-map [compilation-skip-warning-and-info]
+ '(menu-item "Skip Warnings and Info"
+ (lambda ()
+ (interactive)
+ (customize-set-variable 'compilation-skip-threshold 2))
+ :help "Skip over Warnings and Info, stop for errors"
+ :button (:radio . (eq compilation-skip-threshold 2))))
(define-key map [compilation-mode-separator2]
'("----" . nil))
(define-key map [compilation-first-error]
- '("First Error" . first-error))
+ '(menu-item "First Error" first-error
+ :help "Restart at the first error, visit corresponding source code"))
(define-key map [compilation-previous-error]
- '("Previous Error" . previous-error))
+ '(menu-item "Previous Error" previous-error
+ :help "Visit previous `next-error' message and corresponding source code"))
(define-key map [compilation-next-error]
- '("Next Error" . next-error))
+ '(menu-item "Next Error" next-error
+ :help "Visit next `next-error' message and corresponding source code"))
map))
(defvar compilation-minor-mode-map
(define-key map "\M-p" 'compilation-previous-error)
(define-key map "\M-{" 'compilation-previous-file)
(define-key map "\M-}" 'compilation-next-file)
+ (define-key map "g" 'recompile) ; revert
+ (define-key map "q" 'quit-window)
;; Set up the menu-bar
(define-key map [menu-bar compilation]
(cons "Errors" compilation-menu-map))
(define-key map "\M-}" 'compilation-next-file)
(define-key map "\t" 'compilation-next-error)
(define-key map [backtab] 'compilation-previous-error)
+ (define-key map "g" 'recompile) ; revert
+ (define-key map "q" 'quit-window)
(define-key map " " 'scroll-up)
(define-key map "\^?" 'scroll-down)
(define-key map [menu-bar compilation compilation-separator2]
'("----" . nil))
(define-key map [menu-bar compilation compilation-grep]
- '("Search Files (grep)..." . grep))
+ '(menu-item "Search Files (grep)..." grep
+ :help "Run grep, with user-specified args, and collect output in a buffer"))
(define-key map [menu-bar compilation compilation-recompile]
- '("Recompile" . recompile))
+ '(menu-item "Recompile" recompile
+ :help "Re-compile the program including the current buffer"))
(define-key map [menu-bar compilation compilation-compile]
- '("Compile..." . compile))
+ '(menu-item "Compile..." compile
+ :help "Compile the program including the current buffer. Default: run `make'"))
map)
"Keymap for compilation log buffers.
`compilation-minor-mode-map' is a parent of this.")
+(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
+ (tool-bar-local-item
+ "left-arrow" 'previous-error-no-select 'previous-error-no-select map
+ :rtl "right-arrow"
+ :help "Goto previous error")
+ (tool-bar-local-item
+ "right-arrow" 'next-error-no-select 'next-error-no-select map
+ :rtl "left-arrow"
+ :help "Goto next error")
+ (tool-bar-local-item
+ "cancel" 'kill-compilation 'kill-compilation map
+ :enable '(let ((buffer (compilation-find-buffer)))
+ (get-buffer-process buffer))
+ :help "Stop compilation")
+ (tool-bar-local-item
+ "refresh" 'recompile 'recompile map
+ :help "Restart compilation")
+ (append map help))))
+
(put 'compilation-mode 'mode-class 'special)
;;;###autoload
(interactive)
(kill-all-local-variables)
(use-local-map compilation-mode-map)
+ ;; 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
mode-name (or name-of-mode "Compilation"))
(set (make-local-variable 'page-delimiter)
;; Prevent that message from being recognized as a compilation error.
(add-text-properties omax (point)
(append '(compilation-handle-exit t) nil))
- (setq mode-line-process (format ":%s [%s]" process-status (cdr status)))
+ (setq mode-line-process
+ (let ((out-string (format ":%s [%s]" process-status (cdr status)))
+ (msg (format "%s %s" mode-name
+ (replace-regexp-in-string "\n?$" "" (car status)))))
+ (message "%s" msg)
+ (propertize out-string
+ 'help-echo msg 'face (if (> exit-status 0)
+ 'compilation-error
+ 'compilation-info))))
;; Force mode line redisplay soon.
(force-mode-line-update)
(if (and opoint (< opoint omax))
(defun compilation-filter (proc string)
"Process filter for compilation buffers.
-Just inserts the text, but uses `insert-before-markers'."
- (if (buffer-name (process-buffer proc))
- (with-current-buffer (process-buffer proc)
- (let ((inhibit-read-only t))
- (save-excursion
- (goto-char (process-mark proc))
- (insert-before-markers string)
- (run-hooks 'compilation-filter-hook))))))
+Just inserts the text, and runs `compilation-filter-hook'."
+ (when (buffer-live-p (process-buffer proc))
+ (with-current-buffer (process-buffer proc)
+ (let ((inhibit-read-only t)
+ ;; `save-excursion' doesn't use the right insertion-type for us.
+ (pos (copy-marker (point) t)))
+ (unwind-protect
+ (progn
+ (goto-char (process-mark proc))
+ ;; We used to use `insert-before-markers', so that windows with
+ ;; point at `process-mark' scroll along with the output, but we
+ ;; now use window-point-insertion-type instead.
+ (insert string)
+ (set-marker (process-mark proc) (point))
+ (run-hooks 'compilation-filter-hook))
+ (goto-char pos))))))
;;; test if a buffer is a compilation buffer, assuming we're in the buffer
(defsubst compilation-buffer-internal-p ()
(defun compilation-next-error (n &optional different-file pt)
"Move point to the next error in the compilation buffer.
+This function does NOT find the source line like \\[next-error].
Prefix arg N says how many error messages to move forwards (or
backwards, if negative).
-Does NOT find the source line like \\[next-error]."
+Optional arg DIFFERENT-FILE, if non-nil, means find next error for a
+file that is different from the current one.
+Optional arg PT, if non-nil, specifies the value of point to start
+looking for the next message."
(interactive "p")
(or (compilation-buffer-p (current-buffer))
(error "Not in a compilation buffer"))
(or pt (setq pt (point)))
(let* ((msg (get-text-property pt 'message))
+ ;; `loc' is used by the compilation-loop macro.
(loc (car msg))
last)
(if (zerop n)
\f
(defun compilation-find-file (marker filename directory &rest formats)
"Find a buffer for file FILENAME.
+If FILENAME is not found at all, ask the user where to find it.
+Pop up the buffer containing MARKER and scroll to MARKER if we ask
+the user where to find the file.
Search the directories in `compilation-search-path'.
A nil in `compilation-search-path' means to try the
\"current\" directory, which is passed in DIRECTORY.
If DIRECTORY is relative, it is combined with `default-directory'.
If DIRECTORY is nil, that means use `default-directory'.
-If FILENAME is not found at all, ask the user where to find it.
-Pop up the buffer containing MARKER and scroll to MARKER if we ask the user."
+FORMATS, if given, is a list of formats to reformat FILENAME when
+looking for it: for each element FMT in FORMATS, this function
+attempts to find a file whose name is produced by (format FMT FILENAME)."
(or formats (setq formats '("%s")))
(let ((dirs compilation-search-path)
(spec-dir (if directory
;; compilations, to set the beginning of "this compilation", it's a good
;; place to reset compilation-auto-jump-to-next.
(set (make-local-variable 'compilation-auto-jump-to-next)
- compilation-auto-jump-to-first-error))
+ (or compilation-auto-jump-to-first-error
+ (eq compilation-scroll-output 'first-error))))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.gcov\\'" . compilation-mode))