;; Run compiler as inferior of Emacs, and parse its error messages.
;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY. No author or distributor
;; accepts responsibility to anyone for the consequences of using it
;; or for whether it serves any particular purpose or works at all,
;; unless he says so in writing. Refer to the GNU Emacs General Public
;; License for full details.
;; Everyone is granted permission to copy, modify and redistribute
;; GNU Emacs, but only under the conditions described in the
;; GNU Emacs General Public License. A copy of this license is
;; supposed to have been given to you along with GNU Emacs so you
;; can know your rights and responsibilities. It should be in a
;; file named COPYING. Among other things, the copyright notice
;; and this notice must be preserved on all copies.
;; make a more general purpose compilation interface.
;; 1. make compilation-process be buffer-local. (for buffer->process mapping)
;; 2. use the (process-buffer) for process->buffer mapping.
;; 3. make compilation-error-message be a buffer local variable.
;; user preference configurations
(defvar compile-sets-error-buf t
"*A compile command will set the error buf.")
;; end user configurations
(defvar compilation-process nil
"Process created by compile command, or nil if none exists now.
Note that the process may have been \"deleted\" and still
be the value of this variable.")
;; this isn't used in any meaningful way - kept here for
;; reasons of minimum change.
(defvar compilation-error-list nil
"List of error message descriptors for visiting erring functions.
Each error descriptor is a list of length two.
Its car is a marker pointing to an error message.
Its cadr is a marker pointing to the text of the line the message is about,
or nil if that is not interesting.
The value may be t instead of a list;
this means that the buffer of error messages should be reparsed
the next time the list of errors is wanted.")
;; not really used.
(defvar compilation-parsing-end nil
"Position of end of buffer when last error messages parsed.")
;; make this buffer local
(defvar compilation-error-message nil
"Message to print when no more matches for compilation-error-regexp are found")
;; The filename excludes colons to avoid confusion when error message
;; starts with digits.
"\\([^ :\n]+\\(: *\\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\)"
"Regular expression for filename/linenumber in error in compilation log.")
(defvar last-compilation-buffer "*compilation*")
(defun compile (command &optional buf)
"NEW COMPILE:Compile the program including the current buffer.
Default: run `make'. Runs COMMAND, a shell command, in a separate
process asynchronously with output going a buffer (*compilation* by
default). You can then use the command \\[next-error] to find the
next error message and move to the source code that caused it.
Optional ARG is the buffer or name of the buffer to use for output. If
interactive, C-u will cause command to prompt for filename. Default
is the last compilation buffer's name."
(interactive (list (read-string "Compile command: " compile-command)
(read-string "Compilation buffer: "
(setq compile-command command)
(setq last-compilation-buffer buf)
(setq buf last-compilation-buffer))
(compile1 compile-command "No more errors" nil buf))
; (defun grep (command)
; "Run grep, with user-specified args, and collect output in a buffer.
; While grep runs asynchronously, you can use the \\[next-error] command
; to find the text that grep hits refer to."
; (interactive "sRun grep (with args): ")
; (compile1 (concat "grep -n " command " /dev/null")
; "No more grep hits" "grep")))
(defun compile1 (command error-message &optional name-of-mode comp-buf)
"Multi-Buffer version of compile1"
(setq comp-buf (get-buffer-create (or comp-buf "*compilation*")))
(let ((cwd default-directory) ; catch that slipery animal
(comp-buf-name (buffer-name comp-buf))
(watch-flag (eq comp-buf (current-buffer))))
(setq default-directory cwd) ; and restore...
(if (or (not (eq (process-status compilation-process) 'run))
"A compilation process is running in this buffer; kill it? "
(let ((comp-proc compilation-process))
(error "Cannot have two processes in one buffer!")))
(setq last-error-buf comp-buf-name))
(setq mode-name (or name-of-mode "Compilation"))
;; Make log buffer's mode line show process state
(setq mode-line-process '(": %s"))
(setq compilation-process nil)
(setq compilation-error-message error-message)
(setq compilation-error-regexp regexp)
(setq compilation-error-list t)
(start-process "compilation" comp-buf
"-c" (concat "exec " command)))
;; side effects: erase buffer, pop up buffer in other window
(princ " started at ")
(princ (substring (current-time-string) 0 -5))
(princ "cd ")
(set-process-sentinel compilation-process 'compilation-sentinel))
(if watch-flag (goto-char (point-max)))))
;; Called when compilation process changes state.
(defun compilation-sentinel (proc msg)
(cond ((null (buffer-name (process-buffer proc)))
;; buffer killed
(set-process-buffer proc nil))
read more »