| [0b990d] | 1 | ;;; compile.el --- run compiler as inferior of Emacs, parse error messages.
 | 
|---|
 | 2 | 
 | 
|---|
 | 3 | ;; Copyright (C) 1985, 86, 87, 93, 94 Free Software Foundation, Inc.
 | 
|---|
 | 4 | 
 | 
|---|
 | 5 | ;; Author: Roland McGrath <roland@prep.ai.mit.edu>
 | 
|---|
 | 6 | ;; Maintainer: FSF
 | 
|---|
 | 7 | ;; Keywords: tools, processes
 | 
|---|
 | 8 | 
 | 
|---|
 | 9 | ;; This file is part of GNU Emacs.
 | 
|---|
 | 10 | 
 | 
|---|
 | 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | ;; it under the terms of the GNU General Public License as published by
 | 
|---|
 | 13 | ;; the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | ;; any later version.
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | ;; GNU Emacs is distributed in the hope that it will be useful,
 | 
|---|
 | 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 19 | ;; GNU General Public License for more details.
 | 
|---|
 | 20 | 
 | 
|---|
 | 21 | ;; You should have received a copy of the GNU General Public License
 | 
|---|
 | 22 | ;; along with GNU Emacs; see the file COPYING.  If not, write to
 | 
|---|
 | 23 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | 
 | 
|---|
 | 25 | ;;; Commentary:
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 | ;; This package provides the compile and grep facilities documented in
 | 
|---|
 | 28 | ;; the Emacs user's manual.
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | ;;; Code:
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | ;;;###autoload
 | 
|---|
 | 33 | (defvar compilation-mode-hook nil
 | 
|---|
 | 34 |   "*List of hook functions run by `compilation-mode' (see `run-hooks').")
 | 
|---|
 | 35 | 
 | 
|---|
 | 36 | ;;;###autoload
 | 
|---|
 | 37 | (defconst compilation-window-height nil
 | 
|---|
 | 38 |   "*Number of lines in a compilation window.  If nil, use Emacs default.")
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | (defvar compilation-error-list nil
 | 
|---|
 | 41 |   "List of error message descriptors for visiting erring functions.
 | 
|---|
 | 42 | Each error descriptor is a cons (or nil).  Its car is a marker pointing to
 | 
|---|
 | 43 | an error message.  If its cdr is a marker, it points to the text of the
 | 
|---|
 | 44 | line the message is about.  If its cdr is a cons, it is a list
 | 
|---|
 | 45 | \(\(DIRECTORY . FILE\) LINE [COLUMN]\).  Or its cdr may be nil if that
 | 
|---|
 | 46 | error is not interesting.
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | The value may be t instead of a list; this means that the buffer of
 | 
|---|
 | 49 | error messages should be reparsed the next time the list of errors is wanted.
 | 
|---|
 | 50 | 
 | 
|---|
 | 51 | Some other commands (like `diff') use this list to control the error
 | 
|---|
 | 52 | message tracking facilites; if you change its structure, you should make
 | 
|---|
 | 53 | sure you also change those packages.  Perhaps it is better not to change
 | 
|---|
 | 54 | it at all.")
 | 
|---|
 | 55 | 
 | 
|---|
 | 56 | (defvar compilation-old-error-list nil
 | 
|---|
 | 57 |   "Value of `compilation-error-list' after errors were parsed.")
 | 
|---|
 | 58 | 
 | 
|---|
 | 59 | (defvar compilation-parse-errors-function 'compilation-parse-errors 
 | 
|---|
 | 60 |   "Function to call to parse error messages from a compilation.
 | 
|---|
 | 61 | It takes args LIMIT-SEARCH and FIND-AT-LEAST.
 | 
|---|
 | 62 | If LIMIT-SEARCH is non-nil, don't bother parsing past that location.
 | 
|---|
 | 63 | If FIND-AT-LEAST is non-nil, don't bother parsing after finding that 
 | 
|---|
 | 64 | many new errors.
 | 
|---|
 | 65 | It should read in the source files which have errors and set
 | 
|---|
 | 66 | `compilation-error-list' to a list with an element for each error message
 | 
|---|
 | 67 | found.  See that variable for more info.")
 | 
|---|
 | 68 | 
 | 
|---|
 | 69 | ;;;###autoload
 | 
|---|
 | 70 | (defvar compilation-buffer-name-function nil
 | 
|---|
 | 71 |   "Function to compute the name of a compilation buffer.
 | 
|---|
 | 72 | The function receives one argument, the name of the major mode of the
 | 
|---|
 | 73 | compilation buffer.  It should return a string.
 | 
|---|
 | 74 | nil means compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.")
 | 
|---|
 | 75 | 
 | 
|---|
 | 76 | ;;;###autoload
 | 
|---|
 | 77 | (defvar compilation-finish-function nil
 | 
|---|
 | 78 |   "*Function to call when a compilation process finishes.
 | 
|---|
 | 79 | It is called with two arguments: the compilation buffer, and a string
 | 
|---|
 | 80 | describing how the process finished.")
 | 
|---|
 | 81 | 
 | 
|---|
 | 82 | (defvar compilation-last-buffer nil
 | 
|---|
 | 83 |   "The most recent compilation buffer.
 | 
|---|
 | 84 | A buffer becomes most recent when its compilation is started
 | 
|---|
 | 85 | or when it is used with \\[next-error] or \\[compile-goto-error].")
 | 
|---|
 | 86 | 
 | 
|---|
 | 87 | (defvar compilation-in-progress nil
 | 
|---|
 | 88 |   "List of compilation processes now running.")
 | 
|---|
 | 89 | (or (assq 'compilation-in-progress minor-mode-alist)
 | 
|---|
 | 90 |     (setq minor-mode-alist (cons '(compilation-in-progress " Compiling")
 | 
|---|
 | 91 |                                  minor-mode-alist)))
 | 
|---|
 | 92 | 
 | 
|---|
 | 93 | (defvar compilation-parsing-end nil
 | 
|---|
 | 94 |   "Position of end of buffer when last error messages were parsed.")
 | 
|---|
 | 95 | 
 | 
|---|
 | 96 | (defvar compilation-error-message "No more errors"
 | 
|---|
 | 97 |   "Message to print when no more matches are found.")
 | 
|---|
 | 98 | 
 | 
|---|
 | 99 | (defvar compilation-num-errors-found)
 | 
|---|
 | 100 | 
 | 
|---|
 | 101 | (defvar compilation-error-regexp-alist
 | 
|---|
 | 102 |   '(
 | 
|---|
 | 103 |     ;; NOTE!  This first one is repeated in grep-regexp-alist, below.
 | 
|---|
 | 104 | 
 | 
|---|
 | 105 |     ;; 4.3BSD grep, cc, lint pass 1:
 | 
|---|
 | 106 |     ;;  /usr/src/foo/foo.c(8): warning: w may be used before set
 | 
|---|
 | 107 |     ;; or GNU utilities:
 | 
|---|
 | 108 |     ;;  foo.c:8: error message
 | 
|---|
 | 109 |     ;; or HP-UX 7.0 fc:
 | 
|---|
 | 110 |     ;;  foo.f          :16    some horrible error message
 | 
|---|
 | 111 |     ;;
 | 
|---|
 | 112 |     ;; We'll insist that the number be followed by a colon or closing
 | 
|---|
 | 113 |     ;; paren, because otherwise this matches just about anything
 | 
|---|
 | 114 |     ;; containing a number with spaces around it.
 | 
|---|
 | 115 |     ("\n\\([^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)[:) \t]" 1 2)
 | 
|---|
 | 116 | 
 | 
|---|
 | 117 |     ;; 4.3BSD lint pass 2
 | 
|---|
 | 118 |     ;;  strcmp: variable # of args. llib-lc(359)  ::  /usr/src/foo/foo.c(8)
 | 
|---|
 | 119 |     ("[ \t:]\\([^:( \t\n]+\\)[:(](+[ \t]*\\([0-9]+\\))[:) \t]*$" 1 2)
 | 
|---|
 | 120 | 
 | 
|---|
 | 121 |     ;; 4.3BSD lint pass 3
 | 
|---|
 | 122 |     ;;  bloofle defined( /users/wolfgang/foo.c(4) ), but never used
 | 
|---|
 | 123 |     ;; This used to be
 | 
|---|
 | 124 |     ;; ("[ \t(]+\\([^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]+" 1 2)
 | 
|---|
 | 125 |     ;; which is regexp Impressionism - it matches almost anything!
 | 
|---|
 | 126 |     ("([ \t]*\\([^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\))" 1 2)
 | 
|---|
 | 127 | 
 | 
|---|
 | 128 |     ;; Ultrix 3.0 f77:
 | 
|---|
 | 129 |     ;;  fort: Severe: addstf.f, line 82: Missing operator or delimiter symbol
 | 
|---|
 | 130 |     ("\nfort: [^:\n]*: \\([^ \n]*\\), line \\([0-9]+\\):" 1 2)
 | 
|---|
 | 131 |     ;;  Error on line 3 of t.f: Execution error unclassifiable statement    
 | 
|---|
 | 132 |     ;; Unknown who does this:
 | 
|---|
 | 133 |     ;;  Line 45 of "foo.c": bloofel undefined
 | 
|---|
 | 134 |     ;; Absoft FORTRAN 77 Compiler 3.1.3
 | 
|---|
 | 135 |     ;;  error on line 19 of fplot.f: spelling error?
 | 
|---|
 | 136 |     ;;  warning on line 17 of fplot.f: data type is undefined for variable d
 | 
|---|
 | 137 |     ("\\(\n\\|on \\)[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\
 | 
|---|
 | 138 | of[ \t]+\"?\\([^\":\n]+\\)\"?:" 3 2)
 | 
|---|
 | 139 | 
 | 
|---|
 | 140 |     ;; Apollo cc, 4.3BSD fc:
 | 
|---|
 | 141 |     ;;  "foo.f", line 3: Error: syntax error near end of statement
 | 
|---|
 | 142 |     ;; IBM RS6000:
 | 
|---|
 | 143 |     ;;  "vvouch.c", line 19.5: 1506-046 (S) Syntax error.
 | 
|---|
 | 144 |     ;; Unknown compiler:
 | 
|---|
 | 145 |     ;;  File "foobar.ml", lines 5-8, characters 20-155: blah blah
 | 
|---|
 | 146 |     ;; Microtec mcc68k:
 | 
|---|
 | 147 |     ;;  "foo.c", line 32 pos 1; (E) syntax error; unexpected symbol: "lossage"
 | 
|---|
 | 148 |     ("\"\\([^,\" \n\t]+\\)\", lines? \\([0-9]+\\)[:., -]" 1 2)
 | 
|---|
 | 149 | 
 | 
|---|
 | 150 |     ;; MIPS RISC CC - the one distributed with Ultrix:
 | 
|---|
 | 151 |     ;;  ccom: Error: foo.c, line 2: syntax error
 | 
|---|
 | 152 |     ;; DEC AXP OSF/1 cc
 | 
|---|
 | 153 |     ;;  /usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah 
 | 
|---|
 | 154 |     ("rror: \\([^,\" \n\t]+\\)[,:] \\(line \\)?\\([0-9]+\\):" 1 3)
 | 
|---|
 | 155 | 
 | 
|---|
 | 156 |     ;; IBM AIX PS/2 C version 1.1:
 | 
|---|
 | 157 |     ;;  ****** Error number 140 in line 8 of file errors.c ******
 | 
|---|
 | 158 |     ("in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1)
 | 
|---|
 | 159 |     ;; IBM AIX lint is too painful to do right this way.  File name
 | 
|---|
 | 160 |     ;; prefixes entire sections rather than being on each line.
 | 
|---|
 | 161 | 
 | 
|---|
 | 162 |     ;; Lucid Compiler, lcc 3.x
 | 
|---|
 | 163 |     ;; E, file.cc(35,52) Illegal operation on pointers
 | 
|---|
 | 164 |     ("\n[EW], \\([^(\n]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3)
 | 
|---|
 | 165 | 
 | 
|---|
 | 166 |     )
 | 
|---|
 | 167 |   "Alist that specifies how to match errors in compiler output.
 | 
|---|
 | 168 | Each element has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX]).
 | 
|---|
 | 169 | If REGEXP matches, the FILE-IDX'th subexpression gives the file name, and
 | 
|---|
 | 170 | the LINE-IDX'th subexpression gives the line number.  If COLUMN-IDX is
 | 
|---|
 | 171 | given, the COLUMN-IDX'th subexpression gives the column number on that line.")
 | 
|---|
 | 172 | 
 | 
|---|
 | 173 | (defvar compilation-read-command t
 | 
|---|
 | 174 |   "If not nil, M-x compile reads the compilation command to use.
 | 
|---|
 | 175 | Otherwise, M-x compile just uses the value of `compile-command'.")
 | 
|---|
 | 176 | 
 | 
|---|
 | 177 | (defvar compilation-ask-about-save t
 | 
|---|
 | 178 |   "If not nil, M-x compile asks which buffers to save before compiling.
 | 
|---|
 | 179 | Otherwise, it saves all modified buffers without asking.")
 | 
|---|
 | 180 | 
 | 
|---|
 | 181 | (defvar grep-regexp-alist
 | 
|---|
 | 182 |   '(("^\\([^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2))
 | 
|---|
 | 183 |   "Regexp used to match grep hits.  See `compilation-error-regexp-alist'.")
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 | (defvar grep-command "grep -n "
 | 
|---|
 | 186 |   "Last grep command used in \\{grep}; default for next grep.")
 | 
|---|
 | 187 | 
 | 
|---|
 | 188 | ;;;###autoload
 | 
|---|
 | 189 | (defvar compilation-search-path '(nil)
 | 
|---|
 | 190 |   "*List of directories to search for source files named in error messages.
 | 
|---|
 | 191 | Elements should be directory names, not file names of directories.
 | 
|---|
 | 192 | nil as an element means to try the default directory.")
 | 
|---|
 | 193 | 
 | 
|---|
 | 194 | (defvar compile-command "make -k "
 | 
|---|
 | 195 |   "Last shell command used to do a compilation; default for next compilation.
 | 
|---|
 | 196 | 
 | 
|---|
 | 197 | Sometimes it is useful for files to supply local values for this variable.
 | 
|---|
 | 198 | You might also use mode hooks to specify it in certain modes, like this:
 | 
|---|
 | 199 | 
 | 
|---|
 | 200 |     (setq c-mode-hook
 | 
|---|
 | 201 |       '(lambda () (or (file-exists-p \"makefile\") (file-exists-p \"Makefile\")
 | 
|---|
 | 202 |                       (progn (make-local-variable 'compile-command)
 | 
|---|
 | 203 |                              (setq compile-command
 | 
|---|
 | 204 |                                     (concat \"make -k \"
 | 
|---|
 | 205 |                                             buffer-file-name))))))")
 | 
|---|
 | 206 | 
 | 
|---|
 | 207 | (defconst compilation-enter-directory-regexp
 | 
|---|
 | 208 |   ": Entering directory `\\(.*\\)'$"
 | 
|---|
 | 209 |   "Regular expression matching lines that indicate a new current directory.
 | 
|---|
 | 210 | This must contain one \\(, \\) pair around the directory name.
 | 
|---|
 | 211 | 
 | 
|---|
 | 212 | The default value matches lines printed by the `-w' option of GNU Make.")
 | 
|---|
 | 213 | 
 | 
|---|
 | 214 | (defconst compilation-leave-directory-regexp
 | 
|---|
 | 215 |   ": Leaving directory `\\(.*\\)'$"
 | 
|---|
 | 216 |   "Regular expression matching lines that indicate restoring current directory.
 | 
|---|
 | 217 | This may contain one \\(, \\) pair around the name of the directory
 | 
|---|
 | 218 | being moved from.  If it does not, the last directory entered \(by a
 | 
|---|
 | 219 | line matching `compilation-enter-directory-regexp'\) is assumed.
 | 
|---|
 | 220 | 
 | 
|---|
 | 221 | The default value matches lines printed by the `-w' option of GNU Make.")
 | 
|---|
 | 222 | 
 | 
|---|
 | 223 | (defvar compilation-directory-stack nil
 | 
|---|
 | 224 |   "Stack of previous directories for `compilation-leave-directory-regexp'.
 | 
|---|
 | 225 | The head element is the directory the compilation was started in.")
 | 
|---|
 | 226 | 
 | 
|---|
 | 227 | ;; History of compile commands.
 | 
|---|
 | 228 | (defvar compile-history nil)
 | 
|---|
 | 229 | ;; History of grep commands.
 | 
|---|
 | 230 | (defvar grep-history nil)
 | 
|---|
 | 231 | 
 | 
|---|
 | 232 | ;;;###autoload
 | 
|---|
 | 233 | (defun compile (command)
 | 
|---|
 | 234 |   "Compile the program including the current buffer.  Default: run `make'.
 | 
|---|
 | 235 | Runs COMMAND, a shell command, in a separate process asynchronously
 | 
|---|
 | 236 | with output going to the buffer `*compilation*'.
 | 
|---|
 | 237 | 
 | 
|---|
 | 238 | You can then use the command \\[next-error] to find the next error message
 | 
|---|
 | 239 | and move to the source code that caused it.
 | 
|---|
 | 240 | 
 | 
|---|
 | 241 | To run more than one compilation at once, start one and rename the
 | 
|---|
 | 242 | \`*compilation*' buffer to some other name with \\[rename-buffer].
 | 
|---|
 | 243 | Then start the next one.
 | 
|---|
 | 244 | 
 | 
|---|
 | 245 | The name used for the buffer is actually whatever is returned by
 | 
|---|
 | 246 | the function in `compilation-buffer-name-function', so you can set that
 | 
|---|
 | 247 | to a function that generates a unique name."
 | 
|---|
 | 248 |   (interactive
 | 
|---|
 | 249 |    (if compilation-read-command
 | 
|---|
 | 250 |        (list (read-from-minibuffer "Compile command: "
 | 
|---|
 | 251 |                                  compile-command nil nil
 | 
|---|
 | 252 |                                  '(compile-history . 1)))
 | 
|---|
 | 253 |      (list compile-command)))
 | 
|---|
 | 254 |   (setq compile-command command)
 | 
|---|
 | 255 |   (save-some-buffers (not compilation-ask-about-save) nil)
 | 
|---|
 | 256 |   (compile-internal compile-command "No more errors"))
 | 
|---|
 | 257 | 
 | 
|---|
 | 258 | ;;;###autoload
 | 
|---|
 | 259 | (defun grep (command-args)
 | 
|---|
 | 260 |   "Run grep, with user-specified args, and collect output in a buffer.
 | 
|---|
 | 261 | While grep runs asynchronously, you can use the \\[next-error] command
 | 
|---|
 | 262 | to find the text that grep hits refer to.
 | 
|---|
 | 263 | 
 | 
|---|
 | 264 | This command uses a special history list for its arguments, so you can
 | 
|---|
 | 265 | easily repeat a grep command."
 | 
|---|
 | 266 |   (interactive
 | 
|---|
 | 267 |    (list (read-from-minibuffer "Run grep (like this): "
 | 
|---|
 | 268 |                                grep-command nil nil 'grep-history)))
 | 
|---|
 | 269 |   (compile-internal (concat command-args " /dev/null")
 | 
|---|
 | 270 |                     "No more grep hits" "grep"
 | 
|---|
 | 271 |                     ;; Give it a simpler regexp to match.
 | 
|---|
 | 272 |                     nil grep-regexp-alist))
 | 
|---|
 | 273 | 
 | 
|---|
 | 274 | (defun compile-internal (command error-message
 | 
|---|
 | 275 |                                  &optional name-of-mode parser regexp-alist
 | 
|---|
 | 276 |                                  name-function)
 | 
|---|
 | 277 |   "Run compilation command COMMAND (low level interface).
 | 
|---|
 | 278 | ERROR-MESSAGE is a string to print if the user asks to see another error
 | 
|---|
 | 279 | and there are no more errors.  Third argument NAME-OF-MODE is the name
 | 
|---|
 | 280 | to display as the major mode in the compilation buffer.
 | 
|---|
 | 281 | 
 | 
|---|
 | 282 | Fourth arg PARSER is the error parser function (nil means the default).  Fifth
 | 
|---|
 | 283 | arg REGEXP-ALIST is the error message regexp alist to use (nil means the
 | 
|---|
 | 284 | default).  Sixth arg NAME-FUNCTION is a function called to name the buffer (nil
 | 
|---|
 | 285 | means the default).  The defaults for these variables are the global values of
 | 
|---|
 | 286 | \`compilation-parse-errors-function', `compilation-error-regexp-alist', and
 | 
|---|
 | 287 | \`compilation-buffer-name-function', respectively.
 | 
|---|
 | 288 | 
 | 
|---|
 | 289 | Returns the compilation buffer created."
 | 
|---|
 | 290 |   (let (outbuf)
 | 
|---|
 | 291 |     (save-excursion
 | 
|---|
 | 292 |       (or name-of-mode
 | 
|---|
 | 293 |           (setq name-of-mode "Compilation"))
 | 
|---|
 | 294 |       (setq outbuf
 | 
|---|
 | 295 |             (get-buffer-create
 | 
|---|
 | 296 |              (funcall (or name-function compilation-buffer-name-function
 | 
|---|
 | 297 |                           (function (lambda (mode)
 | 
|---|
 | 298 |                                       (concat "*" (downcase mode) "*"))))
 | 
|---|
 | 299 |                       name-of-mode)))
 | 
|---|
 | 300 |       (set-buffer outbuf)
 | 
|---|
 | 301 |       (let ((comp-proc (get-buffer-process (current-buffer))))
 | 
|---|
 | 302 |         (if comp-proc
 | 
|---|
 | 303 |             (if (or (not (eq (process-status comp-proc) 'run))
 | 
|---|
 | 304 |                     (yes-or-no-p
 | 
|---|
 | 305 |                      (format "A %s process is running; kill it? "
 | 
|---|
 | 306 |                              name-of-mode)))
 | 
|---|
 | 307 |                 (condition-case ()
 | 
|---|
 | 308 |                     (progn
 | 
|---|
 | 309 |                       (interrupt-process comp-proc)
 | 
|---|
 | 310 |                       (sit-for 1)
 | 
|---|
 | 311 |                       (delete-process comp-proc))
 | 
|---|
 | 312 |                   (error nil))
 | 
|---|
 | 313 |               (error "Cannot have two processes in `%s' at once"
 | 
|---|
 | 314 |                      (buffer-name))
 | 
|---|
 | 315 |               )))
 | 
|---|
 | 316 |       ;; In case the compilation buffer is current, make sure we get the global
 | 
|---|
 | 317 |       ;; values of compilation-error-regexp-alist, etc.
 | 
|---|
 | 318 |       (kill-all-local-variables))
 | 
|---|
 | 319 |     (let ((regexp-alist (or regexp-alist compilation-error-regexp-alist))
 | 
|---|
 | 320 |           (parser (or parser compilation-parse-errors-function))
 | 
|---|
 | 321 |           (thisdir default-directory)
 | 
|---|
 | 322 |           outwin) 
 | 
|---|
 | 323 |       (save-excursion
 | 
|---|
 | 324 |         ;; Clear out the compilation buffer and make it writable.
 | 
|---|
 | 325 |         ;; Change its default-directory to the directory where the compilation
 | 
|---|
 | 326 |         ;; will happen, and insert a `cd' command to indicate this.
 | 
|---|
 | 327 |         (set-buffer outbuf)
 | 
|---|
 | 328 |         (setq buffer-read-only nil)
 | 
|---|
 | 329 |         (erase-buffer)
 | 
|---|
 | 330 |         ;; BEGIN C JANSSEN ADDITIONS
 | 
|---|
 | 331 |         (if (and (not (string= name-of-mode "grep"))
 | 
|---|
 | 332 |                  (fboundp 'compile-modify-path))
 | 
|---|
 | 333 |             (setq thisdir (compile-modify-path thisdir))
 | 
|---|
 | 334 |           )
 | 
|---|
 | 335 |         ;; END C JANSSEN ADDITIONS
 | 
|---|
 | 336 |         (setq default-directory thisdir)
 | 
|---|
 | 337 |         (insert "cd " thisdir "\n" command "\n")
 | 
|---|
 | 338 |         (set-buffer-modified-p nil))
 | 
|---|
 | 339 |       ;; If we're already in the compilation buffer, go to the end
 | 
|---|
 | 340 |       ;; of the buffer, so point will track the compilation output.
 | 
|---|
 | 341 |       (if (eq outbuf (current-buffer))
 | 
|---|
 | 342 |           (goto-char (point-max)))
 | 
|---|
 | 343 |       ;; Pop up the compilation buffer.
 | 
|---|
 | 344 |       (setq outwin (display-buffer outbuf))
 | 
|---|
 | 345 |       (save-excursion
 | 
|---|
 | 346 |         (set-buffer outbuf)
 | 
|---|
 | 347 |         (compilation-mode)
 | 
|---|
 | 348 |         (buffer-disable-undo (current-buffer))
 | 
|---|
 | 349 |         ;; (setq buffer-read-only t)  ;;; Non-ergonomic.
 | 
|---|
 | 350 |         (set (make-local-variable 'compilation-parse-errors-function) parser)
 | 
|---|
 | 351 |         (set (make-local-variable 'compilation-error-message) error-message)
 | 
|---|
 | 352 |         (set (make-local-variable 'compilation-error-regexp-alist) regexp-alist)
 | 
|---|
 | 353 |         (setq default-directory thisdir
 | 
|---|
 | 354 |               compilation-directory-stack (list default-directory))
 | 
|---|
 | 355 |         (set-window-start outwin (point-min))
 | 
|---|
 | 356 |         (setq mode-name name-of-mode)
 | 
|---|
 | 357 |         (or (eq outwin (selected-window))
 | 
|---|
 | 358 |         ;; BEGIN C JANSSEN MODS
 | 
|---|
 | 359 |             ;; goto the end of the buffer instead of the beginning
 | 
|---|
 | 360 |             ;;(set-window-point outwin (point-min)))
 | 
|---|
 | 361 |             (set-window-point outwin (point-max)))
 | 
|---|
 | 362 |         ;; END C JANSSEN MODS
 | 
|---|
 | 363 |         (and compilation-window-height
 | 
|---|
 | 364 |              (= (window-width outwin) (frame-width))
 | 
|---|
 | 365 |              (let ((w (selected-window)))
 | 
|---|
 | 366 |                (unwind-protect
 | 
|---|
 | 367 |                    (progn
 | 
|---|
 | 368 |                      (select-window outwin)
 | 
|---|
 | 369 |                      (enlarge-window (- compilation-window-height
 | 
|---|
 | 370 |                                         (window-height))))
 | 
|---|
 | 371 |                  (select-window w))))
 | 
|---|
 | 372 |         ;; Start the compilation.
 | 
|---|
 | 373 |         (if (fboundp 'start-process)
 | 
|---|
 | 374 |             (let ((proc (start-process-shell-command (downcase mode-name)
 | 
|---|
 | 375 |                                                      outbuf
 | 
|---|
 | 376 |                                                      command)))
 | 
|---|
 | 377 |               (set-process-sentinel proc 'compilation-sentinel)
 | 
|---|
 | 378 |               (set-process-filter proc 'compilation-filter)
 | 
|---|
 | 379 |               (set-marker (process-mark proc) (point) outbuf)
 | 
|---|
 | 380 |               (setq compilation-in-progress 
 | 
|---|
 | 381 |                     (cons proc compilation-in-progress)))
 | 
|---|
 | 382 |           ;; No asynchronous processes available
 | 
|---|
 | 383 |           (message (format "Executing `%s'..." command))
 | 
|---|
 | 384 |           (let ((status (call-process shell-file-name nil outbuf nil "-c"
 | 
|---|
 | 385 |                                       command))))
 | 
|---|
 | 386 |           (message (format "Executing `%s'...done" command)))))
 | 
|---|
 | 387 |     ;; Make it so the next C-x ` will use this buffer.
 | 
|---|
 | 388 |     (setq compilation-last-buffer outbuf)))
 | 
|---|
 | 389 | 
 | 
|---|
 | 390 | (defvar compilation-minor-mode-map
 | 
|---|
 | 391 |   (let ((map (make-sparse-keymap)))
 | 
|---|
 | 392 |     (define-key map [mouse-2] 'compile-mouse-goto-error)
 | 
|---|
 | 393 |     (define-key map "\C-c\C-c" 'compile-goto-error)
 | 
|---|
 | 394 |     (define-key map "\C-c\C-k" 'kill-compilation)
 | 
|---|
 | 395 |     (define-key map "\M-n" 'compilation-next-error)
 | 
|---|
 | 396 |     (define-key map "\M-p" 'compilation-previous-error)
 | 
|---|
 | 397 |     (define-key map "\M-{" 'compilation-previous-file)
 | 
|---|
 | 398 |     (define-key map "\M-}" 'compilation-next-file)
 | 
|---|
 | 399 |     map)
 | 
|---|
 | 400 |   "Keymap for `compilation-minor-mode'.")
 | 
|---|
 | 401 | 
 | 
|---|
 | 402 | (defvar compilation-mode-map
 | 
|---|
 | 403 |   (let ((map (cons 'keymap compilation-minor-mode-map)))
 | 
|---|
 | 404 |     (define-key map " " 'scroll-up)
 | 
|---|
 | 405 |     (define-key map "\^?" 'scroll-down)
 | 
|---|
 | 406 |     map)
 | 
|---|
 | 407 |   "Keymap for compilation log buffers.
 | 
|---|
 | 408 | `compilation-minor-mode-map' is a cdr of this.")
 | 
|---|
 | 409 | 
 | 
|---|
 | 410 | (defun compilation-mode ()
 | 
|---|
 | 411 |   "Major mode for compilation log buffers.
 | 
|---|
 | 412 | \\<compilation-mode-map>To visit the source for a line-numbered error,
 | 
|---|
 | 413 | move point to the error message line and type \\[compile-goto-error].
 | 
|---|
 | 414 | To kill the compilation, type \\[kill-compilation].
 | 
|---|
 | 415 | 
 | 
|---|
 | 416 | Runs `compilation-mode-hook' with `run-hooks' (which see)."
 | 
|---|
 | 417 |   (interactive)
 | 
|---|
 | 418 |   (fundamental-mode)
 | 
|---|
 | 419 |   (use-local-map compilation-mode-map)
 | 
|---|
 | 420 |   (setq major-mode 'compilation-mode
 | 
|---|
 | 421 |         mode-name "Compilation")
 | 
|---|
 | 422 |   (compilation-setup)
 | 
|---|
 | 423 |   (run-hooks 'compilation-mode-hook))
 | 
|---|
 | 424 | 
 | 
|---|
 | 425 | ;; Prepare the buffer for the compilation parsing commands to work.
 | 
|---|
 | 426 | (defun compilation-setup ()
 | 
|---|
 | 427 |   ;; Make the buffer's mode line show process state.
 | 
|---|
 | 428 |   (setq mode-line-process '(":%s"))
 | 
|---|
 | 429 |   (set (make-local-variable 'compilation-error-list) nil)
 | 
|---|
 | 430 |   (set (make-local-variable 'compilation-old-error-list) nil)
 | 
|---|
 | 431 |   (set (make-local-variable 'compilation-parsing-end) 1)
 | 
|---|
 | 432 |   (set (make-local-variable 'compilation-directory-stack) nil)
 | 
|---|
 | 433 |   (setq compilation-last-buffer (current-buffer)))
 | 
|---|
 | 434 | 
 | 
|---|
 | 435 | (defvar compilation-minor-mode nil
 | 
|---|
 | 436 |   "Non-nil when in compilation-minor-mode.
 | 
|---|
 | 437 | In this minor mode, all the error-parsing commands of the
 | 
|---|
 | 438 | Compilation major mode are available.")
 | 
|---|
 | 439 | (make-variable-buffer-local 'compilation-minor-mode)
 | 
|---|
 | 440 | 
 | 
|---|
 | 441 | (or (assq 'compilation-minor-mode minor-mode-alist)
 | 
|---|
 | 442 |     (setq minor-mode-alist (cons '(compilation-minor-mode " Compilation")
 | 
|---|
 | 443 |                                  minor-mode-alist)))
 | 
|---|
 | 444 | (or (assq 'compilation-minor-mode minor-mode-map-alist)
 | 
|---|
 | 445 |     (setq minor-mode-map-alist (cons (cons 'compilation-minor-mode
 | 
|---|
 | 446 |                                            compilation-minor-mode-map)
 | 
|---|
 | 447 |                                      minor-mode-map-alist)))
 | 
|---|
 | 448 | 
 | 
|---|
 | 449 | ;;;###autoload
 | 
|---|
 | 450 | (defun compilation-minor-mode (&optional arg)
 | 
|---|
 | 451 |   "Toggle compilation minor mode.
 | 
|---|
 | 452 | With arg, turn compilation mode on if and only if arg is positive.
 | 
|---|
 | 453 | See `compilation-mode'."
 | 
|---|
 | 454 |   (interactive "P")
 | 
|---|
 | 455 |   (if (setq compilation-minor-mode (if (null arg)
 | 
|---|
 | 456 |                                        (null compilation-minor-mode)
 | 
|---|
 | 457 |                                      (> (prefix-numeric-value arg) 0)))
 | 
|---|
 | 458 |       (compilation-setup)))
 | 
|---|
 | 459 | 
 | 
|---|
 | 460 | ;; Called when compilation process changes state.
 | 
|---|
 | 461 | (defun compilation-sentinel (proc msg)
 | 
|---|
 | 462 |   "Sentinel for compilation buffers."
 | 
|---|
 | 463 |   (let ((buffer (process-buffer proc)))
 | 
|---|
 | 464 |     (if (memq (process-status proc) '(signal exit))
 | 
|---|
 | 465 |         (progn
 | 
|---|
 | 466 |           (if (null (buffer-name buffer))
 | 
|---|
 | 467 |               ;; buffer killed
 | 
|---|
 | 468 |               (set-process-buffer proc nil)
 | 
|---|
 | 469 |             (let ((obuf (current-buffer))
 | 
|---|
 | 470 |                   omax opoint)
 | 
|---|
 | 471 |               ;; save-excursion isn't the right thing if
 | 
|---|
 | 472 |               ;; process-buffer is current-buffer
 | 
|---|
 | 473 |               (unwind-protect
 | 
|---|
 | 474 |                   (progn
 | 
|---|
 | 475 |                     ;; Write something in the compilation buffer
 | 
|---|
 | 476 |                     ;; and hack its mode line.
 | 
|---|
 | 477 |                     (set-buffer buffer)
 | 
|---|
 | 478 |                     (let ((buffer-read-only nil))
 | 
|---|
 | 479 |                       (setq omax (point-max)
 | 
|---|
 | 480 |                             opoint (point))
 | 
|---|
 | 481 |                       (goto-char omax)
 | 
|---|
 | 482 |                       ;; Record where we put the message, so we can ignore it
 | 
|---|
 | 483 |                       ;; later on.
 | 
|---|
 | 484 |                       (insert ?\n mode-name " " msg)
 | 
|---|
 | 485 |                       (forward-char -1)
 | 
|---|
 | 486 |                       (insert " at " (substring (current-time-string) 0 19))
 | 
|---|
 | 487 |                       (forward-char 1)
 | 
|---|
 | 488 |                       (setq mode-line-process
 | 
|---|
 | 489 |                             (concat ":"
 | 
|---|
 | 490 |                                     (symbol-name (process-status proc))))
 | 
|---|
 | 491 |                       ;; Since the buffer and mode line will show that the
 | 
|---|
 | 492 |                       ;; process is dead, we can delete it now.  Otherwise it
 | 
|---|
 | 493 |                       ;; will stay around until M-x list-processes.
 | 
|---|
 | 494 |                       (delete-process proc)
 | 
|---|
 | 495 |                       ;; Force mode line redisplay soon.
 | 
|---|
 | 496 |                       (set-buffer-modified-p (buffer-modified-p)))
 | 
|---|
 | 497 |                     (if (and opoint (< opoint omax))
 | 
|---|
 | 498 |                         (goto-char opoint))
 | 
|---|
 | 499 |                     (if compilation-finish-function
 | 
|---|
 | 500 |                         (funcall compilation-finish-function buffer msg)))
 | 
|---|
 | 501 |                 (set-buffer obuf))))
 | 
|---|
 | 502 |           (setq compilation-in-progress (delq proc compilation-in-progress))
 | 
|---|
 | 503 |           ))))
 | 
|---|
 | 504 | 
 | 
|---|
 | 505 | (defun compilation-filter (proc string)
 | 
|---|
 | 506 |   "Process filter for compilation buffers.
 | 
|---|
 | 507 | Just inserts the text, but uses `insert-before-markers'."
 | 
|---|
 | 508 |   (save-excursion
 | 
|---|
 | 509 |     (set-buffer (process-buffer proc))
 | 
|---|
 | 510 |     (let ((buffer-read-only nil))
 | 
|---|
 | 511 |       (save-excursion
 | 
|---|
 | 512 |         (goto-char (process-mark proc))
 | 
|---|
 | 513 |         (insert-before-markers string)
 | 
|---|
 | 514 |         (set-marker (process-mark proc) (point))))))
 | 
|---|
 | 515 | 
 | 
|---|
 | 516 | ;; Return the cdr of compilation-old-error-list for the error containing point.
 | 
|---|
 | 517 | (defun compile-error-at-point ()
 | 
|---|
 | 518 |   (compile-reinitialize-errors nil (point))
 | 
|---|
 | 519 |   (let ((errors compilation-old-error-list))
 | 
|---|
 | 520 |     (while (and errors
 | 
|---|
 | 521 |                 (> (point) (car (car errors))))
 | 
|---|
 | 522 |       (setq errors (cdr errors)))
 | 
|---|
 | 523 |     errors))
 | 
|---|
 | 524 | 
 | 
|---|
 | 525 | (defsubst compilation-buffer-p (buffer)
 | 
|---|
 | 526 |   (assq 'compilation-error-list (buffer-local-variables buffer)))
 | 
|---|
 | 527 | 
 | 
|---|
 | 528 | (defun compilation-next-error (n)
 | 
|---|
 | 529 |   "Move point to the next error in the compilation buffer.
 | 
|---|
 | 530 | Does NOT find the source line like \\[next-error]."
 | 
|---|
 | 531 |   (interactive "p")
 | 
|---|
 | 532 |   (or (compilation-buffer-p (current-buffer))
 | 
|---|
 | 533 |       (error "Not in a compilation buffer."))
 | 
|---|
 | 534 |   (setq compilation-last-buffer (current-buffer))
 | 
|---|
 | 535 | 
 | 
|---|
 | 536 |   (let ((errors (compile-error-at-point)))
 | 
|---|
 | 537 | 
 | 
|---|
 | 538 |     ;; Move to the error after the one containing point.
 | 
|---|
 | 539 |     (goto-char (car (if (< n 0)
 | 
|---|
 | 540 |                         (let ((i 0)
 | 
|---|
 | 541 |                               (e compilation-old-error-list))
 | 
|---|
 | 542 |                           ;; See how many cdrs away ERRORS is from the start.
 | 
|---|
 | 543 |                           (while (not (eq e errors))
 | 
|---|
 | 544 |                             (setq i (1+ i)
 | 
|---|
 | 545 |                                   e (cdr e)))
 | 
|---|
 | 546 |                           (if (> (- n) i)
 | 
|---|
 | 547 |                               (error "Moved back past first error")
 | 
|---|
 | 548 |                             (nth (+ i n) compilation-old-error-list)))
 | 
|---|
 | 549 |                       (let ((compilation-error-list (cdr errors)))
 | 
|---|
 | 550 |                         (compile-reinitialize-errors nil nil n)
 | 
|---|
 | 551 |                         (if compilation-error-list
 | 
|---|
 | 552 |                             (nth (1- n) compilation-error-list)
 | 
|---|
 | 553 |                           (error "Moved past last error"))))))))
 | 
|---|
 | 554 | 
 | 
|---|
 | 555 | (defun compilation-previous-error (n)
 | 
|---|
 | 556 |   "Move point to the previous error in the compilation buffer.
 | 
|---|
 | 557 | Does NOT find the source line like \\[next-error]."
 | 
|---|
 | 558 |   (interactive "p")
 | 
|---|
 | 559 |   (compilation-next-error (- n)))
 | 
|---|
 | 560 | 
 | 
|---|
 | 561 | 
 | 
|---|
 | 562 | ;; Given an elt of `compilation-error-list', return an object representing
 | 
|---|
 | 563 | ;; the referenced file which is equal to (but not necessarily eq to) what
 | 
|---|
 | 564 | ;; this function would return for another error in the same file.
 | 
|---|
 | 565 | (defsubst compilation-error-filedata (data)
 | 
|---|
 | 566 |   (setq data (cdr data))
 | 
|---|
 | 567 |   (if (markerp data)
 | 
|---|
 | 568 |       (marker-buffer data)
 | 
|---|
 | 569 |     (car data)))
 | 
|---|
 | 570 | 
 | 
|---|
 | 571 | ;; Return a string describing a value from compilation-error-filedata.
 | 
|---|
 | 572 | ;; This value is not necessarily useful as a file name, but should be
 | 
|---|
 | 573 | ;; indicative to the user of what file's errors are being referred to.
 | 
|---|
 | 574 | (defsubst compilation-error-filedata-file-name (filedata)
 | 
|---|
 | 575 |   (if (bufferp filedata)
 | 
|---|
 | 576 |       (buffer-file-name filedata)
 | 
|---|
 | 577 |     (car filedata)))
 | 
|---|
 | 578 | 
 | 
|---|
 | 579 | (defun compilation-next-file (n)
 | 
|---|
 | 580 |   "Move point to the next error for a different file than the current one."
 | 
|---|
 | 581 |   (interactive "p")
 | 
|---|
 | 582 |   (or (compilation-buffer-p (current-buffer))
 | 
|---|
 | 583 |       (error "Not in a compilation buffer."))
 | 
|---|
 | 584 |   (setq compilation-last-buffer (current-buffer))
 | 
|---|
 | 585 | 
 | 
|---|
 | 586 |   (let ((reversed (< n 0))
 | 
|---|
 | 587 |         errors filedata)
 | 
|---|
 | 588 | 
 | 
|---|
 | 589 |     (if (not reversed)
 | 
|---|
 | 590 |         (setq errors (or (compile-error-at-point)
 | 
|---|
 | 591 |                          (error "Moved past last error")))
 | 
|---|
 | 592 | 
 | 
|---|
 | 593 |       ;; Get a reversed list of the errors up through the one containing point.
 | 
|---|
 | 594 |       (compile-reinitialize-errors nil (point))
 | 
|---|
 | 595 |       (setq errors (reverse compilation-old-error-list)
 | 
|---|
 | 596 |             n (- n))
 | 
|---|
 | 597 | 
 | 
|---|
 | 598 |       ;; Ignore errors after point.  (car ERRORS) will be the error
 | 
|---|
 | 599 |       ;; containing point, (cadr ERRORS) the one before it.
 | 
|---|
 | 600 |       (while (and errors
 | 
|---|
 | 601 |                   (< (point) (car (car errors))))
 | 
|---|
 | 602 |         (setq errors (cdr errors))))
 | 
|---|
 | 603 | 
 | 
|---|
 | 604 |     (while (> n 0)
 | 
|---|
 | 605 |       (setq filedata (compilation-error-filedata (car errors)))
 | 
|---|
 | 606 | 
 | 
|---|
 | 607 |       ;; Skip past the following errors for this file.
 | 
|---|
 | 608 |       (while (equal filedata
 | 
|---|
 | 609 |                     (compilation-error-filedata
 | 
|---|
 | 610 |                      (car (or errors
 | 
|---|
 | 611 |                               (if reversed
 | 
|---|
 | 612 |                                   (error "%s the first erring file"
 | 
|---|
 | 613 |                                          (compilation-error-filedata-file-name
 | 
|---|
 | 614 |                                           filedata))
 | 
|---|
 | 615 |                                 (let ((compilation-error-list nil))
 | 
|---|
 | 616 |                                   ;; Parse some more.
 | 
|---|
 | 617 |                                   (compile-reinitialize-errors nil nil 2)
 | 
|---|
 | 618 |                                   (setq errors compilation-error-list)))
 | 
|---|
 | 619 |                               (error "%s is the last erring file" 
 | 
|---|
 | 620 |                                      (compilation-error-filedata-file-name
 | 
|---|
 | 621 |                                       filedata))))))
 | 
|---|
 | 622 |         (setq errors (cdr errors)))
 | 
|---|
 | 623 | 
 | 
|---|
 | 624 |       (setq n (1- n)))
 | 
|---|
 | 625 | 
 | 
|---|
 | 626 |     ;; Move to the following error.
 | 
|---|
 | 627 |     (goto-char (car (car (or errors
 | 
|---|
 | 628 |                              (if reversed
 | 
|---|
 | 629 |                                  (error "This is the first erring file")
 | 
|---|
 | 630 |                                (let ((compilation-error-list nil))
 | 
|---|
 | 631 |                                  ;; Parse the last one.
 | 
|---|
 | 632 |                                  (compile-reinitialize-errors nil nil 1)
 | 
|---|
 | 633 |                                  compilation-error-list))))))))
 | 
|---|
 | 634 | 
 | 
|---|
 | 635 | (defun compilation-previous-file (n)
 | 
|---|
 | 636 |   "Move point to the previous error for a different file than the current one."
 | 
|---|
 | 637 |   (interactive "p")
 | 
|---|
 | 638 |   (compilation-next-file (- n)))
 | 
|---|
 | 639 | 
 | 
|---|
 | 640 | 
 | 
|---|
 | 641 | (defun kill-compilation ()
 | 
|---|
 | 642 |   "Kill the process made by the \\[compile] command."
 | 
|---|
 | 643 |   (interactive)
 | 
|---|
 | 644 |   (let ((buffer (compilation-find-buffer)))
 | 
|---|
 | 645 |     (if (get-buffer-process buffer)
 | 
|---|
 | 646 |         (interrupt-process (get-buffer-process buffer))
 | 
|---|
 | 647 |       (error "The compilation process is not running."))))
 | 
|---|
 | 648 | 
 | 
|---|
 | 649 | 
 | 
|---|
 | 650 | ;; Parse any new errors in the compilation buffer,
 | 
|---|
 | 651 | ;; or reparse from the beginning if the user has asked for that.
 | 
|---|
 | 652 | (defun compile-reinitialize-errors (reparse
 | 
|---|
 | 653 |                                     &optional limit-search find-at-least)
 | 
|---|
 | 654 |   (save-excursion
 | 
|---|
 | 655 |     (set-buffer compilation-last-buffer)
 | 
|---|
 | 656 |     ;; If we are out of errors, or if user says "reparse",
 | 
|---|
 | 657 |     ;; discard the info we have, to force reparsing.
 | 
|---|
 | 658 |     (if (or (eq compilation-error-list t)
 | 
|---|
 | 659 |             reparse)
 | 
|---|
 | 660 |         (compilation-forget-errors))
 | 
|---|
 | 661 |     (if (and compilation-error-list
 | 
|---|
 | 662 |              (or (not limit-search)
 | 
|---|
 | 663 |                  (> compilation-parsing-end limit-search))
 | 
|---|
 | 664 |              (or (not find-at-least)
 | 
|---|
 | 665 |                  (>= (length compilation-error-list) find-at-least)))
 | 
|---|
 | 666 |         ;; Since compilation-error-list is non-nil, it points to a specific
 | 
|---|
 | 667 |         ;; error the user wanted.  So don't move it around.
 | 
|---|
 | 668 |         nil
 | 
|---|
 | 669 |       ;; This was here for a long time (before my rewrite); why? --roland
 | 
|---|
 | 670 |       ;;(switch-to-buffer compilation-last-buffer)
 | 
|---|
 | 671 |       (set-buffer-modified-p nil)
 | 
|---|
 | 672 |       (if (< compilation-parsing-end (point-max))
 | 
|---|
 | 673 |           ;; compilation-error-list might be non-nil if we have a non-nil
 | 
|---|
 | 674 |           ;; LIMIT-SEARCH or FIND-AT-LEAST arg.  In that case its value
 | 
|---|
 | 675 |           ;; records the current position in the error list, and we must
 | 
|---|
 | 676 |           ;; preserve that after reparsing.
 | 
|---|
 | 677 |           (let ((error-list-pos compilation-error-list))
 | 
|---|
 | 678 |             (funcall compilation-parse-errors-function
 | 
|---|
 | 679 |                      limit-search
 | 
|---|
 | 680 |                      (and find-at-least
 | 
|---|
 | 681 |                           ;; We only need enough new parsed errors to reach
 | 
|---|
 | 682 |                           ;; FIND-AT-LEAST errors past the current
 | 
|---|
 | 683 |                           ;; position.
 | 
|---|
 | 684 |                           (- find-at-least (length compilation-error-list))))
 | 
|---|
 | 685 |             ;; Remember the entire list for compilation-forget-errors.  If
 | 
|---|
 | 686 |             ;; this is an incremental parse, append to previous list.  If
 | 
|---|
 | 687 |             ;; we are parsing anew, compilation-forget-errors cleared
 | 
|---|
 | 688 |             ;; compilation-old-error-list above.
 | 
|---|
 | 689 |             (setq compilation-old-error-list
 | 
|---|
 | 690 |                   (nconc compilation-old-error-list compilation-error-list))
 | 
|---|
 | 691 |             (if error-list-pos
 | 
|---|
 | 692 |                 ;; We started in the middle of an existing list of parsed
 | 
|---|
 | 693 |                 ;; errors before parsing more; restore that position.
 | 
|---|
 | 694 |                 (setq compilation-error-list error-list-pos))
 | 
|---|
 | 695 |             )))))
 | 
|---|
 | 696 | 
 | 
|---|
 | 697 | (defun compile-mouse-goto-error (event)
 | 
|---|
 | 698 |   (interactive "e")
 | 
|---|
 | 699 |   (save-excursion
 | 
|---|
 | 700 |     (set-buffer (window-buffer (posn-window (event-end event))))
 | 
|---|
 | 701 |     (goto-char (posn-point (event-end event)))
 | 
|---|
 | 702 | 
 | 
|---|
 | 703 |     (or (compilation-buffer-p (current-buffer))
 | 
|---|
 | 704 |         (error "Not in a compilation buffer."))
 | 
|---|
 | 705 |     (setq compilation-last-buffer (current-buffer))
 | 
|---|
 | 706 |     (compile-reinitialize-errors nil (point))
 | 
|---|
 | 707 | 
 | 
|---|
 | 708 |     ;; Move to bol; the marker for the error on this line will point there.
 | 
|---|
 | 709 |     (beginning-of-line)
 | 
|---|
 | 710 | 
 | 
|---|
 | 711 |     ;; Move compilation-error-list to the elt of compilation-old-error-list
 | 
|---|
 | 712 |     ;; we want.
 | 
|---|
 | 713 |     (setq compilation-error-list compilation-old-error-list)
 | 
|---|
 | 714 |     (while (and compilation-error-list
 | 
|---|
 | 715 |                 (> (point) (car (car compilation-error-list))))
 | 
|---|
 | 716 |       (setq compilation-error-list (cdr compilation-error-list)))
 | 
|---|
 | 717 |     (or compilation-error-list
 | 
|---|
 | 718 |         (error "No error to go to")))
 | 
|---|
 | 719 |   (select-window (posn-window (event-end event)))
 | 
|---|
 | 720 |   ;; Move to another window, so that next-error's window changes
 | 
|---|
 | 721 |   ;; result in the desired setup.
 | 
|---|
 | 722 |   (or (one-window-p)
 | 
|---|
 | 723 |       (progn
 | 
|---|
 | 724 |         (other-window -1)
 | 
|---|
 | 725 |         ;; other-window changed the selected buffer,
 | 
|---|
 | 726 |         ;; but we didn't want to do that.
 | 
|---|
 | 727 |         (set-buffer compilation-last-buffer)))
 | 
|---|
 | 728 | 
 | 
|---|
 | 729 |   (push-mark)
 | 
|---|
 | 730 |   (next-error 1))
 | 
|---|
 | 731 | 
 | 
|---|
 | 732 | (defun compile-goto-error (&optional argp)
 | 
|---|
 | 733 |   "Visit the source for the error message point is on.
 | 
|---|
 | 734 | Use this command in a compilation log buffer.  Sets the mark at point there.
 | 
|---|
 | 735 | \\[universal-argument] as a prefix arg means to reparse the buffer's error messages first;
 | 
|---|
 | 736 | other kinds of prefix arguments are ignored."
 | 
|---|
 | 737 |   (interactive "P")
 | 
|---|
 | 738 |   (or (compilation-buffer-p (current-buffer))
 | 
|---|
 | 739 |       (error "Not in a compilation buffer."))
 | 
|---|
 | 740 |   (setq compilation-last-buffer (current-buffer))
 | 
|---|
 | 741 |   (compile-reinitialize-errors (consp argp) (point))
 | 
|---|
 | 742 | 
 | 
|---|
 | 743 |   ;; Move to bol; the marker for the error on this line will point there.
 | 
|---|
 | 744 |   (beginning-of-line)
 | 
|---|
 | 745 | 
 | 
|---|
 | 746 |   ;; Move compilation-error-list to the elt of compilation-old-error-list
 | 
|---|
 | 747 |   ;; we want.
 | 
|---|
 | 748 |   (setq compilation-error-list compilation-old-error-list)
 | 
|---|
 | 749 |   (while (and compilation-error-list
 | 
|---|
 | 750 |               (> (point) (car (car compilation-error-list))))
 | 
|---|
 | 751 |     (setq compilation-error-list (cdr compilation-error-list)))
 | 
|---|
 | 752 | 
 | 
|---|
 | 753 |   ;; Move to another window, so that next-error's window changes
 | 
|---|
 | 754 |   ;; result in the desired setup.
 | 
|---|
 | 755 |   (or (one-window-p)
 | 
|---|
 | 756 |       (progn
 | 
|---|
 | 757 |         (other-window -1)
 | 
|---|
 | 758 |         ;; other-window changed the selected buffer,
 | 
|---|
 | 759 |         ;; but we didn't want to do that.
 | 
|---|
 | 760 |         (set-buffer compilation-last-buffer)))
 | 
|---|
 | 761 | 
 | 
|---|
 | 762 |   (push-mark)
 | 
|---|
 | 763 |   (next-error 1))
 | 
|---|
 | 764 | 
 | 
|---|
 | 765 | ;; Return a compilation buffer.
 | 
|---|
 | 766 | ;; If the current buffer is a compilation buffer, return it.
 | 
|---|
 | 767 | ;; If compilation-last-buffer is set to a live buffer, use that.
 | 
|---|
 | 768 | ;; Otherwise, look for a compilation buffer and signal an error
 | 
|---|
 | 769 | ;; if there are none.
 | 
|---|
 | 770 | (defun compilation-find-buffer (&optional other-buffer)
 | 
|---|
 | 771 |   (if (and (not other-buffer)
 | 
|---|
 | 772 |            (compilation-buffer-p (current-buffer)))
 | 
|---|
 | 773 |       ;; The current buffer is a compilation buffer.
 | 
|---|
 | 774 |       (current-buffer)
 | 
|---|
 | 775 |     (if (and compilation-last-buffer (buffer-name compilation-last-buffer)
 | 
|---|
 | 776 |              (or (not other-buffer) (not (eq compilation-last-buffer
 | 
|---|
 | 777 |                                              (current-buffer)))))
 | 
|---|
 | 778 |         compilation-last-buffer
 | 
|---|
 | 779 |       (let ((buffers (buffer-list)))
 | 
|---|
 | 780 |         (while (and buffers (or (not (compilation-buffer-p (car buffers)))
 | 
|---|
 | 781 |                                 (and other-buffer
 | 
|---|
 | 782 |                                      (eq (car buffers) (current-buffer)))))
 | 
|---|
 | 783 |           (setq buffers (cdr buffers)))
 | 
|---|
 | 784 |         (if buffers
 | 
|---|
 | 785 |             (car buffers)
 | 
|---|
 | 786 |           (or (and other-buffer
 | 
|---|
 | 787 |                    (compilation-buffer-p (current-buffer))
 | 
|---|
 | 788 |                    ;; The current buffer is a compilation buffer.
 | 
|---|
 | 789 |                    (progn
 | 
|---|
 | 790 |                      (if other-buffer
 | 
|---|
 | 791 |                          (message "This is the only compilation buffer."))
 | 
|---|
 | 792 |                      (current-buffer)))
 | 
|---|
 | 793 |               (error "No compilation started!")))))))
 | 
|---|
 | 794 | 
 | 
|---|
 | 795 | ;;;###autoload
 | 
|---|
 | 796 | (defun next-error (&optional argp)
 | 
|---|
 | 797 |   "Visit next compilation error message and corresponding source code.
 | 
|---|
 | 798 | This operates on the output from the \\[compile] command.
 | 
|---|
 | 799 | If all preparsed error messages have been processed,
 | 
|---|
 | 800 | the error message buffer is checked for new ones.
 | 
|---|
 | 801 | 
 | 
|---|
 | 802 | A prefix arg specifies how many error messages to move;
 | 
|---|
 | 803 | negative means move back to previous error messages.
 | 
|---|
 | 804 | Just C-u as a prefix means reparse the error message buffer
 | 
|---|
 | 805 | and start at the first error.
 | 
|---|
 | 806 | 
 | 
|---|
 | 807 | \\[next-error] normally applies to the most recent compilation started,
 | 
|---|
 | 808 | but as long as you are in the middle of parsing errors from one compilation
 | 
|---|
 | 809 | output buffer, you stay with that compilation output buffer.
 | 
|---|
 | 810 | 
 | 
|---|
 | 811 | Use \\[next-error] in a compilation output buffer to switch to
 | 
|---|
 | 812 | processing errors from that compilation.
 | 
|---|
 | 813 | 
 | 
|---|
 | 814 | See variables `compilation-parse-errors-function' and
 | 
|---|
 | 815 | \`compilation-error-regexp-alist' for customization ideas."
 | 
|---|
 | 816 |   (interactive "P")
 | 
|---|
 | 817 |   (setq compilation-last-buffer (compilation-find-buffer))
 | 
|---|
 | 818 |   (compilation-goto-locus (compilation-next-error-locus
 | 
|---|
 | 819 |                            ;; We want to pass a number here only if
 | 
|---|
 | 820 |                            ;; we got a numeric prefix arg, not just C-u.
 | 
|---|
 | 821 |                            (and (not (consp argp))
 | 
|---|
 | 822 |                                 (prefix-numeric-value argp))
 | 
|---|
 | 823 |                            (consp argp))))
 | 
|---|
 | 824 | ;;;###autoload (define-key ctl-x-map "`" 'next-error)
 | 
|---|
 | 825 | 
 | 
|---|
 | 826 | (defun compilation-next-error-locus (&optional move reparse)
 | 
|---|
 | 827 |   "Visit next compilation error and return locus in corresponding source code.
 | 
|---|
 | 828 | This operates on the output from the \\[compile] command.
 | 
|---|
 | 829 | If all preparsed error messages have been processed,
 | 
|---|
 | 830 | the error message buffer is checked for new ones.
 | 
|---|
 | 831 | 
 | 
|---|
 | 832 | Returns a cons (ERROR . SOURCE) of two markers: ERROR is a marker at the
 | 
|---|
 | 833 | location of the error message in the compilation buffer, and SOURCE is a
 | 
|---|
 | 834 | marker at the location in the source code indicated by the error message.
 | 
|---|
 | 835 | 
 | 
|---|
 | 836 | Optional first arg MOVE says how many error messages to move forwards (or
 | 
|---|
 | 837 | backwards, if negative); default is 1.  Optional second arg REPARSE, if
 | 
|---|
 | 838 | non-nil, says to reparse the error message buffer and reset to the first
 | 
|---|
 | 839 | error (plus MOVE - 1).
 | 
|---|
 | 840 | 
 | 
|---|
 | 841 | The current buffer should be the desired compilation output buffer."
 | 
|---|
 | 842 |   (or move (setq move 1))
 | 
|---|
 | 843 |   (compile-reinitialize-errors reparse nil (and (not reparse)
 | 
|---|
 | 844 |                                                 (if (< move 1) 0 (1- move))))
 | 
|---|
 | 845 |   (let (next-errors next-error)
 | 
|---|
 | 846 |     (save-excursion
 | 
|---|
 | 847 |       (set-buffer compilation-last-buffer)
 | 
|---|
 | 848 |       ;; compilation-error-list points to the "current" error.
 | 
|---|
 | 849 |       (setq next-errors 
 | 
|---|
 | 850 |             (if (> move 0)
 | 
|---|
 | 851 |                 (nthcdr (1- move)
 | 
|---|
 | 852 |                         compilation-error-list)
 | 
|---|
 | 853 |               ;; Zero or negative arg; we need to move back in the list.
 | 
|---|
 | 854 |               (let ((n (1- move))
 | 
|---|
 | 855 |                     (i 0)
 | 
|---|
 | 856 |                     (e compilation-old-error-list))
 | 
|---|
 | 857 |                 ;; See how many cdrs away the current error is from the start.
 | 
|---|
 | 858 |                 (while (not (eq e compilation-error-list))
 | 
|---|
 | 859 |                   (setq i (1+ i)
 | 
|---|
 | 860 |                         e (cdr e)))
 | 
|---|
 | 861 |                 (if (> (- n) i)
 | 
|---|
 | 862 |                     (error "Moved back past first error")
 | 
|---|
 | 863 |                   (nthcdr (+ i n) compilation-old-error-list))))
 | 
|---|
 | 864 |             next-error (car next-errors))
 | 
|---|
 | 865 |       (while
 | 
|---|
 | 866 |           (if (null next-error)
 | 
|---|
 | 867 |               (progn
 | 
|---|
 | 868 |                 (and move (/= move 1)
 | 
|---|
 | 869 |                      (error (if (> move 0)
 | 
|---|
 | 870 |                                 "Moved past last error")
 | 
|---|
 | 871 |                             "Moved back past first error"))
 | 
|---|
 | 872 |                 (compilation-forget-errors)
 | 
|---|
 | 873 |                 (error (concat compilation-error-message
 | 
|---|
 | 874 |                                (and (get-buffer-process (current-buffer))
 | 
|---|
 | 875 |                                     (eq (process-status
 | 
|---|
 | 876 |                                          (get-buffer-process
 | 
|---|
 | 877 |                                           (current-buffer)))
 | 
|---|
 | 878 |                                         'run)
 | 
|---|
 | 879 |                                     " yet"))))
 | 
|---|
 | 880 |             (setq compilation-error-list (cdr next-errors))
 | 
|---|
 | 881 |             (if (null (cdr next-error))
 | 
|---|
 | 882 |                 ;; This error is boring.  Go to the next.
 | 
|---|
 | 883 |                 t
 | 
|---|
 | 884 |               (or (markerp (cdr next-error))
 | 
|---|
 | 885 |                   ;; This error has a filename/lineno pair.
 | 
|---|
 | 886 |                   ;; Find the file and turn it into a marker.
 | 
|---|
 | 887 |                   (let* ((fileinfo (car (cdr next-error)))
 | 
|---|
 | 888 |                          (buffer (compilation-find-file (cdr fileinfo)
 | 
|---|
 | 889 |                                                         (car fileinfo)
 | 
|---|
 | 890 |                                                         (car next-error))))
 | 
|---|
 | 891 |                     (if (null buffer)
 | 
|---|
 | 892 |                         ;; We can't find this error's file.
 | 
|---|
 | 893 |                         ;; Remove all errors in the same file.
 | 
|---|
 | 894 |                         (progn
 | 
|---|
 | 895 |                           (setq next-errors compilation-old-error-list)
 | 
|---|
 | 896 |                           (while next-errors
 | 
|---|
 | 897 |                             (and (consp (cdr (car next-errors)))
 | 
|---|
 | 898 |                                  (equal (car (cdr (car next-errors)))
 | 
|---|
 | 899 |                                         fileinfo)
 | 
|---|
 | 900 |                                  (progn
 | 
|---|
 | 901 |                                    (set-marker (car (car next-errors)) nil)
 | 
|---|
 | 902 |                                    (setcdr (car next-errors) nil)))
 | 
|---|
 | 903 |                             (setq next-errors (cdr next-errors)))
 | 
|---|
 | 904 |                           ;; Look for the next error.
 | 
|---|
 | 905 |                           t)
 | 
|---|
 | 906 |                       ;; We found the file.  Get a marker for this error.
 | 
|---|
 | 907 |                       ;; compilation-old-error-list is a buffer-local
 | 
|---|
 | 908 |                       ;; variable, so we must be careful to extract its value
 | 
|---|
 | 909 |                       ;; before switching to the source file buffer.
 | 
|---|
 | 910 |                       (let ((errors compilation-old-error-list)
 | 
|---|
 | 911 |                             (last-line (nth 1 (cdr next-error)))
 | 
|---|
 | 912 |                             (column (nth 2 (cdr next-error))))
 | 
|---|
 | 913 |                         (set-buffer buffer)
 | 
|---|
 | 914 |                         (save-excursion
 | 
|---|
 | 915 |                           (save-restriction
 | 
|---|
 | 916 |                             (widen)
 | 
|---|
 | 917 |                             (goto-line last-line)
 | 
|---|
 | 918 |                             (if column
 | 
|---|
 | 919 |                                 (move-to-column column)
 | 
|---|
 | 920 |                               (beginning-of-line))
 | 
|---|
 | 921 |                             (setcdr next-error (point-marker))
 | 
|---|
 | 922 |                             ;; Make all the other error messages referring
 | 
|---|
 | 923 |                             ;; to the same file have markers into the buffer.
 | 
|---|
 | 924 |                             (while errors
 | 
|---|
 | 925 |                               (and (consp (cdr (car errors)))
 | 
|---|
 | 926 |                                    (equal (car (cdr (car errors))) fileinfo)
 | 
|---|
 | 927 |                                    (let* ((this (nth 1 (cdr (car errors))))
 | 
|---|
 | 928 |                                           (column (nth 2 (cdr (car errors))))
 | 
|---|
 | 929 |                                           (lines (- this last-line)))
 | 
|---|
 | 930 |                                      (if (eq selective-display t)
 | 
|---|
 | 931 |                                          ;; When selective-display is t,
 | 
|---|
 | 932 |                                          ;; each C-m is a line boundary,
 | 
|---|
 | 933 |                                          ;; as well as each newline.
 | 
|---|
 | 934 |                                          (if (< lines 0)
 | 
|---|
 | 935 |                                              (re-search-backward "[\n\C-m]"
 | 
|---|
 | 936 |                                                                  nil 'end
 | 
|---|
 | 937 |                                                                  (- lines))
 | 
|---|
 | 938 |                                            (re-search-forward "[\n\C-m]"
 | 
|---|
 | 939 |                                                               nil 'end
 | 
|---|
 | 940 |                                                               lines))
 | 
|---|
 | 941 |                                        (forward-line lines))
 | 
|---|
 | 942 |                                      (if column
 | 
|---|
 | 943 |                                          (move-to-column column))
 | 
|---|
 | 944 |                                      (setq last-line this)
 | 
|---|
 | 945 |                                      (setcdr (car errors) (point-marker))))
 | 
|---|
 | 946 |                               (setq errors (cdr errors)))))))))
 | 
|---|
 | 947 |               ;; If we didn't get a marker for this error, or this
 | 
|---|
 | 948 |               ;; marker's buffer was killed, go on to the next one.
 | 
|---|
 | 949 |               (or (not (markerp (cdr next-error)))
 | 
|---|
 | 950 |                   (not (marker-buffer (cdr next-error))))))
 | 
|---|
 | 951 |         (setq next-errors compilation-error-list
 | 
|---|
 | 952 |               next-error (car next-errors))))
 | 
|---|
 | 953 | 
 | 
|---|
 | 954 |     ;; Skip over multiple error messages for the same source location,
 | 
|---|
 | 955 |     ;; so the next C-x ` won't go to an error in the same place.
 | 
|---|
 | 956 |     (while (and compilation-error-list
 | 
|---|
 | 957 |                 (equal (cdr (car compilation-error-list)) (cdr next-error)))
 | 
|---|
 | 958 |       (setq compilation-error-list (cdr compilation-error-list)))
 | 
|---|
 | 959 | 
 | 
|---|
 | 960 |     ;; We now have a marker for the position of the error source code.
 | 
|---|
 | 961 |     ;; NEXT-ERROR is a cons (ERROR . SOURCE) of two markers.
 | 
|---|
 | 962 |     next-error))
 | 
|---|
 | 963 | 
 | 
|---|
 | 964 | (defun compilation-goto-locus (next-error)
 | 
|---|
 | 965 |   "Jump to an error locus returned by `compilation-next-error-locus'.
 | 
|---|
 | 966 | Takes one argument, a cons (ERROR . SOURCE) of two markers.
 | 
|---|
 | 967 | Selects a window with point at SOURCE, with another window displaying ERROR."
 | 
|---|
 | 968 |   (if (and (window-dedicated-p (selected-window))
 | 
|---|
 | 969 |            (eq (selected-window) (frame-root-window)))
 | 
|---|
 | 970 |       (switch-to-buffer-other-frame (marker-buffer (cdr next-error)))
 | 
|---|
 | 971 |     (switch-to-buffer (marker-buffer (cdr next-error))))
 | 
|---|
 | 972 |   (goto-char (cdr next-error))
 | 
|---|
 | 973 |   ;; If narrowing got in the way of
 | 
|---|
 | 974 |   ;; going to the right place, widen.
 | 
|---|
 | 975 |   (or (= (point) (marker-position (cdr next-error)))
 | 
|---|
 | 976 |       (progn
 | 
|---|
 | 977 |         (widen)
 | 
|---|
 | 978 |         (goto-char (cdr next-error))))
 | 
|---|
 | 979 | 
 | 
|---|
 | 980 |   ;; Show compilation buffer in other window, scrolled to this error.
 | 
|---|
 | 981 |   (let* ((pop-up-windows t)
 | 
|---|
 | 982 |          (w (display-buffer (marker-buffer (car next-error)))))
 | 
|---|
 | 983 |     (set-window-point w (car next-error))
 | 
|---|
 | 984 |     (set-window-start w (car next-error))))
 | 
|---|
 | 985 |  | 
|---|
 | 986 | 
 | 
|---|
 | 987 | ;; Find a buffer for file FILENAME.
 | 
|---|
 | 988 | ;; Search the directories in compilation-search-path.
 | 
|---|
 | 989 | ;; A nil in compilation-search-path means to try the
 | 
|---|
 | 990 | ;; current directory, which is passed in DIR.
 | 
|---|
 | 991 | ;; If FILENAME is not found at all, ask the user where to find it.
 | 
|---|
 | 992 | ;; Pop up the buffer containing MARKER and scroll to MARKER if we ask the user.
 | 
|---|
 | 993 | (defun compilation-find-file (filename dir marker)
 | 
|---|
 | 994 |   (let ((dirs compilation-search-path)
 | 
|---|
 | 995 |         result name)
 | 
|---|
 | 996 |     (while (and dirs (null result))
 | 
|---|
 | 997 |       (setq name (expand-file-name filename (or (car dirs) dir))
 | 
|---|
 | 998 |             result (and (file-exists-p name)
 | 
|---|
 | 999 |                         (find-file-noselect name))
 | 
|---|
 | 1000 |             dirs (cdr dirs)))
 | 
|---|
 | 1001 |     (or result
 | 
|---|
 | 1002 |         ;; The file doesn't exist.
 | 
|---|
 | 1003 |         ;; Ask the user where to find it.
 | 
|---|
 | 1004 |         ;; If he hits C-g, then the next time he does
 | 
|---|
 | 1005 |         ;; next-error, he'll skip past it.
 | 
|---|
 | 1006 |         (progn
 | 
|---|
 | 1007 |           (let* ((pop-up-windows t)
 | 
|---|
 | 1008 |                  (w (display-buffer (marker-buffer marker))))
 | 
|---|
 | 1009 |             (set-window-point w marker)
 | 
|---|
 | 1010 |             (set-window-start w marker))
 | 
|---|
 | 1011 |           (setq name
 | 
|---|
 | 1012 |                 (expand-file-name
 | 
|---|
 | 1013 |                  (read-file-name
 | 
|---|
 | 1014 |                   (format "Find this error in: (default %s) "
 | 
|---|
 | 1015 |                           filename) dir filename t)))
 | 
|---|
 | 1016 |           (if (file-directory-p name)
 | 
|---|
 | 1017 |               (setq name (concat (file-name-as-directory name) filename)))
 | 
|---|
 | 1018 |           (if (file-exists-p name)
 | 
|---|
 | 1019 |               (find-file-noselect name))))))
 | 
|---|
 | 1020 | 
 | 
|---|
 | 1021 | ;; Set compilation-error-list to nil, and unchain the markers that point to the
 | 
|---|
 | 1022 | ;; error messages and their text, so that they no longer slow down gap motion.
 | 
|---|
 | 1023 | ;; This would happen anyway at the next garbage collection, but it is better to
 | 
|---|
 | 1024 | ;; do it right away.
 | 
|---|
 | 1025 | (defun compilation-forget-errors ()
 | 
|---|
 | 1026 |   (while compilation-old-error-list
 | 
|---|
 | 1027 |     (let ((next-error (car compilation-old-error-list)))
 | 
|---|
 | 1028 |       (set-marker (car next-error) nil)
 | 
|---|
 | 1029 |       (if (markerp (cdr next-error))
 | 
|---|
 | 1030 |           (set-marker (cdr next-error) nil)))
 | 
|---|
 | 1031 |     (setq compilation-old-error-list (cdr compilation-old-error-list)))
 | 
|---|
 | 1032 |   (setq compilation-error-list nil
 | 
|---|
 | 1033 |         compilation-directory-stack nil
 | 
|---|
 | 1034 |         compilation-parsing-end 1))
 | 
|---|
 | 1035 | 
 | 
|---|
 | 1036 | 
 | 
|---|
 | 1037 | (defun count-regexp-groupings (regexp)
 | 
|---|
 | 1038 |   "Return the number of \\( ... \\) groupings in REGEXP (a string)."
 | 
|---|
 | 1039 |   (let ((groupings 0)
 | 
|---|
 | 1040 |         (len (length regexp))
 | 
|---|
 | 1041 |         (i 0)
 | 
|---|
 | 1042 |         c)
 | 
|---|
 | 1043 |     (while (< i len)
 | 
|---|
 | 1044 |       (setq c (aref regexp i)
 | 
|---|
 | 1045 |             i (1+ i))
 | 
|---|
 | 1046 |       (cond ((= c ?\[)
 | 
|---|
 | 1047 |              ;; Find the end of this [...].
 | 
|---|
 | 1048 |              (while (and (< i len)
 | 
|---|
 | 1049 |                          (not (= (aref regexp i) ?\])))
 | 
|---|
 | 1050 |                (setq i (1+ i))))
 | 
|---|
 | 1051 |             ((= c ?\\)
 | 
|---|
 | 1052 |              (if (< i len)
 | 
|---|
 | 1053 |                  (progn
 | 
|---|
 | 1054 |                    (setq c (aref regexp i)
 | 
|---|
 | 1055 |                          i (1+ i))
 | 
|---|
 | 1056 |                    (if (= c ?\))
 | 
|---|
 | 1057 |                        ;; We found the end of a grouping,
 | 
|---|
 | 1058 |                        ;; so bump our counter.
 | 
|---|
 | 1059 |                        (setq groupings (1+ groupings))))))))
 | 
|---|
 | 1060 |     groupings))
 | 
|---|
 | 1061 | 
 | 
|---|
 | 1062 | (defun compilation-parse-errors (limit-search find-at-least)
 | 
|---|
 | 1063 |   "Parse the current buffer as grep, cc or lint error messages.
 | 
|---|
 | 1064 | See variable `compilation-parse-errors-function' for the interface it uses."
 | 
|---|
 | 1065 |   (setq compilation-error-list nil)
 | 
|---|
 | 1066 |   (message "Parsing error messages...")
 | 
|---|
 | 1067 |   (let (text-buffer orig orig-expanded parent-expanded
 | 
|---|
 | 1068 |         regexp enter-group leave-group error-group
 | 
|---|
 | 1069 |         alist subexpr error-regexp-groups
 | 
|---|
 | 1070 |         (found-desired nil)
 | 
|---|
 | 1071 |         (compilation-num-errors-found 0))
 | 
|---|
 | 1072 | 
 | 
|---|
 | 1073 |     ;; Don't reparse messages already seen at last parse.
 | 
|---|
 | 1074 |     (goto-char compilation-parsing-end)
 | 
|---|
 | 1075 |     ;; Don't parse the first two lines as error messages.
 | 
|---|
 | 1076 |     ;; This matters for grep.
 | 
|---|
 | 1077 |     (if (bobp)
 | 
|---|
 | 1078 |         (progn
 | 
|---|
 | 1079 |           (forward-line 2)
 | 
|---|
 | 1080 |           ;; Move back so point is before the newline.
 | 
|---|
 | 1081 |           ;; This matters because some error regexps use \n instead of ^
 | 
|---|
 | 1082 |           ;; to be faster.
 | 
|---|
 | 1083 |           (forward-char -1)))
 | 
|---|
 | 1084 | 
 | 
|---|
 | 1085 |     ;; Compile all the regexps we want to search for into one.
 | 
|---|
 | 1086 |     (setq regexp (concat "\\(" compilation-enter-directory-regexp "\\)\\|"
 | 
|---|
 | 1087 |                          "\\(" compilation-leave-directory-regexp "\\)\\|"
 | 
|---|
 | 1088 |                          "\\(" (mapconcat (function
 | 
|---|
 | 1089 |                                            (lambda (elt)
 | 
|---|
 | 1090 |                                              (concat "\\(" (car elt) "\\)")))
 | 
|---|
 | 1091 |                                           compilation-error-regexp-alist
 | 
|---|
 | 1092 |                                           "\\|") "\\)"))
 | 
|---|
 | 1093 | 
 | 
|---|
 | 1094 |     ;; Find out how many \(...\) groupings are in each of the regexps, and set
 | 
|---|
 | 1095 |     ;; *-GROUP to the grouping containing each constituent regexp (whose
 | 
|---|
 | 1096 |     ;; subgroups will come immediately thereafter) of the big regexp we have
 | 
|---|
 | 1097 |     ;; just constructed.
 | 
|---|
 | 1098 |     (setq enter-group 1
 | 
|---|
 | 1099 |           leave-group (+ enter-group
 | 
|---|
 | 1100 |                          (count-regexp-groupings
 | 
|---|
 | 1101 |                           compilation-enter-directory-regexp)
 | 
|---|
 | 1102 |                          1)
 | 
|---|
 | 1103 |           error-group (+ leave-group
 | 
|---|
 | 1104 |                          (count-regexp-groupings
 | 
|---|
 | 1105 |                           compilation-leave-directory-regexp)
 | 
|---|
 | 1106 |                          1))
 | 
|---|
 | 1107 | 
 | 
|---|
 | 1108 |     ;; Compile an alist (IDX FILE LINE [COL]), where IDX is the number of
 | 
|---|
 | 1109 |     ;; the subexpression for an entire error-regexp, and FILE and LINE (and
 | 
|---|
 | 1110 |     ;; possibly COL) are the numbers for the subexpressions giving the file
 | 
|---|
 | 1111 |     ;; name and line number (and possibly column number).
 | 
|---|
 | 1112 |     (setq alist (or compilation-error-regexp-alist
 | 
|---|
 | 1113 |                     (error "compilation-error-regexp-alist is empty!"))
 | 
|---|
 | 1114 |           subexpr (1+ error-group))
 | 
|---|
 | 1115 |     (while alist
 | 
|---|
 | 1116 |       (setq error-regexp-groups
 | 
|---|
 | 1117 |             (cons (list subexpr
 | 
|---|
 | 1118 |                         (+ subexpr (nth 1 (car alist)))
 | 
|---|
 | 1119 |                         (+ subexpr (nth 2 (car alist)))
 | 
|---|
 | 1120 |                         (and (nth 3 (car alist))
 | 
|---|
 | 1121 |                              (+ subexpr (nth 3 (car alist)))))
 | 
|---|
 | 1122 |                   error-regexp-groups))
 | 
|---|
 | 1123 |       (setq subexpr (+ subexpr 1 (count-regexp-groupings (car (car alist)))))
 | 
|---|
 | 1124 |       (setq alist (cdr alist)))
 | 
|---|
 | 1125 | 
 | 
|---|
 | 1126 |     (setq orig default-directory)
 | 
|---|
 | 1127 |     (setq orig-expanded (file-truename orig))
 | 
|---|
 | 1128 |     (setq parent-expanded (expand-file-name "../" orig-expanded))
 | 
|---|
 | 1129 | 
 | 
|---|
 | 1130 |     (while (and (not found-desired)
 | 
|---|
 | 1131 |                 ;; We don't just pass LIMIT-SEARCH to re-search-forward
 | 
|---|
 | 1132 |                 ;; because we want to find matches containing LIMIT-SEARCH
 | 
|---|
 | 1133 |                 ;; but which extend past it.
 | 
|---|
 | 1134 |                 (re-search-forward regexp nil t))
 | 
|---|
 | 1135 | 
 | 
|---|
 | 1136 |       ;; Figure out which constituent regexp matched.
 | 
|---|
 | 1137 |       (cond ((match-beginning enter-group)
 | 
|---|
 | 1138 |              ;; The match was the enter-directory regexp.
 | 
|---|
 | 1139 |              (let ((dir
 | 
|---|
 | 1140 |                     (file-name-as-directory
 | 
|---|
 | 1141 |                      (expand-file-name
 | 
|---|
 | 1142 |                       (buffer-substring (match-beginning (+ enter-group 1))
 | 
|---|
 | 1143 |                                         (match-end (+ enter-group 1)))))))
 | 
|---|
 | 1144 |                ;; The directory name in the "entering" message
 | 
|---|
 | 1145 |                ;; is a truename.  Try to convert it to a form
 | 
|---|
 | 1146 |                ;; like what the user typed in.
 | 
|---|
 | 1147 |                (setq dir
 | 
|---|
 | 1148 |                      (compile-abbreviate-directory dir orig orig-expanded
 | 
|---|
 | 1149 |                                                    parent-expanded))
 | 
|---|
 | 1150 |                (setq compilation-directory-stack
 | 
|---|
 | 1151 |                      (cons dir compilation-directory-stack))
 | 
|---|
 | 1152 |                (and (file-directory-p dir)
 | 
|---|
 | 1153 |                     (setq default-directory dir)))
 | 
|---|
 | 1154 | 
 | 
|---|
 | 1155 |              (and limit-search (>= (point) limit-search)
 | 
|---|
 | 1156 |                   ;; The user wanted a specific error, and we're past it.
 | 
|---|
 | 1157 |                   ;; We do this check here (and in the leave-group case)
 | 
|---|
 | 1158 |                   ;; rather than at the end of the loop because if the last
 | 
|---|
 | 1159 |                   ;; thing seen is an error message, we must carefully
 | 
|---|
 | 1160 |                   ;; discard the last error when it is the first in a new
 | 
|---|
 | 1161 |                   ;; file (see below in the error-group case).
 | 
|---|
 | 1162 |                   (setq found-desired t)))
 | 
|---|
 | 1163 | 
 | 
|---|
 | 1164 |             ((match-beginning leave-group)
 | 
|---|
 | 1165 |              ;; The match was the leave-directory regexp.
 | 
|---|
 | 1166 |              (let ((beg (match-beginning (+ leave-group 1)))
 | 
|---|
 | 1167 |                    (stack compilation-directory-stack))
 | 
|---|
 | 1168 |                (if beg
 | 
|---|
 | 1169 |                    (let ((dir
 | 
|---|
 | 1170 |                           (file-name-as-directory
 | 
|---|
 | 1171 |                            (expand-file-name
 | 
|---|
 | 1172 |                             (buffer-substring beg
 | 
|---|
 | 1173 |                                               (match-end (+ leave-group
 | 
|---|
 | 1174 |                                                             1)))))))
 | 
|---|
 | 1175 |                      ;; The directory name in the "entering" message
 | 
|---|
 | 1176 |                      ;; is a truename.  Try to convert it to a form
 | 
|---|
 | 1177 |                      ;; like what the user typed in.
 | 
|---|
 | 1178 |                      (setq dir
 | 
|---|
 | 1179 |                            (compile-abbreviate-directory dir orig orig-expanded
 | 
|---|
 | 1180 |                                                          parent-expanded))
 | 
|---|
 | 1181 |                      (while (and stack
 | 
|---|
 | 1182 |                                  (not (string-equal (car stack) dir)))
 | 
|---|
 | 1183 |                        (setq stack (cdr stack)))))
 | 
|---|
 | 1184 |                (setq compilation-directory-stack (cdr stack))
 | 
|---|
 | 1185 |                (setq stack (car compilation-directory-stack))
 | 
|---|
 | 1186 |                (if stack
 | 
|---|
 | 1187 |                    (setq default-directory stack))
 | 
|---|
 | 1188 |                )
 | 
|---|
 | 1189 | 
 | 
|---|
 | 1190 |              (and limit-search (>= (point) limit-search)
 | 
|---|
 | 1191 |                   ;; The user wanted a specific error, and we're past it.
 | 
|---|
 | 1192 |                   ;; We do this check here (and in the enter-group case)
 | 
|---|
 | 1193 |                   ;; rather than at the end of the loop because if the last
 | 
|---|
 | 1194 |                   ;; thing seen is an error message, we must carefully
 | 
|---|
 | 1195 |                   ;; discard the last error when it is the first in a new
 | 
|---|
 | 1196 |                   ;; file (see below in the error-group case).
 | 
|---|
 | 1197 |                   (setq found-desired t)))
 | 
|---|
 | 1198 | 
 | 
|---|
 | 1199 |             ((match-beginning error-group)
 | 
|---|
 | 1200 |              ;; The match was the composite error regexp.
 | 
|---|
 | 1201 |              ;; Find out which individual regexp matched.
 | 
|---|
 | 1202 |              (setq alist error-regexp-groups)
 | 
|---|
 | 1203 |              (while (and alist
 | 
|---|
 | 1204 |                          (null (match-beginning (car (car alist)))))
 | 
|---|
 | 1205 |                (setq alist (cdr alist)))
 | 
|---|
 | 1206 |              (if alist
 | 
|---|
 | 1207 |                  (setq alist (car alist))
 | 
|---|
 | 1208 |                (error "compilation-parse-errors: impossible regexp match!"))
 | 
|---|
 | 1209 |              
 | 
|---|
 | 1210 |              ;; Extract the file name and line number from the error message.
 | 
|---|
 | 1211 |              (let ((beginning-of-match (match-beginning 0)) ;looking-at nukes
 | 
|---|
 | 1212 |                    (filename (buffer-substring (match-beginning (nth 1 alist))
 | 
|---|
 | 1213 |                                                (match-end (nth 1 alist))))
 | 
|---|
 | 1214 |                    (linenum (string-to-int
 | 
|---|
 | 1215 |                              (buffer-substring
 | 
|---|
 | 1216 |                               (match-beginning (nth 2 alist))
 | 
|---|
 | 1217 |                               (match-end (nth 2 alist)))))
 | 
|---|
 | 1218 |                    (column (and (nth 3 alist)
 | 
|---|
 | 1219 |                                 (string-to-int
 | 
|---|
 | 1220 |                                  (buffer-substring
 | 
|---|
 | 1221 |                                   (match-beginning (nth 3 alist))
 | 
|---|
 | 1222 |                                   (match-end (nth 3 alist)))))))
 | 
|---|
 | 1223 | 
 | 
|---|
 | 1224 |                ;; Check for a comint-file-name-prefix and prepend it if
 | 
|---|
 | 1225 |                ;; appropriate.  (This is very useful for
 | 
|---|
 | 1226 |                ;; compilation-minor-mode in an rlogin-mode buffer.)
 | 
|---|
 | 1227 |                (and (boundp 'comint-file-name-prefix)
 | 
|---|
 | 1228 |                     ;; If the file name is relative, default-directory will
 | 
|---|
 | 1229 |                     ;; already contain the comint-file-name-prefix (done by
 | 
|---|
 | 1230 |                     ;; compile-abbreviate-directory).
 | 
|---|
 | 1231 |                     (file-name-absolute-p filename)
 | 
|---|
 | 1232 |                     (setq filename (concat comint-file-name-prefix filename)))
 | 
|---|
 | 1233 |                (setq filename (cons default-directory filename))
 | 
|---|
 | 1234 | 
 | 
|---|
 | 1235 |                ;; Locate the erring file and line.
 | 
|---|
 | 1236 |                ;; Cons a new elt onto compilation-error-list,
 | 
|---|
 | 1237 |                ;; giving a marker for the current compilation buffer
 | 
|---|
 | 1238 |                ;; location, and the file and line number of the error.
 | 
|---|
 | 1239 |                (save-excursion
 | 
|---|
 | 1240 |                  (beginning-of-line 1)
 | 
|---|
 | 1241 |                  (let ((this (cons (point-marker)
 | 
|---|
 | 1242 |                                    (list filename linenum column))))
 | 
|---|
 | 1243 |                    ;; Don't add the same source line more than once.
 | 
|---|
 | 1244 |                    (if (equal (cdr this) (cdr (car compilation-error-list)))
 | 
|---|
 | 1245 |                        nil
 | 
|---|
 | 1246 |                      (setq compilation-error-list
 | 
|---|
 | 1247 |                            (cons this
 | 
|---|
 | 1248 |                                  compilation-error-list))
 | 
|---|
 | 1249 |                      (setq compilation-num-errors-found
 | 
|---|
 | 1250 |                            (1+ compilation-num-errors-found)))))
 | 
|---|
 | 1251 |                (and (or (and find-at-least (> compilation-num-errors-found
 | 
|---|
 | 1252 |                                               find-at-least))
 | 
|---|
 | 1253 |                         (and limit-search (>= (point) limit-search)))
 | 
|---|
 | 1254 |                     ;; We have found as many new errors as the user wants,
 | 
|---|
 | 1255 |                     ;; or past the buffer position he indicated.  We
 | 
|---|
 | 1256 |                     ;; continue to parse until we have seen all the
 | 
|---|
 | 1257 |                     ;; consecutive errors in the same file, so the error
 | 
|---|
 | 1258 |                     ;; positions will be recorded as markers in this buffer
 | 
|---|
 | 1259 |                     ;; that might change.
 | 
|---|
 | 1260 |                     (cdr compilation-error-list) ; Must check at least two.
 | 
|---|
 | 1261 |                     (not (equal (car (cdr (nth 0 compilation-error-list)))
 | 
|---|
 | 1262 |                                 (car (cdr (nth 1 compilation-error-list)))))
 | 
|---|
 | 1263 |                     (progn
 | 
|---|
 | 1264 |                       ;; Discard the error just parsed, so that the next
 | 
|---|
 | 1265 |                       ;; parsing run can get it and the following errors in
 | 
|---|
 | 1266 |                       ;; the same file all at once.  If we didn't do this, we
 | 
|---|
 | 1267 |                       ;; would have the same problem we are trying to avoid
 | 
|---|
 | 1268 |                       ;; with the test above, just delayed until the next run!
 | 
|---|
 | 1269 |                       (setq compilation-error-list
 | 
|---|
 | 1270 |                             (cdr compilation-error-list))
 | 
|---|
 | 1271 |                       (goto-char beginning-of-match)
 | 
|---|
 | 1272 |                       (setq found-desired t)))
 | 
|---|
 | 1273 |                )
 | 
|---|
 | 1274 |              )
 | 
|---|
 | 1275 |             (t
 | 
|---|
 | 1276 |              (error "compilation-parse-errors: known groups didn't match!")))
 | 
|---|
 | 1277 | 
 | 
|---|
 | 1278 |       (message "Parsing error messages...%d (%.0f%% of buffer)"
 | 
|---|
 | 1279 |                compilation-num-errors-found
 | 
|---|
 | 1280 |                ;; Use floating-point because (* 100 (point)) frequently
 | 
|---|
 | 1281 |                ;; exceeds the range of Emacs Lisp integers.
 | 
|---|
 | 1282 |                (/ (* 100.0 (point)) (point-max)))
 | 
|---|
 | 1283 | 
 | 
|---|
 | 1284 |       (and limit-search (>= (point) limit-search)
 | 
|---|
 | 1285 |            ;; The user wanted a specific error, and we're past it.
 | 
|---|
 | 1286 |            (setq found-desired t)))
 | 
|---|
 | 1287 |     (setq compilation-parsing-end (if found-desired
 | 
|---|
 | 1288 |                                       (point)
 | 
|---|
 | 1289 |                                     ;; We have searched the whole buffer.
 | 
|---|
 | 1290 |                                     (point-max))))
 | 
|---|
 | 1291 |   (setq compilation-error-list (nreverse compilation-error-list))
 | 
|---|
 | 1292 |   (message "Parsing error messages...done"))
 | 
|---|
 | 1293 | 
 | 
|---|
 | 1294 | ;; If directory DIR is a subdir of ORIG or of ORIG's parent,
 | 
|---|
 | 1295 | ;; return a relative name for it starting from ORIG or its parent.
 | 
|---|
 | 1296 | ;; ORIG-EXPANDED is an expanded version of ORIG.
 | 
|---|
 | 1297 | ;; PARENT-EXPANDED is an expanded version of ORIG's parent.
 | 
|---|
 | 1298 | ;; Those two args could be computed here, but we run faster by
 | 
|---|
 | 1299 | ;; having the caller compute them just once.
 | 
|---|
 | 1300 | (defun compile-abbreviate-directory (dir orig orig-expanded parent-expanded)
 | 
|---|
 | 1301 |   ;; Check for a comint-file-name-prefix and prepend it if appropriate.
 | 
|---|
 | 1302 |   ;; (This is very useful for compilation-minor-mode in an rlogin-mode
 | 
|---|
 | 1303 |   ;; buffer.)
 | 
|---|
 | 1304 |   (if (boundp 'comint-file-name-prefix)
 | 
|---|
 | 1305 |       (setq dir (concat comint-file-name-prefix dir)))
 | 
|---|
 | 1306 | 
 | 
|---|
 | 1307 |   (if (and (> (length dir) (length orig-expanded))
 | 
|---|
 | 1308 |            (string= orig-expanded
 | 
|---|
 | 1309 |                     (substring dir 0 (length orig-expanded))))
 | 
|---|
 | 1310 |       (setq dir
 | 
|---|
 | 1311 |             (concat orig
 | 
|---|
 | 1312 |                     (substring dir (length orig-expanded)))))
 | 
|---|
 | 1313 |   (if (and (> (length dir) (length parent-expanded))
 | 
|---|
 | 1314 |            (string= parent-expanded
 | 
|---|
 | 1315 |                     (substring dir 0 (length parent-expanded))))
 | 
|---|
 | 1316 |     (setq dir
 | 
|---|
 | 1317 |           (concat (file-name-directory
 | 
|---|
 | 1318 |                    (directory-file-name orig))
 | 
|---|
 | 1319 |                   (substring dir (length parent-expanded)))))
 | 
|---|
 | 1320 |   dir)
 | 
|---|
 | 1321 | 
 | 
|---|
 | 1322 | (provide 'compile)
 | 
|---|
 | 1323 | 
 | 
|---|
 | 1324 | ;;; compile.el ends here
 | 
|---|