diff options
| author | Richard M. Stallman | 1997-05-03 04:37:52 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-05-03 04:37:52 +0000 |
| commit | a24770bc7bb14e1e4d4d391320ccc5acad7499c2 (patch) | |
| tree | 0352764dc32a024c475411d81bab424d9024ce56 | |
| parent | 5efb61c794b8a17b749adef4dcb9f0db7087b8fe (diff) | |
| download | emacs-a24770bc7bb14e1e4d4d391320ccc5acad7499c2.tar.gz emacs-a24770bc7bb14e1e4d4d391320ccc5acad7499c2.zip | |
Support compilers that give a message each time the file being
compiled changes but don't include a file name each error message.
Speed up by searching for regexps one by one instead of combining.
(compile-internal): Takes more optional arguments. All five regexp
alists can be given as argument.
Change name of variable regexp-alist to error-regexp-alist. Change
some local variables directly by setq instead of rebinding by let.
(compilation-shell-minor-mode): New minor mode.
Similar to compilation-minor-mode, but key bindings don't
collide with shell mode.
(compilation-shell-minor-mode-map, compilation-shell-minor-mode):
New variables.
(compile-auto-highlight): Doc fix.
(compilation-error-regexp-alist): Removed unnecessary line break
in first regexp. Replaced \\(\\|.* on \\) by \\(.* on \\)? in
regexp for Absoft FORTRAN 77 Compiler 3.1.3. Added regexp for
SPARCcompiler Pascal. Divided long line in regexp for Cray C
compiler error messages. Made comment fit in line at regexp for
Sun Ada (VADS, Solaris). FILE-IDX may be nil, meaning an
error message with no file name, so the file name must be taken
from an earlier message. LINE-IDX may be a function which is
called with two arguments the file name and column strings and
returns an error position descriptor.
(compilation-enter-directory-regexp-alist)
(compilation-leave-directory-regexp-alist): New variables.
(compilation-file-regexp-alist)
(compilation-nomessage-regexp-alist): New variables.
(grep-regexp-alist): Removed unnecessary ^ at beginning of regexp.
(compilation-enter-directory-regexp)
(compilation-leave-directory-regexp): Variables deleted.
Replaced by compilation-enter-directory-regexp-alist and
compilation-leave-directory-regexp-alist.
(compilation-buffer-p): Return true also for buffer in
compilation-shell-minor-mode.
(compilation-next-error-locus): Split a long line.
(count-regexp-groupings): Comment about this function not being
needed any more.
(compilation-current-file, compilation-regexps); New variables.
(compilation-parse-errors): Large parts rewritten. Don't put the
regexps together in one large regexp, instead match them one by one.
Support the generalized subexpression indices.
(compile-collect-regexps, compile-buffer-substring): New functions
supporting compilation-parse-errors.
| -rw-r--r-- | lisp/progmodes/compile.el | 673 |
1 files changed, 386 insertions, 287 deletions
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 4a4a469a45e..51091e8c268 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | 40 | ||
| 41 | (defvar compile-auto-highlight nil | 41 | (defvar compile-auto-highlight nil |
| 42 | "*Specify how many compiler errors to highlight (and parse) initially. | 42 | "*Specify how many compiler errors to highlight (and parse) initially. |
| 43 | \(Highlighting applies to ean error message when the mouse is over it.) | 43 | \(Highlighting applies to an error message when the mouse is over it.) |
| 44 | If this is a number N, all compiler error messages in the first N lines | 44 | If this is a number N, all compiler error messages in the first N lines |
| 45 | are highlighted and parsed as soon as they arrive in Emacs. | 45 | are highlighted and parsed as soon as they arrive in Emacs. |
| 46 | If t, highlight and parse the whole compilation output as soon as it arrives. | 46 | If t, highlight and parse the whole compilation output as soon as it arrives. |
| @@ -140,8 +140,7 @@ or when it is used with \\[next-error] or \\[compile-goto-error].") | |||
| 140 | ;; We'll insist that the number be followed by a colon or closing | 140 | ;; We'll insist that the number be followed by a colon or closing |
| 141 | ;; paren, because otherwise this matches just about anything | 141 | ;; paren, because otherwise this matches just about anything |
| 142 | ;; containing a number with spaces around it. | 142 | ;; containing a number with spaces around it. |
| 143 | ("\ | 143 | ("\\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\ |
| 144 | \\([a-zA-Z]?:?[^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)\\([) \t]\\|\ | ||
| 145 | :\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 2 5) | 144 | :\\([^0-9\n]\\|\\([0-9]+:\\)\\)\\)" 1 2 5) |
| 146 | 145 | ||
| 147 | ;; Microsoft C/C++: | 146 | ;; Microsoft C/C++: |
| @@ -184,7 +183,7 @@ or when it is used with \\[next-error] or \\[compile-goto-error].") | |||
| 184 | ;; Absoft FORTRAN 77 Compiler 3.1.3 | 183 | ;; Absoft FORTRAN 77 Compiler 3.1.3 |
| 185 | ;; error on line 19 of fplot.f: spelling error? | 184 | ;; error on line 19 of fplot.f: spelling error? |
| 186 | ;; warning on line 17 of fplot.f: data type is undefined for variable d | 185 | ;; warning on line 17 of fplot.f: data type is undefined for variable d |
| 187 | ("\\(\\|.* on \\)[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\ | 186 | ("\\(.* on \\)?[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\ |
| 188 | of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2) | 187 | of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2) |
| 189 | 188 | ||
| 190 | ;; Apollo cc, 4.3BSD fc: | 189 | ;; Apollo cc, 4.3BSD fc: |
| @@ -214,6 +213,16 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2) | |||
| 214 | ;; IBM AIX lint is too painful to do right this way. File name | 213 | ;; IBM AIX lint is too painful to do right this way. File name |
| 215 | ;; prefixes entire sections rather than being on each line. | 214 | ;; prefixes entire sections rather than being on each line. |
| 216 | 215 | ||
| 216 | ;; SPARCcompiler Pascal: | ||
| 217 | ;; 20 linjer : array[1..4] of linje; | ||
| 218 | ;; e 18480-----------^--- Inserted ';' | ||
| 219 | ;; and | ||
| 220 | ;; E 18520 line 61 - 0 is undefined | ||
| 221 | ;; These messages don't contain a file name. Instead the compiler gives | ||
| 222 | ;; a message whenever the file being compiled is changed. | ||
| 223 | (" +\\([0-9]+\\) +.*\n[ew] [0-9]+-+" nil 1) | ||
| 224 | ("[Ew] +[0-9]+ line \\([0-9]+\\) - " nil 1) | ||
| 225 | |||
| 217 | ;; Lucid Compiler, lcc 3.x | 226 | ;; Lucid Compiler, lcc 3.x |
| 218 | ;; E, file.cc(35,52) Illegal operation on pointers | 227 | ;; E, file.cc(35,52) Illegal operation on pointers |
| 219 | ("[EW], \\([^(\n]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3) | 228 | ("[EW], \\([^(\n]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3) |
| @@ -223,7 +232,8 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2) | |||
| 223 | \\([0-9]+\\):\\(\\([0-9]+\\)[: \t]\\)?" 1 2 4) | 232 | \\([0-9]+\\):\\(\\([0-9]+\\)[: \t]\\)?" 1 2 4) |
| 224 | 233 | ||
| 225 | ;; Cray C compiler error messages | 234 | ;; Cray C compiler error messages |
| 226 | ("\\(cc\\| cft\\)-[0-9]+ c\\(c\\|f77\\): ERROR \\([^,\n]+, \\)* File = \\([^,\n]+\\), Line = \\([0-9]+\\)" 4 5) | 235 | ("\\(cc\\| cft\\)-[0-9]+ c\\(c\\|f77\\): ERROR \\([^,\n]+, \\)* File = \ |
| 236 | \\([^,\n]+\\), Line = \\([0-9]+\\)" 4 5) | ||
| 227 | 237 | ||
| 228 | ;; IBM C/C++ Tools 2.01: | 238 | ;; IBM C/C++ Tools 2.01: |
| 229 | ;; foo.c(2:0) : informational EDC0804: Function foo is not referenced. | 239 | ;; foo.c(2:0) : informational EDC0804: Function foo is not referenced. |
| @@ -237,7 +247,7 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2) | |||
| 237 | 247 | ||
| 238 | ;; Perl -w: | 248 | ;; Perl -w: |
| 239 | ;; syntax error at automake line 922, near "':'" | 249 | ;; syntax error at automake line 922, near "':'" |
| 240 | ("\n.* at \\([^ ]+\\) line \\([0-9]+\\)," 1 2) | 250 | (".* at \\([^ ]+\\) line \\([0-9]+\\)," 1 2) |
| 241 | ) | 251 | ) |
| 242 | "Alist that specifies how to match errors in compiler output. | 252 | "Alist that specifies how to match errors in compiler output. |
| 243 | Each elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX FILE-FORMAT...]) | 253 | Each elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX FILE-FORMAT...]) |
| @@ -248,6 +258,56 @@ If any FILE-FORMAT is given, each is a format string to produce a file name to | |||
| 248 | try; %s in the string is replaced by the text matching the FILE-IDX'th | 258 | try; %s in the string is replaced by the text matching the FILE-IDX'th |
| 249 | subexpression.") | 259 | subexpression.") |
| 250 | 260 | ||
| 261 | (defvar compilation-enter-directory-regexp-alist | ||
| 262 | '( | ||
| 263 | ;; Matches lines printed by the `-w' option of GNU Make. | ||
| 264 | (".*: Entering directory `\\(.*\\)'$" 1) | ||
| 265 | ) | ||
| 266 | "Alist specifying how to match lines that indicate a new current directory. | ||
| 267 | Note that the match is done at the beginning of lines. | ||
| 268 | Each elt has the form (REGEXP IDX). | ||
| 269 | If REGEXP matches, the IDX'th subexpression gives the directory name. | ||
| 270 | |||
| 271 | The default value matches lines printed by the `-w' option of GNU Make.") | ||
| 272 | |||
| 273 | (defvar compilation-leave-directory-regexp-alist | ||
| 274 | '( | ||
| 275 | ;; Matches lines printed by the `-w' option of GNU Make. | ||
| 276 | (".*: Leaving directory `\\(.*\\)'$" 1) | ||
| 277 | ) | ||
| 278 | "Alist specifying how to match lines that indicate restoring current directory. | ||
| 279 | Note that the match is done at the beginning of lines. | ||
| 280 | Each elt has the form (REGEXP IDX). | ||
| 281 | If REGEXP matches, the IDX'th subexpression gives the name of the directory | ||
| 282 | being moved from. If IDX is nil, the last directory entered \(by a line | ||
| 283 | matching `compilation-enter-directory-regexp-alist'\) is assumed. | ||
| 284 | |||
| 285 | The default value matches lines printed by the `-w' option of GNU Make.") | ||
| 286 | |||
| 287 | (defvar compilation-file-regexp-alist | ||
| 288 | '( | ||
| 289 | ;; This matches entries with date time year file-name: like | ||
| 290 | ;; Thu May 14 10:46:12 1992 mom3.p: | ||
| 291 | ("\\w\\w\\w \\w\\w\\w +[0-9]+ [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9] \\(.*\\):$" 1) | ||
| 292 | ) | ||
| 293 | "Alist specifying how to match lines that indicate a new current file. | ||
| 294 | Note that the match is done at the beginning of lines. | ||
| 295 | Each elt has the form (REGEXP IDX). | ||
| 296 | If REGEXP matches, the IDX'th subexpression gives the file name. This is | ||
| 297 | used with compilers that don't indicate file name in every error message.") | ||
| 298 | |||
| 299 | ;; There is no generally useful regexp that will match non messages, but | ||
| 300 | ;; in special cases there might be one. The lines that are not matched by | ||
| 301 | ;; a regexp take much longer time than the ones that are recognized so if | ||
| 302 | ;; you have same regexeps here, parsing is faster. | ||
| 303 | (defvar compilation-nomessage-regexp-alist | ||
| 304 | '( | ||
| 305 | ) | ||
| 306 | "Alist specifying how to match lines that have no message. | ||
| 307 | Note that the match is done at the beginning of lines. | ||
| 308 | Each elt has the form (REGEXP). This alist is by default empty, but if | ||
| 309 | you have some good regexps here, the parsing of messages will be faster.") | ||
| 310 | |||
| 251 | (defvar compilation-read-command t | 311 | (defvar compilation-read-command t |
| 252 | "If not nil, M-x compile reads the compilation command to use. | 312 | "If not nil, M-x compile reads the compilation command to use. |
| 253 | Otherwise, M-x compile just uses the value of `compile-command'.") | 313 | Otherwise, M-x compile just uses the value of `compile-command'.") |
| @@ -257,7 +317,7 @@ Otherwise, M-x compile just uses the value of `compile-command'.") | |||
| 257 | Otherwise, it saves all modified buffers without asking.") | 317 | Otherwise, it saves all modified buffers without asking.") |
| 258 | 318 | ||
| 259 | (defvar grep-regexp-alist | 319 | (defvar grep-regexp-alist |
| 260 | '(("^\\([a-zA-Z]?:?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2)) | 320 | '(("\\([a-zA-Z]?:?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2)) |
| 261 | "Regexp used to match grep hits. See `compilation-error-regexp-alist'.") | 321 | "Regexp used to match grep hits. See `compilation-error-regexp-alist'.") |
| 262 | 322 | ||
| 263 | ;; The system null device. (Should reference NULL_DEVICE from C.) | 323 | ;; The system null device. (Should reference NULL_DEVICE from C.) |
| @@ -329,22 +389,6 @@ You might also use mode hooks to specify it in certain modes, like this: | |||
| 329 | (concat \"make -k \" | 389 | (concat \"make -k \" |
| 330 | buffer-file-name))))))") | 390 | buffer-file-name))))))") |
| 331 | 391 | ||
| 332 | (defvar compilation-enter-directory-regexp | ||
| 333 | ".*: Entering directory `\\(.*\\)'$" | ||
| 334 | "Regular expression matching lines that indicate a new current directory. | ||
| 335 | This must contain one \\(, \\) pair around the directory name. | ||
| 336 | |||
| 337 | The default value matches lines printed by the `-w' option of GNU Make.") | ||
| 338 | |||
| 339 | (defvar compilation-leave-directory-regexp | ||
| 340 | ".*: Leaving directory `\\(.*\\)'$" | ||
| 341 | "Regular expression matching lines that indicate restoring current directory. | ||
| 342 | This may contain one \\(, \\) pair around the name of the directory | ||
| 343 | being moved from. If it does not, the last directory entered \(by a | ||
| 344 | line matching `compilation-enter-directory-regexp'\) is assumed. | ||
| 345 | |||
| 346 | The default value matches lines printed by the `-w' option of GNU Make.") | ||
| 347 | |||
| 348 | (defvar compilation-directory-stack nil | 392 | (defvar compilation-directory-stack nil |
| 349 | "Stack of previous directories for `compilation-leave-directory-regexp'. | 393 | "Stack of previous directories for `compilation-leave-directory-regexp'. |
| 350 | The head element is the directory the compilation was started in.") | 394 | The head element is the directory the compilation was started in.") |
| @@ -373,7 +417,7 @@ write into the compilation buffer, and to put in its mode line.") | |||
| 373 | compilation-error-regexp-alist) | 417 | compilation-error-regexp-alist) |
| 374 | (list | 418 | (list |
| 375 | ;; | 419 | ;; |
| 376 | ;; Compiler output lines. Recognise `make[n]:' lines too. | 420 | ;; Compiler output lines. Recognize `make[n]:' lines too. |
| 377 | '("^\\([A-Za-z_0-9/\.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:" | 421 | '("^\\([A-Za-z_0-9/\.+-]+\\)\\(\\[\\([0-9]+\\)\\]\\)?[ \t]*:" |
| 378 | (1 font-lock-function-name-face) (3 font-lock-comment-face nil t))) | 422 | (1 font-lock-function-name-face) (3 font-lock-comment-face nil t))) |
| 379 | )) | 423 | )) |
| @@ -464,19 +508,27 @@ easily repeat a find command." | |||
| 464 | (grep command-args))) | 508 | (grep command-args))) |
| 465 | 509 | ||
| 466 | (defun compile-internal (command error-message | 510 | (defun compile-internal (command error-message |
| 467 | &optional name-of-mode parser regexp-alist | 511 | &optional name-of-mode parser |
| 468 | name-function) | 512 | error-regexp-alist name-function |
| 513 | enter-regexp-alist leave-regexp-alist | ||
| 514 | file-regexp-alist nomessage-regexp-alist) | ||
| 469 | "Run compilation command COMMAND (low level interface). | 515 | "Run compilation command COMMAND (low level interface). |
| 470 | ERROR-MESSAGE is a string to print if the user asks to see another error | 516 | ERROR-MESSAGE is a string to print if the user asks to see another error |
| 471 | and there are no more errors. Third argument NAME-OF-MODE is the name | 517 | and there are no more errors. The rest of the arguments, 3-10 are optional. |
| 472 | to display as the major mode in the compilation buffer. | 518 | For them nil means use the default. |
| 473 | 519 | NAME-OF-MODE is the name to display as the major mode in the compilation | |
| 474 | Fourth arg PARSER is the error parser function (nil means the default). Fifth | 520 | buffer. PARSER is the error parser function. ERROR-REGEXP-ALIST is the error |
| 475 | arg REGEXP-ALIST is the error message regexp alist to use (nil means the | 521 | message regexp alist to use. NAME-FUNCTION is a function called to name the |
| 476 | default). Sixth arg NAME-FUNCTION is a function called to name the buffer (nil | 522 | buffer. ENTER-REGEXP-ALIST is the enter directory message regexp alist to use. |
| 477 | means the default). The defaults for these variables are the global values of | 523 | LEAVE-REGEXP-ALIST is the leave directory message regexp alist to use. |
| 478 | \`compilation-parse-errors-function', `compilation-error-regexp-alist', and | 524 | FILE-REGEXP-ALIST is the change current file message regexp alist to use. |
| 479 | \`compilation-buffer-name-function', respectively. | 525 | NOMESSAGE-REGEXP-ALIST is the nomessage regexp alist to use. |
| 526 | The defaults for these variables are the global values of | ||
| 527 | \`compilation-parse-errors-function', `compilation-error-regexp-alist', | ||
| 528 | \`compilation-buffer-name-function', `compilation-enter-directory-regexp-alist', | ||
| 529 | \`compilation-leave-directory-regexp-alist', `compilation-file-regexp-alist', | ||
| 530 | \ and `compilation-nomessage-regexp-alist', respectively. | ||
| 531 | For arg 7-10 a value `t' means an empty alist. | ||
| 480 | 532 | ||
| 481 | Returns the compilation buffer created." | 533 | Returns the compilation buffer created." |
| 482 | (let (outbuf) | 534 | (let (outbuf) |
| @@ -508,9 +560,18 @@ Returns the compilation buffer created." | |||
| 508 | ;; In case the compilation buffer is current, make sure we get the global | 560 | ;; In case the compilation buffer is current, make sure we get the global |
| 509 | ;; values of compilation-error-regexp-alist, etc. | 561 | ;; values of compilation-error-regexp-alist, etc. |
| 510 | (kill-all-local-variables)) | 562 | (kill-all-local-variables)) |
| 511 | (let ((regexp-alist (or regexp-alist compilation-error-regexp-alist)) | 563 | (or error-regexp-alist |
| 512 | (parser (or parser compilation-parse-errors-function)) | 564 | (setq error-regexp-alist compilation-error-regexp-alist)) |
| 513 | (thisdir default-directory) | 565 | (or enter-regexp-alist |
| 566 | (setq enter-regexp-alist compilation-enter-directory-regexp-alist)) | ||
| 567 | (or leave-regexp-alist | ||
| 568 | (setq leave-regexp-alist compilation-leave-directory-regexp-alist)) | ||
| 569 | (or file-regexp-alist | ||
| 570 | (setq file-regexp-alist compilation-file-regexp-alist)) | ||
| 571 | (or nomessage-regexp-alist | ||
| 572 | (setq nomessage-regexp-alist compilation-nomessage-regexp-alist)) | ||
| 573 | (or parser (setq parser compilation-parse-errors-function)) | ||
| 574 | (let ((thisdir default-directory) | ||
| 514 | outwin) | 575 | outwin) |
| 515 | (save-excursion | 576 | (save-excursion |
| 516 | ;; Clear out the compilation buffer and make it writable. | 577 | ;; Clear out the compilation buffer and make it writable. |
| @@ -536,7 +597,16 @@ Returns the compilation buffer created." | |||
| 536 | ;; (setq buffer-read-only t) ;;; Non-ergonomic. | 597 | ;; (setq buffer-read-only t) ;;; Non-ergonomic. |
| 537 | (set (make-local-variable 'compilation-parse-errors-function) parser) | 598 | (set (make-local-variable 'compilation-parse-errors-function) parser) |
| 538 | (set (make-local-variable 'compilation-error-message) error-message) | 599 | (set (make-local-variable 'compilation-error-message) error-message) |
| 539 | (set (make-local-variable 'compilation-error-regexp-alist) regexp-alist) | 600 | (set (make-local-variable 'compilation-error-regexp-alist) |
| 601 | error-regexp-alist) | ||
| 602 | (set (make-local-variable 'compilation-enter-directory-regexp-alist) | ||
| 603 | enter-regexp-alist) | ||
| 604 | (set (make-local-variable 'compilation-leave-directory-regexp-alist) | ||
| 605 | leave-regexp-alist) | ||
| 606 | (set (make-local-variable 'compilation-file-regexp-alist) | ||
| 607 | file-regexp-alist) | ||
| 608 | (set (make-local-variable 'compilation-nomessage-regexp-alist) | ||
| 609 | nomessage-regexp-alist) | ||
| 540 | (setq default-directory thisdir | 610 | (setq default-directory thisdir |
| 541 | compilation-directory-stack (list default-directory)) | 611 | compilation-directory-stack (list default-directory)) |
| 542 | (set-window-start outwin (point-min)) | 612 | (set-window-start outwin (point-min)) |
| @@ -612,6 +682,30 @@ exited abnormally with code %d\n" | |||
| 612 | map) | 682 | map) |
| 613 | "Keymap for `compilation-minor-mode'.") | 683 | "Keymap for `compilation-minor-mode'.") |
| 614 | 684 | ||
| 685 | (defvar compilation-shell-minor-mode-map | ||
| 686 | (let ((map (make-sparse-keymap))) | ||
| 687 | (define-key map [mouse-2] 'compile-mouse-goto-error) | ||
| 688 | (define-key map "\M-\C-m" 'compile-goto-error) | ||
| 689 | (define-key map "\M-\C-n" 'compilation-next-error) | ||
| 690 | (define-key map "\M-\C-p" 'compilation-previous-error) | ||
| 691 | (define-key map "\M-{" 'compilation-previous-file) | ||
| 692 | (define-key map "\M-}" 'compilation-next-file) | ||
| 693 | ;; Set up the menu-bar | ||
| 694 | (define-key map [menu-bar errors-menu] | ||
| 695 | (cons "Errors" (make-sparse-keymap "Errors"))) | ||
| 696 | (define-key map [menu-bar errors-menu stop-subjob] | ||
| 697 | '("Stop" . comint-interrupt-subjob)) | ||
| 698 | (define-key map [menu-bar errors-menu compilation-mode-separator2] | ||
| 699 | '("----" . nil)) | ||
| 700 | (define-key map [menu-bar errors-menu compilation-mode-first-error] | ||
| 701 | '("First Error" . first-error)) | ||
| 702 | (define-key map [menu-bar errors-menu compilation-mode-previous-error] | ||
| 703 | '("Previous Error" . previous-error)) | ||
| 704 | (define-key map [menu-bar errors-menu compilation-mode-next-error] | ||
| 705 | '("Next Error" . next-error)) | ||
| 706 | map) | ||
| 707 | "Keymap for `compilation-shell-minor-mode'.") | ||
| 708 | |||
| 615 | (defvar compilation-mode-map | 709 | (defvar compilation-mode-map |
| 616 | (let ((map (cons 'keymap compilation-minor-mode-map))) | 710 | (let ((map (cons 'keymap compilation-minor-mode-map))) |
| 617 | (define-key map " " 'scroll-up) | 711 | (define-key map " " 'scroll-up) |
| @@ -670,6 +764,22 @@ Runs `compilation-mode-hook' with `run-hooks' (which see)." | |||
| 670 | (set (make-local-variable 'compilation-directory-stack) nil) | 764 | (set (make-local-variable 'compilation-directory-stack) nil) |
| 671 | (setq compilation-last-buffer (current-buffer))) | 765 | (setq compilation-last-buffer (current-buffer))) |
| 672 | 766 | ||
| 767 | (defvar compilation-shell-minor-mode nil | ||
| 768 | "Non-nil when in compilation-shell-minor-mode. | ||
| 769 | In this minor mode, all the error-parsing commands of the | ||
| 770 | Compilation major mode are available but bound to keys that don't | ||
| 771 | collide with Shell mode.") | ||
| 772 | (make-variable-buffer-local 'compilation-shell-minor-mode) | ||
| 773 | |||
| 774 | (or (assq 'compilation-shell-minor-mode minor-mode-alist) | ||
| 775 | (setq minor-mode-alist | ||
| 776 | (cons '(compilation-shell-minor-mode " Shell-Compile") | ||
| 777 | minor-mode-alist))) | ||
| 778 | (or (assq 'compilation-shell-minor-mode minor-mode-map-alist) | ||
| 779 | (setq minor-mode-map-alist (cons (cons 'compilation-shell-minor-mode | ||
| 780 | compilation-shell-minor-mode-map) | ||
| 781 | minor-mode-map-alist))) | ||
| 782 | |||
| 673 | (defvar compilation-minor-mode nil | 783 | (defvar compilation-minor-mode nil |
| 674 | "Non-nil when in compilation-minor-mode. | 784 | "Non-nil when in compilation-minor-mode. |
| 675 | In this minor mode, all the error-parsing commands of the | 785 | In this minor mode, all the error-parsing commands of the |
| @@ -787,7 +897,8 @@ Just inserts the text, but uses `insert-before-markers'." | |||
| 787 | (defsubst compilation-buffer-p (buffer) | 897 | (defsubst compilation-buffer-p (buffer) |
| 788 | (save-excursion | 898 | (save-excursion |
| 789 | (set-buffer buffer) | 899 | (set-buffer buffer) |
| 790 | (or compilation-minor-mode (eq major-mode 'compilation-mode)))) | 900 | (or compilation-shell-minor-mode compilation-minor-mode |
| 901 | (eq major-mode 'compilation-mode)))) | ||
| 791 | 902 | ||
| 792 | (defun compilation-next-error (n) | 903 | (defun compilation-next-error (n) |
| 793 | "Move point to the next error in the compilation buffer. | 904 | "Move point to the next error in the compilation buffer. |
| @@ -979,7 +1090,7 @@ Does NOT find the source line like \\[next-error]." | |||
| 979 | (setq compilation-last-buffer (current-buffer)) | 1090 | (setq compilation-last-buffer (current-buffer)) |
| 980 | ;; `compile-reinitialize-errors' needs to see the complete filename | 1091 | ;; `compile-reinitialize-errors' needs to see the complete filename |
| 981 | ;; on the line where they clicked the mouse. Since it only looks | 1092 | ;; on the line where they clicked the mouse. Since it only looks |
| 982 | ;; upto point, moving point to eol makes sure the filename is | 1093 | ;; up to point, moving point to eol makes sure the filename is |
| 983 | ;; visible to `compile-reinitialize-errors'. | 1094 | ;; visible to `compile-reinitialize-errors'. |
| 984 | (end-of-line) | 1095 | (end-of-line) |
| 985 | (compile-reinitialize-errors nil (point)) | 1096 | (compile-reinitialize-errors nil (point)) |
| @@ -1262,7 +1373,8 @@ The current buffer should be the desired compilation output buffer." | |||
| 1262 | ;; Skip over multiple error messages for the same source location, | 1373 | ;; Skip over multiple error messages for the same source location, |
| 1263 | ;; so the next C-x ` won't go to an error in the same place. | 1374 | ;; so the next C-x ` won't go to an error in the same place. |
| 1264 | (while (and compilation-error-list | 1375 | (while (and compilation-error-list |
| 1265 | (equal (cdr (car compilation-error-list)) (cdr next-error))) | 1376 | (equal (cdr (car compilation-error-list)) |
| 1377 | (cdr next-error))) | ||
| 1266 | (setq compilation-error-list (cdr compilation-error-list)))) | 1378 | (setq compilation-error-list (cdr compilation-error-list)))) |
| 1267 | 1379 | ||
| 1268 | ;; We now have a marker for the position of the error source code. | 1380 | ;; We now have a marker for the position of the error source code. |
| @@ -1361,6 +1473,8 @@ Selects a window with point at SOURCE, with another window displaying ERROR." | |||
| 1361 | ) | 1473 | ) |
| 1362 | 1474 | ||
| 1363 | 1475 | ||
| 1476 | ;; This function is not needed any more by compilation mode. | ||
| 1477 | ;; Does anyone else need it or can it be deleted? | ||
| 1364 | (defun count-regexp-groupings (regexp) | 1478 | (defun count-regexp-groupings (regexp) |
| 1365 | "Return the number of \\( ... \\) groupings in REGEXP (a string)." | 1479 | "Return the number of \\( ... \\) groupings in REGEXP (a string)." |
| 1366 | (let ((groupings 0) | 1480 | (let ((groupings 0) |
| @@ -1386,265 +1500,250 @@ Selects a window with point at SOURCE, with another window displaying ERROR." | |||
| 1386 | (setq groupings (1+ groupings)))))))) | 1500 | (setq groupings (1+ groupings)))))))) |
| 1387 | groupings)) | 1501 | groupings)) |
| 1388 | 1502 | ||
| 1503 | (defvar compilation-current-file nil | ||
| 1504 | "Used by compilation-parse-errors to store filename for file being compiled") | ||
| 1505 | |||
| 1506 | ;; This variable is not used as a global variable. It's defined here just to | ||
| 1507 | ;; shut up the byte compiler. It's bound and used by compilation-parse-errors | ||
| 1508 | ;; and set by compile-collect-regexps. | ||
| 1509 | (defvar compilation-regexps nil) | ||
| 1510 | |||
| 1389 | (defun compilation-parse-errors (limit-search find-at-least) | 1511 | (defun compilation-parse-errors (limit-search find-at-least) |
| 1390 | "Parse the current buffer as grep, cc or lint error messages. | 1512 | "Parse the current buffer as grep, cc, lint or other error messages. |
| 1391 | See variable `compilation-parse-errors-function' for the interface it uses." | 1513 | See variable `compilation-parse-errors-function' for the interface it uses." |
| 1392 | (setq compilation-error-list nil) | 1514 | (setq compilation-error-list nil) |
| 1393 | (message "Parsing error messages...") | 1515 | (message "Parsing error messages...") |
| 1394 | (let (text-buffer orig orig-expanded parent-expanded | 1516 | (if (null compilation-error-regexp-alist) |
| 1395 | regexp enter-group leave-group error-group | 1517 | (error "compilation-error-regexp-alist is empty!")) |
| 1396 | alist subexpr error-regexp-groups | 1518 | (let* ((compilation-regexps nil) ; Variable set by compile-collect-regexps. |
| 1397 | (found-desired nil) | 1519 | (found-desired nil) |
| 1398 | (compilation-num-errors-found 0)) | 1520 | (compilation-num-errors-found 0) |
| 1521 | ;; Set up now the expanded, abbreviated directory variables | ||
| 1522 | ;; that compile-abbreviate-directory will need, so we can | ||
| 1523 | ;; compute them just once here. | ||
| 1524 | (orig (abbreviate-file-name default-directory)) | ||
| 1525 | (orig-expanded (abbreviate-file-name | ||
| 1526 | (file-truename default-directory))) | ||
| 1527 | (parent-expanded (abbreviate-file-name | ||
| 1528 | (expand-file-name "../" orig-expanded)))) | ||
| 1529 | |||
| 1530 | ;; Make a list of all the regexps. Each element has the form | ||
| 1531 | ;; (REGEXP TYPE IDX1 IDX2 ...) | ||
| 1532 | ;; where TYPE is one of leave, enter, file, error or nomessage. | ||
| 1533 | (compile-collect-regexps 'leave compilation-leave-directory-regexp-alist) | ||
| 1534 | (compile-collect-regexps 'enter compilation-enter-directory-regexp-alist) | ||
| 1535 | (compile-collect-regexps 'file compilation-file-regexp-alist) | ||
| 1536 | (compile-collect-regexps 'nomessage compilation-nomessage-regexp-alist) | ||
| 1537 | (compile-collect-regexps 'error compilation-error-regexp-alist) | ||
| 1399 | 1538 | ||
| 1400 | ;; Don't reparse messages already seen at last parse. | 1539 | ;; Don't reparse messages already seen at last parse. |
| 1401 | (goto-char compilation-parsing-end) | 1540 | (goto-char compilation-parsing-end) |
| 1402 | ;; Don't parse the first two lines as error messages. | ||
| 1403 | ;; This matters for grep. | ||
| 1404 | (if (bobp) | 1541 | (if (bobp) |
| 1405 | (progn | 1542 | (progn |
| 1406 | (forward-line 2) | 1543 | (setq compilation-current-file nil) ; No current file at start. |
| 1407 | ;; Move back so point is before the newline. | 1544 | ;; Don't parse the first two lines as error messages. |
| 1408 | ;; This matters because some error regexps use \n instead of ^ | 1545 | ;; This matters for grep. |
| 1409 | ;; to be faster. | 1546 | (forward-line 2))) |
| 1410 | (forward-char -1))) | 1547 | |
| 1411 | 1548 | ;; Parse messages. | |
| 1412 | ;; Compile all the regexps we want to search for into one. | 1549 | (while (not (or found-desired (eobp))) |
| 1413 | (setq regexp (concat "\\(" compilation-enter-directory-regexp "\\)\\|" | 1550 | (let ((this compilation-regexps) (prev nil) (alist nil) type) |
| 1414 | "\\(" compilation-leave-directory-regexp "\\)\\|" | 1551 | ;; Go through the regular expressions. If a match is found, |
| 1415 | "\\(" (mapconcat (function | 1552 | ;; variable alist is set to the corresponding alist and the |
| 1416 | (lambda (elt) | 1553 | ;; matching regexp is moved to the front of compilation-regexps |
| 1417 | (concat "\\(" (car elt) "\\)"))) | 1554 | ;; to make it match faster next time. |
| 1418 | compilation-error-regexp-alist | 1555 | (while (and this (null alist)) |
| 1419 | "\\|") "\\)")) | 1556 | (if (not (looking-at (car (car this)))) |
| 1420 | 1557 | (progn (setq prev this) ; No match, go to next. | |
| 1421 | ;; Find out how many \(...\) groupings are in each of the regexps, and set | 1558 | (setq this (cdr this))) |
| 1422 | ;; *-GROUP to the grouping containing each constituent regexp (whose | 1559 | (setq alist (cdr (car this))) ; Got a match. |
| 1423 | ;; subgroups will come immediately thereafter) of the big regexp we have | 1560 | ;;; (if prev ; If not the first regexp, |
| 1424 | ;; just constructed. | 1561 | ;;; (progn ; move it to the front. |
| 1425 | (setq enter-group 1 | 1562 | ;;; (setcdr prev (cdr this)) |
| 1426 | leave-group (+ enter-group | 1563 | ;;; (setcdr this compilation-regexps) |
| 1427 | (count-regexp-groupings | 1564 | ;;; (setq compilation-regexps this))) |
| 1428 | compilation-enter-directory-regexp) | 1565 | )) |
| 1429 | 1) | 1566 | (if (and alist ; Seen a match and not to |
| 1430 | error-group (+ leave-group | 1567 | (not (eq (setq type (car alist)) 'nomessage))) ; be ignored. |
| 1431 | (count-regexp-groupings | 1568 | (let* ((end-of-match (match-end 0)) |
| 1432 | compilation-leave-directory-regexp) | 1569 | (filename |
| 1433 | 1)) | 1570 | (compile-buffer-substring (car (setq alist (cdr alist))))) |
| 1434 | 1571 | stack) | |
| 1435 | ;; Compile an alist (IDX FILE LINE [COL]), where IDX is the number of | 1572 | (if (eq type 'error) ; error message |
| 1436 | ;; the subexpression for an entire error-regexp, and FILE and LINE (and | 1573 | (let* ((linenum (if (numberp (car (setq alist (cdr alist)))) |
| 1437 | ;; possibly COL) are the numbers for the subexpressions giving the file | 1574 | (string-to-int |
| 1438 | ;; name and line number (and possibly column number). | 1575 | (compile-buffer-substring (car alist))) |
| 1439 | (setq alist (or compilation-error-regexp-alist | 1576 | ;; (car alist) is not a number, must be a |
| 1440 | (error "compilation-error-regexp-alist is empty!")) | 1577 | ;; function that is called below to return |
| 1441 | subexpr (1+ error-group)) | 1578 | ;; an error position descriptor. |
| 1442 | (while alist | 1579 | (car alist))) |
| 1443 | (setq error-regexp-groups | 1580 | ;; Convert to integer later if linenum not a function. |
| 1444 | (cons (list subexpr | 1581 | (column (compile-buffer-substring |
| 1445 | (+ subexpr (nth 1 (car alist))) | 1582 | (car (setq alist (cdr alist))))) |
| 1446 | (+ subexpr (nth 2 (car alist))) | 1583 | this-error) |
| 1447 | (and (nth 3 (car alist)) | 1584 | |
| 1448 | (+ subexpr (nth 3 (car alist))))) | 1585 | ;; Check that we have a file name. |
| 1449 | error-regexp-groups)) | 1586 | (or filename |
| 1450 | (setq subexpr (+ subexpr 1 (count-regexp-groupings (car (car alist))))) | 1587 | ;; No file name in message, we must have seen it before |
| 1451 | (setq alist (cdr alist))) | 1588 | (setq filename compilation-current-file) |
| 1452 | 1589 | (error "\ | |
| 1453 | ;; Set up now the expanded, abbreviated directory variables | 1590 | An error message with no file name and no file name has been seen earlier.")) |
| 1454 | ;; that compile-abbreviate-directory will need, so we can | 1591 | |
| 1455 | ;; compute them just once here. | 1592 | ;; Check for a comint-file-name-prefix and prepend it if |
| 1456 | (setq orig (abbreviate-file-name default-directory) | 1593 | ;; appropriate. (This is very useful for |
| 1457 | orig-expanded (abbreviate-file-name | 1594 | ;; compilation-minor-mode in an rlogin-mode buffer.) |
| 1458 | (file-truename default-directory)) | 1595 | (and (boundp 'comint-file-name-prefix) |
| 1459 | parent-expanded (abbreviate-file-name | 1596 | ;; If file name is relative, default-directory will |
| 1460 | (expand-file-name "../" orig-expanded))) | 1597 | ;; already contain the comint-file-name-prefix (done |
| 1461 | 1598 | ;; by compile-abbreviate-directory). | |
| 1462 | (while (and (not found-desired) | 1599 | (file-name-absolute-p filename) |
| 1463 | ;; Instead of using re-search-forward, | 1600 | (setq filename |
| 1464 | ;; we use this loop which tries only at each line. | 1601 | (concat comint-file-name-prefix filename))) |
| 1465 | (progn | 1602 | |
| 1466 | (while (and (not (eobp)) | 1603 | ;; Some compilers (e.g. Sun's java compiler, reportedly) |
| 1467 | (not (looking-at regexp))) | 1604 | ;; produce bogus file names like "./bar//foo.c" for file |
| 1468 | (forward-line 1)) | 1605 | ;; "bar/foo.c"; expand-file-name will collapse these into |
| 1469 | (not (eobp)))) | 1606 | ;; "/foo.c" and fail to find the appropriate file. So we |
| 1470 | 1607 | ;; look for doubled slashes in the file name and fix them | |
| 1471 | ;; Move to the end of the match we just found. | 1608 | ;; up in the buffer. |
| 1472 | (goto-char (match-end 0)) | 1609 | (setq filename (command-line-normalize-file-name filename)) |
| 1473 | 1610 | ||
| 1474 | ;; Figure out which constituent regexp matched. | 1611 | (setq filename |
| 1475 | (cond ((match-beginning enter-group) | 1612 | (cons filename (cons default-directory (cdr alist)))) |
| 1476 | ;; The match was the enter-directory regexp. | 1613 | |
| 1477 | (let ((dir | 1614 | ;; Locate the erring file and line. |
| 1478 | (file-name-as-directory | 1615 | ;; Make this-error a new elt for compilation-error-list, |
| 1479 | (expand-file-name | 1616 | ;; giving a marker for the current compilation buffer |
| 1480 | (buffer-substring (match-beginning (+ enter-group 1)) | 1617 | ;; location, and the file and line number of the error. |
| 1481 | (match-end (+ enter-group 1))))))) | 1618 | ;; Save, as the start of the error, the beginning of the |
| 1482 | ;; The directory name in the "entering" message | 1619 | ;; line containing the match. |
| 1483 | ;; is a truename. Try to convert it to a form | 1620 | (if (setq this-error |
| 1484 | ;; like what the user typed in. | 1621 | (if (numberp linenum) |
| 1485 | (setq dir | 1622 | (list (point-marker) filename linenum |
| 1486 | (compile-abbreviate-directory dir orig orig-expanded | 1623 | (and column (string-to-int column))) |
| 1487 | parent-expanded)) | 1624 | ;; If linenum is not a number then it must be |
| 1488 | (setq compilation-directory-stack | 1625 | ;; a function returning an error position |
| 1489 | (cons dir compilation-directory-stack)) | 1626 | ;; descriptor or nil (meaning no position). |
| 1490 | (and (file-directory-p dir) | 1627 | (save-excursion |
| 1491 | (setq default-directory dir))) | 1628 | (funcall linenum filename column)))) |
| 1492 | 1629 | ||
| 1493 | (and limit-search (>= (point) limit-search) | 1630 | ;; We have an error position descriptor. |
| 1494 | ;; The user wanted a specific error, and we're past it. | 1631 | ;; If we have found as many new errors as the user |
| 1495 | ;; We do this check here (and in the leave-group case) | 1632 | ;; wants, or if we are past the buffer position he |
| 1496 | ;; rather than at the end of the loop because if the last | 1633 | ;; indicated, then we continue to parse until we have |
| 1497 | ;; thing seen is an error message, we must carefully | 1634 | ;; seen all consecutive errors in the same file. This |
| 1498 | ;; discard the last error when it is the first in a new | 1635 | ;; means that all the errors of a source file will be |
| 1499 | ;; file (see below in the error-group case). | 1636 | ;; seen in one parsing run, so that the error positions |
| 1500 | (setq found-desired t))) | 1637 | ;; will be recorded as markers in the source file |
| 1501 | 1638 | ;; buffer that will move when the buffer is changed. | |
| 1502 | ((match-beginning leave-group) | 1639 | (if (and (or (and find-at-least |
| 1503 | ;; The match was the leave-directory regexp. | 1640 | (>= compilation-num-errors-found |
| 1504 | (let ((beg (match-beginning (+ leave-group 1))) | ||
| 1505 | (stack compilation-directory-stack)) | ||
| 1506 | (if beg | ||
| 1507 | (let ((dir | ||
| 1508 | (file-name-as-directory | ||
| 1509 | (expand-file-name | ||
| 1510 | (buffer-substring beg | ||
| 1511 | (match-end (+ leave-group | ||
| 1512 | 1))))))) | ||
| 1513 | ;; The directory name in the "leaving" message | ||
| 1514 | ;; is a truename. Try to convert it to a form | ||
| 1515 | ;; like what the user typed in. | ||
| 1516 | (setq dir | ||
| 1517 | (compile-abbreviate-directory dir orig orig-expanded | ||
| 1518 | parent-expanded)) | ||
| 1519 | (while (and stack | ||
| 1520 | (not (string-equal (car stack) dir))) | ||
| 1521 | (setq stack (cdr stack))))) | ||
| 1522 | (setq compilation-directory-stack (cdr stack)) | ||
| 1523 | (setq stack (car compilation-directory-stack)) | ||
| 1524 | (if stack | ||
| 1525 | (setq default-directory stack)) | ||
| 1526 | ) | ||
| 1527 | |||
| 1528 | (and limit-search (>= (point) limit-search) | ||
| 1529 | ;; The user wanted a specific error, and we're past it. | ||
| 1530 | ;; We do this check here (and in the enter-group case) | ||
| 1531 | ;; rather than at the end of the loop because if the last | ||
| 1532 | ;; thing seen is an error message, we must carefully | ||
| 1533 | ;; discard the last error when it is the first in a new | ||
| 1534 | ;; file (see below in the error-group case). | ||
| 1535 | (setq found-desired t))) | ||
| 1536 | |||
| 1537 | ((match-beginning error-group) | ||
| 1538 | ;; The match was the composite error regexp. | ||
| 1539 | ;; Find out which individual regexp matched. | ||
| 1540 | (setq alist error-regexp-groups) | ||
| 1541 | (while (and alist | ||
| 1542 | (null (match-beginning (car (car alist))))) | ||
| 1543 | (setq alist (cdr alist))) | ||
| 1544 | (if alist | ||
| 1545 | (setq alist (car alist)) | ||
| 1546 | (error "compilation-parse-errors: impossible regexp match!")) | ||
| 1547 | |||
| 1548 | ;; Extract the file name and line number from the error message. | ||
| 1549 | (let ((beginning-of-match (match-beginning 0)) ;looking-at nukes | ||
| 1550 | (filename (buffer-substring (match-beginning (nth 1 alist)) | ||
| 1551 | (match-end (nth 1 alist)))) | ||
| 1552 | (linenum (string-to-int | ||
| 1553 | (buffer-substring | ||
| 1554 | (match-beginning (nth 2 alist)) | ||
| 1555 | (match-end (nth 2 alist))))) | ||
| 1556 | (column (and (nth 3 alist) | ||
| 1557 | (match-beginning (nth 3 alist)) | ||
| 1558 | (string-to-int | ||
| 1559 | (buffer-substring | ||
| 1560 | (match-beginning (nth 3 alist)) | ||
| 1561 | (match-end (nth 3 alist))))))) | ||
| 1562 | |||
| 1563 | ;; Check for a comint-file-name-prefix and prepend it if | ||
| 1564 | ;; appropriate. (This is very useful for | ||
| 1565 | ;; compilation-minor-mode in an rlogin-mode buffer.) | ||
| 1566 | (and (boundp 'comint-file-name-prefix) | ||
| 1567 | ;; If the file name is relative, default-directory will | ||
| 1568 | ;; already contain the comint-file-name-prefix (done by | ||
| 1569 | ;; compile-abbreviate-directory). | ||
| 1570 | (file-name-absolute-p filename) | ||
| 1571 | (setq filename (concat comint-file-name-prefix filename))) | ||
| 1572 | |||
| 1573 | ;; Some compilers (e.g. Sun's java compiler, reportedly) | ||
| 1574 | ;; produce bogus file names like "./bar//foo.c" for the file | ||
| 1575 | ;; "bar/foo.c"; expand-file-name will collapse these into | ||
| 1576 | ;; "/foo.c" and fail to find the appropriate file. So we look | ||
| 1577 | ;; for doubled slashes in the file name and fix them up in the | ||
| 1578 | ;; buffer. | ||
| 1579 | (setq filename (command-line-normalize-file-name filename)) | ||
| 1580 | (setq filename (cons filename (cons default-directory | ||
| 1581 | (nthcdr 4 alist)))) | ||
| 1582 | |||
| 1583 | |||
| 1584 | ;; Locate the erring file and line. | ||
| 1585 | ;; Cons a new elt onto compilation-error-list, | ||
| 1586 | ;; giving a marker for the current compilation buffer | ||
| 1587 | ;; location, and the file and line number of the error. | ||
| 1588 | (save-excursion | ||
| 1589 | ;; Save as the start of the error the beginning of the | ||
| 1590 | ;; line containing the match unless the match starts at a | ||
| 1591 | ;; newline, in which case the beginning of the next line. | ||
| 1592 | (goto-char beginning-of-match) | ||
| 1593 | (forward-line (if (eolp) 1 0)) | ||
| 1594 | (let ((this (cons (point-marker) | ||
| 1595 | (list filename linenum column)))) | ||
| 1596 | ;; Don't add the same source line more than once. | ||
| 1597 | (if (and compilation-skip-to-next-location | ||
| 1598 | (equal (cdr this) | ||
| 1599 | (cdr (car compilation-error-list)))) | ||
| 1600 | nil | ||
| 1601 | (setq compilation-error-list | ||
| 1602 | (cons this | ||
| 1603 | compilation-error-list)) | ||
| 1604 | (setq compilation-num-errors-found | ||
| 1605 | (1+ compilation-num-errors-found))))) | ||
| 1606 | (and (or (and find-at-least (> compilation-num-errors-found | ||
| 1607 | find-at-least)) | 1641 | find-at-least)) |
| 1608 | (and limit-search (>= (point) limit-search))) | 1642 | (and limit-search |
| 1609 | ;; We have found as many new errors as the user wants, | 1643 | (>= end-of-match limit-search))) |
| 1610 | ;; or past the buffer position he indicated. We | 1644 | compilation-error-list ;At least one previous. |
| 1611 | ;; continue to parse until we have seen all the | 1645 | (not (equal ; Same filename? |
| 1612 | ;; consecutive errors in the same file, so the error | 1646 | (car (cdr (car compilation-error-list))) |
| 1613 | ;; positions will be recorded as markers in this buffer | 1647 | (car (cdr this-error))))) |
| 1614 | ;; that might change. | 1648 | ;; We are past the limits and the last error |
| 1615 | (cdr compilation-error-list) ; Must check at least two. | 1649 | ;; parsed, didn't belong to the same source file |
| 1616 | (not (equal (car (cdr (nth 0 compilation-error-list))) | 1650 | ;; as the earlier ones i.e. we have seen all the |
| 1617 | (car (cdr (nth 1 compilation-error-list))))) | 1651 | ;; errors belonging to the earlier file. We don't |
| 1618 | (progn | 1652 | ;; add the error just parsed so that the next |
| 1619 | ;; Discard the error just parsed, so that the next | 1653 | ;; parsing run can get it and the following errors |
| 1620 | ;; parsing run can get it and the following errors in | 1654 | ;; in the same file all at once. |
| 1621 | ;; the same file all at once. If we didn't do this, we | 1655 | (setq found-desired t) |
| 1622 | ;; would have the same problem we are trying to avoid | 1656 | |
| 1623 | ;; with the test above, just delayed until the next run! | 1657 | (goto-char end-of-match) ; Prepare for next message. |
| 1624 | (setq compilation-error-list | 1658 | ;; Don't add the same source line more than once. |
| 1625 | (cdr compilation-error-list)) | 1659 | (and (not (and |
| 1626 | (goto-char beginning-of-match) | 1660 | compilation-error-list |
| 1627 | (setq found-desired t))) | 1661 | (equal (cdr (car compilation-error-list)) |
| 1628 | ) | 1662 | (cdr this-error)))) |
| 1629 | ) | 1663 | (setq compilation-error-list |
| 1630 | (t | 1664 | (cons this-error compilation-error-list) |
| 1631 | (error "compilation-parse-errors: known groups didn't match!"))) | 1665 | compilation-num-errors-found |
| 1632 | 1666 | (1+ compilation-num-errors-found)))))) | |
| 1633 | (message "Parsing error messages...%d (%.0f%% of buffer)" | 1667 | |
| 1668 | ;; Not an error message. | ||
| 1669 | (if (eq type `file) ; Change current file. | ||
| 1670 | (and filename (setq compilation-current-file filename)) | ||
| 1671 | ;; Enter or leave directory. | ||
| 1672 | (setq stack compilation-directory-stack) | ||
| 1673 | (and filename | ||
| 1674 | (file-directory-p | ||
| 1675 | (setq filename | ||
| 1676 | ;; The directory name in the message | ||
| 1677 | ;; is a truename. Try to convert it to a form | ||
| 1678 | ;; like what the user typed in. | ||
| 1679 | (compile-abbreviate-directory | ||
| 1680 | (file-name-as-directory | ||
| 1681 | (expand-file-name filename)) | ||
| 1682 | orig orig-expanded parent-expanded))) | ||
| 1683 | (if (eq type 'leave) | ||
| 1684 | (while (and stack | ||
| 1685 | (not (string-equal (car stack) | ||
| 1686 | filename))) | ||
| 1687 | (setq stack (cdr stack))) | ||
| 1688 | (setq compilation-directory-stack | ||
| 1689 | (cons filename compilation-directory-stack) | ||
| 1690 | default-directory filename))) | ||
| 1691 | (and (eq type 'leave | ||
| 1692 | stack | ||
| 1693 | (setq compilation-directory-stack (cdr stack)) | ||
| 1694 | (setq stack (car compilation-directory-stack)) | ||
| 1695 | (setq default-directory stack))) | ||
| 1696 | (goto-char end-of-match) ; Prepare to look at next message. | ||
| 1697 | (and limit-search (>= end-of-match limit-search) | ||
| 1698 | ;; The user wanted a specific error, and we're past it. | ||
| 1699 | ;; We do this check here rather than at the end of the | ||
| 1700 | ;; loop because if the last thing seen is an error | ||
| 1701 | ;; message, we must carefully discard the last error | ||
| 1702 | ;; when it is the first in a new file (see above in | ||
| 1703 | ;; the error-message case) | ||
| 1704 | (setq found-desired t)))) | ||
| 1705 | |||
| 1706 | ;; Go to before the last character in the message so that we will | ||
| 1707 | ;; see the next line also when the message ended at end of line. | ||
| 1708 | ;; When we ignore the last error message above, this will | ||
| 1709 | ;; cancel the effect of forward-line below so that point | ||
| 1710 | ;; doesn't move. | ||
| 1711 | (forward-char -1) | ||
| 1712 | |||
| 1713 | ;; Is this message necessary any more? Parsing is now so fast | ||
| 1714 | ;; that you might not need to know how it proceeds. | ||
| 1715 | (message | ||
| 1716 | "Parsing error messages...%d found. %.0f%% of buffer seen." | ||
| 1634 | compilation-num-errors-found | 1717 | compilation-num-errors-found |
| 1635 | ;; Use floating-point because (* 100 (point)) frequently | 1718 | ;; Use floating-point because (* 100 (point)) frequently |
| 1636 | ;; exceeds the range of Emacs Lisp integers. | 1719 | ;; exceeds the range of Emacs Lisp integers. |
| 1637 | (/ (* 100.0 (point)) (point-max))) | 1720 | (/ (* 100.0 (point)) (point-max))) |
| 1638 | 1721 | )) | |
| 1639 | (and limit-search (>= (point) limit-search) | 1722 | |
| 1640 | ;; The user wanted a specific error, and we're past it. | 1723 | (forward-line 1))) ; End of while loop. Look at next line. |
| 1641 | (setq found-desired t))) | 1724 | |
| 1642 | (setq compilation-parsing-end (if found-desired | 1725 | (setq compilation-parsing-end (point)) |
| 1643 | (point) | 1726 | (setq compilation-error-list (nreverse compilation-error-list)) |
| 1644 | ;; We have searched the whole buffer. | 1727 | ;;; (message "Parsing error messages...done. %d found. %.0f%% of buffer seen." |
| 1645 | (point-max)))) | 1728 | ;;; compilation-num-errors-found |
| 1646 | (setq compilation-error-list (nreverse compilation-error-list)) | 1729 | ;;; (/ (* 100.0 (point)) (point-max))) |
| 1647 | (message "Parsing error messages...done")) | 1730 | (message "Parsing error messages...done."))) |
| 1731 | |||
| 1732 | (defun compile-collect-regexps (type this) | ||
| 1733 | ;; Add elements to variable compilation-regexps that is bound in | ||
| 1734 | ;; compilation-parse-errors. | ||
| 1735 | (and (not (eq this t)) | ||
| 1736 | (while this | ||
| 1737 | (setq compilation-regexps | ||
| 1738 | (cons (cons (car (car this)) (cons type (cdr (car this)))) | ||
| 1739 | compilation-regexps)) | ||
| 1740 | (setq this (cdr this))))) | ||
| 1741 | |||
| 1742 | (defun compile-buffer-substring (index) | ||
| 1743 | ;; Get substring matched by INDEXth subexpression. | ||
| 1744 | (if index | ||
| 1745 | (let ((beg (match-beginning index))) | ||
| 1746 | (if beg (buffer-substring beg (match-end index)))))) | ||
| 1648 | 1747 | ||
| 1649 | ;; If directory DIR is a subdir of ORIG or of ORIG's parent, | 1748 | ;; If directory DIR is a subdir of ORIG or of ORIG's parent, |
| 1650 | ;; return a relative name for it starting from ORIG or its parent. | 1749 | ;; return a relative name for it starting from ORIG or its parent. |