;;; flymake.el -- a universal on-the-fly syntax checker
-;; Copyright (C) 2003-2011 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2012 Free Software Foundation, Inc.
;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
;; Maintainer: Pavel Kobyakov <pk_at_work@yahoo.com>
;;; Code:
-(eval-when-compile (require 'cl))
+(eval-when-compile (require 'cl-lib))
(if (featurep 'xemacs) (require 'overlay))
(defvar flymake-is-running nil
(make-variable-buffer-local 'flymake-output-residual)
(defgroup flymake nil
- "A universal on-the-fly syntax checker."
+ "Universal on-the-fly syntax checker."
:version "23.1"
:group 'tools)
This function is used in sort to move most possible file names
to the beginning of the list (File.h -> File.cpp moved to top)."
(and (equal (file-name-sans-extension flymake-included-file-name)
- (file-name-sans-extension (file-name-nondirectory file-one)))
+ (file-name-base file-one))
(not (equal file-one file-two))))
(defcustom flymake-check-file-limit 8192
(with-current-buffer source-buffer
(flymake-parse-output-and-residual output)))))
-(defun flymake-process-sentinel (process event)
+(defun flymake-process-sentinel (process _event)
"Sentinel for syntax check buffers."
(when (memq (process-status process) '(signal exit))
(let* ((exit-status (process-exit-status process))
(defun flymake-er-get-line-err-info-list (err-info)
(nth 1 err-info))
-(defstruct (flymake-ler
+(cl-defstruct (flymake-ler
(:constructor nil)
(:constructor flymake-ler-make-ler (file line type text &optional full-file)))
file line type text full-file)
"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 mouse-face)
+(defcustom flymake-error-bitmap '(exclamation-mark error)
+ "Bitmap used in the fringe for indicating errors.
+The value may also be a list of two elements where the second
+element specifies the face for the bitmap."
+ :group 'flymake
+ :version "24.3"
+ :type 'symbol)
+
+(defcustom flymake-warning-bitmap 'question-mark
+ "Bitmap used in the fringe for indicating warnings.
+The value may also be a list of two elements where the second
+element specifies the face for the bitmap."
+ :group 'flymake
+ :version "24.3"
+ :type 'symbol)
+
+(defcustom flymake-fringe-indicator-position 'left-fringe
+ "The position to put flymake fringe indicator.
+The value can be nil, left-fringe or right-fringe.
+Fringe indicators are disabled if nil."
+ :group 'flymake
+ :version "24.3"
+ :type '(choice (const left-fringe)
+ (const right-fringe)
+ (const :tag "No fringe indicators" nil)))
+
+(defun flymake-make-overlay (beg end tooltip-text face bitmap mouse-face)
"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 t))
+ (fringe (and flymake-fringe-indicator-position
+ (propertize "!" 'display
+ (cons flymake-fringe-indicator-position
+ (if (listp bitmap)
+ 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)
+ (overlay-put ov 'evaporate t)
+ (overlay-put ov 'before-string fringe)
;;+(flymake-log 3 "created overlay %s" ov)
ov)
(flymake-log 3 "created an overlay at (%d-%d)" beg end)))
has-flymake-overlays))
(defface flymake-errline
- '((((class color) (background dark)) (:background "Firebrick4"))
- (((class color) (background light)) (:background "LightPink"))
- (t (:bold t)))
+ '((t :inherit error))
"Face used for marking error lines."
:group 'flymake)
(defface flymake-warnline
- '((((class color) (background dark)) (:background "DarkBlue"))
- (((class color) (background light)) (:background "LightBlue2"))
- (t (:bold t)))
+ '((t :inherit warning))
"Face used for marking warning lines."
:group 'flymake)
(beg line-beg)
(end line-end)
(tooltip-text (flymake-ler-text (nth 0 line-err-info-list)))
- (face nil))
+ (face nil)
+ (bitmap nil))
(goto-char line-beg)
(while (looking-at "[ \t]")
(setq end (point)))
(if (> (flymake-get-line-err-count line-err-info-list "e") 0)
- (setq face 'flymake-errline)
- (setq face 'flymake-warnline))
+ (setq face 'flymake-errline
+ bitmap flymake-error-bitmap)
+ (setq face 'flymake-warnline
+ bitmap flymake-warning-bitmap))
- (flymake-make-overlay beg end tooltip-text face nil)))
+ (flymake-make-overlay beg end tooltip-text face bitmap nil)))
(defun flymake-parse-err-lines (err-info-list lines)
"Parse err LINES, store info in ERR-INFO-LIST."
;; PHP
("\\(?: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
- (" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[ \t\n]*\\(.+\\)"
+ ;; ant/javac. Note this also matches gcc warnings!
+ (" *\\(\\[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))
;; :type '(repeat (string number number number))
;;)
+(defvar flymake-warning-re "^[wW]arning"
+ "Regexp matching against err-text to detect a warning.")
+
(defun flymake-parse-line (line)
"Parse LINE to see if it is an error or warning.
Return its components if so, nil otherwise."
(match-string (nth 4 (car patterns)) line)
(flymake-patch-err-text (substring line (match-end 0)))))
(or err-text (setq err-text "<no error text>"))
- (if (and err-text (string-match "^[wW]arning" err-text))
+ (if (and err-text (string-match flymake-warning-re err-text))
(setq err-type "w")
)
(flymake-log 3 "parse line: file-idx=%s line-idx=%s file=%s line=%s text=%s" file-idx line-idx
(flymake-log 1 "deleted file %s" file-name)))
(defun flymake-safe-delete-directory (dir-name)
- (condition-case err
+ (condition-case nil
(progn
(delete-directory dir-name)
(flymake-log 1 "deleted dir %s" dir-name))
(flymake-log 1 "Failed to delete dir %s, error ignored" dir-name))))
(defcustom flymake-compilation-prevents-syntax-check t
- "If non-nil, syntax check won't be started in case compilation is running."
+ "If non-nil, don't start syntax check if compilation is running."
:group 'flymake
:type 'boolean)
(defun flymake-start-syntax-check-process (cmd args dir)
"Start syntax check process."
- (let* ((process nil))
- (condition-case err
- (progn
- (when dir
- (let ((default-directory dir))
- (flymake-log 3 "starting process on dir %s" default-directory)))
- (setq process (apply 'start-file-process
- "flymake-proc" (current-buffer) cmd args))
- (set-process-sentinel process 'flymake-process-sentinel)
- (set-process-filter process 'flymake-process-filter)
- (push process flymake-processes)
-
- (setq flymake-is-running t)
- (setq flymake-last-change-time nil)
- (setq flymake-check-start-time (flymake-float-time))
-
- (flymake-report-status nil "*")
- (flymake-log 2 "started process %d, command=%s, dir=%s"
- (process-id process) (process-command process)
- 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)))
- (source-file-name buffer-file-name)
- (cleanup-f (flymake-get-cleanup-function source-file-name)))
- (flymake-log 0 err-str)
- (funcall cleanup-f)
- (flymake-report-fatal-status "PROCERR" err-str))))))
+ (condition-case err
+ (let* ((process
+ (let ((default-directory (or dir default-directory)))
+ (when dir
+ (flymake-log 3 "starting process on dir %s" dir))
+ (apply 'start-file-process
+ "flymake-proc" (current-buffer) cmd args))))
+ (set-process-sentinel process 'flymake-process-sentinel)
+ (set-process-filter process 'flymake-process-filter)
+ (push process flymake-processes)
+
+ (setq flymake-is-running t)
+ (setq flymake-last-change-time nil)
+ (setq flymake-check-start-time (flymake-float-time))
+
+ (flymake-report-status nil "*")
+ (flymake-log 2 "started process %d, command=%s, dir=%s"
+ (process-id process) (process-command process)
+ 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)))
+ (source-file-name buffer-file-name)
+ (cleanup-f (flymake-get-cleanup-function source-file-name)))
+ (flymake-log 0 err-str)
+ (funcall cleanup-f)
+ (flymake-report-fatal-status "PROCERR" err-str)))))
(defun flymake-kill-process (proc)
"Kill process PROC."
;;;###autoload
(define-minor-mode flymake-mode
- "Minor mode to do on-the-fly syntax checking.
-When called interactively, toggles the minor mode.
-With arg, turn Flymake mode on if and only if arg is positive."
+ "Toggle on-the-fly syntax checking.
+With a prefix argument ARG, enable the mode if ARG is positive,
+and disable it otherwise. If called from Lisp, enable the mode
+if ARG is omitted or nil."
:group 'flymake :lighter flymake-mode-line
(cond
;; Turning the mode ON.
(flymake-mode
- (if (not (flymake-can-syntax-check-file buffer-file-name))
- (flymake-log 2 "flymake cannot check syntax in buffer %s" (buffer-name))
+ (cond
+ ((not buffer-file-name)
+ (message "Flymake unable to run without a buffer file name"))
+ ((not (flymake-can-syntax-check-file buffer-file-name))
+ (flymake-log 2 "flymake cannot check syntax in buffer %s" (buffer-name)))
+ (t
(add-hook 'after-change-functions 'flymake-after-change-function nil t)
(add-hook 'after-save-hook 'flymake-after-save-hook nil t)
(add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook nil t)
(setq flymake-timer
(run-at-time nil 1 'flymake-on-timer-event (current-buffer)))
- (when flymake-start-syntax-check-on-find-file
- (flymake-start-syntax-check))))
+ (when (and flymake-start-syntax-check-on-find-file
+ ;; Since we write temp files in current dir, there's no point
+ ;; trying if the directory is read-only (bug#8954).
+ (file-writable-p (file-name-directory buffer-file-name)))
+ (with-demoted-errors
+ (flymake-start-syntax-check))))))
;; Turning the mode OFF.
(t
:group 'flymake
:type 'boolean)
-(defun flymake-after-change-function (start stop len)
+(defun flymake-after-change-function (start stop _len)
"Start syntax check for current buffer if it isn't already running."
;;+(flymake-log 0 "setting change time to %s" (flymake-float-time))
(let((new-text (buffer-substring start stop)))
(cancel-timer flymake-timer)
(setq flymake-timer nil)))
+;;;###autoload
(defun flymake-find-file-hook ()
;;+(when flymake-start-syntax-check-on-find-file
;;+ (flymake-log 3 "starting syntax check on file open")
(flymake-log 3 "create-temp-inplace: file=%s temp=%s" file-name temp-name)
temp-name))
-(defun flymake-create-temp-with-folder-structure (file-name prefix)
+(defun flymake-create-temp-with-folder-structure (file-name _prefix)
(unless (stringp file-name)
(error "Invalid file-name"))
(when temp-master-file-name
(flymake-get-tex-args temp-master-file-name))))
-(defun flymake-get-include-dirs-dot (base-dir)
+(defun flymake-get-include-dirs-dot (_base-dir)
'("."))
;;;; xml-specific init-cleanup routines