-;;; flymake.el --- a universal on-the-fly syntax checker
+;;; 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: Pavel Kobyakov <pk_at_work@yahoo.com>
+;; Maintainer: Leo Liu <sdl.web@gmail.com>
;; Version: 0.3
;; Keywords: c languages tools
;;; Commentary:
;;
-;; Flymake is a minor Emacs mode performing on-the-fly syntax
-;; checks using the external syntax check tool (for C/C++ this
-;; is usually the compiler)
+;; Flymake is a minor Emacs mode performing on-the-fly syntax checks
+;; using the external syntax check tool (for C/C++ this is usually the
+;; compiler).
;;; Bugs/todo:
;;; Code:
(eval-when-compile (require 'cl-lib))
-(if (featurep 'xemacs) (require 'overlay))
-(defvar flymake-is-running nil
- "If t, flymake syntax check process is running for the current buffer.")
-(make-variable-buffer-local 'flymake-is-running)
+(defgroup flymake nil
+ "Universal on-the-fly syntax checker."
+ :version "23.1"
+ :link '(custom-manual "(flymake) Top")
+ :group 'tools)
-(defvar flymake-timer nil
- "Timer for starting syntax check.")
-(make-variable-buffer-local 'flymake-timer)
+(defcustom flymake-error-bitmap '(exclamation-mark error)
+ "Bitmap (a symbol) 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. For possible bitmap
+symbols, see `fringe-bitmaps'. See also `flymake-warning-bitmap'.
-(defvar flymake-last-change-time nil
- "Time of last buffer change.")
-(make-variable-buffer-local 'flymake-last-change-time)
+The option `flymake-fringe-indicator-position' controls how and where
+this is used."
+ :group 'flymake
+ :version "24.3"
+ :type '(choice (symbol :tag "Bitmap")
+ (list :tag "Bitmap and face"
+ (symbol :tag "Bitmap")
+ (face :tag "Face"))))
-(defvar flymake-check-start-time nil
- "Time at which syntax check was started.")
-(make-variable-buffer-local 'flymake-check-start-time)
+(defcustom flymake-warning-bitmap 'question-mark
+ "Bitmap (a symbol) 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. For possible bitmap
+symbols, see `fringe-bitmaps'. See also `flymake-error-bitmap'.
-(defvar flymake-check-was-interrupted nil
- "Non-nil if syntax check was killed by `flymake-compile'.")
-(make-variable-buffer-local 'flymake-check-was-interrupted)
+The option `flymake-fringe-indicator-position' controls how and where
+this is used."
+ :group 'flymake
+ :version "24.3"
+ :type '(choice (symbol :tag "Bitmap")
+ (list :tag "Bitmap and face"
+ (symbol :tag "Bitmap")
+ (face :tag "Face"))))
-(defvar flymake-err-info nil
- "Sorted list of line numbers and lists of err info in the form (file, err-text).")
-(make-variable-buffer-local 'flymake-err-info)
+(defcustom flymake-fringe-indicator-position 'left-fringe
+ "The position to put flymake fringe indicator.
+The value can be nil (do not use indicators), `left-fringe' or `right-fringe'.
+See `flymake-error-bitmap' and `flymake-warning-bitmap'."
+ :group 'flymake
+ :version "24.3"
+ :type '(choice (const left-fringe)
+ (const right-fringe)
+ (const :tag "No fringe indicators" nil)))
-(defvar flymake-new-err-info nil
- "Same as `flymake-err-info', effective when a syntax check is in progress.")
-(make-variable-buffer-local 'flymake-new-err-info)
-
-;;;; [[ cross-emacs compatibility routines
-(defsubst flymake-makehash (&optional test)
- "Create and return a new hash table using TEST to compare keys.
-It uses the function `make-hash-table' to make a hash-table if
-you use GNU Emacs, otherwise it uses `makehash'."
- (if (fboundp 'make-hash-table)
- (if test (make-hash-table :test test) (make-hash-table))
- (with-no-warnings
- (makehash test))))
-
-(defalias 'flymake-float-time
- (if (fboundp 'float-time)
- 'float-time
- (if (featurep 'xemacs)
- (lambda ()
- (multiple-value-bind (s0 s1 s2) (values-list (current-time))
- (+ (* (float (ash 1 16)) s0) (float s1) (* 0.0000001 s2)))))))
-
-(defalias 'flymake-replace-regexp-in-string
- (if (eval-when-compile (fboundp 'replace-regexp-in-string))
- 'replace-regexp-in-string
- (lambda (regexp rep str)
- (replace-in-string str regexp rep))))
-
-(defalias 'flymake-split-string
- (if (condition-case nil (equal (split-string " bc " " " t) '("bc"))
- (error nil))
- (lambda (str pattern) (split-string str pattern t))
- (lambda (str pattern)
- "Split STR into a list of substrings bounded by PATTERN.
-Zero-length substrings at the beginning and end of the list are omitted."
- (let ((split (split-string str pattern)))
- (while (equal (car split) "") (setq split (cdr split)))
- (setq split (nreverse split))
- (while (equal (car split) "") (setq split (cdr split)))
- (nreverse split)))))
-
-(defalias 'flymake-get-temp-dir
- (if (fboundp 'temp-directory)
- 'temp-directory
- (lambda () temporary-file-directory)))
-
-(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."
- (unless window (setq window (selected-window)))
- (unless position (setq position (window-point window)))
- (unless dx (setq dx 0))
- (unless dy (setq dy 0))
-
- (let* ((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)))
-
-(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'."
- (if (featurep 'xemacs)
- (let* ((pos (flymake-get-point-pixel-pos))
- (x-pos (nth 0 pos))
- (y-pos (nth 1 pos))
- (fake-event-props '(button 1 x 1 y 1)))
- (setq fake-event-props (plist-put fake-event-props 'x x-pos))
- (setq fake-event-props (plist-put fake-event-props 'y y-pos))
- (popup-menu (flymake-make-xemacs-menu menu-data)
- (make-event 'button-press fake-event-props)))
- (x-popup-menu (if (eval-when-compile (fboundp 'posn-at-point))
- (flymake-posn-at-point-as-event)
- (list (flymake-get-point-pixel-pos) (selected-window)))
- (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))))
-
-(if (featurep 'xemacs) (progn
-
-(defun flymake-nop ()
- "Do nothing."
- nil)
-
-(defun flymake-make-xemacs-menu (menu-data)
- "Return a menu specifier using MENU-DATA."
- (let* ((menu-title (nth 0 menu-data))
- (menu-items (nth 1 menu-data))
- (menu-commands nil))
- (setq menu-commands (mapcar (lambda (foo)
- (vector (nth 0 foo) (or (nth 1 foo) '(flymake-nop)) t))
- menu-items))
- (cons menu-title menu-commands)))
-
-)) ;; xemacs
-
-(unless (eval-when-compile (fboundp 'posn-at-point))
-
-(defun flymake-current-row ()
- "Return current row number in current frame."
- (if (fboundp 'window-edges)
- (+ (car (cdr (window-edges))) (count-lines (window-start) (point)))
- (count-lines (window-start) (point))))
-
-(defun flymake-selected-frame ()
- "Return the frame that is now selected."
- (if (fboundp 'window-edges)
- (selected-frame)
- (selected-window)))
-
-(defun flymake-get-point-pixel-pos ()
- "Return point position in pixels: (x, y)."
- (let ((mouse-pos (mouse-position))
- (pixel-pos nil)
- (ret nil))
- (if (car (cdr mouse-pos))
- (progn
- (set-mouse-position (flymake-selected-frame) (current-column) (flymake-current-row))
- (setq pixel-pos (mouse-pixel-position))
- (set-mouse-position (car mouse-pos) (car (cdr mouse-pos)) (cdr (cdr mouse-pos)))
- (setq ret (list (car (cdr pixel-pos)) (cdr (cdr pixel-pos)))))
- (progn
- (setq ret '(0 0))))
- (flymake-log 3 "mouse pos is %s" ret)
- ret))
+(defcustom flymake-compilation-prevents-syntax-check t
+ "If non-nil, don't start syntax check if compilation is running."
+ :group 'flymake
+ :type 'boolean)
-) ;; End of (unless (fboundp 'posn-at-point)
+(defcustom flymake-start-syntax-check-on-newline t
+ "Start syntax check if newline char was added/removed from the buffer."
+ :group 'flymake
+ :type 'boolean)
-;;;; ]]
+(defcustom flymake-no-changes-timeout 0.5
+ "Time to wait after last change before starting compilation."
+ :group 'flymake
+ :type 'number)
+
+(defcustom flymake-gui-warnings-enabled t
+ "Enables/disables GUI warnings."
+ :group 'flymake
+ :type 'boolean)
+
+(defcustom flymake-start-syntax-check-on-find-file t
+ "Start syntax check on find file."
+ :group 'flymake
+ :type 'boolean)
(defcustom flymake-log-level -1
"Logging level, only messages with level lower or equal will be logged.
:group 'flymake
:type 'integer)
-
-;; (defcustom flymake-log-file-name "~/flymake.log"
-;; "Where to put the flymake log if logging is enabled.
-;;
-;; See `flymake-log-level' if you want to control what is logged."
-;; :group 'flymake
-;; :type 'string)
-
-(defun flymake-log (level text &rest args)
- "Log a message at level LEVEL.
-If LEVEL is higher than `flymake-log-level', the message is
-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)))
- (message "%s" msg)
- ;;(with-temp-buffer
- ;; (insert msg)
- ;; (insert "\n")
- ;; (flymake-save-buffer-in-file "~/flymake.log") ; make log file name customizable
- ;;)
- )))
-
-(defun flymake-ins-after (list pos val)
- "Insert VAL into LIST after position POS.
-POS counts from zero."
- (let ((tmp (copy-sequence list)))
- (setcdr (nthcdr pos tmp) (cons val (nthcdr (1+ pos) tmp)))
- tmp))
-
-(defun flymake-set-at (list pos val)
- "Set VAL at position POS in LIST.
-POS counts from zero."
- (let ((tmp (copy-sequence list)))
- (setcar (nthcdr pos tmp) val)
- tmp))
-
-(defvar flymake-processes nil
- "List of currently active flymake processes.")
-
-(defvar flymake-output-residual nil)
-(make-variable-buffer-local 'flymake-output-residual)
-
-(defgroup flymake nil
- "Universal on-the-fly syntax checker."
- :version "23.1"
- :group 'tools)
-
(defcustom flymake-xml-program
(if (executable-find "xmlstarlet") "xmlstarlet" "xml")
"Program to use for XML validation."
:group 'flymake
:version "24.4")
+(defcustom flymake-master-file-dirs '("." "./src" "./UnitTest")
+ "Dirs where to look for master files."
+ :group 'flymake
+ :type '(repeat (string)))
+
+(defcustom flymake-master-file-count-limit 32
+ "Max number of master files to check."
+ :group 'flymake
+ :type 'integer)
+
(defcustom flymake-allowed-file-name-masks
'(("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'" flymake-simple-make-init)
("\\.xml\\'" flymake-xml-init)
(const :tag "flymake-get-real-file-name" nil)
function))))
+(defvar-local flymake-is-running nil
+ "If t, flymake syntax check process is running for the current buffer.")
+
+(defvar-local flymake-timer nil
+ "Timer for starting syntax check.")
+
+(defvar-local flymake-last-change-time nil
+ "Time of last buffer change.")
+
+(defvar-local flymake-check-start-time nil
+ "Time at which syntax check was started.")
+
+(defvar-local flymake-check-was-interrupted nil
+ "Non-nil if syntax check was killed by `flymake-compile'.")
+
+(defvar-local flymake-err-info nil
+ "Sorted list of line numbers and lists of err info in the form (file, err-text).")
+
+(defvar-local flymake-new-err-info nil
+ "Same as `flymake-err-info', effective when a syntax check is in progress.")
+
+(defun flymake-log (level text &rest args)
+ "Log a message at level LEVEL.
+If LEVEL is higher than `flymake-log-level', the message is
+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-message text args)))
+ (message "%s" msg))))
+
+(defun flymake-ins-after (list pos val)
+ "Insert VAL into LIST after position POS.
+POS counts from zero."
+ (let ((tmp (copy-sequence list)))
+ (setcdr (nthcdr pos tmp) (cons val (nthcdr (1+ pos) tmp)))
+ tmp))
+
+(defun flymake-set-at (list pos val)
+ "Set VAL at position POS in LIST.
+POS counts from zero."
+ (let ((tmp (copy-sequence list)))
+ (setcar (nthcdr pos tmp) val)
+ tmp))
+
+(defvar flymake-processes nil
+ "List of currently active flymake processes.")
+
+(defvar-local flymake-output-residual nil)
+
(defun flymake-get-file-name-mode-and-masks (file-name)
"Return the corresponding entry from `flymake-allowed-file-name-masks'."
(unless (stringp file-name)
'flymake-simple-cleanup))
(defun flymake-get-real-file-name-function (file-name)
- (or (nth 4 (flymake-get-file-name-mode-and-masks file-name))
+ (or (nth 2 (flymake-get-file-name-mode-and-masks file-name))
'flymake-get-real-file-name))
-(defvar flymake-find-buildfile-cache (flymake-makehash 'equal))
+(defvar flymake-find-buildfile-cache (make-hash-table :test #'equal))
(defun flymake-get-buildfile-from-cache (dir-name)
"Look up DIR-NAME in cache and return its associated value.
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))
(equal (flymake-fix-file-name file-name-one)
(flymake-fix-file-name file-name-two)))
-(defcustom flymake-master-file-dirs '("." "./src" "./UnitTest")
- "Dirs where to look for master files."
- :group 'flymake
- :type '(repeat (string)))
-
-(defcustom flymake-master-file-count-limit 32
- "Max number of master files to check."
- :group 'flymake
- :type 'integer)
-
;; This is bound dynamically to pass a parameter to a sort predicate below
(defvar flymake-included-file-name)
(file-name-base file-one))
(not (equal file-one file-two))))
-(defcustom flymake-check-file-limit 8192
+(defvar flymake-check-file-limit 8192
"Maximum number of chars to look at when checking possible master file.
-Nil means search the entire file."
- :group 'flymake
- :type '(choice (const :tag "No limit" nil)
- (integer :tag "Characters")))
+Nil means search the entire file.")
(defun flymake-check-patch-master-file-buffer
(master-file-temp-buffer
(flymake-log 2 "found master file %s" master-file-name))
found))
+;;; XXX: remove
(defun flymake-replace-region (beg end rep)
"Replace text in BUFFER in region (BEG END) with REP."
(save-excursion
(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."
(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 (flymake-count-lines)))
- (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
- (- (flymake-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."
"Determine whether overlay OV was created by flymake."
(and (overlayp ov) (overlay-get ov 'flymake-overlay)))
-(defcustom flymake-error-bitmap '(exclamation-mark error)
- "Bitmap (a symbol) 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. For possible bitmap
-symbols, see `fringe-bitmaps'. See also `flymake-warning-bitmap'.
-
-The option `flymake-fringe-indicator-position' controls how and where
-this is used."
- :group 'flymake
- :version "24.3"
- :type '(choice (symbol :tag "Bitmap")
- (list :tag "Bitmap and face"
- (symbol :tag "Bitmap")
- (face :tag "Face"))))
-
-(defcustom flymake-warning-bitmap 'question-mark
- "Bitmap (a symbol) 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. For possible bitmap
-symbols, see `fringe-bitmaps'. See also `flymake-error-bitmap'.
-
-The option `flymake-fringe-indicator-position' controls how and where
-this is used."
- :group 'flymake
- :version "24.3"
- :type '(choice (symbol :tag "Bitmap")
- (list :tag "Bitmap and face"
- (symbol :tag "Bitmap")
- (face :tag "Face"))))
-
-(defcustom flymake-fringe-indicator-position 'left-fringe
- "The position to put flymake fringe indicator.
-The value can be nil (do not use indicators), `left-fringe' or `right-fringe'.
-See `flymake-error-bitmap' and `flymake-warning-bitmap'."
- :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)
+(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
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)
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."
(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))
Return last one as residual if it does not end with newline char.
Returns ((LINES) RESIDUAL)."
(when (and output (> (length output) 0))
- (let* ((lines (flymake-split-string output "[\n\r]+"))
+ (let* ((lines (split-string output "[\n\r]+" t))
(complete (equal "\n" (char-to-string (aref output (1- (length output))))))
(residual nil))
(when (not complete)
(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)
("\\(?: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))
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))
-;;)
-
-(defvar flymake-warning-re "^[wW]arning"
- "Regexp matching against err-text to detect a warning.")
+(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.
+Takes a single argument, the error's text and should return non-nil
+if it's a warning.
+Instead of a function, it can also be a regular expression.")
(defun flymake-parse-line (line)
"Parse LINE to see if it is an error or warning.
(line-idx (nth 2 (car patterns))))
(setq raw-file-name (if file-idx (match-string file-idx line) nil))
- (setq line-no (if line-idx (string-to-number (match-string line-idx line)) 0))
+ (setq line-no (if line-idx (string-to-number
+ (match-string line-idx line)) 0))
(setq err-text (if (> (length (car patterns)) 4)
(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 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
- raw-file-name line-no err-text)
+ (flymake-patch-err-text
+ (substring line (match-end 0)))))
+ (if (null err-text)
+ (setq err-text "<no error text>")
+ (when (cond ((stringp flymake-warning-predicate)
+ (string-match flymake-warning-predicate err-text))
+ ((functionp flymake-warning-predicate)
+ (funcall flymake-warning-predicate 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 raw-file-name line-no err-text)
(setq matched t)))
(setq patterns (cdr patterns)))
(if matched
(shell-quote-argument basedir)
" DUMPVARS=INCLUDE_DIRS dumpvars"))
(output (shell-command-to-string command-line))
- (lines (flymake-split-string output "\n"))
+ (lines (split-string output "\n" t))
(count (length lines))
(idx 0)
(inc-dirs nil))
(while (and (< idx count) (not (string-match "^INCLUDE_DIRS=.*" (nth idx lines))))
(setq idx (1+ idx)))
(when (< idx count)
- (let* ((inc-lines (flymake-split-string (nth idx lines) " *-I"))
+ (let* ((inc-lines (split-string (nth idx lines) " *-I" t))
(inc-count (length inc-lines)))
(while (> inc-count 0)
(when (not (string-match "^INCLUDE_DIRS=.*" (nth (1- inc-count) inc-lines)))
- (push (flymake-replace-regexp-in-string "\"" "" (nth (1- inc-count) inc-lines)) inc-dirs))
+ (push (replace-regexp-in-string "\"" "" (nth (1- inc-count) inc-lines)) inc-dirs))
(setq inc-count (1- inc-count)))))
(flymake-add-project-include-dirs-to-cache basedir inc-dirs)
inc-dirs)))
-(defcustom flymake-get-project-include-dirs-function 'flymake-get-project-include-dirs-imp
- "Function used to get project include dirs, one parameter: basedir name."
- :group 'flymake
- :type 'function)
+(defvar flymake-get-project-include-dirs-function #'flymake-get-project-include-dirs-imp
+ "Function used to get project include dirs, one parameter: basedir name.")
(defun flymake-get-project-include-dirs (basedir)
(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 (flymake-split-string includes path-separator) nil)))
+ (if includes (split-string includes path-separator t) nil)))
-(defvar flymake-project-include-dirs-cache (flymake-makehash 'equal))
+(defvar flymake-project-include-dirs-cache (make-hash-table :test #'equal))
(defun flymake-get-project-include-dirs-from-cache (base-dir)
(gethash base-dir flymake-project-include-dirs-cache))
(error
(flymake-log 1 "Failed to delete dir %s, error ignored" dir-name))))
-(defcustom flymake-compilation-prevents-syntax-check t
- "If non-nil, don't start syntax check if compilation is running."
- :group 'flymake
- :type 'boolean)
-
(defun flymake-start-syntax-check ()
"Start syntax checking for current buffer."
(interactive)
(setq flymake-is-running t)
(setq flymake-last-change-time nil)
- (setq flymake-check-start-time (flymake-float-time))
+ (setq flymake-check-start-time (float-time))
(flymake-report-status nil "*")
(flymake-log 2 "started process %d, command=%s, dir=%s"
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)
(flymake-stop-all-syntax-checks)
(call-interactively 'compile))
-(defcustom flymake-no-changes-timeout 0.5
- "Time to wait after last change before starting compilation."
- :group 'flymake
- :type 'number)
-
(defun flymake-on-timer-event (buffer)
"Start a syntax check for buffer BUFFER if necessary."
(when (buffer-live-p buffer)
(with-current-buffer buffer
(when (and (not flymake-is-running)
flymake-last-change-time
- (> (- (flymake-float-time) flymake-last-change-time)
+ (> (- (float-time) flymake-last-change-time)
flymake-no-changes-timeout))
(setq flymake-last-change-time nil)
(flymake-log 3 "starting syntax check as more than 1 second passed since last change")
(flymake-start-syntax-check)))))
-(defun flymake-current-line-no ()
- "Return number of current line in current buffer."
- (count-lines (point-min) (if (eobp) (point) (1+ (point)))))
-
-(defun flymake-count-lines ()
- "Return number of lines in buffer BUFFER."
- (count-lines (point-min) (point-max)))
-
-(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 (flymake-current-line-no))
- (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."
(forward-line (1- line))))
;; flymake minor mode declarations
-(defvar flymake-mode-line nil)
-
-(make-variable-buffer-local 'flymake-mode-line)
-
-(defvar flymake-mode-line-e-w nil)
-
-(make-variable-buffer-local 'flymake-mode-line-e-w)
-
-(defvar flymake-mode-line-status nil)
-
-(make-variable-buffer-local 'flymake-mode-line-status)
+(defvar-local flymake-mode-line nil)
+(defvar-local flymake-mode-line-e-w nil)
+(defvar-local flymake-mode-line-status nil)
(defun flymake-report-status (e-w &optional status)
"Show status in mode line."
"Display a warning to user."
(message-box warning))
-(defcustom flymake-gui-warnings-enabled t
- "Enables/disables GUI warnings."
- :group 'flymake
- :type 'boolean)
-
(defun flymake-report-fatal-status (status warning)
"Display a warning and switch flymake mode off."
(when flymake-gui-warnings-enabled
(flymake-log 0 "switched OFF Flymake mode for buffer %s due to fatal status %s, warning %s"
(buffer-name) status warning))
-(defcustom flymake-start-syntax-check-on-find-file t
- "Start syntax check on find file."
- :group 'flymake
- :type 'boolean)
-
;;;###autoload
-(define-minor-mode flymake-mode
- "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."
+(define-minor-mode flymake-mode nil
:group 'flymake :lighter flymake-mode-line
(cond
(flymake-mode 0)
(flymake-log 1 "flymake mode turned OFF for buffer %s" (buffer-name)))
-(defcustom flymake-start-syntax-check-on-newline t
- "Start syntax check if newline char was added/removed from the buffer."
- :group 'flymake
- :type 'boolean)
-
(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))
+ ;;+(flymake-log 0 "setting change time to %s" (float-time))
(let((new-text (buffer-substring start stop)))
(when (and flymake-start-syntax-check-on-newline (equal new-text "\n"))
(flymake-log 3 "starting syntax check as new-line has been seen")
(flymake-start-syntax-check))
- (setq flymake-last-change-time (flymake-float-time))))
+ (setq flymake-last-change-time (float-time))))
(defun flymake-after-save-hook ()
(if (local-variable-p 'flymake-mode (current-buffer)) ; (???) other way to determine whether flymake is active in buffer being saved?
(defun flymake-goto-next-error ()
"Go to next error in err ring."
(interactive)
- (let ((line-no (flymake-get-next-err-line-no flymake-err-info (flymake-current-line-no))))
+ (let ((line-no (flymake-get-next-err-line-no flymake-err-info (line-number-at-pos))))
(when (not line-no)
(setq line-no (flymake-get-first-err-line-no flymake-err-info))
(flymake-log 1 "passed end of file"))
(defun flymake-goto-prev-error ()
"Go to previous error in err ring."
(interactive)
- (let ((line-no (flymake-get-prev-err-line-no flymake-err-info (flymake-current-line-no))))
+ (let ((line-no (flymake-get-prev-err-line-no flymake-err-info (line-number-at-pos))))
(when (not line-no)
(setq line-no (flymake-get-last-err-line-no flymake-err-info))
(flymake-log 1 "passed beginning of file"))
;; trying to remove the leading / of absolute file names.
(slash-pos (string-match "/" dir))
(temp-dir (expand-file-name (substring dir (1+ slash-pos))
- (flymake-get-temp-dir))))
+ temporary-file-directory)))
(file-truename (expand-file-name (file-name-nondirectory file-name)
temp-dir))))
(defun flymake-delete-temp-directory (dir-name)
"Attempt to delete temp dir created by `flymake-create-temp-with-folder-structure', do not fail on error."
- (let* ((temp-dir (flymake-get-temp-dir))
+ (let* ((temp-dir temporary-file-directory)
(suffix (substring dir-name (1+ (length temp-dir)))))
(while (> (length suffix) 0)
(file-truename (expand-file-name suffix temp-dir)))
(setq suffix (file-name-directory suffix)))))
-(defvar flymake-temp-source-file-name nil)
-(make-variable-buffer-local 'flymake-temp-source-file-name)
-
-(defvar flymake-master-file-name nil)
-(make-variable-buffer-local 'flymake-master-file-name)
-
-(defvar flymake-temp-master-file-name nil)
-(make-variable-buffer-local 'flymake-temp-master-file-name)
-
-(defvar flymake-base-dir nil)
-(make-variable-buffer-local 'flymake-base-dir)
+(defvar-local flymake-temp-source-file-name nil)
+(defvar-local flymake-master-file-name nil)
+(defvar-local flymake-temp-master-file-name nil)
+(defvar-local flymake-base-dir nil)
(defun flymake-init-create-temp-buffer-copy (create-temp-f)
"Make a temporary copy of the current buffer, save its name in buffer data and return the name."
'flymake-create-temp-inplace))))
(provide 'flymake)
-
;;; flymake.el ends here