]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/compile.el
merge trunk
[gnu-emacs] / lisp / progmodes / compile.el
index f22ee4f7ea5d51b2d1fc1a6151311875f3f05b7c..10fd7a75eaaa88b8eceaf0294f92e6bc90e3ddac 100644 (file)
@@ -30,7 +30,7 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(eval-when-compile (require 'cl-lib))
 (require 'tool-bar)
 (require 'comint)
 
@@ -171,6 +171,15 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
      "\\(?:^cucumber\\(?: -p [^[:space:]]+\\)?\\|#\\)\
 \\(?: \\)\\([^\(].*\\):\\([1-9][0-9]*\\)" 1 2)
 
+    (msft
+     ;; Must be before edg-1, so that MSVC's longer messages are
+     ;; considered before EDG.
+     ;; The message may be a "warning", "error", or "fatal error" with
+     ;; an error code, or "see declaration of" without an error code.
+     "^ *\\([0-9]+>\\)?\\(\\(?:[a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) ?\
+: \\(?:see declaration\\|\\(?:warnin\\(g\\)\\|[a-z ]+\\) C[0-9]+:\\)"
+     2 3 nil (4))
+
     (edg-1
      "^\\([^ \n]+\\)(\\([0-9]+\\)): \\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
      1 2 nil (3 . 4))
@@ -209,7 +218,7 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
     ;; due to matching filenames via \\(.*?\\).  This might be faster.
     (maven
      ;; Maven is a popular free software build tool for Java.
-     "\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\] " 1 2 3)
+     "\\([\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\] " 1 2 3)
 
     (jikes-line
      "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* \\(?:Error\\|Warnin\\(g\\)\\)\\)"
@@ -488,9 +497,12 @@ What matched the HYPERLINK'th subexpression has `mouse-face' and
 `compilation-message-face' applied.  If this is nil, the text
 matched by the whole REGEXP becomes the hyperlink.
 
-Additional HIGHLIGHTs take the shape (SUBMATCH FACE), where SUBMATCH is
-the number of a submatch that should be highlighted when it matches,
-and FACE is an expression returning the face to use for that submatch.."
+Additional HIGHLIGHTs take the shape (SUBMATCH FACE), where
+SUBMATCH is the number of a submatch and FACE is an expression
+which evaluates to a face name (a symbol or string).
+Alternatively, FACE can evaluate to a property list of the
+form (face FACE PROP1 VAL1 PROP2 VAL2 ...), in which case all the
+listed text properties PROP# are given values VAL# as well."
   :type '(repeat (choice (symbol :tag "Predefined symbol")
                         (sexp :tag "Error specification")))
   :link `(file-link :tag "example file"
@@ -674,6 +686,34 @@ starting the compilation process."
   :group 'compilation
   :version "22.1")
 
+;; The next three faces must be able to stand out against the
+;; `mode-line' and `mode-line-inactive' faces.
+
+(defface compilation-mode-line-fail
+  '((default :inherit compilation-error)
+    (((class color) (min-colors 16)) (:foreground "Red1" :weight bold))
+    (((class color) (min-colors 8)) (:foreground "red"))
+    (t (:inverse-video t :weight bold)))
+  "Face for Compilation mode's \"error\" mode line indicator."
+  :group 'compilation
+  :version "24.3")
+
+(defface compilation-mode-line-run
+  '((t :inherit compilation-warning))
+  "Face for Compilation mode's \"running\" mode line indicator."
+  :group 'compilation
+  :version "24.3")
+
+(defface compilation-mode-line-exit
+  '((default :inherit compilation-info)
+    (((class color) (min-colors 16))
+     (:foreground "ForestGreen" :weight bold))
+    (((class color)) (:foreground "green" :weight bold))
+    (t (:weight bold)))
+  "Face for Compilation mode's \"exit\" mode line indicator."
+  :group 'compilation
+  :version "24.3")
+
 (defface compilation-line-number
   '((t :inherit font-lock-keyword-face))
   "Face for displaying line numbers in compiler messages."
@@ -717,12 +757,10 @@ Faces `compilation-error-face', `compilation-warning-face',
 (defvar compilation-leave-directory-face 'font-lock-builtin-face
   "Face name to use for leaving directory messages.")
 
-
-
 ;; Used for compatibility with the old compile.el.
 (defvar compilation-parse-errors-function nil)
-(make-obsolete 'compilation-parse-errors-function
-               'compilation-error-regexp-alist "24.1")
+(make-obsolete-variable 'compilation-parse-errors-function
+                       'compilation-error-regexp-alist "24.1")
 
 (defcustom compilation-auto-jump-to-first-error nil
   "If non-nil, automatically jump to the first error during compilation."
@@ -763,7 +801,7 @@ info, are considered errors."
          3)))
   (setq compilation-skip-threshold level)
   (message "Skipping %s"
-           (case compilation-skip-threshold
+           (pcase compilation-skip-threshold
              (0 "Nothing")
              (1 "Info messages")
              (2 "Warnings and info"))))
@@ -798,7 +836,7 @@ from a different message."
 ;; modified using the same *compilation* buffer. this necessitates
 ;; re-parsing markers.
 
-;; (defstruct (compilation--loc
+;; (cl-defstruct (compilation--loc
 ;;             (:constructor nil)
 ;;             (:copier nil)
 ;;             (:constructor compilation--make-loc
@@ -847,7 +885,7 @@ from a different message."
 ;; These are the value of the `compilation-message' text-properties in the
 ;; compilation buffer.
 
-(defstruct (compilation--message
+(cl-defstruct (compilation--message
             (:constructor nil)
             (:copier nil)
             ;; (:type list)                ;Old representation.
@@ -1068,14 +1106,14 @@ FMTS is a list of format specs for transforming the file name.
         end-marker loc end-loc)
     (if (not (and marker (marker-buffer marker)))
        (setq marker nil)               ; no valid marker for this file
-      (setq loc (or line 1))           ; normalize no linenumber to line 1
+      (unless line (setq line 1))       ; normalize no linenumber to line 1
       (catch 'marker                   ; find nearest loc, at least one exists
        (dolist (x (cddr (compilation--file-struct->loc-tree
                           file-struct)))       ; Loop over remaining lines.
-         (if (> (car x) loc)           ; Still bigger.
+         (if (> (car x) line)          ; Still bigger.
              (setq marker-line x)
-           (if (> (- (or (car marker-line) 1) loc)
-                  (- loc (car x)))     ; Current line is nearer.
+           (if (> (- (or (car marker-line) 1) line)
+                  (- line (car x)))    ; Current line is nearer.
                (setq marker-line x))
            (throw 'marker t))))
       (setq marker (compilation--loc->marker (cadr marker-line))
@@ -1093,15 +1131,15 @@ FMTS is a list of format specs for transforming the file name.
          (save-restriction
            (widen)
            (goto-char (marker-position marker))
-           (when (or end-col end-line)
+           ;; Set end-marker if appropriate and go to line.
+           (if (not (or end-col end-line))
+               (beginning-of-line (- line marker-line -1))
              (beginning-of-line (- (or end-line line) marker-line -1))
              (if (or (null end-col) (< end-col 0))
                  (end-of-line)
                (compilation-move-to-column end-col screen-columns))
-             (setq end-marker (point-marker)))
-           (beginning-of-line (if end-line
-                                  (- line end-line -1)
-                                (- loc marker-line -1)))
+             (setq end-marker (point-marker))
+             (when end-line (beginning-of-line (- line end-line -1))))
            (if col
                (compilation-move-to-column col screen-columns)
              (forward-to-indentation 0))
@@ -1184,7 +1222,7 @@ FMTS is a list of format specs for transforming the file name.
   (goto-char end)
   (unless (bolp)
     ;; We generally don't like to parse partial lines.
-    (assert (eobp))
+    (cl-assert (eobp))
     (when (let ((proc (get-buffer-process (current-buffer))))
             (and proc (memq (process-status proc) '(run open))))
       (setq end (line-beginning-position))))
@@ -1300,16 +1338,27 @@ to `compilation-error-regexp-alist' if RULES is nil."
             (compilation--put-prop
              end-col 'font-lock-face compilation-column-face)
 
+           ;; Obey HIGHLIGHT.
             (dolist (extra-item (nthcdr 6 item))
               (let ((mn (pop extra-item)))
                 (when (match-beginning mn)
                   (let ((face (eval (car extra-item))))
                     (cond
                      ((null face))
-                     ((symbolp face)
+                     ((or (symbolp face) (stringp face))
                       (put-text-property
                        (match-beginning mn) (match-end mn)
                        'font-lock-face face))
+                    ((and (listp face)
+                          (eq (car face) 'face)
+                          (or (symbolp (cadr face))
+                              (stringp (cadr face))))
+                      (put-text-property
+                       (match-beginning mn) (match-end mn)
+                       'font-lock-face (cadr face))
+                      (add-text-properties
+                       (match-beginning mn) (match-end mn)
+                       (nthcdr 2 face)))
                      (t
                       (error "Don't know how to handle face %S"
                              face)))))))
@@ -1457,23 +1506,12 @@ Otherwise, construct a buffer name from NAME-OF-MODE."
        (t
         (concat "*" (downcase name-of-mode) "*"))))
 
-;; This is a rough emulation of the old hack, until the transition to new
-;; compile is complete.
-(defun compile-internal (command error-message
-                                &optional _name-of-mode parser
-                                error-regexp-alist name-function
-                                _enter-regexp-alist _leave-regexp-alist
-                                file-regexp-alist _nomessage-regexp-alist
-                                _no-async highlight-regexp _local-map)
-  (if parser
-      (error "Compile now works very differently, see `compilation-error-regexp-alist'"))
-  (let ((compilation-error-regexp-alist
-        (append file-regexp-alist (or error-regexp-alist
-                                      compilation-error-regexp-alist)))
-       (compilation-error (replace-regexp-in-string "^No more \\(.+\\)s\\.?"
-                                                    "\\1" error-message)))
-    (compilation-start command nil name-function highlight-regexp)))
-(make-obsolete 'compile-internal 'compilation-start "22.1")
+(defcustom compilation-always-kill nil
+  "If t, always kill a running compilation process before starting a new one.
+If nil, ask to kill it."
+  :type 'boolean
+  :version "24.3"
+  :group 'compilation)
 
 ;;;###autoload
 (defun compilation-start (command &optional mode name-function highlight-regexp)
@@ -1507,19 +1545,20 @@ Returns the compilation buffer created."
              (get-buffer-create
                (compilation-buffer-name name-of-mode mode name-function)))
       (let ((comp-proc (get-buffer-process (current-buffer))))
-       (if comp-proc
-           (if (or (not (eq (process-status comp-proc) 'run))
-                   (yes-or-no-p
-                    (format "A %s process is running; kill it? "
-                            name-of-mode)))
-               (condition-case ()
-                   (progn
-                     (interrupt-process comp-proc)
-                     (sit-for 1)
-                     (delete-process comp-proc))
-                 (error nil))
-             (error "Cannot have two processes in `%s' at once"
-                    (buffer-name)))))
+      (if comp-proc
+          (if (or (not (eq (process-status comp-proc) 'run))
+                  (eq (process-query-on-exit-flag comp-proc) nil)
+                  (yes-or-no-p
+                   (format "A %s process is running; kill it? "
+                           name-of-mode)))
+              (condition-case ()
+                  (progn
+                    (interrupt-process comp-proc)
+                    (sit-for 1)
+                    (delete-process comp-proc))
+                (error nil))
+            (error "Cannot have two processes in `%s' at once"
+                   (buffer-name)))))
       ;; first transfer directory from where M-x compile was called
       (setq default-directory thisdir)
       ;; Make compilation buffer read-only.  The filter can still write it.
@@ -1574,7 +1613,7 @@ Returns the compilation buffer created."
       (let ((process-environment
             (append
              compilation-environment
-             (if (if (boundp 'system-uses-terminfo) ; `if' for compiler warning
+             (if (if (boundp 'system-uses-terminfo);`If' for compiler warning.
                      system-uses-terminfo)
                  (list "TERM=dumb" "TERMCAP="
                        (format "COLUMNS=%d" (window-width)))
@@ -1624,13 +1663,20 @@ Returns the compilation buffer created."
                           nil `("-c" ,command))))
                     (start-file-process-shell-command (downcase mode-name)
                                                       outbuf command))))
-             ;; Make the buffer's mode line show process state.
-             (setq mode-line-process
-                   (list (propertize ":%s" 'face 'compilation-warning)))
-             (set-process-sentinel proc 'compilation-sentinel)
-             (unless (eq mode t)
-               ;; Keep the comint filter, since it's needed for proper handling
-               ;; of the prompts.
+              ;; Make the buffer's mode line show process state.
+              (setq mode-line-process
+                    '(:propertize ":%s" face compilation-mode-line-run))
+
+              ;; Set the process as killable without query by default.
+              ;; This allows us to start a new compilation without
+              ;; getting prompted.
+              (when compilation-always-kill
+                (set-process-query-on-exit-flag proc nil))
+
+              (set-process-sentinel proc 'compilation-sentinel)
+              (unless (eq mode t)
+                ;; Keep the comint filter, since it's needed for proper
+               ;; handling of the prompts.
                (set-process-filter proc 'compilation-filter))
              ;; Use (point-max) here so that output comes in
              ;; after the initial text,
@@ -1646,9 +1692,9 @@ Returns the compilation buffer created."
                    (cons proc compilation-in-progress)))
          ;; No asynchronous processes available.
          (message "Executing `%s'..." command)
-         ;; Fake modeline display as if `start-process' were run.
+         ;; Fake mode line display as if `start-process' were run.
          (setq mode-line-process
-               (list (propertize ":run" 'face 'compilation-warning)))
+               '(:propertize ":run" face compilation-mode-line-run))
          (force-mode-line-update)
          (sit-for 0)                   ; Force redisplay
          (save-excursion
@@ -1884,6 +1930,9 @@ Runs `compilation-mode-hook' with `run-mode-hooks' (which see).
   (setq buffer-read-only t)
   (run-mode-hooks 'compilation-mode-hook))
 
+;;;###autoload
+(put 'define-compilation-mode 'doc-string-elt 3)
+
 (defmacro define-compilation-mode (mode name doc &rest body)
   "This is like `define-derived-mode' without the PARENT argument.
 The parent is always `compilation-mode' and the customizable `compilation-...'
@@ -2043,9 +2092,10 @@ commands of Compilation major mode are available.  See
                                                        (car status)))))
            (message "%s" msg)
            (propertize out-string
-                       'help-echo msg 'face (if (> exit-status 0)
-                                                'compilation-error
-                                              'compilation-info))))
+                       'help-echo msg
+                       'face (if (> exit-status 0)
+                                 'compilation-mode-line-fail
+                               'compilation-mode-line-exit))))
     ;; Force mode line redisplay soon.
     (force-mode-line-update)
     (if (and opoint (< opoint omax))
@@ -2383,7 +2433,7 @@ region and the first line of the next region."
     (push fs compilation-gcpro)
     (let ((loc (compilation-assq (or line 1) (cdr fs))))
       (setq loc (compilation-assq col loc))
-      (assert (null (cdr loc)))
+      (cl-assert (null (cdr loc)))
       (setcdr loc (compilation--make-cdrloc line fs marker))
       loc)))
 
@@ -2429,10 +2479,7 @@ and overlay is highlighted between MK and END-MK."
                 ;; the error location if the two buffers are in two
                 ;; different frames.  So don't do it if it's not necessary.
                 pre-existing
-              (let ((display-buffer-reuse-frames t)
-                    (pop-up-windows t))
-               ;; Pop up a window.
-                (display-buffer (marker-buffer msg)))))
+             (display-buffer (marker-buffer msg))))
         (highlight-regexp (with-current-buffer (marker-buffer msg)
                             ;; also do this while we change buffer
                             (compilation-set-window w msg)
@@ -2653,8 +2700,8 @@ The file-structure looks like this:
 (defun compilation--flush-file-structure (file)
   (or (consp file) (setq file (list file)))
   (let ((fs (compilation-get-file-structure file)))
-    (assert (eq fs (gethash file compilation-locs)))
-    (assert (eq fs (gethash (cons (caar fs) (cadr (car fs)))
+    (cl-assert (eq fs (gethash file compilation-locs)))
+    (cl-assert (eq fs (gethash (cons (caar fs) (cadr (car fs)))
                             compilation-locs)))
     (maphash (lambda (k v)
                (if (eq v fs) (remhash k compilation-locs)))