]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/flymake.el
Update docs for `customize-mode'
[gnu-emacs] / lisp / progmodes / flymake.el
index 48ff486a9e54f1770748cc86e37e6891b6785868..30c9fed45ca2523802402b379732bdd158c41129 100644 (file)
@@ -1,6 +1,6 @@
 ;;; flymake.el --- a universal on-the-fly syntax checker  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2016 Free Software Foundation, Inc.
 
 ;; Author:  Pavel Kobyakov <pk_at_work@yahoo.com>
 ;; Maintainer: Leo Liu <sdl.web@gmail.com>
@@ -40,6 +40,7 @@
 (defgroup flymake nil
   "Universal on-the-fly syntax checker."
   :version "23.1"
+  :link '(custom-manual "(flymake) Top")
   :group 'tools)
 
 (defcustom flymake-error-bitmap '(exclamation-mark error)
@@ -192,55 +193,6 @@ NAME is the file name function to use, default `flymake-get-real-file-name'."
 (defvar-local flymake-new-err-info nil
   "Same as `flymake-err-info', effective when a syntax check is in progress.")
 
-(defun flymake-posn-at-point-as-event (&optional position window dx dy)
-  "Return pixel position of top left corner of glyph at POSITION.
-
-The position is relative to top left corner of WINDOW, as a
-mouse-1 click event (identical to the event that would be
-triggered by clicking mouse button 1 at the top left corner of
-the glyph).
-
-POSITION and WINDOW default to the position of point in the
-selected window.
-
-DX and DY specify optional offsets from the top left of the glyph."
-  (let* ((window (or window (selected-window)))
-        (position (or position (window-point window)))
-        (dx (or dx 0))
-        (dy (or dy 0))
-        (pos (posn-at-point position window))
-         (x-y (posn-x-y pos))
-         (edges (window-inside-pixel-edges window))
-         (win-x-y (window-pixel-edges window)))
-    ;; adjust for window edges
-    (setcar (nthcdr 2 pos)
-            (cons (+ (car x-y) (car  edges) (- (car win-x-y))  dx)
-                  (+ (cdr x-y) (cadr edges) (- (cadr win-x-y)) dy)))
-    (list 'mouse-1 pos)))
-
-;;; XXX: get rid of the following two functions
-
-(defun flymake-popup-menu (menu-data)
-  "Pop up the flymake menu at point, using the data MENU-DATA.
-POS is a list of the form ((X Y) WINDOW), where X and Y are
-pixels positions from the top left corner of WINDOW's frame.
-MENU-DATA is a list of error and warning messages returned by
-`flymake-make-err-menu-data'."
-  (x-popup-menu (flymake-posn-at-point-as-event)
-               (flymake-make-emacs-menu menu-data)))
-
-(defun flymake-make-emacs-menu (menu-data)
-  "Return a menu specifier using MENU-DATA.
-MENU-DATA is a list of error and warning messages returned by
-`flymake-make-err-menu-data'.
-See `x-popup-menu' for the menu specifier format."
-  (let* ((menu-title     (nth 0 menu-data))
-        (menu-items     (nth 1 menu-data))
-        (menu-commands  (mapcar (lambda (foo)
-                                   (cons (nth 0 foo) (nth 1 foo)))
-                                 menu-items)))
-    (list menu-title (cons "" menu-commands))))
-
 (defun flymake-log (level text &rest args)
   "Log a message at level LEVEL.
 If LEVEL is higher than `flymake-log-level', the message is
@@ -248,7 +200,7 @@ ignored.  Otherwise, it is printed using `message'.
 TEXT is a format control string, and the remaining arguments ARGS
 are the string substitutions (see the function `format')."
   (if (<= level flymake-log-level)
-      (let* ((msg (apply 'format text args)))
+      (let* ((msg (apply #'format-message text args)))
        (message "%s" msg))))
 
 (defun flymake-ins-after (list pos val)
@@ -335,7 +287,7 @@ Return its file name if found, or nil if not found."
             nil)))))
 
 (defun flymake-fix-file-name (name)
-  "Replace all occurrences of '\' with '/'."
+  "Replace all occurrences of `\\' with `/'."
   (when name
     (setq name (expand-file-name name))
     (setq name (abbreviate-file-name name))
@@ -558,16 +510,6 @@ Create parent directories as needed."
   (write-region nil nil file-name nil 566)
   (flymake-log 3 "saved buffer %s in file %s" (buffer-name) file-name))
 
-(defun flymake-save-string-to-file (file-name data)
-  "Save string DATA to file FILE-NAME."
-  (write-region data nil file-name nil 566))
-
-(defun flymake-read-file-to-string (file-name)
-  "Read contents of file FILE-NAME and return as a string."
-  (with-temp-buffer
-    (insert-file-contents file-name)
-    (buffer-substring (point-min) (point-max))))
-
 (defun flymake-process-filter (process output)
   "Parse OUTPUT and highlight error lines.
 It's flymake process filter."
@@ -613,29 +555,31 @@ It's flymake process filter."
              (setq flymake-is-running nil))))))))
 
 (defun flymake-post-syntax-check (exit-status command)
-  (setq flymake-err-info flymake-new-err-info)
-  (setq flymake-new-err-info nil)
-  (setq flymake-err-info
-        (flymake-fix-line-numbers
-         flymake-err-info 1 (count-lines (point-min) (point-max))))
-  (flymake-delete-own-overlays)
-  (flymake-highlight-err-lines flymake-err-info)
-  (let (err-count warn-count)
-    (setq err-count (flymake-get-err-count flymake-err-info "e"))
-    (setq warn-count  (flymake-get-err-count flymake-err-info "w"))
-    (flymake-log 2 "%s: %d error(s), %d warning(s) in %.2f second(s)"
-                (buffer-name) err-count warn-count
-                (- (float-time) flymake-check-start-time))
-    (setq flymake-check-start-time nil)
-
-    (if (and (equal 0 err-count) (equal 0 warn-count))
-       (if (equal 0 exit-status)
-           (flymake-report-status "" "")       ; PASSED
-         (if (not flymake-check-was-interrupted)
-             (flymake-report-fatal-status "CFGERR"
-                                          (format "Configuration error has occurred while running %s" command))
-           (flymake-report-status nil ""))) ; "STOPPED"
-      (flymake-report-status (format "%d/%d" err-count warn-count) ""))))
+  (save-restriction
+    (widen)
+    (setq flymake-err-info flymake-new-err-info)
+    (setq flymake-new-err-info nil)
+    (setq flymake-err-info
+          (flymake-fix-line-numbers
+           flymake-err-info 1 (count-lines (point-min) (point-max))))
+    (flymake-delete-own-overlays)
+    (flymake-highlight-err-lines flymake-err-info)
+    (let (err-count warn-count)
+      (setq err-count (flymake-get-err-count flymake-err-info "e"))
+      (setq warn-count  (flymake-get-err-count flymake-err-info "w"))
+      (flymake-log 2 "%s: %d error(s), %d warning(s) in %.2f second(s)"
+                   (buffer-name) err-count warn-count
+                   (- (float-time) flymake-check-start-time))
+      (setq flymake-check-start-time nil)
+
+      (if (and (equal 0 err-count) (equal 0 warn-count))
+          (if (equal 0 exit-status)
+              (flymake-report-status "" "") ; PASSED
+            (if (not flymake-check-was-interrupted)
+                (flymake-report-fatal-status "CFGERR"
+                                             (format "Configuration error has occurred while running %s" command))
+              (flymake-report-status nil ""))) ; "STOPPED"
+        (flymake-report-status (format "%d/%d" err-count warn-count) "")))))
 
 (defun flymake-parse-output-and-residual (output)
   "Split OUTPUT into lines, merge in residual if necessary."
@@ -746,10 +690,10 @@ line number outside the file being compiled."
   "Determine whether overlay OV was created by flymake."
   (and (overlayp ov) (overlay-get ov 'flymake-overlay)))
 
-(defun flymake-make-overlay (beg end tooltip-text face bitmap mouse-face)
+(defun flymake-make-overlay (beg end tooltip-text face bitmap)
   "Allocate a flymake overlay in range BEG and END."
   (when (not (flymake-region-has-flymake-overlays beg end))
-    (let ((ov (make-overlay beg end nil t t))
+    (let ((ov (make-overlay beg end nil t))
          (fringe (and flymake-fringe-indicator-position
                       (propertize "!" 'display
                                   (cons flymake-fringe-indicator-position
@@ -757,7 +701,6 @@ line number outside the file being compiled."
                                             bitmap
                                           (list bitmap)))))))
       (overlay-put ov 'face           face)
-      (overlay-put ov 'mouse-face     mouse-face)
       (overlay-put ov 'help-echo      tooltip-text)
       (overlay-put ov 'flymake-overlay  t)
       (overlay-put ov 'priority 100)
@@ -809,42 +752,19 @@ Return t if it has at least one flymake overlay, nil if no overlay."
 Perhaps use text from LINE-ERR-INFO-LIST to enhance highlighting."
   (goto-char (point-min))
   (forward-line (1- line-no))
-  (let* ((line-beg (point-at-bol))
-        (line-end (point-at-eol))
-        (beg      line-beg)
-        (end      line-end)
-        (tooltip-text (flymake-ler-text (nth 0 line-err-info-list)))
-        (face     nil)
-        (bitmap   nil))
-
-    (goto-char line-beg)
-    (while (looking-at "[ \t]")
-      (forward-char))
-
-    (setq beg (point))
-
-    (goto-char line-end)
-    (while (and (looking-at "[ \t\r\n]") (> (point) 1))
-      (backward-char))
-
-    (setq end (1+ (point)))
-
-    (when (<= end beg)
-      (setq beg line-beg)
-      (setq end line-end))
-
-    (when (= end beg)
-      (goto-char end)
-      (forward-line)
-      (setq end (point)))
-
-    (if (> (flymake-get-line-err-count line-err-info-list "e") 0)
-       (setq face 'flymake-errline
-             bitmap flymake-error-bitmap)
-      (setq face 'flymake-warnline
-           bitmap flymake-warning-bitmap))
-
-    (flymake-make-overlay beg end tooltip-text face bitmap nil)))
+  (pcase-let* ((beg (progn (back-to-indentation) (point)))
+               (end (progn
+                      (end-of-line)
+                      (skip-chars-backward " \t\f\t\n" beg)
+                      (if (eq (point) beg)
+                          (line-beginning-position 2)
+                        (point))))
+               (tooltip-text (mapconcat #'flymake-ler-text line-err-info-list "\n"))
+               (`(,face ,bitmap)
+                (if (> (flymake-get-line-err-count line-err-info-list "e") 0)
+                    (list 'flymake-errline flymake-error-bitmap)
+                  (list 'flymake-warnline flymake-warning-bitmap))))
+    (flymake-make-overlay beg end tooltip-text face bitmap)))
 
 (defun flymake-parse-err-lines (err-info-list lines)
   "Parse err LINES, store info in ERR-INFO-LIST."
@@ -865,7 +785,7 @@ Perhaps use text from LINE-ERR-INFO-LIST to enhance highlighting."
        (when (flymake-same-files real-file-name source-file-name)
          (setq line-err-info (flymake-ler-set-file line-err-info nil))
          (setq err-info-list (flymake-add-err-info err-info-list line-err-info))))
-      (flymake-log 3 "parsed '%s', %s line-err-info" (nth idx lines) (if line-err-info "got" "no"))
+      (flymake-log 3 "parsed `%s', %s line-err-info" (nth idx lines) (if line-err-info "got" "no"))
       (setq idx (1+ idx)))
     err-info-list))
 
@@ -906,16 +826,16 @@ Convert it to flymake internal format."
   (append
    '(
      ;; MS Visual C++ 6.0
-     ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \: \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
+     ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) : \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
       1 3 nil 4)
      ;; jikes
-     ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[0-9]+\:[0-9]+\:[0-9]+\: \\(\\(Error\\|Warning\\|Caution\\|Semantic Error\\):[ \t\n]*\\(.+\\)\\)"
+     ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\):\\([0-9]+\\):[0-9]+:[0-9]+:[0-9]+: \\(\\(Error\\|Warning\\|Caution\\|Semantic Error\\):[ \t\n]*\\(.+\\)\\)"
       1 3 nil 4)
      ;; MS midl
      ("midl[ ]*:[ ]*\\(command line error .*\\)"
       nil nil nil 1)
      ;; MS C#
-     ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),[0-9]+)\: \\(\\(error\\|warning\\|fatal error\\) \\(CS[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
+     ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),[0-9]+): \\(\\(error\\|warning\\|fatal error\\) \\(CS[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
       1 3 nil 4)
      ;; perl
      ("\\(.*\\) at \\([^ \n]+\\) line \\([0-9]+\\)[,.\n]" 2 3 nil 1)
@@ -923,7 +843,7 @@ Convert it to flymake internal format."
      ("\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)" 2 3 nil 1)
      ;; LaTeX warnings (fileless) ("\\(LaTeX \\(Warning\\|Error\\): .*\\) on input line \\([0-9]+\\)" 20 3 nil 1)
      ;; ant/javac.  Note this also matches gcc warnings!
-     (" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\\(?:\:[0-9]+\\)?\:[ \t\n]*\\(.+\\)"
+     (" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\):\\([0-9]+\\)\\(?::[0-9]+\\)?:[ \t\n]*\\(.+\\)"
       2 4 nil 5))
    ;; compilation-error-regexp-alist)
    (flymake-reformat-err-line-patterns-from-compile-el compilation-error-regexp-alist-alist))
@@ -932,19 +852,6 @@ Convert it to flymake internal format."
 Use `flymake-reformat-err-line-patterns-from-compile-el' to add patterns
 from compile.el")
 
-;;(defcustom flymake-err-line-patterns
-;;  '(
-;;    ; MS Visual C++ 6.0
-;;    ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \: \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
-;;       1 3 4)
-;;   ; jikes
-;;   ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[0-9]+\:[0-9]+\:[0-9]+\: \\(\\(Error\\|Warning\\|Caution\\):[ \t\n]*\\(.+\\)\\)"
-;;       1 3 4))
-;;    "patterns for matching error/warning lines, (regexp file-idx line-idx err-text-idx)"
-;;   :group 'flymake
-;;   :type '(repeat (string number number number))
-;;)
-
 (define-obsolete-variable-alias 'flymake-warning-re 'flymake-warning-predicate "24.4")
 (defvar flymake-warning-predicate "^[wW]arning"
   "Predicate matching against error text to detect a warning.
@@ -1082,7 +989,7 @@ For the format of LINE-ERR-INFO, see `flymake-ler-make-ler'."
   (funcall flymake-get-project-include-dirs-function basedir))
 
 (defun flymake-get-system-include-dirs ()
-  "System include dirs - from the 'INCLUDE' env setting."
+  "System include dirs - from the `INCLUDE' env setting."
   (let* ((includes (getenv "INCLUDE")))
     (if includes (split-string includes path-separator t) nil)))
 
@@ -1177,8 +1084,10 @@ For the format of LINE-ERR-INFO, see `flymake-ler-make-ler'."
                      default-directory)
         process)
     (error
-     (let* ((err-str (format "Failed to launch syntax check process '%s' with args %s: %s"
-                             cmd args (error-message-string err)))
+     (let* ((err-str
+             (format-message
+              "Failed to launch syntax check process `%s' with args %s: %s"
+              cmd args (error-message-string err)))
             (source-file-name buffer-file-name)
             (cleanup-f        (flymake-get-cleanup-function source-file-name)))
        (flymake-log 0 err-str)
@@ -1223,45 +1132,36 @@ For the format of LINE-ERR-INFO, see `flymake-ler-make-ler'."
        (flymake-log 3 "starting syntax check as more than 1 second passed since last change")
        (flymake-start-syntax-check)))))
 
-(defun flymake-display-err-menu-for-current-line ()
-  "Display a menu with errors/warnings for current line if it has errors and/or warnings."
-  (interactive)
-  (let* ((line-no             (line-number-at-pos))
-        (line-err-info-list  (nth 0 (flymake-find-err-info flymake-err-info line-no)))
-        (menu-data           (flymake-make-err-menu-data line-no line-err-info-list))
-        (choice              nil))
-    (if menu-data
-       (progn
-         (setq choice (flymake-popup-menu menu-data))
-         (flymake-log 3 "choice=%s" choice)
-         (when choice
-           (eval choice)))
-      (flymake-log 1 "no errors for line %d" line-no))))
-
-(defun flymake-make-err-menu-data (line-no line-err-info-list)
-  "Make a (menu-title (item-title item-action)*) list with errors/warnings from LINE-ERR-INFO-LIST."
-  (let* ((menu-items  nil))
-    (when line-err-info-list
-      (let* ((count           (length line-err-info-list))
-            (menu-item-text  nil))
-       (while (> count 0)
-         (setq menu-item-text (flymake-ler-text (nth (1- count) line-err-info-list)))
-         (let* ((file       (flymake-ler-file (nth (1- count) line-err-info-list)))
-                (full-file  (flymake-ler-full-file (nth (1- count) line-err-info-list)))
-                (line       (flymake-ler-line (nth (1- count) line-err-info-list))))
-           (if file
-               (setq menu-item-text (concat menu-item-text " - " file "(" (format "%d" line) ")")))
-           (setq menu-items (cons (list menu-item-text
-                                        (if file (list 'flymake-goto-file-and-line full-file line) nil))
-                                  menu-items)))
-         (setq count (1- count)))
-       (flymake-log 3 "created menu-items with %d item(s)" (length menu-items))))
-    (if menu-items
-       (let* ((menu-title  (format "Line %d: %d error(s), %d warning(s)" line-no
-                                   (flymake-get-line-err-count line-err-info-list "e")
-                                   (flymake-get-line-err-count line-err-info-list "w"))))
-         (list menu-title menu-items))
-      nil)))
+(define-obsolete-function-alias 'flymake-display-err-menu-for-current-line
+  'flymake-popup-current-error-menu "24.4")
+
+(defun flymake-popup-current-error-menu (&optional event)
+  "Pop up a menu with errors/warnings for current line."
+  (interactive (list last-nonmenu-event))
+  (let* ((line-no (line-number-at-pos))
+         (errors (or (car (flymake-find-err-info flymake-err-info line-no))
+                     (user-error "No errors for current line")))
+         (menu (mapcar (lambda (x)
+                         (if (flymake-ler-file x)
+                             (cons (format "%s - %s(%d)"
+                                           (flymake-ler-text x)
+                                           (flymake-ler-file x)
+                                           (flymake-ler-line x))
+                                   x)
+                           (list (flymake-ler-text x))))
+                       errors))
+         (event (if (mouse-event-p event)
+                    event
+                  (list 'mouse-1 (posn-at-point))))
+         (title (format "Line %d: %d error(s), %d warning(s)"
+                        line-no
+                        (flymake-get-line-err-count errors "e")
+                        (flymake-get-line-err-count errors "w")))
+         (choice (x-popup-menu event (list title (cons "" menu)))))
+    (flymake-log 3 "choice=%s" choice)
+    (when choice
+      (flymake-goto-file-and-line (flymake-ler-full-file choice)
+                                  (flymake-ler-line choice)))))
 
 (defun flymake-goto-file-and-line (file line)
   "Try to get buffer for FILE and goto line LINE in it."