From: Andreas Gerler Date: Sun, 26 Apr 2026 17:50:27 +0000 (+0200) Subject: update flymake X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=93f3bef9f95f746ea91e92e9bf7c046fea7d5375;p=emacsconfig.git update flymake --- diff --git a/elpa/flymake-1.4.1.signed b/elpa/flymake-1.4.1.signed deleted file mode 100644 index bbcbb78c..00000000 --- a/elpa/flymake-1.4.1.signed +++ /dev/null @@ -1 +0,0 @@ -Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) (trust undefined) created at 2025-04-23T11:05:01+0200 using EDDSA \ No newline at end of file diff --git a/elpa/flymake-1.4.1/flymake-autoloads.el b/elpa/flymake-1.4.1/flymake-autoloads.el deleted file mode 100644 index 0b5cfea9..00000000 --- a/elpa/flymake-1.4.1/flymake-autoloads.el +++ /dev/null @@ -1,138 +0,0 @@ -;;; flymake-autoloads.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*- -;; Generated by the `loaddefs-generate' function. - -;; This file is part of GNU Emacs. - -;;; Code: - -(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path))) - - - -;;; Generated autoloads from flymake.el - -(autoload 'flymake-log "flymake" "\ -Log, at level LEVEL, the message MSG formatted with ARGS. -LEVEL is passed to `display-warning', which is used to display -the warning. If this form is included in a file, -the generated warning contains an indication of the file that -generated it. - -(fn LEVEL MSG &rest ARGS)" nil t) -(autoload 'flymake-make-diagnostic "flymake" "\ -Make a Flymake diagnostic for LOCUS's region from BEG to END. -LOCUS is a buffer object or a string designating a file name. - -TYPE is a diagnostic symbol (see Info Node `(Flymake)Flymake error -types') - -INFO is a description of the problem detected. It may be a string, or -list (ORIGIN CODE MESSAGE) appropriately categorizing and describing the -diagnostic. ORIGIN may be a string or nil. CODE maybe be a string, a -number or nil. MESSAGE must be a string. - -DATA is any object that the caller wishes to attach to the created -diagnostic for later retrieval with `flymake-diagnostic-data'. - -If LOCUS is a buffer, BEG and END should be buffer positions inside it. -If LOCUS designates a file, BEG and END should be a cons (LINE . COL) -indicating a file position. In this second case, END may be omitted in -which case the region is computed using `flymake-diag-region' if the -diagnostic is appended to an actual buffer. - -OVERLAY-PROPERTIES is an alist of properties attached to the created -diagnostic, overriding the default properties and any properties listed -in the `flymake-overlay-control' property of the diagnostic's type -symbol. - -(fn LOCUS BEG END TYPE INFO &optional DATA OVERLAY-PROPERTIES)") -(autoload 'flymake-diagnostics "flymake" "\ -Get Flymake diagnostics in region determined by BEG and END. - -If neither BEG or END is supplied, use whole accessible buffer, -otherwise if BEG is non-nil and END is nil, consider only -diagnostics at BEG. - -(fn &optional BEG END)") -(autoload 'flymake-diag-region "flymake" "\ -Compute BUFFER's region (BEG . END) corresponding to LINE and COL. -If COL is nil, return a region just for LINE. Return nil if the -region is invalid. This function saves match data. - -(fn BUFFER LINE &optional COL)") -(autoload 'flymake-mode "flymake" "\ -Toggle Flymake mode on or off. - -Flymake is an Emacs minor mode for on-the-fly syntax checking. -Flymake collects diagnostic information from multiple sources, -called backends, and visually annotates the buffer with the -results. - -Flymake performs these checks while the user is editing. -The customization variables `flymake-start-on-flymake-mode', -`flymake-no-changes-timeout' determine the exact circumstances -whereupon Flymake decides to initiate a check of the buffer. - -The commands `flymake-goto-next-error' and -`flymake-goto-prev-error' can be used to navigate among Flymake -diagnostics annotated in the buffer. - -By default, `flymake-mode' doesn't override the \\[next-error] command, but -if you're using Flymake a lot (and don't use the regular compilation -mechanisms that often), it can be useful to put something like -the following in your init file: - - (setq next-error-function \\='flymake-goto-next-error) - -The visual appearance of each type of diagnostic can be changed -by setting properties `flymake-overlay-control', `flymake-bitmap' -and `flymake-severity' on the symbols of diagnostic types (like -`:error', `:warning' and `:note'). - -Activation or deactivation of backends used by Flymake in each -buffer happens via the special hook -`flymake-diagnostic-functions'. - -Some backends may take longer than others to respond or complete, -and some may decide to disable themselves if they are not -suitable for the current buffer. The commands -`flymake-running-backends', `flymake-disabled-backends' and -`flymake-reporting-backends' summarize the situation, as does the -special *Flymake log* buffer. - -This is a minor mode. If called interactively, toggle the `Flymake -mode' mode. If the prefix argument is positive, enable the mode, and if -it is zero or negative, disable the mode. - -If called from Lisp, toggle the mode if ARG is `toggle'. Enable the -mode if ARG is nil, omitted, or is a positive number. Disable the mode -if ARG is a negative number. - -To check whether the minor mode is enabled in the current buffer, -evaluate the variable `flymake-mode'. - -The mode's hook is called both when the mode is enabled and when it is -disabled. - -\\{flymake-mode-map} - -(fn &optional ARG)" t) -(autoload 'flymake-mode-on "flymake" "\ -Turn Flymake mode on.") -(autoload 'flymake-mode-off "flymake" "\ -Turn Flymake mode off.") -(register-definition-prefixes "flymake" '("flymake-")) - -;;; End of scraped data - -(provide 'flymake-autoloads) - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; no-native-compile: t -;; coding: utf-8-emacs-unix -;; End: - -;;; flymake-autoloads.el ends here diff --git a/elpa/flymake-1.4.1/flymake-pkg.el b/elpa/flymake-1.4.1/flymake-pkg.el deleted file mode 100644 index 7f285b88..00000000 --- a/elpa/flymake-1.4.1/flymake-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;; Generated package description from flymake.el -*- no-byte-compile: t -*- -(define-package "flymake" "1.4.1" "A universal on-the-fly syntax checker" '((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) :commit "a25fc9a518dc1c4bf1ef86bb949ed2f3c995adea" :url "https://elpa.gnu.org/packages/flymake.html" :authors '(("Pavel Kobyakov" . "pk_at_work@yahoo.com")) :maintainer '("Spencer Baugh" . "sbaugh@janestreet.com") :keywords '("c" "languages" "tools")) diff --git a/elpa/flymake-1.4.1/flymake.el b/elpa/flymake-1.4.1/flymake.el deleted file mode 100644 index 26a7b67f..00000000 --- a/elpa/flymake-1.4.1/flymake.el +++ /dev/null @@ -1,2273 +0,0 @@ -;;; flymake.el --- A universal on-the-fly syntax checker -*- lexical-binding: t; -*- - -;; Copyright (C) 2003-2025 Free Software Foundation, Inc. - -;; Author: Pavel Kobyakov -;; Maintainer: Spencer Baugh -;; Version: 1.4.1 -;; Keywords: c languages tools -;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) - -;; This is a GNU ELPA :core package. Avoid functionality that is not -;; compatible with the version of Emacs recorded above. - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: -;; -;; Flymake is a minor Emacs mode performing on-the-fly syntax checks. -;; -;; Flymake collects diagnostic information for multiple sources, -;; called backends, and visually annotates the relevant portions in -;; the buffer. -;; -;; This file contains the UI for displaying and interacting with the -;; results produced by these backends, as well as entry points for -;; backends to hook on to. -;; -;; The main interactive entry point is the `flymake-mode' minor mode, -;; which periodically and automatically initiates checks as the user -;; is editing the buffer. The variables `flymake-no-changes-timeout', -;; `flymake-start-on-flymake-mode' give finer control over the events -;; triggering a check, as does the interactive command `flymake-start', -;; which immediately starts a check. -;; -;; Shortly after each check, a summary of collected diagnostics should -;; appear in the mode-line. If it doesn't, there might not be a -;; suitable Flymake backend for the current buffer's major mode, in -;; which case Flymake will indicate this in the mode-line. The -;; indicator will be `!' (exclamation mark), if all the configured -;; backends errored (or decided to disable themselves) and `?' -;; (question mark) if no backends were even configured. -;; -;; For programmers interested in writing a new Flymake backend, the -;; docstring of `flymake-diagnostic-functions', the Flymake manual, and the -;; code of existing backends are probably good starting points. -;; -;; The user wishing to customize the appearance of error types should -;; set properties on the symbols associated with each diagnostic type. -;; The standard diagnostic symbols are `:error', `:warning' and -;; `:note' (though a specific backend may define and use more). The -;; following properties can be set: -;; -;; * `flymake-bitmap', an image displayed in the fringe according to -;; `flymake-fringe-indicator-position'. The value actually follows -;; the syntax of `flymake-error-bitmap' (which see). It is overridden -;; by any `before-string' overlay property. -;; -;; * `flymake-severity', a non-negative integer specifying the -;; diagnostic's severity. The higher, the more serious. If the -;; overlay property `priority' is not specified, `severity' is used to -;; set it and help sort overlapping overlays. -;; -;; * `flymake-overlay-control', an alist ((OVPROP . VALUE) ...) of -;; further properties used to affect the appearance of Flymake -;; annotations. With the exception of `category' and `evaporate', -;; these properties are applied directly to the created overlay. See -;; Info Node `(elisp)Overlay Properties'. -;; -;; * `flymake-category', a symbol whose property list is considered a -;; default for missing values of any other properties. This is useful -;; to backend authors when creating new diagnostic types that differ -;; from an existing type by only a few properties. The category -;; symbols `flymake-error', `flymake-warning' and `flymake-note' make -;; good candidates for values of this property. -;; -;; For instance, to omit the fringe bitmap displayed for the standard -;; `:note' type, set its `flymake-bitmap' property to nil: -;; -;; (put :note 'flymake-bitmap nil) -;; -;; To change the face for `:note' type, add a `face' entry to its -;; `flymake-overlay-control' property. -;; -;; (push '(face . highlight) (get :note 'flymake-overlay-control)) -;; -;; If you push another alist entry in front, it overrides the previous -;; one. So this effectively removes the face from `:note' -;; diagnostics. -;; -;; (push '(face . nil) (get :note 'flymake-overlay-control)) -;; -;; To erase customizations and go back to the original look for -;; `:note' types: -;; -;; (cl-remf (symbol-plist :note) 'flymake-overlay-control) -;; (cl-remf (symbol-plist :note) 'flymake-bitmap) -;; -;;; Code: - -(require 'cl-lib) -(require 'thingatpt) ; end-of-thing -(require 'warnings) ; warning-numeric-level, display-warning -(require 'compile) ; for some faces -;; We need the next `require' to avoid compiler warnings and run-time -;; errors about mouse-wheel-up/down-event in builds --without-x, where -;; mwheel is not preloaded. -(require 'mwheel) -;; when-let*, if-let*, hash-table-keys, hash-table-values: -(eval-when-compile (require 'subr-x)) -(require 'project) - -(defgroup flymake nil - "Universal on-the-fly syntax checker." - :version "23.1" - :link '(custom-manual "(flymake) Top") - :group 'tools) - -(add-to-list 'customize-package-emacs-version-alist - '(Flymake ("1.3.4" . "30.1") - ("1.3.5" . "30.1") - ("1.3.6" . "30.1"))) - -(defcustom flymake-error-bitmap '(flymake-double-exclamation-mark - compilation-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." - :version "24.3" - :type '(choice (symbol :tag "Bitmap") - (list :tag "Bitmap and face" - (symbol :tag "Bitmap") - (face :tag "Face")))) - -(defcustom flymake-warning-bitmap '(exclamation-mark compilation-warning) - "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." - :version "24.3" - :type '(choice (symbol :tag "Bitmap") - (list :tag "Bitmap and face" - (symbol :tag "Bitmap") - (face :tag "Face")))) - -(defcustom flymake-note-bitmap '(exclamation-mark compilation-info) - "Bitmap (a symbol) used in the fringe for indicating info notes. -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." - :version "26.1" - :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'." - :version "24.3" - :type '(choice (const left-fringe) - (const right-fringe) - (const :tag "No fringe indicators" nil))) - -(defcustom flymake-indicator-type 'fringes - "Indicate which indicator type to use for display errors. - -The value can be nil (don't indicate errors but just highlight them), -the symbol `fringes' (use fringes) or the symbol `margins' (use -margins). - -Difference between fringes and margin is that fringes support displaying -bitmaps on graphical displays and margins display text in a blank area -from current buffer that works in both graphical and text displays. -Thus, even when `fringes' is selected, margins will still be used on -text displays and also when fringes are disabled. - -See Info node `Fringes' and Info node `(elisp)Display Margins'." - :version "31.1" - :type '(choice (const :tag "Use Fringes" fringes) - (const :tag "Use Margins" margins) - (const :tag "No indicators" nil))) - -(defcustom flymake-margin-indicators-string - '((error "!!" compilation-error) - (warning "!" compilation-warning) - (note "!" compilation-info)) - "Strings used for margins indicators. -The value of each list may be a list of 3 elements where specifies the -error type, the string to use and its face, -or a list of 2 elements specifying only the error type and -the corresponding string. - -The option `flymake-margin-indicator-position' controls how and where -this is used." - :version "30.1" - :type '(repeat :tag "Error types lists" - (list :tag "String and face for error types" - (symbol :tag "Error type") - (string :tag "String") - (face :tag "Face")))) - -(defcustom flymake-autoresize-margins t - "If non-nil, automatically resize margin-width calling `flymake--resize-margins'. - -Only relevant if `flymake-indicator-type' is set to margins." - :version "30.1" - :type 'boolean) - -(defcustom flymake-margin-indicator-position 'left-margin - "The position to put Flymake margin indicator. -The value can be nil (do not use indicators), `left-margin' or `right-margin'. -See `flymake-margin-indicators-string'." - :version "30.1" - :type '(choice (const left-margin) - (const right-margin) - (const :tag "No margin indicators" nil))) - -(make-obsolete-variable 'flymake-start-syntax-check-on-newline - "can check on newline in post-self-insert-hook" - "27.1") - -(defcustom flymake-no-changes-timeout 0.5 - "Time to wait after last change before automatically checking buffer. -If nil, never start checking buffer automatically like this." - :type '(choice (number :tag "Timeout in seconds") - (const :tag "No check on timeout" nil))) - -(defcustom flymake-gui-warnings-enabled t - "Enables/disables GUI warnings." - :type 'boolean) -(make-obsolete-variable 'flymake-gui-warnings-enabled - "it no longer has any effect." "26.1") - -(define-obsolete-variable-alias 'flymake-start-syntax-check-on-find-file - 'flymake-start-on-flymake-mode "26.1") - -(defcustom flymake-start-on-flymake-mode t - "If non-nil, start syntax check when `flymake-mode' is enabled. -Specifically, start it when the buffer is actually displayed." - :version "26.1" - :type 'boolean) - -(defcustom flymake-start-on-save-buffer t - "If non-nil, start syntax check when a buffer is saved. -Specifically, start it when the saved buffer is actually displayed." - :version "27.1" - :type 'boolean) - -(defcustom flymake-log-level -1 - "Obsolete and ignored variable." - :type 'integer) -(make-obsolete-variable 'flymake-log-level - "it is superseded by `warning-minimum-log-level.'" - "26.1") - -(defcustom flymake-wrap-around t - "If non-nil, moving to errors wraps around buffer boundaries." - :version "26.1" - :type 'boolean) - -(defcustom flymake-suppress-zero-counters :warning - "Control appearance of zero-valued diagnostic counters in mode line. - -If set to t, suppress all zero counters. If set to a severity -symbol like `:warning' (the default) suppress zero counters less -severe than that severity, according to `warning-numeric-level'. -If set to nil, don't suppress any zero counters." - :type 'symbol) - -(when (fboundp 'define-fringe-bitmap) - (define-fringe-bitmap 'flymake-double-exclamation-mark - (vector #b00000000 - #b00000000 - #b00000000 - #b00000000 - #b01100110 - #b01100110 - #b01100110 - #b01100110 - #b01100110 - #b01100110 - #b01100110 - #b01100110 - #b00000000 - #b01100110 - #b00000000 - #b00000000 - #b00000000))) - -(defvar-local flymake-timer nil - "Timer for starting syntax check.") - -(defvar-local flymake-check-start-time nil - "Time at which syntax check was started.") - -(defvar-local flymake--original-margin-width nil - "Store original margin width. -Used by `flymake--resize-margins' for restoring original margin width -when flymake is turned off.") - -(defun flymake--log-1 (level sublog msg &rest args) - "Do actual work for `flymake-log'." - (let (;; never popup the log buffer - (warning-minimum-level :emergency) - (warning-type-format - (format " [%s %s]" - (or sublog 'flymake) - ;; Handle file names with "%" correctly. (Bug#51549) - (replace-regexp-in-string "%" "%%" - (buffer-name (current-buffer)))))) - (display-warning (list 'flymake sublog) - (apply #'format-message msg args) - (if (numberp level) - (or (nth level - '(:emergency :error :warning :debug :debug) ) - :error) - level) - "*Flymake log*"))) - -(defun flymake-switch-to-log-buffer () - "Go to the *Flymake log* buffer." - (interactive) - (switch-to-buffer "*Flymake log*")) - -;;;###autoload -(defmacro flymake-log (level msg &rest args) - "Log, at level LEVEL, the message MSG formatted with ARGS. -LEVEL is passed to `display-warning', which is used to display -the warning. If this form is included in a file, -the generated warning contains an indication of the file that -generated it." - (let* ((file (if (fboundp 'macroexp-file-name) - (macroexp-file-name) - (and (not load-file-name) - (bound-and-true-p byte-compile-current-file)))) - (sublog (if (stringp file) - (intern - (file-name-nondirectory - (file-name-sans-extension file)))))) - `(flymake--log-1 ,level ',sublog ,msg ,@args))) - -(defun flymake-error (text &rest args) - "Format TEXT with ARGS and signal an error for Flymake." - (let ((msg (apply #'format-message text args))) - (flymake-log :error "%s" msg) - (error (concat "[Flymake] " msg)))) - -(cl-defstruct (flymake--diag - (:constructor flymake--diag-make)) - locus beg end type origin code message backend data overlay-properties overlay - ;; FIXME: See usage of these two in `flymake--highlight-line'. - ;; Ideally they wouldn't be needed. - orig-beg orig-end) - -;;;###autoload -(defun flymake-make-diagnostic (locus - beg - end - type - info - &optional data - overlay-properties) - "Make a Flymake diagnostic for LOCUS's region from BEG to END. -LOCUS is a buffer object or a string designating a file name. - -TYPE is a diagnostic symbol (see Info Node `(Flymake)Flymake error -types') - -INFO is a description of the problem detected. It may be a string, or -list (ORIGIN CODE MESSAGE) appropriately categorizing and describing the -diagnostic. ORIGIN may be a string or nil. CODE maybe be a string, a -number or nil. MESSAGE must be a string. - -DATA is any object that the caller wishes to attach to the created -diagnostic for later retrieval with `flymake-diagnostic-data'. - -If LOCUS is a buffer, BEG and END should be buffer positions inside it. -If LOCUS designates a file, BEG and END should be a cons (LINE . COL) -indicating a file position. In this second case, END may be omitted in -which case the region is computed using `flymake-diag-region' if the -diagnostic is appended to an actual buffer. - -OVERLAY-PROPERTIES is an alist of properties attached to the created -diagnostic, overriding the default properties and any properties listed -in the `flymake-overlay-control' property of the diagnostic's type -symbol." - (when (stringp locus) - (setq locus (expand-file-name locus))) - (cond ((stringp info) - (setq info (list nil nil info))) - ((numberp (cadr info)) - (setf (cadr info) (number-to-string (cadr info))))) - (flymake--diag-make :locus locus :beg beg :end end - :type type :origin (car info) :code (cadr info) - :message (caddr info) :data data - :overlay-properties overlay-properties - :orig-beg beg - :orig-end end)) - -;;;###autoload -(defun flymake-diagnostics (&optional beg end) - "Get Flymake diagnostics in region determined by BEG and END. - -If neither BEG or END is supplied, use whole accessible buffer, -otherwise if BEG is non-nil and END is nil, consider only -diagnostics at BEG." - (save-restriction - (widen) - (cl-loop for o in - (cond (end (overlays-in beg end)) - (beg (overlays-at beg)) - (t (overlays-in (point-min) (point-max)))) - when (overlay-get o 'flymake-diagnostic) collect it))) - -(defmacro flymake--diag-accessor (public internal thing) - "Make PUBLIC an alias for INTERNAL, add doc using THING." - `(defsubst ,public (diag) - ,(format "Get Flymake diagnostic DIAG's %s." (symbol-name thing)) - (,internal diag))) - -(flymake--diag-accessor flymake-diagnostic-type flymake--diag-type type) -(flymake--diag-accessor flymake-diagnostic-backend flymake--diag-backend backend) -(flymake--diag-accessor flymake-diagnostic-origin flymake--diag-origin backend) -(flymake--diag-accessor flymake-diagnostic-code flymake--diag-code backend) -(flymake--diag-accessor flymake-diagnostic-message flymake--diag-message backend) -(flymake--diag-accessor flymake-diagnostic-data flymake--diag-data data) -(flymake--diag-accessor flymake-diagnostic-beg flymake--diag-beg beg) -(flymake--diag-accessor flymake-diagnostic-end flymake--diag-end end) -(flymake--diag-accessor flymake-diagnostic-buffer flymake--diag-locus locus) - -(defcustom flymake-diagnostic-format-alist - '((:help-echo . (origin code oneliner)) - (:eol . (oneliner)) - (:eldoc . (origin code message)) - (:eldoc-echo . (origin code oneliner)) - (t . (origin code oneliner))) - "How to format diagnostics for different output destinations. -Value is an alist where each element looks like (DESTINATION . PARTS). -DESTINATION is a symbol designating an outlet. One of: - -- `:help-echo', for the native Flymake echoing of diagnostics in the - echo area as used my `flymake-goto-next-error' and `flymake-goto-prev-error'; -- `:eol', for use with `flymake-show-diagnostics-at-end-of-line'; -- `:eldoc', for use with Flymake's ElDoc backend; -- `:eldoc-echo', for use with Flymake's ElDoc backend, but for ElDoc's own - confined outlets; -- t for all other destinations. - -PARTS says which parts of the diagnostic to include. It is a list of -symbols where the following values are meaningful: - -- `origin': include diagnostic origin if it exists; -- `code': include diagnostics code if it exists; -- `message': include the full diagnostic's message text; -- `oneliner': include truncated diagnostic text;" - :package-version '(Flymake . "1.4.0") - :type '(alist :key-type (choice (const :help-echo) - (const :eol) - (const :eldoc) - (const :eldoc-echo) - (const t)) - :value-type (set (const origin) - (const code) - (const message) - (const oneliner)))) - -(cl-defun flymake-diagnostic-text (diag - &optional (parts '(origin code message))) - "Describe diagnostic DIAG's as a string. -PARTS says which parts of the diagnostic to include. It is a list of -symbols as described in `flymake-diagnostic-format-alist' (which see). -PARTS defaults to `(origin code message)'." - (let* ((w parts) - (a (and (memq 'origin w) (flymake--diag-origin diag))) - (b (and (memq 'code w) (flymake--diag-code diag))) - (c (cond ((memq 'message w) (flymake--diag-message diag)) - ((memq 'oneliner w) - (let* ((msg (flymake--diag-message diag))) - (substring msg 0 (cl-loop for i from 0 for a across msg - when (eq a ?\n) return i))))))) - (concat a - (when (and a b) " ") - (when b (concat "[" b "]")) - (when (and c (or a b)) ": ") - c))) - -(defun flymake--format-diagnostic (diag destination face-prop) - (let ((txt (flymake-diagnostic-text - diag (alist-get destination flymake-diagnostic-format-alist - (alist-get t flymake-diagnostic-format-alist - '(origin code message)))))) - (if face-prop - (propertize txt 'face - (flymake--lookup-type-property - (flymake-diagnostic-type diag) face-prop - 'flymake-error)) - txt))) - -(defun flymake-diagnostic-oneliner (diag &optional nopaintp) - "Get truncated one-line text string for diagnostic DIAG. -This is useful for displaying the DIAG's text to the user in -confined spaces, such as the echo are. Unless NOPAINTP is t, -propertize returned text with the `echo-face' property of DIAG's -type." - (let* ((txt (flymake-diagnostic-text diag '(origin code oneliner)))) - (if nopaintp txt - (propertize txt 'face - (flymake--lookup-type-property - (flymake-diagnostic-type diag) 'echo-face 'flymake-error))))) -(make-obsolete 'flymake-diagnostic-oneliner - "use `flymake-diagnostic-text' instead." - "Flymake package version 1.4.0") - -(cl-defun flymake--really-all-overlays () - "Get flymake-related overlays. -If BEG is non-nil and END is nil, consider only `overlays-at' -BEG. Otherwise consider `overlays-in' the region comprised by BEG -and END, defaulting to the whole buffer. Remove all that do not -verify FILTER, a function, and sort them by COMPARE (using KEY)." - (save-restriction - (widen) - (cl-remove-if-not (lambda (o) (overlay-get o 'flymake-overlay)) - (overlays-in (point-min) (point-max))))) - -(defface flymake-error - '((((supports :underline (:style wave))) - :underline (:style wave :color "Red1")) - (t - :inherit error)) - "Face used for marking error regions." - :version "24.4") - -(defface flymake-warning - '((((supports :underline (:style wave))) - :underline (:style wave :color "deep sky blue")) - (t - :inherit warning)) - "Face used for marking warning regions." - :version "24.4") - -(defface flymake-note - '((((supports :underline (:style wave))) - :underline (:style wave :color "yellow green")) - (t - :inherit warning)) - "Face used for marking note regions." - :version "26.1") - -(defface flymake-error-echo - '((t :inherit compilation-error)) - "Face used for showing summarized descriptions of errors." - :package-version '(Flymake . "1.3.4")) - -(defface flymake-warning-echo - '((t :inherit compilation-warning)) - "Face used for showing summarized descriptions of warnings." - :package-version '(Flymake . "1.3.4")) - -(defface flymake-note-echo - '((t :inherit compilation-info)) - "Face used for showing summarized descriptions of notes." - :package-version '(Flymake . "1.3.4")) - -(defface flymake-end-of-line-diagnostics-face - '((t :height 0.85 :box (:line-width -1))) - "Face used for end-of-line diagnostics. -See variable `flymake-show-diagnostics-at-end-of-line'." - :package-version '(Flymake . "1.3.5")) - -(defface flymake-error-echo-at-eol - '((t :inherit (flymake-end-of-line-diagnostics-face compilation-error))) - "Face like `flymake-error-echo', but for end-of-line overlays." - :package-version '(Flymake . "1.3.5")) - -(defface flymake-warning-echo-at-eol - '((t :inherit (flymake-end-of-line-diagnostics-face compilation-warning))) - "Face like `flymake-warning-echo', but for end-of-line overlays." - :package-version '(Flymake . "1.3.5")) - -(defface flymake-note-echo-at-eol - '((t :inherit (flymake-end-of-line-diagnostics-face compilation-info))) - "Face like `flymake-note-echo', but for end-of-line overlays." - :package-version '(Flymake . "1.3.5")) - -(defface flymake-eol-information-face - '((t :inherit (flymake-end-of-line-diagnostics-face) - :box nil - :slant italic)) - "Face used for information about end-of-line diagnostics." - :package-version '(Flymake . "1.3.6")) - -(defcustom flymake-show-diagnostics-at-end-of-line nil - "If non-nil, add diagnostic summary messages at end-of-line. -The value `short' means that only the most severe diagnostic -shall be shown. Any other non-nil value means show all -diagnostic summaries at end-of-line." - :type '(choice (const :tag "Display most severe diagnostic" short) - (const :tag "Display all diagnostics" t) - (const :tag "Don't display diagnostics at end-of-line" nil)) - :package-version '(Flymake . "1.3.6")) - -(define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1") -(define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1") - -;;;###autoload -(defun flymake-diag-region (buffer line &optional col) - "Compute BUFFER's region (BEG . END) corresponding to LINE and COL. -If COL is nil, return a region just for LINE. Return nil if the -region is invalid. This function saves match data." - (condition-case-unless-debug _err - (with-current-buffer buffer - (let ((line (min (max line 1) - (line-number-at-pos (point-max) 'absolute)))) - (save-excursion - (save-match-data - (goto-char (point-min)) - (forward-line (1- line)) - (cl-flet ((fallback-bol - () - (back-to-indentation) - (if (eobp) - (line-beginning-position 0) - (point))) - (fallback-eol - (beg) - (progn - (end-of-line) - (skip-chars-backward " \t\f\n" beg) - (if (eq (point) beg) - (line-beginning-position 2) - (point))))) - (if (and col (cl-plusp col)) - (let* ((beg (progn (forward-char (1- col)) - (point))) - (sexp-end (or (ignore-errors (end-of-thing 'sexp)) - (ignore-errors (end-of-thing 'symbol)))) - (end (or (and sexp-end - (not (= sexp-end beg)) - sexp-end) - (and (< (goto-char (1+ beg)) (point-max)) - (point))))) - (if end - (cons beg end) - (cons (setq beg (fallback-bol)) - (fallback-eol beg)))) - (let* ((beg (fallback-bol)) - (end (fallback-eol beg))) - (cons beg end)))))))) - (error (flymake-log :warning "Invalid region line=%s col=%s" line col) - nil))) - -(defvar flymake-diagnostic-functions nil - "Special hook of Flymake backends that check a buffer. - -The functions in this hook diagnose problems in a buffer's -contents and provide information to the Flymake user interface -about where and how to annotate problems diagnosed in a buffer. - -Each backend function must be prepared to accept an arbitrary -number of arguments: - -* the first argument is always REPORT-FN, a callback function - detailed below; - -* the remaining arguments are keyword-value pairs in the - form (:KEY VALUE :KEY2 VALUE2...). - -Currently, Flymake may provide these keyword-value pairs: - -* `:recent-changes', a list of recent changes since the last time - the backend function was called for the buffer. An empty list - indicates that no changes have been recorded. If it is the - first time that this backend function is called for this - activation of `flymake-mode', then this argument isn't provided - at all (i.e. it's not merely nil). - - Each element is in the form (BEG END TEXT) where BEG and END - are buffer positions, and TEXT is a string containing the text - contained between those positions (if any) after the change was - performed. - -* `:changes-start' and `:changes-end', the minimum and maximum - buffer positions touched by the recent changes. These are only - provided if `:recent-changes' is also provided. - -Whenever Flymake or the user decides to re-check the buffer, -backend functions are called as detailed above and are expected -to initiate this check, but aren't required to complete it before -exiting: if the computation involved is expensive, especially for -large buffers, that task can be scheduled for the future using -asynchronous processes or other asynchronous mechanisms. - -In any case, backend functions are expected to return quickly or -signal an error, in which case the backend is disabled. Flymake -will not try disabled backends again for any future checks of -this buffer. To reset the list of disabled backends, turn -`flymake-mode' off and on again, or interactively call -`flymake-start' with a prefix argument. - -If the function returns, Flymake considers the backend to be -\"running\". If it has not done so already, the backend is -expected to call the function REPORT-FN with a single argument -REPORT-ACTION also followed by an optional list of keyword-value -pairs in the form (:REPORT-KEY VALUE :REPORT-KEY2 VALUE2...). - -Currently accepted values for REPORT-ACTION are: - -* A (possibly empty) list of diagnostic objects created with - `flymake-make-diagnostic', causing Flymake to delete all - previous diagnostic annotations in the buffer and create new - ones from this list. - - A backend may call REPORT-FN repeatedly in this manner, but - only until Flymake considers that the most recently requested - buffer check is now obsolete because, say, buffer contents have - changed in the meantime. The backend is only given notice of - this via a renewed call to the backend function. Thus, to - prevent making obsolete reports and wasting resources, backend - functions should first cancel any ongoing processing from - previous calls. - -* The symbol `:panic', signaling that the backend has encountered - an exceptional situation and should be disabled. - -Currently accepted REPORT-KEY arguments are: - -* `:explanation' value should give user-readable details of - the situation encountered, if any. - -* `:force': value should be a boolean suggesting that Flymake - consider the report even if it was somehow unexpected. - -* `:region': a cons (BEG . END) of buffer positions indicating - that the report applies to that region only. Specifically, - this means that Flymake will only delete diagnostic annotations - of past reports if they intersect the region by at least one - character.") - -(put 'flymake-diagnostic-functions 'safe-local-variable #'null) - -(put :error 'flymake-category 'flymake-error) -(put :warning 'flymake-category 'flymake-warning) -(put :note 'flymake-category 'flymake-note) - -(defvar flymake-diagnostic-types-alist '()) -(make-obsolete-variable - 'flymake-diagnostic-types-alist - "Set properties on the diagnostic symbols instead. See Info -Node `(Flymake)Flymake error types'" - "27.1") - -(put 'flymake-error 'face 'flymake-error) -(put 'flymake-error 'flymake-bitmap 'flymake-error-bitmap) -(put 'flymake-error 'flymake-margin-string (alist-get 'error flymake-margin-indicators-string)) -(put 'flymake-error 'severity (warning-numeric-level :error)) -(put 'flymake-error 'mode-line-face 'flymake-error-echo) -(put 'flymake-error 'echo-face 'flymake-error-echo) -(put 'flymake-error 'eol-face 'flymake-error-echo-at-eol) -(put 'flymake-error 'flymake-type-name "error") - -(put 'flymake-warning 'face 'flymake-warning) -(put 'flymake-warning 'flymake-bitmap 'flymake-warning-bitmap) -(put 'flymake-warning 'flymake-margin-string (alist-get 'warning flymake-margin-indicators-string)) -(put 'flymake-warning 'severity (warning-numeric-level :warning)) -(put 'flymake-warning 'mode-line-face 'flymake-warning-echo) -(put 'flymake-warning 'echo-face 'flymake-warning-echo) -(put 'flymake-warning 'eol-face 'flymake-warning-echo-at-eol) -(put 'flymake-warning 'flymake-type-name "warning") - -(put 'flymake-note 'face 'flymake-note) -(put 'flymake-note 'flymake-bitmap 'flymake-note-bitmap) -(put 'flymake-note 'flymake-margin-string (alist-get 'note flymake-margin-indicators-string)) -(put 'flymake-note 'severity (warning-numeric-level :debug)) -(put 'flymake-note 'mode-line-face 'flymake-note-echo) -(put 'flymake-note 'echo-face 'flymake-note-echo) -(put 'flymake-note 'eol-face 'flymake-note-echo-at-eol) -(put 'flymake-note 'flymake-type-name "note") - -(defun flymake--lookup-type-property (type prop &optional default) - "Look up PROP for diagnostic TYPE. -If TYPE doesn't declare PROP in its plist or in the symbol of its -associated `flymake-category' return DEFAULT." - ;; This function also consults `flymake-diagnostic-types-alist' for - ;; backward compatibility. - ;; - (if (plist-member (symbol-plist type) prop) - ;; allow nil values to survive - (get type prop) - (let (alist) - (or - (alist-get - prop (setq - alist - (alist-get type flymake-diagnostic-types-alist))) - (when-let* ((cat (or - (get type 'flymake-category) - (alist-get 'flymake-category alist))) - (plist (and (symbolp cat) - (symbol-plist cat))) - (cat-probe (plist-member plist prop))) - (cadr cat-probe)) - default)))) - -(defun flymake--severity (type) - "Get the severity for diagnostic TYPE." - (flymake--lookup-type-property type 'severity - (warning-numeric-level :error))) - -(defun flymake--indicator-overlay-spec (type) - "Return INDICATOR as propertized string to use in error indicators." - (let* ((indicator (flymake--lookup-type-property - type - (cond ((eq flymake-indicator-type 'fringes) - 'flymake-bitmap) - ((eq flymake-indicator-type 'margins) - 'flymake-margin-string)) - (alist-get 'bitmap (alist-get type ; backward compat - flymake-diagnostic-types-alist)))) - (value (if (symbolp indicator) - (symbol-value indicator) - indicator)) - (valuelist (if (listp value) - value - (list value))) - (indicator-car (car valuelist))) - - (cond - ((and (symbolp indicator-car) - flymake-fringe-indicator-position) - (propertize "!" 'display - (cons flymake-fringe-indicator-position valuelist))) - ((and (stringp indicator-car) - flymake-margin-indicator-position) - (propertize "!" - 'display - `((margin ,flymake-margin-indicator-position) - ,(propertize indicator-car - 'face `(:inherit (,(cdr valuelist) default)) - 'mouse-face 'highlight - 'help-echo "Open Flymake diagnostics" - 'keymap (let ((map (make-sparse-keymap))) - (define-key - map `[,flymake-margin-indicator-position mouse-1] - #'flymake-show-buffer-diagnostics) - map)))))))) - -(defun flymake--resize-margins (&optional orig-width) - "Resize current window margins according to `flymake-margin-indicator-position'. -Return to original margin width if ORIG-WIDTH is non-nil." - (when (and (eq flymake-indicator-type 'margins) - flymake-autoresize-margins) - (cond - ((and orig-width flymake--original-margin-width) - (if (eq flymake-margin-indicator-position 'left-margin) - (setq left-margin-width flymake--original-margin-width) - (setq right-margin-width flymake--original-margin-width))) - (t - (if (eq flymake-margin-indicator-position 'left-margin) - (setq flymake--original-margin-width left-margin-width - left-margin-width 2) - (setq flymake--original-margin-width right-margin-width - right-margin-width 2)))) - ;; Apply margin to all windows available. - (mapc (lambda (x) - (set-window-buffer x (window-buffer x))) - (get-buffer-window-list nil nil 'visible)))) - -(defun flymake--equal-diagnostic-p (a b) - "Tell if A and B are equivalent `flymake--diag' objects." - (or (eq a b) - (cl-loop for comp in '(flymake--diag-end - flymake--diag-beg - flymake-diagnostic-type - flymake-diagnostic-backend - flymake-diagnostic-origin - flymake-diagnostic-code - flymake-diagnostic-message) - always (equal (funcall comp a) (funcall comp b))))) - -(defun flymake--delete-overlay (ov) - "Like `delete-overlay', delete OV, but do some more stuff." - (let ((eolov (overlay-get ov 'eol-ov))) - (when eolov - (let ((src-ovs (delq ov (overlay-get eolov 'flymake-eol-source-overlays)))) - (overlay-put eolov 'flymake-eol-source-overlays src-ovs))) - (delete-overlay ov))) - -(defun flymake--eol-overlay-summary (src-ovs) - "Helper function for `flymake--update-eol-overlays'." - (cl-flet ((summarize (d) - (flymake--format-diagnostic d :eol 'eol-face))) - (let* ((diags - (cl-sort - (mapcar (lambda (o) (overlay-get o 'flymake-diagnostic)) src-ovs) - #'> - :key (lambda (d) (flymake--severity (flymake-diagnostic-type d))))) - (summary - (concat - " " - (cond ((eq flymake-show-diagnostics-at-end-of-line 'short) - (concat - (summarize (car diags)) - (and (cdr diags) - (concat - " " - (propertize (format "and %s more" - (1- (length diags))) - 'face 'flymake-eol-information-face))))) - (t - (mapconcat #'summarize diags " ")))))) - (put-text-property 0 1 'cursor t summary) - summary))) - -(defun flymake--update-eol-overlays () - "Update the `before-string' property of end-of-line overlays." - (save-restriction - (widen) - (dolist (o (overlays-in (point-min) (point-max))) - (when (overlay-get o 'flymake--eol-overlay) - (if-let* ((src-ovs (overlay-get o 'flymake-eol-source-overlays))) - (overlay-put o 'before-string (flymake--eol-overlay-summary src-ovs)) - (delete-overlay o)))))) - -(cl-defun flymake--highlight-line (diagnostic &optional foreign) - "Attempt to overlay DIAGNOSTIC in current buffer. - -FOREIGN says if DIAGNOSTIC is \"foreign\" to the current buffer, -i.e. managed by another buffer where `flymake-mode' is also -active. - -This function mayskip overlay creation if a diagnostic which is -the same as DIAGNOSTIC is already highlighted -(in the sense of `flymake--equal-diagnostic-p'). In that case -the action to take depends on FOREIGN. If nil the existing -overlay is deleted, else no overlay is created. - -Return nil or the overlay created." - (let* ((type (or (flymake-diagnostic-type diagnostic) - :error)) - (beg (flymake--diag-beg diagnostic)) - (end (flymake--diag-end diagnostic)) - (convert (lambda (cell) - (flymake-diag-region (current-buffer) - (car cell) - (cdr cell)))) - ov) - ;; Convert (LINE . COL) forms of `flymake--diag-beg' and - ;; `flymake--diag-end'. Record the converted positions. - ;; - (cond ((and (consp beg) (not (null end))) - (setq beg (car (funcall convert beg))) - (when (consp end) - (setq end (car (funcall convert end))))) - ((consp beg) - (cl-destructuring-bind (a . b) (funcall convert beg) - (setq beg a end b)))) - (setf (flymake--diag-beg diagnostic) beg - (flymake--diag-end diagnostic) end) - ;; Try to remedy the situation if the same diagnostic is already - ;; registered in the same place. This happens for clashes between - ;; domestic and foreign diagnostics - (cl-loop for e in (flymake-diagnostics beg end) - for eov = (flymake--diag-overlay e) - when (flymake--equal-diagnostic-p e diagnostic) - ;; FIXME. This is an imperfect heuristic. Ideally, we'd - ;; want to delete no overlays and keep annotating the - ;; superseded foreign in an overlay but hide it from most - ;; `flymake-diagnostics' calls. If the target buffer is - ;; killed we can keep the "latent" state of the foreign - ;; diagnostic (with filename and updated line/col info). - ;; If it is revisited the foreign diagnostic can be - ;; revived again. - do (if foreign - (cl-return-from flymake--highlight-line nil) - (setf (flymake--diag-beg e) - (flymake--diag-orig-beg e) - (flymake--diag-end e) - (flymake--diag-orig-end e)) - (flymake--delete-overlay eov))) - (setq ov (make-overlay beg end)) - (setf (flymake--diag-overlay diagnostic) ov) - (when (= (overlay-start ov) (overlay-end ov)) - ;; Some backends report diagnostics with invalid bounds. Don't - ;; bother. - (delete-overlay ov) - (cl-return-from flymake--highlight-line nil)) - (setf (flymake--diag-beg diagnostic) (overlay-start ov) - (flymake--diag-end diagnostic) (overlay-end ov)) - ;; First set `category' in the overlay - ;; - (overlay-put ov 'category - (flymake--lookup-type-property type 'flymake-category)) - ;; Now "paint" the overlay with all the other non-category - ;; properties. - (cl-loop - for (ov-prop . value) in - (append (reverse - (flymake--diag-overlay-properties diagnostic)) - (reverse ; ensure earlier props override later ones - (flymake--lookup-type-property type 'flymake-overlay-control)) - (alist-get type flymake-diagnostic-types-alist)) - do (overlay-put ov ov-prop value)) - ;; Now ensure some essential defaults are set - ;; - (cl-flet ((default-maybe - (prop value) - (unless (plist-member (overlay-properties ov) prop) - (overlay-put ov prop (flymake--lookup-type-property - type prop value))))) - (default-maybe 'face 'flymake-error) - (default-maybe 'before-string (flymake--indicator-overlay-spec type)) - ;; (default-maybe 'after-string - ;; (flymake--diag-text diagnostic)) - (default-maybe 'help-echo - (lambda (window _ov pos) - (with-selected-window window - (mapconcat - (lambda (d) - (flymake--format-diagnostic d :help-echo 'echo-face)) - (flymake-diagnostics pos) - "\n")))) - (default-maybe 'severity (warning-numeric-level :error)) - ;; Use (PRIMARY . SECONDARY) priority, to avoid clashing with - ;; `region' face, for example (bug#34022). - (default-maybe 'priority (cons nil (+ 40 (overlay-get ov 'severity))))) - ;; Some properties can't be overridden. - ;; - (overlay-put ov 'evaporate t) - (overlay-put ov 'flymake-overlay t) - (overlay-put ov 'flymake-diagnostic diagnostic) - ;; Handle `flymake-show-diagnostics-at-end-of-line' - ;; - (when flymake-show-diagnostics-at-end-of-line - (save-excursion - (goto-char (overlay-start ov)) - (let* ((start (line-end-position)) - (end (min (1+ start) (point-max))) - (eolov (car - (cl-remove-if-not - (lambda (o) (overlay-get o 'flymake-eol-source-overlays)) - (overlays-in start end))))) - ;; FIXME: 1. no checking if there are unexpectedly more than - ;; one eolov at point. - (if eolov - (push ov (overlay-get eolov 'flymake-eol-source-overlays)) - (setq eolov (make-overlay start end nil t nil)) - (overlay-put eolov 'flymake-overlay t) - (overlay-put eolov 'flymake--eol-overlay t) - (overlay-put eolov 'flymake-eol-source-overlays (list ov)) - (overlay-put eolov 'evaporate (not (= start end)))) ; FIXME: fishy - (overlay-put ov 'eol-ov eolov)))) - ov)) - -;; Nothing in Flymake uses this at all any more, so this is just for -;; third-party compatibility. -(define-obsolete-function-alias 'flymake-display-warning 'message-box "26.1") - -(defvar-local flymake--state nil - "State of a buffer's multiple Flymake backends. -The keys to this hash table are functions as found in -`flymake-diagnostic-functions'. The values are structures -of the type `flymake--state', with these slots: - -`running', a symbol to keep track of a backend's replies via its -REPORT-FN argument. A backend is running if this key is -present. If nil, Flymake isn't expecting any replies from the -backend. - -`diags', a (possibly empty) list of recent diagnostic objects -created by the backend with `flymake-make-diagnostic'. - -`reported-p', a boolean indicating if the backend has replied -since it last was contacted. - -`disabled', a string with the explanation for a previous -exceptional situation reported by the backend, nil if the -backend is operating normally. - -`foreign-diags', a hash table of buffers/files to -collections of diagnostics outside the buffer where this -`flymake--state' pertains.") - -(cl-defstruct (flymake--state - (:constructor flymake--make-backend-state)) - running reported-p disabled diags (foreign-diags - (make-hash-table))) - -(defmacro flymake--with-backend-state (backend state-var &rest body) - "Bind BACKEND's STATE-VAR to its state, run BODY." - (declare (indent 2) (debug (sexp sexp &rest form))) - (let ((b (make-symbol "b"))) - `(let* ((,b ,backend) - (,state-var - (or (gethash ,b flymake--state) - (puthash ,b (flymake--make-backend-state) - flymake--state)))) - ,@body))) - -(defun flymake-is-running () - "Tell if Flymake has running backends in this buffer." - (flymake-running-backends)) - -;; FIXME: clone of `isearch-intersects-p'! Make this an util. -(defun flymake--intersects-p (start0 end0 start1 end1) - "Return t if regions START0..END0 and START1..END1 intersect." - (or (and (>= start0 start1) (< start0 end1)) - (and (> end0 start1) (<= end0 end1)) - (and (>= start1 start0) (< start1 end0)) - (and (> end1 start0) (<= end1 end0)))) - -(cl-defun flymake--handle-report - (backend token report-action - &key explanation force region - &allow-other-keys) - "Handle reports from BACKEND identified by TOKEN. -BACKEND, REPORT-ACTION and EXPLANATION, and FORCE conform to the -calling convention described in -`flymake-diagnostic-functions' (which see). Optional FORCE says -to handle a report even if TOKEN was not expected. REGION is -a (BEG . END) pair of buffer positions indicating that this -report applies to that region." - (let ((state (or (gethash backend flymake--state) - (error "Can't find state for %s in `flymake--state'" - backend))) - expected-token) - (cond - ((null state) - (flymake-error - "Unexpected report from unknown backend %s" backend)) - ((flymake--state-disabled state) - (flymake-error - "Unexpected report from disabled backend %s" backend)) - ((progn - (setq expected-token (flymake--state-running state)) - (null expected-token)) - ;; should never happen - (flymake-error "Unexpected report from stopped backend %s" backend)) - ((not (or (eq expected-token token) - force)) - (flymake-error "Obsolete report from backend %s with explanation %s" - backend explanation)) - ((eq :panic report-action) - (flymake--disable-backend backend explanation)) - ((not (listp report-action)) - (flymake--disable-backend backend - (format "Unknown action %S" report-action)) - (flymake-error "Expected report, but got unknown key %s" report-action)) - (t - (flymake--publish-diagnostics report-action - :backend backend - :state state - :region region) - (when flymake-check-start-time - (flymake-log :debug "backend %s reported %d diagnostics in %.2f second(s)" - backend - (length report-action) - (float-time - (time-since flymake-check-start-time)))))) - (setf (flymake--state-reported-p state) t) - ;; All of the above might have touched the eol overlays, so issue - ;; a call to update them. But check running and reporting - ;; backends first to flickering when multiple backends touch the - ;; same eol overlays. - (when (and flymake-show-diagnostics-at-end-of-line - (not (cl-set-difference (flymake-running-backends) - (flymake-reporting-backends)))) - (flymake--update-eol-overlays)) - (flymake--update-diagnostics-listings (current-buffer)))) - -(defun flymake--clear-foreign-diags (state) - (maphash (lambda (_buffer diags) - (cl-loop for d in diags - when (flymake--diag-overlay d) - do (flymake--delete-overlay it))) - (flymake--state-foreign-diags state)) - (clrhash (flymake--state-foreign-diags state))) - -(defvar-local flymake-mode nil) - -(defvar-local flymake--mode-line-counter-cache nil - "A cache used in `flymake-mode-line-counters'.") - -(cl-defun flymake--publish-diagnostics (diags &key backend state region) - "Helper for `flymake--handle-report'. -Publish DIAGS, which contain diagnostics for the current buffer -and other buffers." - (dolist (d diags) (setf (flymake--diag-backend d) backend)) - (save-restriction - (widen) - ;; First, clean up. Remove diagnostics from bookkeeping lists and - ;; their overlays from buffers. - ;; - (cond - (;; If there is a `region' arg, only affect the diagnostics whose - ;; overlays are in a certain region. Discard "foreign" - ;; diagnostics. - region - (cl-loop for diag in (flymake--state-diags state) - for ov = (flymake--diag-overlay diag) - if (or (not (overlay-buffer ov)) - (flymake--intersects-p - (overlay-start ov) (overlay-end ov) - (car region) (cdr region))) - do (flymake--delete-overlay ov) - else collect diag into surviving - finally (setf (flymake--state-diags state) - surviving))) - (;; Else, if this is the first report, zero all lists and delete - ;; all associated overlays. - (not (flymake--state-reported-p state)) - (cl-loop for diag in (flymake--state-diags state) - for ov = (flymake--diag-overlay diag) - when ov do (flymake--delete-overlay ov)) - (setf (flymake--state-diags state) nil) - ;; Also clear all overlays for `foreign-diags' in all other - ;; buffers. - (flymake--clear-foreign-diags state)) - (;; If this is not the first report, do no cleanup. - t)) - - ;; Now place new overlays for all diagnostics: "domestic" - ;; diagnostics are for the current buffer; "foreign" may be for a - ;; some other live buffer or for a file name that hasn't a buffer - ;; yet. If a foreign diagnostic is for a buffer, convert to a - ;; file name, protecting it against that buffer's killing. - ;; - (cl-loop - for d in diags - for locus = (flymake--diag-locus d) - do (cond ((eq locus (current-buffer)) - (push d (flymake--state-diags state)) - (flymake--highlight-line d)) - (t - (when (or (buffer-live-p locus) - (setq locus (find-buffer-visiting locus))) - (with-current-buffer locus - (when flymake-mode (flymake--highlight-line d 'foreign)) - ;; Ensure locus of a foreign diag is always a file-name - ;; string, even if created from a buffer. - (setf (flymake--diag-locus d) (buffer-file-name)))) - (cl-assert (stringp (flymake--diag-locus d))) - (push d (gethash (flymake--diag-locus d) - (flymake--state-foreign-diags state)))))) - ;; Finally, flush some caches - (setq flymake--mode-line-counter-cache nil))) - -(defun flymake-make-report-fn (backend &optional token) - "Make a suitable anonymous report function for BACKEND. -BACKEND is used to help Flymake distinguish different diagnostic -sources. If provided, TOKEN helps Flymake distinguish between -different runs of the same backend." - (let ((buffer (current-buffer))) - (lambda (&rest args) - (when (buffer-live-p buffer) - (with-current-buffer buffer - (apply #'flymake--handle-report backend token args)))))) - -(defun flymake--collect (fn &optional message-prefix) - "Collect Flymake backends matching FN. -If MESSAGE-PREFIX, echo a message using that prefix." - (unless flymake--state - (user-error "Flymake is not initialized")) - (let (retval) - (maphash (lambda (backend state) - (when (funcall fn state) (push backend retval))) - flymake--state) - (when message-prefix - (message "%s%s" - message-prefix - (mapconcat (lambda (s) (format "%s" s)) - retval ", "))) - retval)) - -(defun flymake-running-backends () - "Compute running Flymake backends in current buffer." - (interactive) - (flymake--collect #'flymake--state-running - (and (called-interactively-p 'interactive) - "Running backends: "))) - -(defun flymake-disabled-backends () - "Compute disabled Flymake backends in current buffer." - (interactive) - (flymake--collect #'flymake--state-disabled - (and (called-interactively-p 'interactive) - "Disabled backends: "))) - -(defun flymake-reporting-backends () - "Compute reporting Flymake backends in current buffer." - (interactive) - (flymake--collect #'flymake--state-reported-p - (and (called-interactively-p 'interactive) - "Reporting backends: "))) - -(defun flymake--disable-backend (backend &optional explanation) - "Disable BACKEND because EXPLANATION. -If it is running also stop it." - (flymake-log :warning "Disabling backend %s because %S" backend explanation) - (flymake--with-backend-state backend state - (setf (flymake--state-running state) nil - (flymake--state-disabled state) explanation - (flymake--state-reported-p state) t))) - -(defun flymake--run-backend (backend &optional args) - "Run the backend BACKEND, re-enabling if necessary. -ARGS is a keyword-value plist passed to the backend along -with a report function." - (flymake-log :debug "Running backend %s" backend) - (let ((run-token (gensym "backend-token"))) - (flymake--with-backend-state backend state - (setf (flymake--state-running state) run-token - (flymake--state-disabled state) nil - (flymake--state-reported-p state) nil)) - (condition-case-unless-debug err - (apply backend (flymake-make-report-fn backend run-token) - args) - (error - (flymake--disable-backend backend err))))) - -(defvar-local flymake--recent-changes nil - "Recent changes collected by `flymake-after-change-function'.") -(defvar flymake-mode) - -(defun flymake--import-foreign-diagnostics () - ;; Other diagnostic sources may already target this buffer's file - ;; before we turned on: these sources may be of two types... - (let ((source (current-buffer)) - (bfn buffer-file-name)) - ;; 1. For `flymake-list-only-diagnostics': here, we do nothing. - ;; FIXME: We could remove the corresponding entry from that - ;; variable, as we assume that new diagnostics will come in soon - ;; via the brand new `flymake-mode' setup. For simplicity's - ;; sake, we have opted to leave the backend for now. - nil - ;; 2. other buffers where a backend has created "foreign - ;; diagnostics" and pointed them here. We must highlight them in - ;; this buffer, i.e. create overlays for them. Those other - ;; buffers and backends are still responsible for them, i.e. the - ;; current buffer does not "own" these foreign diags. - (dolist (buffer (buffer-list)) - (with-current-buffer buffer - (when flymake-mode - (maphash (lambda (_backend state) - (maphash (lambda (file diags) - (when (or (eq file source) - (string= bfn (expand-file-name file))) - (with-current-buffer source - (mapc (lambda (diag) - (flymake--highlight-line diag - 'foreign)) - diags)))) - (flymake--state-foreign-diags state))) - flymake--state)))))) - -(defun flymake-start (&optional deferred force) - "Start a syntax check for the current buffer. -DEFERRED is a list of symbols designating conditions to wait for -before actually starting the check. If it is nil (the list is -empty), start it immediately, else defer the check to when those -conditions are met. Currently recognized conditions are -`post-command', for waiting until the current command is over, -`on-display', for waiting until the buffer is actually displayed -in a window. If DEFERRED is t, wait for all known conditions. - -With optional FORCE run even disabled backends. - -Interactively, with a prefix arg, FORCE is t." - (interactive (list nil current-prefix-arg)) - (let ((deferred (if (eq t deferred) - '(post-command on-display) - deferred)) - (buffer (current-buffer))) - (cl-labels - ((start-post-command - () - (remove-hook 'post-command-hook #'start-post-command - nil) - ;; The buffer may have disappeared already, e.g. because of - ;; code like `(with-temp-buffer (python-mode) ...)'. - (when (buffer-live-p buffer) - (with-current-buffer buffer - (flymake-start (remove 'post-command deferred) force)))) - (start-on-display - () - (remove-hook 'window-configuration-change-hook #'start-on-display - 'local) - (flymake-start (remove 'on-display deferred) force))) - (cond ((and (memq 'post-command deferred) - this-command) - (add-hook 'post-command-hook - #'start-post-command - 'append nil)) - ((and (memq 'on-display deferred) - (not (get-buffer-window (current-buffer)))) - (add-hook 'window-configuration-change-hook - #'start-on-display - 'append 'local)) - (flymake-mode - (setq flymake-check-start-time (float-time)) - (let ((backend-args - (and - flymake--recent-changes - (list :recent-changes - flymake--recent-changes - :changes-start - (cl-reduce - #'min (mapcar #'car flymake--recent-changes)) - :changes-end - (cl-reduce - #'max (mapcar #'cadr flymake--recent-changes)))))) - (setq flymake--recent-changes nil) - (run-hook-wrapped - 'flymake-diagnostic-functions - (lambda (backend) - (flymake--with-backend-state backend state - (setf (flymake--state-reported-p state) nil)))) - (run-hook-wrapped - 'flymake-diagnostic-functions - (lambda (backend) - (cond - ((and (not force) - (flymake--with-backend-state backend state - (flymake--state-disabled state))) - (flymake-log :debug "Backend %s is disabled, not starting" - backend)) - (t - (flymake--run-backend backend backend-args))) - nil))) - (flymake--import-foreign-diagnostics)))))) - -(defvar flymake-mode-map - (let ((map (make-sparse-keymap))) - (define-key map - `[,flymake-fringe-indicator-position mouse-1] - #'flymake-show-buffer-diagnostics) - map) - "Keymap for `flymake-mode'") - -;;;###autoload -(define-minor-mode flymake-mode - "Toggle Flymake mode on or off. - -Flymake is an Emacs minor mode for on-the-fly syntax checking. -Flymake collects diagnostic information from multiple sources, -called backends, and visually annotates the buffer with the -results. - -Flymake performs these checks while the user is editing. -The customization variables `flymake-start-on-flymake-mode', -`flymake-no-changes-timeout' determine the exact circumstances -whereupon Flymake decides to initiate a check of the buffer. - -The commands `flymake-goto-next-error' and -`flymake-goto-prev-error' can be used to navigate among Flymake -diagnostics annotated in the buffer. - -By default, `flymake-mode' doesn't override the \\[next-error] command, but -if you're using Flymake a lot (and don't use the regular compilation -mechanisms that often), it can be useful to put something like -the following in your init file: - - (setq next-error-function \\='flymake-goto-next-error) - -The visual appearance of each type of diagnostic can be changed -by setting properties `flymake-overlay-control', `flymake-bitmap' -and `flymake-severity' on the symbols of diagnostic types (like -`:error', `:warning' and `:note'). - -Activation or deactivation of backends used by Flymake in each -buffer happens via the special hook -`flymake-diagnostic-functions'. - -Some backends may take longer than others to respond or complete, -and some may decide to disable themselves if they are not -suitable for the current buffer. The commands -`flymake-running-backends', `flymake-disabled-backends' and -`flymake-reporting-backends' summarize the situation, as does the -special *Flymake log* buffer." :group 'flymake :lighter - flymake-mode-line-format :keymap flymake-mode-map - (cond - ;; Turning the mode ON. - (flymake-mode - (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) - (add-hook 'eldoc-documentation-functions 'flymake-eldoc-function t t) - - (when (and (eq flymake-indicator-type 'fringes) - (not (cl-case flymake-fringe-indicator-position - (left-fringe (< 0 (nth 0 (window-fringes)))) - (right-fringe (< 0 (nth 1 (window-fringes))))))) - ;; There are no fringes in the buffer, fallback to margins. - (setq-local flymake-indicator-type 'margins)) - - ;; AutoResize margins. - (flymake--resize-margins) - - ;; We can't just `clrhash' `flymake--state': there may be in - ;; in-transit requests from other backends if `flymake-mode' was - ;; already active. I.e. `flymake-mode' function should be as - ;; idempotent as possible. See bug#69809. - (unless flymake--state (setq flymake--state (make-hash-table))) - (setq flymake--recent-changes nil) - (when flymake-start-on-flymake-mode (flymake-start t))) - - ;; Turning the mode OFF. - (t - (remove-hook 'after-change-functions 'flymake-after-change-function t) - (remove-hook 'after-save-hook 'flymake-after-save-hook t) - (remove-hook 'kill-buffer-hook 'flymake-kill-buffer-hook t) - ;;+(remove-hook 'find-file-hook (function flymake-find-file-hook) t) - (remove-hook 'eldoc-documentation-functions 'flymake-eldoc-function t) - - ;; return margin to original size - (flymake--resize-margins t) - - (when flymake-timer - (cancel-timer flymake-timer) - (setq flymake-timer nil)) - (mapc #'flymake--delete-overlay (flymake--really-all-overlays)) - (when flymake--state - (maphash (lambda (_backend state) - (flymake--clear-foreign-diags state)) - flymake--state)))) - ;; turning Flymake on or off has consequences for listings - (flymake--update-diagnostics-listings (current-buffer))) - -(defun flymake--schedule-timer-maybe () - "(Re)schedule an idle timer for checking the buffer. -Do it only if `flymake-no-changes-timeout' is non-nil." - (when flymake-timer (cancel-timer flymake-timer)) - (when flymake-no-changes-timeout - (setq - flymake-timer - (run-with-idle-timer - ;; This can use time-convert instead of seconds-to-time, - ;; once we can assume Emacs 27 or later. - (seconds-to-time flymake-no-changes-timeout) - nil - (lambda (buffer) - (when (buffer-live-p buffer) - (with-current-buffer buffer - (when (and flymake-mode - flymake-no-changes-timeout) - (flymake-log - :debug "starting syntax check after idle for %s seconds" - flymake-no-changes-timeout) - (flymake-start t)) - (setq flymake-timer nil)))) - (current-buffer))))) - -;;;###autoload -(defun flymake-mode-on () - "Turn Flymake mode on." - (flymake-mode 1)) - -;;;###autoload -(defun flymake-mode-off () - "Turn Flymake mode off." - (flymake-mode 0)) - -(make-obsolete 'flymake-mode-on 'flymake-mode "26.1") -(make-obsolete 'flymake-mode-off 'flymake-mode "26.1") - -(defun flymake-after-change-function (start stop pre-change-len) - "Start syntax check for current buffer if it isn't already running. -START and STOP and LEN are as in `after-change-functions'." - (let((new-text (buffer-substring start stop))) - (push (list start stop new-text) flymake--recent-changes) - (flymake--schedule-timer-maybe)) - ;; Some special handling to prevent eol overlays from temporarily - ;; moving to wrong line - (when (and flymake-show-diagnostics-at-end-of-line - (zerop pre-change-len)) - (save-excursion - (goto-char start) - (when-let* ((probe (search-forward "\n" stop t)) - (eolovs (cl-remove-if-not - (lambda (o) - (let ((lbound - (cl-loop for s in (overlay-get o 'flymake-eol-source-overlays) - minimizing (overlay-start s)))) - (and lbound (< lbound (1- probe))))) - (overlays-at (line-end-position))))) - (goto-char start) - (let ((newend (line-end-position))) - (dolist (ov eolovs) (move-overlay ov newend (1+ newend)))))))) - -(defun flymake-after-save-hook () - (when flymake-start-on-save-buffer - (flymake-log :debug "starting syntax check as buffer was saved") - (flymake-start t))) - -(defun flymake-kill-buffer-hook () - ;; Explicitly set flymake off, because that does a lot of useful - ;; cleanup. - (flymake-mode -1)) - -(defun flymake-find-file-hook () - (unless (or flymake-mode - (null flymake-diagnostic-functions)) - (flymake-mode) - (flymake-log :warning "Turned on in `flymake-find-file-hook'"))) - -(defun flymake-eldoc-function (report-doc &rest _) - "Document diagnostics at point. -Intended for `eldoc-documentation-functions' (which see)." - (when-let* ((diags (flymake-diagnostics (point)))) - (funcall report-doc - (mapconcat (lambda (d) - (flymake--format-diagnostic d :eldoc 'echo-face)) - diags "\n") - :echo (mapconcat - (lambda (d) - (flymake--format-diagnostic d :eldoc-echo 'echo-face)) - diags "\n")))) - -(defun flymake-goto-next-error (&optional n filter interactive) - "Go to Nth next Flymake diagnostic that matches FILTER. -Interactively, always move to the next diagnostic. With a prefix -arg, skip any diagnostics with a severity less than `:warning'. - -If `flymake-wrap-around' is non-nil and no more next diagnostics, -resumes search from top. - -FILTER is a list of diagnostic types. Only diagnostics with -matching severities matching are considered. If nil (the -default) no filter is applied." - ;; TODO: let filter be a number, a severity below which diags are - ;; skipped. - (interactive (list 1 - (if current-prefix-arg - '(:error :warning)) - t)) - (let* ((n (or n 1)) - (ovs (cl-loop - for o in (overlays-in (point-min) (point-max)) - for diag = (overlay-get o 'flymake-diagnostic) - when (and diag (or (not filter) (cl-find - (flymake--severity - (flymake-diagnostic-type diag)) - filter :key #'flymake--severity))) - collect o into retval - finally (cl-return - (cl-sort retval (if (cl-plusp n) #'< #'>) - :key #'overlay-start)))) - (tail (cl-member-if (lambda (ov) - (if (cl-plusp n) - (> (overlay-start ov) - (point)) - (< (overlay-start ov) - (point)))) - ovs)) - (chain (if flymake-wrap-around - (if tail - (progn (setcdr (last tail) ovs) tail) - (and ovs (setcdr (last ovs) ovs))) - tail)) - (target (nth (1- n) chain))) - (cond (target - (goto-char (overlay-start target)) - (when interactive - (message - "%s" - (funcall (overlay-get target 'help-echo) - (selected-window) target (point))))) - (interactive - (user-error "No more Flymake diagnostics%s" - (if filter - (format " of %s severity" - (mapconcat #'symbol-name filter ", ")) "")))))) - -(defun flymake-goto-prev-error (&optional n filter interactive) - "Go to Nth previous Flymake diagnostic that matches FILTER. -Interactively, always move to the previous diagnostic. With a -prefix arg, skip any diagnostics with a severity less than -`:warning'. - -If `flymake-wrap-around' is non-nil and no more previous -diagnostics, resumes search from bottom. - -FILTER is a list of diagnostic types. Only diagnostics with -matching severities matching are considered. If nil (the -default) no filter is applied." - (interactive (list 1 (if current-prefix-arg - '(:error :warning)) - t)) - (flymake-goto-next-error (- (or n 1)) filter interactive)) - - -;;; Mode-line and menu -;;; -(easy-menu-define flymake-menu flymake-mode-map "Flymake menu." - '("Flymake" - [ "Go to next problem" flymake-goto-next-error t ] - [ "Go to previous problem" flymake-goto-prev-error t ] - [ "Check now" flymake-start t ] - [ "List all problems" flymake-show-buffer-diagnostics t ] - "--" - [ "Go to log buffer" flymake-switch-to-log-buffer t ] - [ "Turn off Flymake" flymake-mode t ])) - -(defcustom flymake-mode-line-format - '(" " flymake-mode-line-title flymake-mode-line-exception - flymake-mode-line-counters) - "Mode line construct for customizing Flymake information." - :type '(repeat (choice string symbol))) - -(defcustom flymake-mode-line-counter-format - '("[" - flymake-mode-line-error-counter - flymake-mode-line-warning-counter - flymake-mode-line-note-counter "]") - "Mode-line construct for formatting Flymake diagnostic counters. -This is a suitable place for placing the `flymake-mode-line-error-counter', -`flymake-mode-line-warning-counter' and `flymake-mode-line-note-counter' -constructs. -Separating each of these with space is not necessary." - :type '(repeat (choice string symbol))) - -(defcustom flymake-mode-line-lighter "Flymake" - "The string to use in the Flymake mode line." - :type 'string - :version "29.1") - -(defvar flymake-mode-line-title '(:eval (flymake--mode-line-title)) - "Mode-line construct to show Flymake's mode name and menu.") - -(defvar flymake-mode-line-exception '(:eval (flymake--mode-line-exception)) - "Mode-line construct to report on exceptional Flymake status.") - -(defvar flymake-mode-line-counters '(:eval (flymake--mode-line-counters)) - "Mode-line construct for counting Flymake diagnostics. -The counters are only placed if some Flymake backend initialized -correctly.") - -(defvar flymake-mode-line-error-counter - `(:eval (flymake--mode-line-counter :error))) -(defvar flymake-mode-line-warning-counter - `(:eval (flymake--mode-line-counter :warning))) -(defvar flymake-mode-line-note-counter - `(:eval (flymake--mode-line-counter :note))) - -(put 'flymake-mode-line-format 'risky-local-variable t) -(put 'flymake-mode-line-title 'risky-local-variable t) -(put 'flymake-mode-line-exception 'risky-local-variable t) -(put 'flymake-mode-line-counters 'risky-local-variable t) -(put 'flymake-mode-line-error-counter 'risky-local-variable t) -(put 'flymake-mode-line-warning-counter 'risky-local-variable t) -(put 'flymake-mode-line-note-counter 'risky-local-variable t) - -(defun flymake--mode-line-title () - `(:propertize - ,flymake-mode-line-lighter - mouse-face mode-line-highlight - help-echo - ,(lambda (w &rest _) - (with-current-buffer (window-buffer w) - ;; Mouse can activate tool-tip without window being active. - ;; `flymake--state' is buffer local and is null when line - ;; lighter appears in *Help* `describe-mode'. - (concat - (unless (null flymake--state) - (concat - (format "%s known backends\n" (hash-table-count flymake--state)) - (format "%s running\n" (length (flymake-running-backends))) - (format "%s disabled\n" (length (flymake-disabled-backends))))) - "mouse-1: Display minor mode menu\n" - "mouse-2: Show help for minor mode"))) - keymap - ,(let ((map (make-sparse-keymap))) - (define-key map [mode-line down-mouse-1] - flymake-menu) - (define-key map [mode-line down-mouse-3] - flymake-menu) - (define-key map [mode-line mouse-2] - (lambda () - (interactive) - (describe-function 'flymake-mode))) - map))) - -(defun flymake--mode-line-exception () - "Helper for `flymake-mode-line-exception'." - (pcase-let* ((running) (reported) - (`(,ind ,face ,explain) - (cond ((zerop (hash-table-count flymake--state)) - '("?" nil "No known backends")) - ((cl-set-difference - (setq running (flymake-running-backends)) - (setq reported (flymake-reporting-backends))) - `("Wait" compilation-mode-line-run - ,(format "Waiting for %s running backend(s)" - (length (cl-set-difference running reported))))) - ((and (flymake-disabled-backends) (null running)) - '("!" compilation-mode-line-run - "All backends disabled")) - (t - '(nil nil nil))))) - (when ind - `(":" - (:propertize ,ind face ,face - help-echo ,explain - keymap ,(let ((map (make-sparse-keymap))) - (define-key map [mode-line mouse-1] - 'flymake-switch-to-log-buffer) - map)))))) - -(defun flymake--mode-line-counters () - (when (flymake-running-backends) flymake-mode-line-counter-format)) - -(defun flymake--mode-line-counter-scroll-prev (event) - (interactive "e") - (let* ((event-start (event-start event)) - (posn-string (posn-string event-start)) - (type (get-text-property - (cdr posn-string) 'flymake--diagnostic-type (car posn-string)))) - (with-selected-window (posn-window event-start) - (flymake-goto-prev-error 1 (list type) t)))) - -(defun flymake--mode-line-counter-scroll-next (event) - (interactive "e") - (let* ((event-start (event-start event)) - (posn-string (posn-string event-start)) - (type (get-text-property - (cdr posn-string) 'flymake--diagnostic-type (car posn-string)))) - (with-selected-window (posn-window event-start) - (flymake-goto-next-error 1 (list type) t)))) - -(defvar flymake--mode-line-counter-map - (let ((map (make-sparse-keymap))) - ;; BEWARE: `mouse-wheel-UP-event' corresponds to `wheel-DOWN' events - ;; and vice versa!! - (with-no-warnings - (define-key map (vector 'mode-line mouse-wheel-down-event) - #'flymake--mode-line-counter-scroll-prev) - (define-key map [mode-line wheel-down] - #'flymake--mode-line-counter-scroll-next) - (define-key map (vector 'mode-line mouse-wheel-up-event) - #'flymake--mode-line-counter-scroll-next) - (define-key map [mode-line wheel-up] - #'flymake--mode-line-counter-scroll-prev)) - map)) - -(defun flymake--mode-line-counter-1 (type) - "Helper for `flymake--mode-line-counter'." - (let ((count 0) - (face (flymake--lookup-type-property type - 'mode-line-face - 'compilation-error))) - (dolist (d (flymake-diagnostics)) - (when (= (flymake--severity type) - (flymake--severity (flymake-diagnostic-type d))) - (cl-incf count))) - (when (or (cl-plusp count) - (cond ((eq flymake-suppress-zero-counters t) - nil) - (flymake-suppress-zero-counters - (>= (flymake--severity type) - (warning-numeric-level - flymake-suppress-zero-counters))) - (t t))) - `(,(if (eq type :error) "" '(:propertize " ")) - (:propertize - ,(format "%d" count) - face ,face - mouse-face mode-line-highlight - help-echo ,(format "Number of %s; scroll mouse to view." - (cond - ((eq type :error) "errors") - ((eq type :warning) "warnings") - ((eq type :note) "notes") - (t (format "%s diagnostics" type)))) - flymake--diagnostic-type ,type - keymap ,flymake--mode-line-counter-map))))) - -(defun flymake--mode-line-counter (type) - "Compute number of diagnostics in buffer with TYPE's severity. -TYPE is usually keyword `:error', `:warning' or `:note'." - (let ((probe (alist-get type flymake--mode-line-counter-cache 'none))) - (if (eq probe 'none) - (setf (alist-get type flymake--mode-line-counter-cache) - (flymake--mode-line-counter-1 type)) - probe))) - - -;;; Per-buffer diagnostic listings -;;; -(defvar-local flymake--diagnostics-buffer-source nil) - -(defvar flymake-diagnostics-buffer-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "RET") 'flymake-goto-diagnostic) - (define-key map (kbd "SPC") 'flymake-show-diagnostic) - map)) - -(defun flymake-show-diagnostic (pos &optional other-window) - "From Flymake diagnostics buffer, show source of diagnostic at POS." - (interactive (list (point) t)) - (let* ((id (or (tabulated-list-get-id pos) - (user-error "Nothing at point"))) - (diag (plist-get id :diagnostic)) - (locus (flymake--diag-locus diag)) - (beg (flymake--diag-beg diag)) - (end (flymake--diag-end diag)) - (visit (lambda (b e) - (goto-char b) - (pulse-momentary-highlight-region - b (or e (line-end-position)))))) - (with-current-buffer (cond ((bufferp locus) locus) - (t (find-file-noselect locus))) - (with-selected-window - (display-buffer (current-buffer) other-window) - (cond (;; an annotated diagnostic (most common case), or a - ;; non-annotated buffer diag - (number-or-marker-p beg) - (funcall visit beg end)) - (;; a non-annotated file diag (TODO: could use `end' - ;; here, too) - (pcase-let ((`(,bbeg . ,bend) - (flymake-diag-region (current-buffer) - (car beg) - (cdr beg)))) - (funcall visit bbeg bend))))) - (current-buffer)))) - -(defun flymake-goto-diagnostic (pos) - "From Flymake diagnostics buffer, goto source of diagnostic at POS. -POS can be a buffer position or a button" - (interactive "d") - (pop-to-buffer - (flymake-show-diagnostic (if (button-type pos) (button-start pos) pos)))) - -(defvar flymake--tabulated-list-format-base - `[("File" 15) - ("Line" 5 ,(lambda (l1 l2) - (< (plist-get (car l1) :line) - (plist-get (car l2) :line))) - :right-align t) - ("Col" 3 nil :right-align t) - ("Type" 8 ,(lambda (l1 l2) - (< (plist-get (car l1) :severity) - (plist-get (car l2) :severity)))) - ("Origin" 8 t) - ("Code" 8 t) - ("Message" 0 t)]) - -(defun flymake--tabulated-setup-1 (diags project-root) - "Helper for `flymake--tabulated-setup'. -Sets `tabulated-list-format' and `tabulated-list-entries', dinamically -resizing columns and ommiting redudant columns." - (cl-loop - with fields = (copy-tree flymake--tabulated-list-format-base t) - initially (cl-loop for y across fields do (setf (cadr y) nil)) - for diag in diags - for locus = (flymake-diagnostic-buffer diag) - for file = (if (bufferp locus) - (buffer-file-name locus) - locus) - for overlay = (flymake--diag-overlay diag) - for (line . col) = - (cond (;; has live overlay, use overlay for position - (and overlay (overlay-buffer overlay)) - (with-current-buffer (overlay-buffer overlay) - (save-excursion - (goto-char (overlay-start overlay)) - (cons (line-number-at-pos) - (- (point) - (line-beginning-position)))))) - (;; diagnostic not annotated, maybe foreign, check for cons - (consp (flymake--diag-beg diag)) - (flymake--diag-beg diag)) - (;; may still be a valid foreign diagnostic - (consp (flymake--diag-orig-beg diag)) - (flymake--diag-orig-beg diag)) - (;; somehow dead annotated diagnostic, ignore/give up - t nil)) - for type = (flymake-diagnostic-type diag) - for data-line = `[,(and project-root - `(,(file-name-nondirectory file) - help-echo ,(file-relative-name file project-root) - face nil - mouse-face highlight - action flymake-goto-diagnostic - mouse-action flymake-goto-diagnostic )) - ,(format "%s" line) - ,(format "%s" col) - ,(propertize (format "%s" - (flymake--lookup-type-property - type 'flymake-type-name type)) - 'face (flymake--lookup-type-property - type 'mode-line-face 'flymake-error)) - ,(flymake-diagnostic-origin diag) - ,(flymake-diagnostic-code diag) - (,(flymake-diagnostic-text diag '(oneliner)) - mouse-face highlight - help-echo "mouse-2: visit this diagnostic" - face nil - action flymake-goto-diagnostic - mouse-action flymake-goto-diagnostic)] - for meta = (and line col - (list :diagnostic diag - :line line - :severity (flymake--lookup-type-property - type - 'severity (warning-numeric-level :error)))) - when meta - do (cl-loop for x across data-line - for y across fields - for z across flymake--tabulated-list-format-base - for xlen = (cond ((stringp x) (length x)) - (t (length (car x)))) - when (cl-plusp xlen) - do (setf (cadr y) - (max xlen - (or (cadr y) (cadr z))))) - collect (list meta data-line) into data - finally - ;; `data' and `fields' now hold more or less suitable values for - ;; `tabulated-list-entries' and `tabulated-list-format' respectively, - ;; but we need to trim them, first removing the columns of data where - ;; the corresponding field is known to be nil for every line, and - ;; then removing the field description itself. - (cl-loop - for entry in data - do (setf (cadr entry) (cl-loop for x across (cadr entry) - for y across fields - when (cadr y) - vconcat (vector (or x "-"))))) - (setq tabulated-list-entries data - tabulated-list-format - (cl-loop for y across fields - when (cadr y) vconcat (vector y))))) - -(defun flymake--tabulated-setup (use-project) - "Helper for `flymake-diagnostics-buffer-mode'. -And also `flymake-project-diagnostics-mode'." - (let ((saved-r-b-f revert-buffer-function) - (refresh - (lambda () - (cond - (use-project - (let ((p (project-current))) - (flymake--tabulated-setup-1 - (flymake--project-diagnostics p) - (project-root p)))) - (t - ;; Do nothing if 'flymake--diagnostics-buffer-source' has - ;; not yet been set to a valid buffer. This could happen - ;; when this function is called too early. For example - ;; 'global-display-line-numbers-mode' calls us from its - ;; mode hook, when the diagnostic buffer has just been - ;; created by 'flymake-show-buffer-diagnostics', but is not - ;; yet set up properly (Bug#40529). - (flymake--tabulated-setup-1 - (and (bufferp flymake--diagnostics-buffer-source) - (with-current-buffer flymake--diagnostics-buffer-source - (and flymake-mode - (flymake-diagnostics)))) - nil))) - (tabulated-list-init-header)))) - (setq revert-buffer-function - (lambda (&rest args) - (funcall refresh) - (apply saved-r-b-f args))))) - -(define-derived-mode flymake-diagnostics-buffer-mode tabulated-list-mode - "Flymake diagnostics" - "A mode for listing Flymake diagnostics." - :interactive nil - (flymake--tabulated-setup nil)) - -(defun flymake--diagnostics-buffer-name () - (format "*Flymake diagnostics for `%s'*" (current-buffer))) - -(define-obsolete-function-alias 'flymake-show-diagnostics-buffer - 'flymake-show-buffer-diagnostics "1.2.1") - -(defun flymake--fit-diagnostics-window (window) - (fit-window-to-buffer window 15 8)) - -(defun flymake-show-buffer-diagnostics (&optional diagnostic) - "Show listing of Flymake diagnostics for current buffer. -With optional DIAGNOSTIC, find and highlight this diagnostic in the -listing. - -Interactively, grab DIAGNOSTIC from context. For mouse events in -margins and fringes, use the first diagnostic in the corresponding line, -else look in the click position. For non-mouse events, look for -diagnostics at point. - -This function doesn't move point" - (interactive - (if (mouse-event-p last-command-event) - (with-selected-window (posn-window (event-end last-command-event)) - (with-current-buffer (window-buffer) - (let* ((event-point (posn-point (event-end last-command-event))) - (diags - (or - (flymake-diagnostics event-point) - (let (event-lbp event-lep) - (save-excursion - (goto-char event-point) - (setq event-lbp (line-beginning-position) - event-lep (line-end-position))) - (flymake-diagnostics event-lbp event-lep)))) - (diag (car diags))) - (unless diag - (error "No diagnostics here")) - (list diag)))) - (flymake-diagnostics (point)))) - (unless flymake-mode - (user-error "Flymake mode is not enabled in the current buffer")) - (let* ((name (flymake--diagnostics-buffer-name)) - (source (current-buffer)) - (target (or (get-buffer name) - (with-current-buffer (get-buffer-create name) - (flymake-diagnostics-buffer-mode) - (current-buffer)))) - window) - (with-current-buffer target - (setq flymake--diagnostics-buffer-source source) - (revert-buffer) - (setq window - (display-buffer (current-buffer) - `((display-buffer-reuse-window - display-buffer-below-selected) - (window-height . flymake--fit-diagnostics-window)))) - (when (and window diagnostic) - (with-selected-window window - (cl-loop initially (goto-char (point-min)) - until (eobp) - until (eq (plist-get (tabulated-list-get-id) :diagnostic) - diagnostic) - do (forward-line) - finally - (recenter) - (pulse-momentary-highlight-one-line - (point) 'highlight))))))) - - -;;; Per-project diagnostic listing -;;; - -(defvar flymake-list-only-diagnostics nil - "Diagnostics list meant for listing, not highlighting. -This variable holds an alist ((FILE-NAME . DIAGS) ...) where -FILE-NAME is a string holding an absolute file name and DIAGS is -a list of diagnostic objects created with -`flymake-make-diagnostic'. These diagnostics are never annotated -as overlays in actual buffers: they merely serve as temporary -stand-ins for more accurate diagnostics that are produced once -the file they refer to is visited and `flymake-mode' is turned on -in the resulting buffer. - -Flymake backends that somehow gain sporadic information about -diagnostics in neighboring files may freely modify this variable -by adding or removing entries to for those files. If the -information about those neighboring files is acquired repeatedly -and reliably, it may be more sensible to report them as -\"foreign\" diagnostics instead. - -Commands such as `flymake-show-project-diagnostics' will include -some of this variable's contents the diagnostic listings.") - -(defvar-local flymake--project-diagnostic-list-project nil) - -(define-derived-mode flymake-project-diagnostics-mode tabulated-list-mode - "Flymake diagnostics" - "A mode for listing Flymake diagnostics in a project." - :interactive nil - (flymake--tabulated-setup t)) - -(cl-defun flymake--project-diagnostics (&optional (project (project-current))) - "Get all known relevant diagnostics for PROJECT." - (let* ((root (project-root project)) - (visited-buffers (cl-remove-if-not #'buffer-file-name (project-buffers project))) - buffer-annotated-diags - relevant-foreign-diags - list-only-diags - annotated-diag-files) - (setq buffer-annotated-diags - (cl-loop for buf in visited-buffers - for diags = (with-current-buffer buf - (flymake-diagnostics)) - when diags do - (push (buffer-file-name buf) annotated-diag-files) - append (cl-sort diags #'< :key #'flymake-diagnostic-beg))) - (cl-loop - for buf in visited-buffers - do (with-current-buffer buf - (when flymake-mode - (maphash - (lambda (_backend state) - (maphash - (lambda (foreign-file diags) - (setq foreign-file (expand-file-name foreign-file)) - ;; FIXME: This is not right if more than one visited - ;; source targets the same foreign file. Don't - ;; think we can get away without some kind of - ;; `cl-remove-duplicates' here that utilizes - ;; `flymake--equal-diagnostic-p'. - (unless (member foreign-file annotated-diag-files) - (push foreign-file annotated-diag-files) - (setq relevant-foreign-diags - (append relevant-foreign-diags - diags)))) - (flymake--state-foreign-diags state))) - flymake--state)))) - (setq list-only-diags - (cl-loop for (file-name . diags) in flymake-list-only-diagnostics - if (and (string-prefix-p (expand-file-name root) file-name) - (not (member file-name annotated-diag-files))) - append diags)) - (append buffer-annotated-diags relevant-foreign-diags list-only-diags))) - -(defun flymake--project-diagnostics-buffer (root) - (get-buffer-create (format "*Flymake diagnostics for `%s'*" root))) - -(defun flymake-show-project-diagnostics () - "Show a list of Flymake diagnostics for the current project." - (interactive) - (let* ((prj (project-current)) - (root (project-root prj)) - (buffer (flymake--project-diagnostics-buffer root))) - (with-current-buffer buffer - (flymake-project-diagnostics-mode) - (setq-local flymake--project-diagnostic-list-project prj) - (revert-buffer) - (display-buffer (current-buffer) - `((display-buffer-reuse-window - display-buffer-at-bottom) - (window-height . flymake--fit-diagnostics-window)))))) - -(defun flymake--update-diagnostics-listings (buffer) - "Update diagnostics listings somehow relevant to BUFFER." - (dolist (probe (buffer-list)) - (with-current-buffer probe - (when (or (and (eq major-mode 'flymake-project-diagnostics-mode) - flymake--project-diagnostic-list-project - (buffer-file-name buffer) - (memq buffer - (project-buffers flymake--project-diagnostic-list-project))) - (and (eq major-mode 'flymake-diagnostics-buffer-mode) - (eq flymake--diagnostics-buffer-source buffer))) - (revert-buffer))))) - -(provide 'flymake) - -;;; flymake.el ends here diff --git a/elpa/flymake-1.4.5.signed b/elpa/flymake-1.4.5.signed new file mode 100644 index 00000000..a18a81e7 --- /dev/null +++ b/elpa/flymake-1.4.5.signed @@ -0,0 +1 @@ +Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) (trust undefined) created at 2026-03-09T22:10:02+0100 using EDDSA \ No newline at end of file diff --git a/elpa/flymake-1.4.5/README-elpa b/elpa/flymake-1.4.5/README-elpa new file mode 100644 index 00000000..2decf7e5 --- /dev/null +++ b/elpa/flymake-1.4.5/README-elpa @@ -0,0 +1,79 @@ +Flymake is a minor Emacs mode performing on-the-fly syntax checks. + +Flymake collects diagnostic information for multiple sources, +called backends, and visually annotates the relevant portions in +the buffer. + +This file contains the UI for displaying and interacting with the +results produced by these backends, as well as entry points for +backends to hook on to. + +The main interactive entry point is the `flymake-mode' minor mode, +which periodically and automatically initiates checks as the user +is editing the buffer. The variables `flymake-no-changes-timeout', +`flymake-start-on-flymake-mode' give finer control over the events +triggering a check, as does the interactive command `flymake-start', +which immediately starts a check. + +Shortly after each check, a summary of collected diagnostics should +appear in the mode-line. If it doesn't, there might not be a +suitable Flymake backend for the current buffer's major mode, in +which case Flymake will indicate this in the mode-line. The +indicator will be `!' (exclamation mark), if all the configured +backends errored (or decided to disable themselves) and `?' +(question mark) if no backends were even configured. + +For programmers interested in writing a new Flymake backend, the +docstring of `flymake-diagnostic-functions', the Flymake manual, and the +code of existing backends are probably good starting points. + +The user wishing to customize the appearance of error types should +set properties on the symbols associated with each diagnostic type. +The standard diagnostic symbols are `:error', `:warning' and +`:note' (though a specific backend may define and use more). The +following properties can be set: + +* `flymake-bitmap', an image displayed in the fringe according to +`flymake-fringe-indicator-position'. The value actually follows +the syntax of `flymake-error-bitmap' (which see). It is overridden +by any `before-string' overlay property. + +* `flymake-severity', a non-negative integer specifying the +diagnostic's severity. The higher, the more serious. If the +overlay property `priority' is not specified, `severity' is used to +set it and help sort overlapping overlays. + +* `flymake-overlay-control', an alist ((OVPROP . VALUE) ...) of +further properties used to affect the appearance of Flymake +annotations. With the exception of `category' and `evaporate', +these properties are applied directly to the created overlay. See +Info Node `(elisp)Overlay Properties'. + +* `flymake-category', a symbol whose property list is considered a +default for missing values of any other properties. This is useful +to backend authors when creating new diagnostic types that differ +from an existing type by only a few properties. The category +symbols `flymake-error', `flymake-warning' and `flymake-note' make +good candidates for values of this property. + +For instance, to omit the fringe bitmap displayed for the standard +`:note' type, set its `flymake-bitmap' property to nil: + + (put :note 'flymake-bitmap nil) + +To change the face for `:note' type, add a `face' entry to its +`flymake-overlay-control' property. + + (push '(face . highlight) (get :note 'flymake-overlay-control)) + +If you push another alist entry in front, it overrides the previous +one. So this effectively removes the face from `:note' +diagnostics. + + (push '(face . nil) (get :note 'flymake-overlay-control)) + +To erase customizations and go back to the original look for +`:note' types: + + (cl-remf (symbol-plist :note) 'flymake-overlay-control) + (cl-remf (symbol-plist :note) 'flymake-bitmap) \ No newline at end of file diff --git a/elpa/flymake-1.4.5/dir b/elpa/flymake-1.4.5/dir new file mode 100644 index 00000000..c5e42a8d --- /dev/null +++ b/elpa/flymake-1.4.5/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs misc features +* Flymake: (flymake). A universal on-the-fly syntax checker. diff --git a/elpa/flymake-1.4.5/doclicense.texi b/elpa/flymake-1.4.5/doclicense.texi new file mode 100644 index 00000000..eaf3da0e --- /dev/null +++ b/elpa/flymake-1.4.5/doclicense.texi @@ -0,0 +1,505 @@ +@c The GNU Free Documentation License. +@center Version 1.3, 3 November 2008 + +@c This file is intended to be included within another document, +@c hence no sectioning command or @node. + +@display +Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. +@uref{https://fsf.org/} + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document @dfn{free} in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The ``Document'', below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as ``you''. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section +of the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, La@TeX{} input +format, SGML or XML using a publicly available +DTD, and standard-conforming simple HTML, +PostScript or PDF designed for human modification. Examples +of transparent image formats include PNG, XCF and +JPG@. Opaque formats include proprietary formats that can be +read and edited only by proprietary word processors, SGML or +XML for which the DTD and/or processing tools are +not generally available, and the machine-generated HTML, +PostScript or PDF produced by some word processors for +output purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The ``publisher'' means any person or entity that distributes copies +of the Document to the public. + +A section ``Entitled XYZ'' means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as ``Acknowledgements'', +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' +of such a section when you modify the Document means that it remains a +section ``Entitled XYZ'' according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@item +COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +@enumerate A +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document's license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled ``History'', Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled ``History'' in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the ``History'' section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve +the Title of the section, and preserve in the section all the +substance and tone of each of the contributor acknowledgements and/or +dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled ``Endorsements''. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled ``Endorsements'' or +to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties---for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled ``History'' +in the various original documents, forming one section Entitled +``History''; likewise combine any sections Entitled ``Acknowledgements'', +and any sections Entitled ``Dedications''. You must delete all +sections Entitled ``Endorsements.'' + +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an ``aggregate'' if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled ``Acknowledgements'', +``Dedications'', or ``History'', the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +@uref{https://www.gnu.org/licenses/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +@item +RELICENSING + +``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the +site means any set of copyrightable works thus published on the MMC +site. + +``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +``Incorporate'' means to publish or republish a Document, in whole or +in part, as part of another Document. + +An MMC is ``eligible for relicensing'' if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole +or in part into the MMC, (1) had no cover texts or invariant sections, +and (2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + +@end enumerate + +@page +@heading ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group + Copyright (C) @var{year} @var{your name}. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. +@end group +@end smallexample + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the ``with@dots{}Texts.''@: line with this: + +@smallexample +@group + with the Invariant Sections being @var{list their titles}, with + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts + being @var{list}. +@end group +@end smallexample + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@c Local Variables: +@c ispell-local-pdict: "ispell-dict" +@c End: diff --git a/elpa/flymake-1.4.5/docstyle.texi b/elpa/flymake-1.4.5/docstyle.texi new file mode 100644 index 00000000..e7404398 --- /dev/null +++ b/elpa/flymake-1.4.5/docstyle.texi @@ -0,0 +1,19 @@ +@c Emacs documentation style settings +@documentencoding UTF-8 +@c These two require Texinfo 5.0 or later, so we use the older +@c equivalent @set variables supported in 4.11 and hence +@ignore +@codequotebacktick on +@codequoteundirected on +@end ignore +@set txicodequoteundirected +@set txicodequotebacktick +@iftex +@c It turns out TeX sometimes fails to hyphenate, so we help it here +@hyphenation{au-to-mat-i-cal-ly} +@hyphenation{spec-i-fied} +@hyphenation{work-a-round} +@hyphenation{work-a-rounds} +@hyphenation{un-marked} +@hyphenation{dic-tion-ary} +@end iftex diff --git a/elpa/flymake-1.4.5/flymake-autoloads.el b/elpa/flymake-1.4.5/flymake-autoloads.el new file mode 100644 index 00000000..7d943555 --- /dev/null +++ b/elpa/flymake-1.4.5/flymake-autoloads.el @@ -0,0 +1,138 @@ +;;; flymake-autoloads.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*- +;; Generated by the `loaddefs-generate' function. + +;; This file is part of GNU Emacs. + +;;; Code: + +(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path))) + + + +;;; Generated autoloads from flymake.el + +(autoload 'flymake-log "flymake" +"Log, at level LEVEL, the message MSG formatted with ARGS. +LEVEL is passed to `display-warning', which is used to display +the warning. If this form is included in a file, +the generated warning contains an indication of the file that +generated it. + +(fn LEVEL MSG &rest ARGS)" nil t) +(autoload 'flymake-make-diagnostic "flymake" +"Make a Flymake diagnostic for LOCUS's region from BEG to END. +LOCUS is a buffer object or a string designating a file name. + +TYPE is a diagnostic symbol (see Info Node `(Flymake)Flymake error +types') + +INFO is a description of the problem detected. It may be a string, or +list (ORIGIN CODE MESSAGE) appropriately categorizing and describing the +diagnostic. ORIGIN may be a string or nil. CODE maybe be a string, a +number or nil. MESSAGE must be a string. + +DATA is any object that the caller wishes to attach to the created +diagnostic for later retrieval with `flymake-diagnostic-data'. + +If LOCUS is a buffer, BEG and END should be buffer positions inside it. +If LOCUS designates a file, BEG and END should be a cons (LINE . COL) +indicating a file position. In this second case, END may be omitted in +which case the region is computed using `flymake-diag-region' if the +diagnostic is appended to an actual buffer. + +OVERLAY-PROPERTIES is an alist of properties attached to the created +diagnostic, overriding the default properties and any properties listed +in the `flymake-overlay-control' property of the diagnostic's type +symbol. + +(fn LOCUS BEG END TYPE INFO &optional DATA OVERLAY-PROPERTIES)") +(autoload 'flymake-diagnostics "flymake" +"Get Flymake diagnostics in region determined by BEG and END. + +If neither BEG or END is supplied, use whole accessible buffer, +otherwise if BEG is non-nil and END is nil, consider only +diagnostics at BEG. + +(fn &optional BEG END)") +(autoload 'flymake-diag-region "flymake" +"Compute BUFFER's region (BEG . END) corresponding to LINE and COL. +If COL is nil, return a region just for LINE. Return nil if the +region is invalid. This function saves match data. + +(fn BUFFER LINE &optional COL)") +(autoload 'flymake-mode "flymake" +"Toggle Flymake mode on or off. + +Flymake is an Emacs minor mode for on-the-fly syntax checking. +Flymake collects diagnostic information from multiple sources, +called backends, and visually annotates the buffer with the +results. + +Flymake performs these checks while the user is editing. +The customization variables `flymake-start-on-flymake-mode', +`flymake-no-changes-timeout' determine the exact circumstances +whereupon Flymake decides to initiate a check of the buffer. + +The commands `flymake-goto-next-error' and +`flymake-goto-prev-error' can be used to navigate among Flymake +diagnostics annotated in the buffer. + +By default, `flymake-mode' doesn't override the \\[next-error] command, but +if you're using Flymake a lot (and don't use the regular compilation +mechanisms that often), it can be useful to put something like +the following in your init file: + + (setq next-error-function \\='flymake-goto-next-error) + +The visual appearance of each type of diagnostic can be changed +by setting properties `flymake-overlay-control', `flymake-bitmap' +and `flymake-severity' on the symbols of diagnostic types (like +`:error', `:warning' and `:note'). + +Activation or deactivation of backends used by Flymake in each +buffer happens via the special hook +`flymake-diagnostic-functions'. + +Some backends may take longer than others to respond or complete, +and some may decide to disable themselves if they are not +suitable for the current buffer. The commands +`flymake-running-backends', `flymake-disabled-backends' and +`flymake-reporting-backends' summarize the situation, as does the +special *Flymake log* buffer. + +This is a minor mode. If called interactively, toggle the `Flymake +mode' mode. If the prefix argument is positive, enable the mode, and if +it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the mode +if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate the variable `flymake-mode'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +\\{flymake-mode-map} + +(fn &optional ARG)" t) +(autoload 'flymake-mode-on "flymake" +"Turn Flymake mode on.") +(autoload 'flymake-mode-off "flymake" +"Turn Flymake mode off.") +(register-definition-prefixes "flymake" '("flymake-")) + +;;; End of scraped data + +(provide 'flymake-autoloads) + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; no-native-compile: t +;; coding: utf-8-emacs-unix +;; End: + +;;; flymake-autoloads.el ends here diff --git a/elpa/flymake-1.4.5/flymake-pkg.el b/elpa/flymake-1.4.5/flymake-pkg.el new file mode 100644 index 00000000..390773f9 --- /dev/null +++ b/elpa/flymake-1.4.5/flymake-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from flymake.el -*- no-byte-compile: t; lexical-binding:t -*- +(define-package "flymake" "1.4.5" "A universal on-the-fly syntax checker" '((emacs "26.1") (eldoc "1.14.0") (project "0.11.1")) :commit "ab47eadb60795f2a08a4444179e395d5e34d68b1" :url "https://elpa.gnu.org/packages/flymake.html" :authors '(("Pavel Kobyakov" . "pk_at_work@yahoo.com")) :maintainer '("Spencer Baugh" . "sbaugh@janestreet.com") :keywords '("c" "languages" "tools")) diff --git a/elpa/flymake-1.4.5/flymake.el b/elpa/flymake-1.4.5/flymake.el new file mode 100644 index 00000000..4e828eba --- /dev/null +++ b/elpa/flymake-1.4.5/flymake.el @@ -0,0 +1,2476 @@ +;;; flymake.el --- A universal on-the-fly syntax checker -*- lexical-binding: t; -*- + +;; Copyright (C) 2003-2026 Free Software Foundation, Inc. + +;; Author: Pavel Kobyakov +;; Maintainer: Spencer Baugh +;; Version: 1.4.5 +;; Keywords: c languages tools +;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.11.1")) + +;; This is a GNU ELPA :core package. Avoid functionality that is not +;; compatible with the version of Emacs recorded above. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; +;; Flymake is a minor Emacs mode performing on-the-fly syntax checks. +;; +;; Flymake collects diagnostic information for multiple sources, +;; called backends, and visually annotates the relevant portions in +;; the buffer. +;; +;; This file contains the UI for displaying and interacting with the +;; results produced by these backends, as well as entry points for +;; backends to hook on to. +;; +;; The main interactive entry point is the `flymake-mode' minor mode, +;; which periodically and automatically initiates checks as the user +;; is editing the buffer. The variables `flymake-no-changes-timeout', +;; `flymake-start-on-flymake-mode' give finer control over the events +;; triggering a check, as does the interactive command `flymake-start', +;; which immediately starts a check. +;; +;; Shortly after each check, a summary of collected diagnostics should +;; appear in the mode-line. If it doesn't, there might not be a +;; suitable Flymake backend for the current buffer's major mode, in +;; which case Flymake will indicate this in the mode-line. The +;; indicator will be `!' (exclamation mark), if all the configured +;; backends errored (or decided to disable themselves) and `?' +;; (question mark) if no backends were even configured. +;; +;; For programmers interested in writing a new Flymake backend, the +;; docstring of `flymake-diagnostic-functions', the Flymake manual, and the +;; code of existing backends are probably good starting points. +;; +;; The user wishing to customize the appearance of error types should +;; set properties on the symbols associated with each diagnostic type. +;; The standard diagnostic symbols are `:error', `:warning' and +;; `:note' (though a specific backend may define and use more). The +;; following properties can be set: +;; +;; * `flymake-bitmap', an image displayed in the fringe according to +;; `flymake-fringe-indicator-position'. The value actually follows +;; the syntax of `flymake-error-bitmap' (which see). It is overridden +;; by any `before-string' overlay property. +;; +;; * `flymake-severity', a non-negative integer specifying the +;; diagnostic's severity. The higher, the more serious. If the +;; overlay property `priority' is not specified, `severity' is used to +;; set it and help sort overlapping overlays. +;; +;; * `flymake-overlay-control', an alist ((OVPROP . VALUE) ...) of +;; further properties used to affect the appearance of Flymake +;; annotations. With the exception of `category' and `evaporate', +;; these properties are applied directly to the created overlay. See +;; Info Node `(elisp)Overlay Properties'. +;; +;; * `flymake-category', a symbol whose property list is considered a +;; default for missing values of any other properties. This is useful +;; to backend authors when creating new diagnostic types that differ +;; from an existing type by only a few properties. The category +;; symbols `flymake-error', `flymake-warning' and `flymake-note' make +;; good candidates for values of this property. +;; +;; For instance, to omit the fringe bitmap displayed for the standard +;; `:note' type, set its `flymake-bitmap' property to nil: +;; +;; (put :note 'flymake-bitmap nil) +;; +;; To change the face for `:note' type, add a `face' entry to its +;; `flymake-overlay-control' property. +;; +;; (push '(face . highlight) (get :note 'flymake-overlay-control)) +;; +;; If you push another alist entry in front, it overrides the previous +;; one. So this effectively removes the face from `:note' +;; diagnostics. +;; +;; (push '(face . nil) (get :note 'flymake-overlay-control)) +;; +;; To erase customizations and go back to the original look for +;; `:note' types: +;; +;; (cl-remf (symbol-plist :note) 'flymake-overlay-control) +;; (cl-remf (symbol-plist :note) 'flymake-bitmap) +;; +;;; Code: + +(require 'cl-lib) +(require 'thingatpt) ; end-of-thing +(require 'warnings) ; warning-numeric-level, display-warning +(require 'compile) ; for some faces +;; We need the next `require' to avoid compiler warnings and run-time +;; errors about mouse-wheel-up/down-event in builds --without-x, where +;; mwheel is not preloaded. +(require 'mwheel) +;; when-let*, if-let*, hash-table-keys, hash-table-values: +(eval-when-compile (require 'subr-x)) +(require 'project) + +(defgroup flymake nil + "Universal on-the-fly syntax checker." + :version "23.1" + :link '(custom-manual "(flymake) Top") + :group 'tools) + +(add-to-list 'customize-package-emacs-version-alist + '(Flymake ("1.3.4" . "30.1") + ("1.3.5" . "30.1") + ("1.3.6" . "30.1"))) + +(defcustom flymake-error-bitmap '(flymake-double-exclamation-mark + flymake-error-fringe) + "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." + :version "31.1" + :type '(choice (symbol :tag "Bitmap") + (list :tag "Bitmap and face" + (symbol :tag "Bitmap") + (face :tag "Face")))) + +(defcustom flymake-warning-bitmap '(exclamation-mark flymake-warning-fringe) + "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." + :version "31.1" + :type '(choice (symbol :tag "Bitmap") + (list :tag "Bitmap and face" + (symbol :tag "Bitmap") + (face :tag "Face")))) + +(defcustom flymake-note-bitmap '(exclamation-mark flymake-note-fringe) + "Bitmap (a symbol) used in the fringe for indicating info notes. +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." + :version "31.1" + :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'." + :version "24.3" + :type '(choice (const left-fringe) + (const right-fringe) + (const :tag "No fringe indicators" nil))) + +(defcustom flymake-indicator-type 'auto + "Indicate which indicator type to use for display errors. + +The value can be nil (don't indicate errors but just highlight them), +the symbol `fringes' (use fringes), the symbol `margins' (use margins), +or the symbol `auto' to automatically guess. + +Difference between fringes and margin is that fringes support displaying +bitmaps on graphical displays and margins display text in a blank area +from current buffer that works in both graphical and text displays. +When margins are selected, Flymake may need to resize them for each +buffer. See `flymake-autoresize-margins'. + +See Info node `Fringes' and Info node `(elisp)Display Margins'." + :version "31.1" + :type '(choice (const :tag "Use Fringes" fringes) + (const :tag "Use Margins" margins) + (const :tag "Use fringes if possible, otherwise margins" auto) + (const :tag "No indicators" nil))) + +(defcustom flymake-margin-indicators-string + '((error "‼" compilation-error) + (warning "!" compilation-warning) + (note "!" compilation-info)) + "Strings used for margins indicators. +The value of each list may be a list of 3 elements where specifies the +error type, the string to use and its face, +or a list of 2 elements specifying only the error type and +the corresponding string. + +The option `flymake-margin-indicator-position' controls how and where +this is used. + +Note that the default value \"DOUBLE EXCLAMATION MARK\" for the +indicator of the \\+`error' type will be silently replaced by the +ASCII equivalent if that character is not displayable by the terminal." + :version "30.1" + :type '(repeat :tag "Error types lists" + (list :tag "String and face for error types" + (symbol :tag "Error type") + (string :tag "String") + (face :tag "Face")))) + +(defcustom flymake-autoresize-margins t + "If non-nil, automatically resize margin-width. + +Only relevant if `flymake-indicator-type' is set to `margins' or `auto'." + :version "30.1" + :type 'boolean) + +(defcustom flymake-margin-indicator-position 'left-margin + "The position to put Flymake margin indicator. +The value can be nil (do not use indicators), `left-margin' or `right-margin'. +See `flymake-margin-indicators-string'." + :version "30.1" + :type '(choice (const left-margin) + (const right-margin) + (const :tag "No margin indicators" nil))) + +(make-obsolete-variable 'flymake-start-syntax-check-on-newline + "can check on newline in post-self-insert-hook" + "27.1") + +(defcustom flymake-no-changes-timeout 0.5 + "Time to wait after last change before automatically checking buffer. +If nil, never start checking buffer automatically like this." + :type '(choice (number :tag "Timeout in seconds") + (const :tag "No check on timeout" nil))) + +(defcustom flymake-gui-warnings-enabled t + "Enables/disables GUI warnings." + :type 'boolean) +(make-obsolete-variable 'flymake-gui-warnings-enabled + "it no longer has any effect." "26.1") + +(define-obsolete-variable-alias 'flymake-start-syntax-check-on-find-file + 'flymake-start-on-flymake-mode "26.1") + +(defcustom flymake-start-on-flymake-mode t + "If non-nil, start syntax check when `flymake-mode' is enabled. +Specifically, start it when the buffer is actually displayed." + :version "26.1" + :type 'boolean) + +(defcustom flymake-start-on-save-buffer t + "If non-nil, start syntax check when a buffer is saved. +Specifically, start it when the saved buffer is actually displayed." + :version "27.1" + :type 'boolean) + +(defcustom flymake-log-level -1 + "Obsolete and ignored variable." + :type 'integer) +(make-obsolete-variable 'flymake-log-level + "it is superseded by `warning-minimum-log-level.'" + "26.1") + +(defcustom flymake-wrap-around t + "If non-nil, moving to errors wraps around buffer boundaries." + :version "26.1" + :type 'boolean) + +(defcustom flymake-suppress-zero-counters :warning + "Control appearance of zero-valued diagnostic counters in mode line. + +If set to t, suppress all zero counters. If set to a severity +symbol like `:warning' (the default) suppress zero counters less +severe than that severity, according to `warning-numeric-level'. +If set to nil, don't suppress any zero counters." + :type 'symbol) + +(when (fboundp 'define-fringe-bitmap) + (define-fringe-bitmap 'flymake-double-exclamation-mark + (vector #b00000000 + #b00000000 + #b00000000 + #b00000000 + #b01100110 + #b01100110 + #b01100110 + #b01100110 + #b01100110 + #b01100110 + #b01100110 + #b01100110 + #b00000000 + #b01100110 + #b00000000 + #b00000000 + #b00000000))) + +(defvar-local flymake-timer nil + "Timer for starting syntax check.") + +(defvar-local flymake-check-start-time nil + "Time at which syntax check was started.") + +(defun flymake--log-1 (level sublog msg &rest args) + "Do actual work for `flymake-log'." + (let (;; never popup the log buffer + (warning-minimum-level :emergency) + (warning-type-format + (format " [%s %s]" + (or sublog 'flymake) + ;; Handle file names with "%" correctly. (Bug#51549) + (replace-regexp-in-string "%" "%%" + (buffer-name (current-buffer)))))) + (display-warning (list 'flymake sublog) + (apply #'format-message msg args) + (if (numberp level) + (or (nth level + '(:emergency :error :warning :debug :debug) ) + :error) + level) + "*Flymake log*"))) + +(defun flymake-switch-to-log-buffer () + "Go to the *Flymake log* buffer." + (interactive) + (switch-to-buffer "*Flymake log*")) + +;;;###autoload +(defmacro flymake-log (level msg &rest args) + "Log, at level LEVEL, the message MSG formatted with ARGS. +LEVEL is passed to `display-warning', which is used to display +the warning. If this form is included in a file, +the generated warning contains an indication of the file that +generated it." + (let* ((file (if (fboundp 'macroexp-file-name) + (macroexp-file-name) + (and (not load-file-name) + (bound-and-true-p byte-compile-current-file)))) + (sublog (if (stringp file) + (intern + (file-name-nondirectory + (file-name-sans-extension file)))))) + `(flymake--log-1 ,level ',sublog ,msg ,@args))) + +(defun flymake-error (text &rest args) + "Format TEXT with ARGS and signal an error for Flymake." + (let ((msg (apply #'format-message text args))) + (flymake-log :error "%s" msg) + (error (concat "[Flymake] " msg)))) + +(cl-defstruct (flymake--diag + (:constructor flymake--diag-make)) + locus beg end type origin code message backend data overlay-properties overlay + ;; FIXME: See usage of these two in `flymake--highlight-line'. + ;; Ideally they wouldn't be needed. + orig-beg orig-end) + +;;;###autoload +(defun flymake-make-diagnostic (locus + beg + end + type + info + &optional data + overlay-properties) + "Make a Flymake diagnostic for LOCUS's region from BEG to END. +LOCUS is a buffer object or a string designating a file name. + +TYPE is a diagnostic symbol (see Info Node `(Flymake)Flymake error +types') + +INFO is a description of the problem detected. It may be a string, or +list (ORIGIN CODE MESSAGE) appropriately categorizing and describing the +diagnostic. ORIGIN may be a string or nil. CODE maybe be a string, a +number or nil. MESSAGE must be a string. + +DATA is any object that the caller wishes to attach to the created +diagnostic for later retrieval with `flymake-diagnostic-data'. + +If LOCUS is a buffer, BEG and END should be buffer positions inside it. +If LOCUS designates a file, BEG and END should be a cons (LINE . COL) +indicating a file position. In this second case, END may be omitted in +which case the region is computed using `flymake-diag-region' if the +diagnostic is appended to an actual buffer. + +OVERLAY-PROPERTIES is an alist of properties attached to the created +diagnostic, overriding the default properties and any properties listed +in the `flymake-overlay-control' property of the diagnostic's type +symbol." + (when (stringp locus) + (setq locus (expand-file-name locus))) + (cond ((stringp info) + (setq info (list nil nil info))) + ((numberp (cadr info)) + (setf (cadr info) (number-to-string (cadr info))))) + (flymake--diag-make :locus locus :beg beg :end end + :type type :origin (car info) :code (cadr info) + :message (caddr info) :data data + :overlay-properties overlay-properties + :orig-beg beg + :orig-end end)) + +;;;###autoload +(defun flymake-diagnostics (&optional beg end) + "Get Flymake diagnostics in region determined by BEG and END. + +If neither BEG or END is supplied, use whole accessible buffer, +otherwise if BEG is non-nil and END is nil, consider only +diagnostics at BEG." + (save-restriction + (widen) + (cl-loop for o in + (cond (end (overlays-in beg end)) + (beg (overlays-at beg)) + (t (overlays-in (point-min) (point-max)))) + when (overlay-get o 'flymake-diagnostic) collect it))) + +(defmacro flymake--diag-accessor (public internal thing) + "Make PUBLIC an alias for INTERNAL, add doc using THING." + `(defsubst ,public (diag) + ,(format "Get Flymake diagnostic DIAG's %s." (symbol-name thing)) + (,internal diag))) + +(flymake--diag-accessor flymake-diagnostic-type flymake--diag-type type) +(flymake--diag-accessor flymake-diagnostic-backend flymake--diag-backend backend) +(flymake--diag-accessor flymake-diagnostic-origin flymake--diag-origin backend) +(flymake--diag-accessor flymake-diagnostic-code flymake--diag-code backend) +(flymake--diag-accessor flymake-diagnostic-message flymake--diag-message backend) +(flymake--diag-accessor flymake-diagnostic-data flymake--diag-data data) +(flymake--diag-accessor flymake-diagnostic-beg flymake--diag-beg beg) +(flymake--diag-accessor flymake-diagnostic-end flymake--diag-end end) +(flymake--diag-accessor flymake-diagnostic-buffer flymake--diag-locus locus) + +(defcustom flymake-diagnostic-format-alist + '((:help-echo . (origin code oneliner)) + (:eol . (oneliner)) + (:eldoc . (origin code message)) + (:eldoc-echo . (origin code oneliner)) + (t . (origin code oneliner))) + "How to format diagnostics for different output destinations. +Value is an alist where each element looks like (DESTINATION . PARTS). +DESTINATION is a symbol designating an outlet. One of: + +- `:help-echo', for the native Flymake echoing of diagnostics in the + echo area as used my `flymake-goto-next-error' and `flymake-goto-prev-error'; +- `:eol', for use with `flymake-show-diagnostics-at-end-of-line'; +- `:eldoc', for use with Flymake's ElDoc backend; +- `:eldoc-echo', for use with Flymake's ElDoc backend, but for ElDoc's own + confined outlets; +- t for all other destinations. + +PARTS says which parts of the diagnostic to include. It is a list of +symbols where the following values are meaningful: + +- `origin': include diagnostic origin if it exists; +- `code': include diagnostics code if it exists; +- `message': include the full diagnostic's message text; +- `oneliner': include truncated diagnostic text;" + :package-version '(Flymake . "1.4.0") + :type '(alist :key-type (choice (const :help-echo) + (const :eol) + (const :eldoc) + (const :eldoc-echo) + (const t)) + :value-type (set (const origin) + (const code) + (const message) + (const oneliner)))) + +(cl-defun flymake-diagnostic-text (diag + &optional (parts '(origin code message))) + "Describe diagnostic DIAG's as a string. +PARTS says which parts of the diagnostic to include. It is a list of +symbols as described in `flymake-diagnostic-format-alist' (which see). +PARTS defaults to `(origin code message)'." + (let* ((w parts) + (a (and (memq 'origin w) (flymake--diag-origin diag))) + (b (and (memq 'code w) (flymake--diag-code diag))) + (c (cond ((memq 'message w) (flymake--diag-message diag)) + ((memq 'oneliner w) + (let* ((msg (flymake--diag-message diag))) + (substring msg 0 (cl-loop for i from 0 for a across msg + when (eq a ?\n) return i))))))) + (concat a + (when (and a b) " ") + (when b (concat "[" b "]")) + (when (and c (or a b)) ": ") + c))) + +(defun flymake--format-diagnostic (diag destination face-prop) + (let ((txt (flymake-diagnostic-text + diag (alist-get destination flymake-diagnostic-format-alist + (alist-get t flymake-diagnostic-format-alist + '(origin code message)))))) + (if face-prop + (propertize txt 'face + (flymake--lookup-type-property + (flymake-diagnostic-type diag) face-prop + 'flymake-error)) + txt))) + +(defun flymake-diagnostic-oneliner (diag &optional nopaintp) + "Get truncated one-line text string for diagnostic DIAG. +This is useful for displaying the DIAG's text to the user in +confined spaces, such as the echo are. Unless NOPAINTP is t, +propertize returned text with the `echo-face' property of DIAG's +type." + (let* ((txt (flymake-diagnostic-text diag '(origin code oneliner)))) + (if nopaintp txt + (propertize txt 'face + (flymake--lookup-type-property + (flymake-diagnostic-type diag) 'echo-face 'flymake-error))))) +(make-obsolete 'flymake-diagnostic-oneliner + "use `flymake-diagnostic-text' instead." + "Flymake package version 1.4.0") + +(cl-defun flymake--really-all-overlays () + "Get flymake-related overlays. +If BEG is non-nil and END is nil, consider only `overlays-at' +BEG. Otherwise consider `overlays-in' the region comprised by BEG +and END, defaulting to the whole buffer. Remove all that do not +verify FILTER, a function, and sort them by COMPARE (using KEY)." + (save-restriction + (widen) + (cl-remove-if-not (lambda (o) (overlay-get o 'flymake-overlay)) + (overlays-in (point-min) (point-max))))) + +(defface flymake-error + '((((supports :underline (:style wave))) + :underline (:style wave :color "Red1")) + (t + :inherit error)) + "Face used for marking error regions." + :version "24.4") + +(defface flymake-warning + '((((supports :underline (:style wave))) + :underline (:style wave :color "deep sky blue")) + (t + :inherit warning)) + "Face used for marking warning regions." + :version "24.4") + +(defface flymake-note + '((((supports :underline (:style wave))) + :underline (:style wave :color "yellow green")) + (t + :inherit warning)) + "Face used for marking note regions." + :version "26.1") + +(defface flymake-error-echo + '((t :inherit compilation-error)) + "Face used for showing summarized descriptions of errors." + :package-version '(Flymake . "1.3.4")) + +(defface flymake-warning-echo + '((t :inherit compilation-warning)) + "Face used for showing summarized descriptions of warnings." + :package-version '(Flymake . "1.3.4")) + +(defface flymake-note-echo + '((t :inherit compilation-info)) + "Face used for showing summarized descriptions of notes." + :package-version '(Flymake . "1.3.4")) + +(defface flymake-end-of-line-diagnostics-face + '((t :height 0.85)) + "Face used for end-of-line diagnostics. +See variable `flymake-show-diagnostics-at-end-of-line'." + :package-version '(Flymake . "1.3.5")) + +(defface flymake-error-echo-at-eol + '((t :inherit (flymake-end-of-line-diagnostics-face compilation-error))) + "Face like `flymake-error-echo', but for end-of-line overlays." + :package-version '(Flymake . "1.3.5")) + +(defface flymake-warning-echo-at-eol + '((t :inherit (flymake-end-of-line-diagnostics-face compilation-warning))) + "Face like `flymake-warning-echo', but for end-of-line overlays." + :package-version '(Flymake . "1.3.5")) + +(defface flymake-note-echo-at-eol + '((t :inherit (flymake-end-of-line-diagnostics-face compilation-info))) + "Face like `flymake-note-echo', but for end-of-line overlays." + :package-version '(Flymake . "1.3.5")) + +(defface flymake-eol-information-face + '((t :inherit (flymake-end-of-line-diagnostics-face) + :box nil + :slant italic)) + "Face used for information about end-of-line diagnostics." + :package-version '(Flymake . "1.3.6")) + +(defface flymake-error-fringe '((t :inherit compilation-error)) + "Face used by default in the `flymake-error-bitmap'." + :version "31.1" + :package-version '(Flymake . "1.4.4")) + +(defface flymake-warning-fringe '((t :inherit compilation-warning)) + "Face used by default in the `flymake-warning-bitmap'." + :version "31.1" + :package-version '(Flymake . "1.4.4")) + +(defface flymake-note-fringe '((t :inherit compilation-info)) + "Face used by default in the `flymake-note-bitmap'." + :version "31.1" + :package-version '(Flymake . "1.4.4")) + +(defcustom flymake-show-diagnostics-at-end-of-line nil + "If non-nil, add diagnostic summary messages at end-of-line. +The value `short' means that only the most severe diagnostic +shall be shown. +The value `fancy' means to layout diagnostic summary information +below the affected line with Unicode graphics. +Any other non-nil value means show all diagnostic summaries at +end-of-line." + :type '(choice (const :tag "Display most severe diagnostic" short) + (const :tag "Display all diagnostics" t) + (const :tag "Display all diagnostics using Unicode" fancy) + (const :tag "Don't display diagnostics at end-of-line" nil)) + :package-version '(Flymake . "1.3.6")) + +(define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1") +(define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1") + +;;;###autoload +(defun flymake-diag-region (buffer line &optional col) + "Compute BUFFER's region (BEG . END) corresponding to LINE and COL. +If COL is nil, return a region just for LINE. Return nil if the +region is invalid. This function saves match data." + (condition-case-unless-debug _err + (with-current-buffer buffer + (let ((line (min (max line 1) + (line-number-at-pos (point-max) 'absolute)))) + (save-excursion + (save-match-data + (goto-char (point-min)) + (forward-line (1- line)) + (cl-flet ((fallback-bol + () + (back-to-indentation) + (if (eobp) + (line-beginning-position 0) + (point))) + (fallback-eol + (beg) + (progn + (end-of-line) + (skip-chars-backward " \t\f\n" beg) + (if (eq (point) beg) + (line-beginning-position 2) + (point))))) + (if (and col (cl-plusp col)) + (let* ((beg (progn (forward-char (1- col)) + (point))) + (sexp-end (or (ignore-errors (end-of-thing 'sexp)) + (ignore-errors (end-of-thing 'symbol)))) + (end (or (and sexp-end + (not (= sexp-end beg)) + sexp-end) + (and (< (goto-char (1+ beg)) (point-max)) + (point))))) + (if end + (cons beg end) + (cons (setq beg (fallback-bol)) + (fallback-eol beg)))) + (let* ((beg (fallback-bol)) + (end (fallback-eol beg))) + (cons beg end)))))))) + (error (flymake-log :warning "Invalid region line=%s col=%s" line col) + nil))) + +(defvar flymake-diagnostic-functions nil + "Special hook of Flymake backends that check a buffer. + +The functions in this hook diagnose problems in a buffer's contents and +provide information to the Flymake user interface about where and how to +annotate problems diagnosed in a buffer. + +Each backend function must be prepared to accept an arbitrary number of +arguments: + +* the first argument is always REPORT-FN, a callback function + detailed below; + +* the remaining arguments are keyword-value pairs in the + form (:KEY VALUE :KEY2 VALUE2...). + +Currently, Flymake may provide these keyword-value pairs: + +* `:recent-changes', a list of recent changes since the last time the + backend function was called for the buffer. An empty list indicates + that no changes have been recorded. If it is the first time that this + backend function is called for this activation of `flymake-mode', then + this argument isn't provided at all (i.e. it's not merely nil). + + Each element is in the form (BEG END TEXT) where BEG and END are + buffer positions, and TEXT is a string containing the text contained + between those positions (if any) after the change was performed. + +* `:changes-start' and `:changes-end', the minimum and maximum buffer + positions touched by the recent changes. These are only provided if + `:recent-changes' is also provided. + +Whenever Flymake or the user decides to re-check the buffer, backend +functions are called as detailed above and are expected to initiate this +check, but aren't required to complete it before exiting: if the +computation involved is expensive, especially for large buffers, that +task can be scheduled for the future using asynchronous processes or +other asynchronous mechanisms. + +In any case, backend functions are expected to return quickly or signal +an error, in which case the backend is disabled. Flymake will not try +disabled backends again for any future checks of this buffer. To reset +the list of disabled backends, turn `flymake-mode' off and on again, or +interactively call `flymake-start' with a prefix argument. + +If the function returns, Flymake considers the backend to be +\"running\". If it has not done so already, the backend is expected to +call the function REPORT-FN with a single argument REPORT-ACTION also +followed by an optional list of keyword-value pairs in the +form (:REPORT-KEY VALUE :REPORT-KEY2 VALUE2...). + +Currently accepted values for REPORT-ACTION are: + +* A (possibly empty) list of diagnostic objects created with + `flymake-make-diagnostic', causing Flymake to delete all previous + diagnostic annotations in the buffer and create new ones from this + list. + + A backend may call REPORT-FN repeatedly in this manner, but only until + Flymake considers that the most recently requested buffer check is now + obsolete because, say, buffer contents have changed in the meantime. + The backend is only given notice of this via a renewed call to the + backend function. Thus, to prevent making obsolete reports and + wasting resources, backend functions should first cancel any ongoing + processing from previous calls. + +* The symbol `:panic', signaling that the backend has encountered an + exceptional situation and should be disabled. + +Currently accepted REPORT-KEY arguments are: + +* `:explanation' value should give user-readable details of the + situation encountered, if any. + +* `:force': value should be a boolean suggesting that Flymake consider + the report even if it was somehow unexpected. + +* `:region': a cons (BEG . END) of buffer positions specifying that + Flymake should only delete diagnostic annotations of past reports if + they intersect the region by at least one character. The list of + diagnostics objects in the report need not be contained in the region. + This makes it allows backends to choose between accumulating or + completely replacing diagnostics across different invocations of + REPORT-FN, by specifying a either 0-length region or the full buffer.") + +(put 'flymake-diagnostic-functions 'safe-local-variable #'null) + +(put :error 'flymake-category 'flymake-error) +(put :warning 'flymake-category 'flymake-warning) +(put :note 'flymake-category 'flymake-note) + +(defvar flymake-diagnostic-types-alist '()) +(make-obsolete-variable + 'flymake-diagnostic-types-alist + "Set properties on the diagnostic symbols instead. See Info +Node `(Flymake)Flymake error types'" + "27.1") + +(put 'flymake-error 'face 'flymake-error) +(put 'flymake-error 'flymake-bitmap 'flymake-error-bitmap) +(put 'flymake-error 'flymake-margin-string (alist-get 'error flymake-margin-indicators-string)) +(put 'flymake-error 'severity (warning-numeric-level :error)) +(put 'flymake-error 'mode-line-face 'flymake-error-echo) +(put 'flymake-error 'echo-face 'flymake-error-echo) +(put 'flymake-error 'eol-face 'flymake-error-echo-at-eol) +(put 'flymake-error 'flymake-type-name "error") + +(put 'flymake-warning 'face 'flymake-warning) +(put 'flymake-warning 'flymake-bitmap 'flymake-warning-bitmap) +(put 'flymake-warning 'flymake-margin-string (alist-get 'warning flymake-margin-indicators-string)) +(put 'flymake-warning 'severity (warning-numeric-level :warning)) +(put 'flymake-warning 'mode-line-face 'flymake-warning-echo) +(put 'flymake-warning 'echo-face 'flymake-warning-echo) +(put 'flymake-warning 'eol-face 'flymake-warning-echo-at-eol) +(put 'flymake-warning 'flymake-type-name "warning") + +(put 'flymake-note 'face 'flymake-note) +(put 'flymake-note 'flymake-bitmap 'flymake-note-bitmap) +(put 'flymake-note 'flymake-margin-string (alist-get 'note flymake-margin-indicators-string)) +(put 'flymake-note 'severity (warning-numeric-level :debug)) +(put 'flymake-note 'mode-line-face 'flymake-note-echo) +(put 'flymake-note 'echo-face 'flymake-note-echo) +(put 'flymake-note 'eol-face 'flymake-note-echo-at-eol) +(put 'flymake-note 'flymake-type-name "note") + +(defun flymake--lookup-type-property (type prop &optional default) + "Look up PROP for diagnostic TYPE. +If TYPE doesn't declare PROP in its plist or in the symbol of its +associated `flymake-category' return DEFAULT." + ;; This function also consults `flymake-diagnostic-types-alist' for + ;; backward compatibility. + ;; + (if (plist-member (symbol-plist type) prop) + ;; allow nil values to survive + (get type prop) + (let (alist) + (or + (alist-get + prop (setq + alist + (alist-get type flymake-diagnostic-types-alist))) + (when-let* ((cat (or + (get type 'flymake-category) + (alist-get 'flymake-category alist))) + (plist (and (symbolp cat) + (symbol-plist cat))) + (cat-probe (plist-member plist prop))) + (cadr cat-probe)) + default)))) + +(defun flymake--severity (type) + "Get the severity for diagnostic TYPE." + (flymake--lookup-type-property type 'severity + (warning-numeric-level :error))) + +(defun flymake--equal-diagnostic-p (a b) + "Tell if A and B are equivalent `flymake--diag' objects." + (or (eq a b) + (cl-loop for comp in '(flymake--diag-end + flymake--diag-beg + flymake-diagnostic-type + flymake-diagnostic-backend + flymake-diagnostic-origin + flymake-diagnostic-code + flymake-diagnostic-message) + always (equal (funcall comp a) (funcall comp b))))) + +(defun flymake--delete-overlay (ov) + "Like `delete-overlay', delete OV, but do some more stuff." + (let ((eolov (overlay-get ov 'flymake--eol-ov))) + (when eolov + (let ((src-ovs (delq ov (overlay-get eolov 'flymake-eol-source-overlays)))) + (overlay-put eolov 'flymake-eol-source-overlays src-ovs))) + (delete-overlay ov))) + +(cl-defun flymake--highlight-line (diagnostic &optional foreign) + "Attempt to overlay DIAGNOSTIC in current buffer. + +FOREIGN says if DIAGNOSTIC is \"foreign\" to the current buffer, +i.e. managed by another buffer where `flymake-mode' is also +active. + +This function mayskip overlay creation if a diagnostic which is +the same as DIAGNOSTIC is already highlighted +(in the sense of `flymake--equal-diagnostic-p'). In that case +the action to take depends on FOREIGN. If nil the existing +overlay is deleted, else no overlay is created. + +Return nil or the overlay created." + (let* ((type (or (flymake-diagnostic-type diagnostic) + :error)) + (beg (flymake--diag-beg diagnostic)) + (end (flymake--diag-end diagnostic)) + (convert (lambda (cell) + (flymake-diag-region (current-buffer) + (car cell) + (cdr cell)))) + ov) + ;; Convert (LINE . COL) forms of `flymake--diag-beg' and + ;; `flymake--diag-end'. Record the converted positions. + ;; + (cond ((and (consp beg) (not (null end))) + (setq beg (car (funcall convert beg))) + (when (consp end) + (setq end (car (funcall convert end))))) + ((consp beg) + (cl-destructuring-bind (a . b) (funcall convert beg) + (setq beg a end b)))) + (setf (flymake--diag-beg diagnostic) beg + (flymake--diag-end diagnostic) end) + ;; Try to remedy the situation if the same diagnostic is already + ;; registered in the same place. This happens for clashes between + ;; domestic and foreign diagnostics + (cl-loop for e in (flymake-diagnostics beg end) + for eov = (flymake--diag-overlay e) + when (flymake--equal-diagnostic-p e diagnostic) + ;; FIXME. This is an imperfect heuristic. Ideally, we'd + ;; want to delete no overlays and keep annotating the + ;; superseded foreign in an overlay but hide it from most + ;; `flymake-diagnostics' calls. If the target buffer is + ;; killed we can keep the "latent" state of the foreign + ;; diagnostic (with filename and updated line/col info). + ;; If it is revisited the foreign diagnostic can be + ;; revived again. + do (if foreign + (cl-return-from flymake--highlight-line nil) + (setf (flymake--diag-beg e) + (flymake--diag-orig-beg e) + (flymake--diag-end e) + (flymake--diag-orig-end e)) + (flymake--delete-overlay eov))) + (setq ov (make-overlay beg end)) + (setf (flymake--diag-overlay diagnostic) ov) + (when (= (overlay-start ov) (overlay-end ov)) + ;; Some backends report diagnostics with invalid bounds. Don't + ;; bother. + (delete-overlay ov) + (cl-return-from flymake--highlight-line nil)) + (setf (flymake--diag-beg diagnostic) (overlay-start ov) + (flymake--diag-end diagnostic) (overlay-end ov)) + ;; First set `category' in the overlay + ;; + (overlay-put ov 'category + (flymake--lookup-type-property type 'flymake-category)) + ;; Now "paint" the overlay with all the other non-category + ;; properties. + (cl-loop + for (ov-prop . value) in + (append (reverse + (flymake--diag-overlay-properties diagnostic)) + (reverse ; ensure earlier props override later ones + (flymake--lookup-type-property type 'flymake-overlay-control)) + (alist-get type flymake-diagnostic-types-alist)) + do (overlay-put ov ov-prop value)) + ;; Now ensure some essential defaults are set + ;; + (cl-flet ((default-maybe + (prop value) + (unless (plist-member (overlay-properties ov) prop) + (overlay-put ov prop (flymake--lookup-type-property + type prop value))))) + (default-maybe 'face 'flymake-error) + (default-maybe + 'before-string + (propertize + "!" 'display + (if (eq flymake-indicator-type 'auto) + `((when (flymake--suitably-fringed-p) . + ,(flymake--bs-display type 'fringes)) + (when (not (flymake--suitably-fringed-p)) . + ,(flymake--bs-display type 'margins))) + (flymake--bs-display type flymake-indicator-type)))) + (default-maybe 'help-echo + (lambda (window _ov pos) + (with-selected-window window + (mapconcat + (lambda (d) + (flymake--format-diagnostic d :help-echo 'echo-face)) + (flymake-diagnostics pos) + "\n")))) + (default-maybe 'severity (warning-numeric-level :error)) + ;; Use (PRIMARY . SECONDARY) priority, to avoid clashing with + ;; `region' face, for example (bug#34022). + (default-maybe 'priority (cons nil (+ 40 (overlay-get ov 'severity))))) + ;; Some properties can't be overridden. + ;; + (overlay-put ov 'evaporate t) + (overlay-put ov 'flymake-overlay t) + (overlay-put ov 'modification-hooks + `(,(lambda (ov after &rest _) + (when-let* ((eolov + (and (null after) (overlay-get ov 'flymake--eol-ov)))) + (delete-overlay eolov))))) + (overlay-put ov 'flymake-diagnostic diagnostic) + ;; Handle `flymake-show-diagnostics-at-end-of-line' + ;; + (when flymake-show-diagnostics-at-end-of-line + (save-excursion + (goto-char (overlay-start ov)) + (let* ((start (line-end-position)) + (end (min (1+ start) (point-max))) + (eolov (car + (cl-remove-if-not + (lambda (o) (overlay-get o 'flymake-eol-source-overlays)) + (overlays-in start end))))) + ;; FIXME: 1. no checking if there are unexpectedly more than + ;; one eolov at point. + (if eolov + (push ov (overlay-get eolov 'flymake-eol-source-overlays)) + (setq eolov (make-overlay start end nil t nil)) + (overlay-put eolov 'flymake-overlay t) + (overlay-put eolov 'flymake--eol-overlay t) + (overlay-put eolov 'flymake-eol-source-overlays (list ov)) + (overlay-put eolov 'evaporate (not (= start end)))) ; FIXME: fishy + (overlay-put ov 'flymake--eol-ov eolov)))) + ov)) + +;; Nothing in Flymake uses this at all any more, so this is just for +;; third-party compatibility. +(define-obsolete-function-alias 'flymake-display-warning 'message-box "26.1") + +(defvar-local flymake--state nil + "State of a buffer's multiple Flymake backends. +The keys to this hash table are functions as found in +`flymake-diagnostic-functions'. The values are structures +of the type `flymake--state', with these slots: + +`running', a symbol to keep track of a backend's replies via its +REPORT-FN argument. A backend is running if this key is +present. If nil, Flymake isn't expecting any replies from the +backend. + +`diags', a (possibly empty) list of recent diagnostic objects +created by the backend with `flymake-make-diagnostic'. + +`reported-p', a boolean indicating if the backend has replied +since it last was contacted. + +`disabled', a string with the explanation for a previous +exceptional situation reported by the backend, nil if the +backend is operating normally. + +`foreign-diags', a hash table of buffers/files to +collections of diagnostics outside the buffer where this +`flymake--state' pertains.") + +(cl-defstruct (flymake--state + (:constructor flymake--make-backend-state)) + running reported-p disabled diags (foreign-diags + (make-hash-table))) + +(defmacro flymake--with-backend-state (backend state-var &rest body) + "Bind BACKEND's STATE-VAR to its state, run BODY." + (declare (indent 2) (debug (sexp sexp &rest form))) + (let ((b (make-symbol "b"))) + `(let* ((,b ,backend) + (,state-var + (or (gethash ,b flymake--state) + (puthash ,b (flymake--make-backend-state) + flymake--state)))) + ,@body))) + +(defun flymake-is-running () + "Tell if Flymake has running backends in this buffer." + (flymake-running-backends)) + +;; FIXME: clone of `isearch-intersects-p'! Make this an util. +(defun flymake--intersects-p (start0 end0 start1 end1) + "Return t if regions START0..END0 and START1..END1 intersect." + (or (and (>= start0 start1) (< start0 end1)) + (and (> end0 start1) (<= end0 end1)) + (and (>= start1 start0) (< start1 end0)) + (and (> end1 start0) (<= end1 end0)))) + +(cl-defun flymake--handle-report + (backend token report-action + &key explanation force region + &allow-other-keys) + "Handle reports from BACKEND identified by TOKEN. +BACKEND, REPORT-ACTION and EXPLANATION, and FORCE conform to the +calling convention described in +`flymake-diagnostic-functions' (which see). Optional FORCE says +to handle a report even if TOKEN was not expected. REGION is +a (BEG . END) pair of buffer positions indicating that this +report applies to that region." + (let ((state (or (gethash backend flymake--state) + (error "Can't find state for %s in `flymake--state'" + backend))) + expected-token) + (cond + ((null state) + (flymake-error + "Unexpected report from unknown backend %s" backend)) + ((flymake--state-disabled state) + (flymake-error + "Unexpected report from disabled backend %s" backend)) + ((progn + (setq expected-token (flymake--state-running state)) + (null expected-token)) + ;; should never happen + (flymake-error "Unexpected report from stopped backend %s" backend)) + ((not (or (eq expected-token token) + force)) + (flymake-error "Obsolete report from backend %s with explanation %s" + backend explanation)) + ((eq :panic report-action) + (flymake--disable-backend backend explanation)) + ((not (listp report-action)) + (flymake--disable-backend backend + (format "Unknown action %S" report-action)) + (flymake-error "Expected report, but got unknown key %s" report-action)) + (t + (flymake--publish-diagnostics report-action + :backend backend + :state state + :region region) + (when flymake-check-start-time + (flymake-log :debug "backend %s reported %d diagnostics in %.2f second(s)" + backend + (length report-action) + (float-time + (time-since flymake-check-start-time)))))) + (setf (flymake--state-reported-p state) t) + ;; All of the above might have touched the eol overlays, so issue + ;; a call to update them. But check running and reporting + ;; backends first to flickering when multiple backends touch the + ;; same eol overlays. + (when (and flymake-show-diagnostics-at-end-of-line + (not (cl-set-difference (flymake-running-backends) + (flymake-reporting-backends)))) + (flymake--update-eol-overlays)) + (flymake--update-diagnostics-listings (current-buffer)))) + +(defun flymake--clear-foreign-diags (state) + (maphash (lambda (_buffer diags) + (cl-loop for d in diags + when (flymake--diag-overlay d) + do (flymake--delete-overlay it))) + (flymake--state-foreign-diags state)) + (clrhash (flymake--state-foreign-diags state))) + +(defun flymake--clear-state (state) + (cl-loop for diag in (flymake--state-diags state) + for ov = (flymake--diag-overlay diag) + when ov do (flymake--delete-overlay ov)) + (setf (flymake--state-diags state) nil) + (flymake--clear-foreign-diags state)) + +(defvar-local flymake-mode nil) + +(defvar-local flymake--mode-line-counter-cache nil + "A cache used in `flymake-mode-line-counters'.") + +(cl-defun flymake--publish-diagnostics (diags &key backend state region) + "Helper for `flymake--handle-report'. +Publish DIAGS, which contain diagnostics for the current buffer +and other buffers." + (dolist (d diags) (setf (flymake--diag-backend d) backend)) + (save-restriction + (widen) + ;; First, clean up. Remove diagnostics from bookkeeping lists and + ;; their overlays from buffers. + ;; + (cond + (;; If there is a `region' arg, only affect the diagnostics whose + ;; overlays are in a certain region. Ignore "foreign" + ;; diagnostics. + region + (cl-loop for diag in (flymake--state-diags state) + for ov = (flymake--diag-overlay diag) + if (or (not (overlay-buffer ov)) + (flymake--intersects-p + (overlay-start ov) (overlay-end ov) + (car region) (cdr region))) + do (flymake--delete-overlay ov) + else collect diag into surviving + finally (setf (flymake--state-diags state) + surviving))) + (;; Else, if this is the first report, fully clear this state. + (not (flymake--state-reported-p state)) + (flymake--clear-state state)) + (;; If this is not the first report, do no cleanup. + t)) + + ;; Now place new overlays for all diagnostics: "domestic" + ;; diagnostics are for the current buffer; "foreign" may be for a + ;; some other live buffer or for a file name that hasn't a buffer + ;; yet. If a foreign diagnostic is for a buffer, convert to a + ;; file name, protecting it against that buffer's killing. + ;; + (cl-loop + for d in diags + for locus = (flymake--diag-locus d) + do (cond ((eq locus (current-buffer)) + (push d (flymake--state-diags state)) + (flymake--highlight-line d)) + (t + (when (or (buffer-live-p locus) + (setq locus (find-buffer-visiting locus))) + (with-current-buffer locus + (when flymake-mode (flymake--highlight-line d 'foreign)) + ;; Ensure locus of a foreign diag is always a file-name + ;; string, even if created from a buffer. + (setf (flymake--diag-locus d) (buffer-file-name)))) + (cl-assert (stringp (flymake--diag-locus d))) + (push d (gethash (flymake--diag-locus d) + (flymake--state-foreign-diags state)))))) + ;; Finally, flush some caches + (setq flymake--mode-line-counter-cache nil))) + +(defun flymake-make-report-fn (backend &optional token) + "Make a suitable anonymous report function for BACKEND. +BACKEND is used to help Flymake distinguish different diagnostic +sources. If provided, TOKEN helps Flymake distinguish between +different runs of the same backend." + (let ((buffer (current-buffer))) + (lambda (&rest args) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (apply #'flymake--handle-report backend token args)))))) + +(defun flymake--collect (fn &optional message-prefix) + "Collect Flymake backends matching FN. +If MESSAGE-PREFIX, echo a message using that prefix." + (unless flymake--state + (user-error "Flymake is not initialized")) + (let (retval) + (maphash (lambda (backend state) + (when (funcall fn state) (push backend retval))) + flymake--state) + (when message-prefix + (message "%s%s" + message-prefix + (mapconcat (lambda (s) (format "%s" s)) + retval ", "))) + retval)) + +(defun flymake-running-backends () + "Compute running Flymake backends in current buffer." + (interactive) + (flymake--collect #'flymake--state-running + (and (called-interactively-p 'interactive) + "Running backends: "))) + +(defun flymake-disabled-backends () + "Compute disabled Flymake backends in current buffer." + (interactive) + (flymake--collect #'flymake--state-disabled + (and (called-interactively-p 'interactive) + "Disabled backends: "))) + +(defun flymake-reporting-backends () + "Compute reporting Flymake backends in current buffer." + (interactive) + (flymake--collect #'flymake--state-reported-p + (and (called-interactively-p 'interactive) + "Reporting backends: "))) + +(defun flymake--disable-backend (backend &optional explanation) + "Disable BACKEND because EXPLANATION. +If it is running also stop it." + (flymake-log :warning "Disabling backend %s because %S" backend explanation) + (flymake--with-backend-state backend state + (setf (flymake--state-running state) nil + (flymake--state-disabled state) explanation + (flymake--state-reported-p state) t))) + +(defun flymake--run-backend (backend &optional args) + "Run the backend BACKEND, re-enabling if necessary. +ARGS is a keyword-value plist passed to the backend along +with a report function." + (flymake-log :debug "Running backend %s" backend) + (let ((run-token (gensym "backend-token"))) + (flymake--with-backend-state backend state + (setf (flymake--state-running state) run-token + (flymake--state-disabled state) nil + (flymake--state-reported-p state) nil)) + (condition-case-unless-debug err + (apply backend (flymake-make-report-fn backend run-token) + args) + (error + (flymake--disable-backend backend err))))) + +(defvar-local flymake--recent-changes nil + "Recent changes collected by `flymake-after-change-function'.") +(defvar flymake-mode) + +(defun flymake--import-foreign-diagnostics () + ;; Other diagnostic sources may already target this buffer's file + ;; before we turned on: these sources may be of two types... + (let ((source (current-buffer)) + (bfn buffer-file-name)) + ;; 1. For `flymake-list-only-diagnostics': here, we do nothing. + ;; FIXME: We could remove the corresponding entry from that + ;; variable, as we assume that new diagnostics will come in soon + ;; via the brand new `flymake-mode' setup. For simplicity's + ;; sake, we have opted to leave the backend for now. + nil + ;; 2. other buffers where a backend has created "foreign + ;; diagnostics" and pointed them here. We must highlight them in + ;; this buffer, i.e. create overlays for them. Those other + ;; buffers and backends are still responsible for them, i.e. the + ;; current buffer does not "own" these foreign diags. + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when flymake-mode + (maphash (lambda (_backend state) + (maphash (lambda (file diags) + (when (or (eq file source) + (string= bfn (expand-file-name file))) + (with-current-buffer source + (mapc (lambda (diag) + (flymake--highlight-line diag + 'foreign)) + diags)))) + (flymake--state-foreign-diags state))) + flymake--state)))))) + +(defun flymake-start (&optional deferred force) + "Start a syntax check for the current buffer. +DEFERRED is a list of symbols designating conditions to wait for +before actually starting the check. If it is nil (the list is +empty), start it immediately, else defer the check to when those +conditions are met. Currently recognized conditions are +`post-command', for waiting until the current command is over, +`on-display', for waiting until the buffer is actually displayed +in a window. If DEFERRED is t, wait for all known conditions. + +With optional FORCE run even disabled backends. + +Interactively, with a prefix arg, FORCE is t." + (interactive (list nil current-prefix-arg)) + (let ((deferred (if (eq t deferred) + '(post-command on-display) + deferred)) + (buffer (current-buffer))) + (cl-labels + ((visible-buffer-window () + (and (or (not (daemonp)) + (not (eq (selected-frame) terminal-frame))) + (get-buffer-window (current-buffer)))) + (start-post-command () + (remove-hook 'post-command-hook #'start-post-command + nil) + ;; The buffer may have disappeared already, e.g. because of + ;; code like `(with-temp-buffer (python-mode) ...)'. + (when (buffer-live-p buffer) + (with-current-buffer buffer + (flymake-start (remove 'post-command deferred) force)))) + (start-on-display () + (remove-hook 'window-configuration-change-hook #'start-on-display + 'local) + ;; Double check that buffer is actually visible (bug#77313) + (if (visible-buffer-window) + (setq deferred (remove 'on-display deferred))) + (flymake-start deferred force))) + (cond ((and (memq 'post-command deferred) + this-command) + (add-hook 'post-command-hook + #'start-post-command + 'append nil)) + ((and (memq 'on-display deferred) + (not (visible-buffer-window))) + (add-hook 'window-configuration-change-hook + #'start-on-display + 'append 'local)) + (flymake-mode + ;; The buffer about to be annotated is visible. Check + ;; necessary conditions to auto-set margins here (bug#77313) + (when-let* ((w (and (eq flymake-indicator-type 'auto) + flymake-autoresize-margins + (visible-buffer-window)))) + (unless (flymake--suitably-fringed-p w) + (flymake--resize-margins))) + (setq flymake-check-start-time (float-time)) + (let ((backend-args + (and + flymake--recent-changes + (list :recent-changes + flymake--recent-changes + :changes-start + (cl-reduce + #'min (mapcar #'car flymake--recent-changes)) + :changes-end + (cl-reduce + #'max (mapcar #'cadr flymake--recent-changes)))))) + (setq flymake--recent-changes nil) + ;; Delete all overlays that didn't come from one of the + ;; current diagnostic functions. + ;; Sometimes diagnostic functions are removed from + ;; `flymake-diagnostic-functions' (e.g. by eglot). This + ;; leaves overlays in the buffer which otherwise won't be + ;; cleaned up until `flymake-mode' is restarted. + ;; See bug#78862 + (maphash (lambda (backend state) + (unless (memq backend flymake-diagnostic-functions) + (flymake--clear-state state))) + flymake--state) + (run-hook-wrapped + 'flymake-diagnostic-functions + (lambda (backend) + (flymake--with-backend-state backend state + (setf (flymake--state-reported-p state) nil)))) + (run-hook-wrapped + 'flymake-diagnostic-functions + (lambda (backend) + (cond + ((and (not force) + (flymake--with-backend-state backend state + (flymake--state-disabled state))) + (flymake-log :debug "Backend %s is disabled, not starting: %S" + backend + (flymake--with-backend-state backend state + (flymake--state-disabled state)))) + (t + (flymake--run-backend backend backend-args))) + nil))) + (flymake--import-foreign-diagnostics)))))) + +(defvar flymake-mode-map + (let ((map (make-sparse-keymap))) + (define-key map + `[,flymake-fringe-indicator-position mouse-1] + #'flymake-show-buffer-diagnostics) + map) + "Keymap for `flymake-mode'") + +(defvar-local flymake-current-diagnostic-line 0 + "The line of the most recently focused diagnostic in a diagnostics buffer.") + +;;;###autoload +(define-minor-mode flymake-mode + "Toggle Flymake mode on or off. + +Flymake is an Emacs minor mode for on-the-fly syntax checking. +Flymake collects diagnostic information from multiple sources, +called backends, and visually annotates the buffer with the +results. + +Flymake performs these checks while the user is editing. +The customization variables `flymake-start-on-flymake-mode', +`flymake-no-changes-timeout' determine the exact circumstances +whereupon Flymake decides to initiate a check of the buffer. + +The commands `flymake-goto-next-error' and +`flymake-goto-prev-error' can be used to navigate among Flymake +diagnostics annotated in the buffer. + +By default, `flymake-mode' doesn't override the \\[next-error] command, but +if you're using Flymake a lot (and don't use the regular compilation +mechanisms that often), it can be useful to put something like +the following in your init file: + + (setq next-error-function \\='flymake-goto-next-error) + +The visual appearance of each type of diagnostic can be changed +by setting properties `flymake-overlay-control', `flymake-bitmap' +and `flymake-severity' on the symbols of diagnostic types (like +`:error', `:warning' and `:note'). + +Activation or deactivation of backends used by Flymake in each +buffer happens via the special hook +`flymake-diagnostic-functions'. + +Some backends may take longer than others to respond or complete, +and some may decide to disable themselves if they are not +suitable for the current buffer. The commands +`flymake-running-backends', `flymake-disabled-backends' and +`flymake-reporting-backends' summarize the situation, as does the +special *Flymake log* buffer." :group 'flymake :lighter + flymake-mode-line-format :keymap flymake-mode-map + (cond + ;; Turning the mode ON. + (flymake-mode + (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) + (add-hook 'eldoc-documentation-functions 'flymake-eldoc-function t t) + + ;; Maybe auto-resize margins + (when (and (eq flymake-indicator-type 'margins) flymake-autoresize-margins) + (flymake--resize-margins)) + + ;; We can't just `clrhash' `flymake--state': there may be in + ;; in-transit requests from other backends if `flymake-mode' was + ;; already active. I.e. `flymake-mode' function should be as + ;; idempotent as possible. See bug#69809. + (unless flymake--state (setq flymake--state (make-hash-table))) + (setq flymake--recent-changes nil) + (when flymake-start-on-flymake-mode (flymake-start t))) + + ;; Turning the mode OFF. + (t + (remove-hook 'after-change-functions 'flymake-after-change-function t) + (remove-hook 'after-save-hook 'flymake-after-save-hook t) + (remove-hook 'kill-buffer-hook 'flymake-kill-buffer-hook t) + ;;+(remove-hook 'find-file-hook (function flymake-find-file-hook) t) + (remove-hook 'eldoc-documentation-functions 'flymake-eldoc-function t) + + ;; return any resized margin to original size + (flymake--restore-margins) + + (when flymake-timer + (cancel-timer flymake-timer) + (setq flymake-timer nil)) + (mapc #'flymake--delete-overlay (flymake--really-all-overlays)) + (when flymake--state + (maphash (lambda (_backend state) + (flymake--clear-foreign-diags state)) + flymake--state)))) + ;; turning Flymake on or off has consequences for listings + (flymake--update-diagnostics-listings (current-buffer))) + +(defun flymake--schedule-timer-maybe () + "(Re)schedule an idle timer for checking the buffer. +Do it only if `flymake-no-changes-timeout' is non-nil." + (when flymake-timer (cancel-timer flymake-timer)) + (when flymake-no-changes-timeout + (setq + flymake-timer + (run-with-idle-timer + ;; This can use time-convert instead of seconds-to-time, + ;; once we can assume Emacs 27 or later. + (seconds-to-time flymake-no-changes-timeout) + nil + (lambda (buffer) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (when (and flymake-mode + flymake-no-changes-timeout) + (flymake-log + :debug "starting syntax check after idle for %s seconds" + flymake-no-changes-timeout) + (flymake-start t)) + (setq flymake-timer nil)))) + (current-buffer))))) + +;;;###autoload +(defun flymake-mode-on () + "Turn Flymake mode on." + (flymake-mode 1)) + +;;;###autoload +(defun flymake-mode-off () + "Turn Flymake mode off." + (flymake-mode 0)) + +(make-obsolete 'flymake-mode-on 'flymake-mode "26.1") +(make-obsolete 'flymake-mode-off 'flymake-mode "26.1") + +(defun flymake-after-change-function (start stop pre-change-len) + "Start syntax check for current buffer if it isn't already running. +START and STOP and LEN are as in `after-change-functions'." + (let((new-text (buffer-substring start stop))) + (push (list start stop new-text) flymake--recent-changes) + (flymake--schedule-timer-maybe)) + ;; Some special handling to prevent eol overlays from temporarily + ;; moving to wrong line + (when (and flymake-show-diagnostics-at-end-of-line + (zerop pre-change-len)) + (save-excursion + (goto-char start) + (when-let* ((probe (search-forward "\n" stop t)) + (eolovs (cl-remove-if-not + (lambda (o) + (let ((lbound + (cl-loop for s in (overlay-get o 'flymake-eol-source-overlays) + minimizing (overlay-start s)))) + (and lbound (< lbound (1- probe))))) + (overlays-at (line-end-position))))) + (goto-char start) + (let ((newend (line-end-position))) + (dolist (ov eolovs) (move-overlay ov newend (1+ newend)))))))) + +(defun flymake-after-save-hook () + (when flymake-start-on-save-buffer + (flymake-log :debug "starting syntax check as buffer was saved") + (flymake-start t))) + +(defun flymake-kill-buffer-hook () + ;; Explicitly set flymake off, because that does a lot of useful + ;; cleanup. + (flymake-mode -1)) + +(defun flymake-find-file-hook () + (unless (or flymake-mode + (null flymake-diagnostic-functions)) + (flymake-mode) + (flymake-log :warning "Turned on in `flymake-find-file-hook'"))) + +(defun flymake-eldoc-function (report-doc &rest _) + "Document diagnostics at point. +Intended for `eldoc-documentation-functions' (which see)." + (when-let* ((diags (flymake-diagnostics (point)))) + (funcall report-doc + (mapconcat (lambda (d) + (flymake--format-diagnostic d :eldoc 'echo-face)) + diags "\n") + :echo (mapconcat + (lambda (d) + (flymake--format-diagnostic d :eldoc-echo 'echo-face)) + diags "\n")))) + +(defun flymake-goto-next-error (&optional n filter interactive) + "Go to Nth next Flymake diagnostic that matches FILTER. +Interactively, always move to the next diagnostic. With a prefix +arg, skip any diagnostics with a severity less than `:warning'. + +If `flymake-wrap-around' is non-nil and no more next diagnostics, +resumes search from top. + +FILTER is a list of diagnostic types. Only diagnostics with +matching severities matching are considered. If nil (the +default) no filter is applied." + ;; TODO: let filter be a number, a severity below which diags are + ;; skipped. + (interactive (list 1 + (if current-prefix-arg + '(:error :warning)) + t)) + (let* ((n (or n 1)) + (ovs (cl-loop + for o in (overlays-in (point-min) (point-max)) + for diag = (overlay-get o 'flymake-diagnostic) + when (and diag (or (not filter) (cl-find + (flymake--severity + (flymake-diagnostic-type diag)) + filter :key #'flymake--severity))) + collect o into retval + finally (cl-return + (cl-sort retval (if (cl-plusp n) #'< #'>) + :key #'overlay-start)))) + (tail ;; For compatibility with older Emacs. + (with-suppressed-warnings ((obsolete cl-member-if)) + (cl-member-if (lambda (ov) + (if (cl-plusp n) + (> (overlay-start ov) + (point)) + (< (overlay-start ov) + (point)))) + ovs))) + (chain (if flymake-wrap-around + (if tail + (progn (setcdr (last tail) ovs) tail) + (and ovs (setcdr (last ovs) ovs))) + tail)) + (target (nth (1- n) chain))) + (cond (target + (goto-char (overlay-start target)) + (when interactive + (message + "%s" + (funcall (overlay-get target 'help-echo) + (selected-window) target (point))))) + (interactive + (user-error "No more Flymake diagnostics%s" + (if filter + (format " of %s severity" + (mapconcat #'symbol-name filter ", ")) "")))))) + +(defun flymake-goto-prev-error (&optional n filter interactive) + "Go to Nth previous Flymake diagnostic that matches FILTER. +Interactively, always move to the previous diagnostic. With a +prefix arg, skip any diagnostics with a severity less than +`:warning'. + +If `flymake-wrap-around' is non-nil and no more previous +diagnostics, resumes search from bottom. + +FILTER is a list of diagnostic types. Only diagnostics with +matching severities matching are considered. If nil (the +default) no filter is applied." + (interactive (list 1 (if current-prefix-arg + '(:error :warning)) + t)) + (flymake-goto-next-error (- (or n 1)) filter interactive)) + + +;;; Mode-line and menu +;;; +(easy-menu-define flymake-menu flymake-mode-map "Flymake menu." + '("Flymake" + [ "Go to next problem" flymake-goto-next-error t ] + [ "Go to previous problem" flymake-goto-prev-error t ] + [ "Check now" flymake-start t ] + [ "List all problems" flymake-show-buffer-diagnostics t ] + "--" + [ "Go to log buffer" flymake-switch-to-log-buffer t ] + [ "Turn off Flymake" flymake-mode t ])) + +(defcustom flymake-mode-line-format + '(" " flymake-mode-line-title flymake-mode-line-exception + flymake-mode-line-counters) + "Mode line construct for customizing Flymake information." + :type '(repeat (choice string symbol))) + +(defcustom flymake-mode-line-counter-format + '("[" + flymake-mode-line-error-counter + flymake-mode-line-warning-counter + flymake-mode-line-note-counter "]") + "Mode-line construct for formatting Flymake diagnostic counters. +This is a suitable place for placing the `flymake-mode-line-error-counter', +`flymake-mode-line-warning-counter' and `flymake-mode-line-note-counter' +constructs. +Separating each of these with space is not necessary." + :type '(repeat (choice string symbol))) + +(defcustom flymake-mode-line-lighter "Flymake" + "The string to use in the Flymake mode line." + :type 'string + :version "29.1") + +(defvar flymake-mode-line-title '(:eval (flymake--mode-line-title)) + "Mode-line construct to show Flymake's mode name and menu.") + +(defvar flymake-mode-line-exception '(:eval (flymake--mode-line-exception)) + "Mode-line construct to report on exceptional Flymake status.") + +(defvar flymake-mode-line-counters '(:eval (flymake--mode-line-counters)) + "Mode-line construct for counting Flymake diagnostics. +The counters are only placed if some Flymake backend initialized +correctly.") + +(defvar flymake-mode-line-error-counter + `(:eval (flymake--mode-line-counter :error))) +(defvar flymake-mode-line-warning-counter + `(:eval (flymake--mode-line-counter :warning))) +(defvar flymake-mode-line-note-counter + `(:eval (flymake--mode-line-counter :note))) + +(put 'flymake-mode-line-format 'risky-local-variable t) +(put 'flymake-mode-line-title 'risky-local-variable t) +(put 'flymake-mode-line-exception 'risky-local-variable t) +(put 'flymake-mode-line-counters 'risky-local-variable t) +(put 'flymake-mode-line-error-counter 'risky-local-variable t) +(put 'flymake-mode-line-warning-counter 'risky-local-variable t) +(put 'flymake-mode-line-note-counter 'risky-local-variable t) + +(defun flymake--mode-line-title () + `(:propertize + ,flymake-mode-line-lighter + mouse-face mode-line-highlight + help-echo + ,(lambda (w &rest _) + (with-current-buffer (window-buffer w) + ;; Mouse can activate tool-tip without window being active. + ;; `flymake--state' is buffer local and is null when line + ;; lighter appears in *Help* `describe-mode'. + (concat + (unless (null flymake--state) + (concat + (format "%s known backends\n" (hash-table-count flymake--state)) + (format "%s running\n" (length (flymake-running-backends))) + (format "%s disabled\n" (length (flymake-disabled-backends))))) + "mouse-1: Display minor mode menu\n" + "mouse-2: Show help for minor mode"))) + keymap + ,(let ((map (make-sparse-keymap))) + (define-key map [mode-line down-mouse-1] + flymake-menu) + (define-key map [mode-line down-mouse-3] + flymake-menu) + (define-key map [mode-line mouse-2] + (lambda () + (interactive) + (describe-function 'flymake-mode))) + map))) + +(defun flymake--mode-line-exception () + "Helper for `flymake-mode-line-exception'." + (pcase-let* ((running) (reported) + (`(,ind ,face ,explain) + (cond ((zerop (hash-table-count flymake--state)) + '("?" nil "No known backends")) + ((cl-set-difference + (setq running (flymake-running-backends)) + (setq reported (flymake-reporting-backends))) + `("Wait" compilation-mode-line-run + ,(format "Waiting for %s running backend(s)" + (length (cl-set-difference running reported))))) + ((and (flymake-disabled-backends) (null running)) + '("!" compilation-mode-line-run + "All backends disabled")) + (t + '(nil nil nil))))) + (when ind + `(":" + (:propertize ,ind face ,face + help-echo ,explain + keymap ,(let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + 'flymake-switch-to-log-buffer) + map)))))) + +(defun flymake--mode-line-counters () + (when (flymake-running-backends) flymake-mode-line-counter-format)) + +(defun flymake--mode-line-counter-scroll-prev (event) + (interactive "e") + (let* ((event-start (event-start event)) + (posn-string (posn-string event-start)) + (type (get-text-property + (cdr posn-string) 'flymake--diagnostic-type (car posn-string)))) + (with-selected-window (posn-window event-start) + (flymake-goto-prev-error 1 (list type) t)))) + +(defun flymake--mode-line-counter-scroll-next (event) + (interactive "e") + (let* ((event-start (event-start event)) + (posn-string (posn-string event-start)) + (type (get-text-property + (cdr posn-string) 'flymake--diagnostic-type (car posn-string)))) + (with-selected-window (posn-window event-start) + (flymake-goto-next-error 1 (list type) t)))) + +(defvar flymake--mode-line-counter-map + (let ((map (make-sparse-keymap))) + ;; BEWARE: `mouse-wheel-UP-event' corresponds to `wheel-DOWN' events + ;; and vice versa!! + (with-no-warnings + (define-key map (vector 'mode-line mouse-wheel-down-event) + #'flymake--mode-line-counter-scroll-prev) + (define-key map [mode-line wheel-down] + #'flymake--mode-line-counter-scroll-next) + (define-key map (vector 'mode-line mouse-wheel-up-event) + #'flymake--mode-line-counter-scroll-next) + (define-key map [mode-line wheel-up] + #'flymake--mode-line-counter-scroll-prev)) + (define-key map [mode-line mouse-1] + #'flymake-show-buffer-diagnostics) + map)) + +(defun flymake--mode-line-counter-1 (type) + "Helper for `flymake--mode-line-counter'." + (let ((count 0) + (face (flymake--lookup-type-property type + 'mode-line-face + 'compilation-error))) + (dolist (d (flymake-diagnostics)) + (when (= (flymake--severity type) + (flymake--severity (flymake-diagnostic-type d))) + (cl-incf count))) + (when (or (cl-plusp count) + (cond ((eq flymake-suppress-zero-counters t) + nil) + (flymake-suppress-zero-counters + (>= (flymake--severity type) + (warning-numeric-level + flymake-suppress-zero-counters))) + (t t))) + `(,(if (eq type :error) "" '(:propertize " ")) + (:propertize + ,(format "%d" count) + face ,face + mouse-face mode-line-highlight + help-echo ,(format "Number of %s; scroll mouse to view." + (cond + ((eq type :error) "errors") + ((eq type :warning) "warnings") + ((eq type :note) "notes") + (t (format "%s diagnostics" type)))) + flymake--diagnostic-type ,type + keymap ,flymake--mode-line-counter-map))))) + +(defun flymake--mode-line-counter (type) + "Compute number of diagnostics in buffer with TYPE's severity. +TYPE is usually keyword `:error', `:warning' or `:note'." + (let ((probe (alist-get type flymake--mode-line-counter-cache 'none))) + (if (eq probe 'none) + (setf (alist-get type flymake--mode-line-counter-cache) + (flymake--mode-line-counter-1 type)) + probe))) + + +;;; Per-buffer diagnostic listings +;;; +(defvar-local flymake--diagnostics-buffer-source nil) + +(defvar flymake-diagnostics-buffer-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") #'flymake-goto-diagnostic) + (define-key map (kbd "SPC") #'flymake-show-diagnostic) + (define-key map (kbd "C-o") #'flymake-show-diagnostic) + (define-key map (kbd "C-m") #'flymake-goto-diagnostic) + (when (fboundp 'next-error-this-buffer-no-select) + (define-key map (kbd "n") #'next-error-this-buffer-no-select) + (define-key map (kbd "p") #'previous-error-this-buffer-no-select)) + map)) + +(defun flymake-show-diagnostic (pos &optional other-window) + "From Flymake diagnostics buffer, show source of diagnostic at POS." + (interactive (list (point) t)) + (let* ((diagnostics-buffer (current-buffer)) + (id (or (tabulated-list-get-id pos) + (user-error "Nothing at point"))) + (diag (plist-get id :diagnostic)) + (locus (flymake--diag-locus diag)) + (beg (flymake--diag-beg diag)) + (end (flymake--diag-end diag)) + (visit (lambda (b e) + (goto-char b) + (pulse-momentary-highlight-region + b (or e (line-end-position)))))) + (setq flymake-current-diagnostic-line (line-number-at-pos pos)) + (with-current-buffer (cond ((bufferp locus) locus) + (t (find-file-noselect locus))) + (with-selected-window + (display-buffer (current-buffer) other-window) + (cond (;; an annotated diagnostic (most common case), or a + ;; non-annotated buffer diag + (number-or-marker-p beg) + (funcall visit beg end)) + (;; a non-annotated file diag (TODO: could use `end' + ;; here, too) + (pcase-let ((`(,bbeg . ,bend) + (flymake-diag-region (current-buffer) + (car beg) + (cdr beg)))) + (funcall visit bbeg bend))))) + ;; Emacs < 27 + (setq next-error-last-buffer diagnostics-buffer) + (current-buffer)))) + +(defun flymake-goto-diagnostic (pos) + "From Flymake diagnostics buffer, goto source of diagnostic at POS. +POS can be a buffer position or a button" + (interactive "d") + (pop-to-buffer + (flymake-show-diagnostic (if (button-type pos) (button-start pos) pos)))) + +(defvar flymake--tabulated-list-format-base + `[("File" 15) + ("Line" 4 ,(lambda (l1 l2) + (< (plist-get (car l1) :line) + (plist-get (car l2) :line))) + :right-align t) + ("Col" 3 nil :right-align t) + ("Type" 4 ,(lambda (l1 l2) + (< (plist-get (car l1) :severity) + (plist-get (car l2) :severity)))) + ("Origin" 6 t) + ("Code" 4 t) + ("Message" 0 t)]) + +(defun flymake--tabulated-setup-1 (diags project-root) + "Helper for `flymake--tabulated-setup'. +Sets `tabulated-list-format' and `tabulated-list-entries', dynamically +resizing columns and omitting redundant columns." + (cl-loop + with fields = (copy-tree flymake--tabulated-list-format-base t) + initially (cl-loop for y across fields do (setf (cadr y) nil)) + for diag in diags + for locus = (flymake-diagnostic-buffer diag) + for file = (if (bufferp locus) + (buffer-file-name locus) + locus) + for overlay = (flymake--diag-overlay diag) + for (line . col) = + (cond (;; has live overlay, use overlay for position + (and overlay (overlay-buffer overlay)) + (with-current-buffer (overlay-buffer overlay) + (save-excursion + (goto-char (overlay-start overlay)) + (cons (line-number-at-pos) + (- (point) + (line-beginning-position)))))) + (;; diagnostic not annotated, maybe foreign, check for cons + (consp (flymake--diag-beg diag)) + (flymake--diag-beg diag)) + (;; may still be a valid foreign diagnostic + (consp (flymake--diag-orig-beg diag)) + (flymake--diag-orig-beg diag)) + (;; somehow dead annotated diagnostic, ignore/give up + t nil)) + for type = (flymake-diagnostic-type diag) + for data-line = `[,(and project-root + `(,(file-name-nondirectory file) + help-echo ,(file-relative-name file project-root) + face nil + mouse-face highlight + action flymake-goto-diagnostic + mouse-action flymake-goto-diagnostic )) + ,(format "%s" line) + ,(format "%s" col) + ,(propertize (format "%s" + (flymake--lookup-type-property + type 'flymake-type-name type)) + 'face (flymake--lookup-type-property + type 'mode-line-face 'flymake-error)) + ,(flymake-diagnostic-origin diag) + ,(flymake-diagnostic-code diag) + (,(flymake-diagnostic-text diag '(oneliner)) + mouse-face highlight + help-echo "mouse-2: visit this diagnostic" + face nil + action flymake-goto-diagnostic + mouse-action flymake-goto-diagnostic)] + for meta = (and line col + (list :diagnostic diag + :line line + :severity (flymake--lookup-type-property + type + 'severity (warning-numeric-level :error)))) + when meta + do (cl-loop for x across data-line + for y across fields + for z across flymake--tabulated-list-format-base + for xlen = (cond ((stringp x) (length x)) + (t (length (car x)))) + when (cl-plusp xlen) + do (setf (cadr y) + (max xlen + (or (cadr y) (cadr z))))) + collect (list meta data-line) into data + finally + ;; `data' and `fields' now hold more or less suitable values for + ;; `tabulated-list-entries' and `tabulated-list-format' respectively, + ;; but we need to trim them, first removing the columns of data where + ;; the corresponding field is known to be nil for every line, and + ;; then removing the field description itself. + (cl-loop + for entry in data + do (setf (cadr entry) (cl-loop for x across (cadr entry) + for y across fields + when (cadr y) + vconcat (vector (or x "-"))))) + (setq tabulated-list-entries data + tabulated-list-format + (cl-loop for y across fields + when (cadr y) vconcat (vector y))))) + +(defun flymake--tabulated-setup (use-project) + "Helper for `flymake-diagnostics-buffer-mode'. +And also `flymake-project-diagnostics-mode'." + (setq-local next-error-function #'flymake--diagnostics-next-error) + (let ((saved-r-b-f revert-buffer-function) + (refresh + (lambda () + (cond + (use-project + (let ((p (project-current))) + (flymake--tabulated-setup-1 + (flymake--project-diagnostics p) + (project-root p)))) + (t + ;; Do nothing if 'flymake--diagnostics-buffer-source' has + ;; not yet been set to a valid buffer. This could happen + ;; when this function is called too early. For example + ;; 'global-display-line-numbers-mode' calls us from its + ;; mode hook, when the diagnostic buffer has just been + ;; created by 'flymake-show-buffer-diagnostics', but is not + ;; yet set up properly (Bug#40529). + (flymake--tabulated-setup-1 + (and (bufferp flymake--diagnostics-buffer-source) + (with-current-buffer flymake--diagnostics-buffer-source + (and flymake-mode + (flymake-diagnostics)))) + nil))) + (tabulated-list-init-header)))) + (setq revert-buffer-function + (lambda (&rest args) + (funcall refresh) + (apply saved-r-b-f args))))) + +(defun flymake--diagnostics-next-error (n &optional reset) + "`next-error-function' for flymake diagnostics buffers. +N is an integer representing how many errors to move. +If RESET is non-nil, return to the beginning of the errors before +moving." + (let ((line (if reset 1 flymake-current-diagnostic-line)) + (total-lines (count-lines (point-min) (point-max)))) + (goto-char (point-min)) + (unless (zerop total-lines) + (let ((target-line (+ line n))) + (setq target-line (max 1 target-line)) + (setq target-line (min target-line total-lines)) + (forward-line (1- target-line)))) + (when-let* ((win (get-buffer-window nil t))) + (set-window-point win (point))) + (flymake-goto-diagnostic (point)))) + +(define-derived-mode flymake-diagnostics-buffer-mode tabulated-list-mode + "Flymake diagnostics" + "A mode for listing Flymake diagnostics." + :interactive nil + (flymake--tabulated-setup nil)) + +(defun flymake--diagnostics-buffer-name () + (format "*Flymake diagnostics for `%s'*" (current-buffer))) + +(define-obsolete-function-alias 'flymake-show-diagnostics-buffer + 'flymake-show-buffer-diagnostics "1.2.1") + +(defun flymake--fit-diagnostics-window (window) + (fit-window-to-buffer window 15 8)) + +(defun flymake-show-buffer-diagnostics (&optional diagnostic) + "Show listing of Flymake diagnostics for current buffer. +With optional DIAGNOSTIC, find and highlight this diagnostic in the +listing. + +Interactively, grab DIAGNOSTIC from context. For mouse events in +margins and fringes, use the first diagnostic in the corresponding line, +else look in the click position. For non-mouse events, look for +diagnostics at point. + +This function doesn't move point" + (interactive + (if (mouse-event-p last-command-event) + (with-selected-window (posn-window (event-end last-command-event)) + (with-current-buffer (window-buffer) + (let* ((event-point (posn-point (event-end last-command-event))) + (diags + (or + (flymake-diagnostics event-point) + (let (event-lbp event-lep) + (save-excursion + (goto-char event-point) + (setq event-lbp (line-beginning-position) + event-lep (line-end-position))) + (flymake-diagnostics event-lbp event-lep)))) + (diag (car diags))) + (unless diag + (error "No diagnostics here")) + (list diag)))) + (flymake-diagnostics (point)))) + (unless flymake-mode + (user-error "Flymake mode is not enabled in the current buffer")) + (let* ((name (flymake--diagnostics-buffer-name)) + (source (current-buffer)) + (target (or (get-buffer name) + (with-current-buffer (get-buffer-create name) + (flymake-diagnostics-buffer-mode) + (current-buffer)))) + window) + (with-current-buffer target + (setq flymake--diagnostics-buffer-source source) + (setq next-error-last-buffer (current-buffer)) + (revert-buffer) + (setq window + (display-buffer (current-buffer) + `((display-buffer-reuse-window + display-buffer-below-selected) + (window-height . flymake--fit-diagnostics-window)))) + (when (and window diagnostic) + (with-selected-window window + (cl-loop initially (goto-char (point-min)) + until (eobp) + until (eq (plist-get (tabulated-list-get-id) :diagnostic) + diagnostic) + do (forward-line) + finally + (recenter) + (pulse-momentary-highlight-one-line + (point) 'highlight))))))) + + +;;; Per-project diagnostic listing +;;; + +(defvar flymake-list-only-diagnostics nil + "Diagnostics list meant for listing, not highlighting. +This variable holds an alist ((FILE-NAME . DIAGS) ...) where +FILE-NAME is a string holding an absolute file name and DIAGS is +a list of diagnostic objects created with +`flymake-make-diagnostic'. These diagnostics are never annotated +as overlays in actual buffers: they merely serve as temporary +stand-ins for more accurate diagnostics that are produced once +the file they refer to is visited and `flymake-mode' is turned on +in the resulting buffer. + +Flymake backends that somehow gain sporadic information about +diagnostics in neighboring files may freely modify this variable +by adding or removing entries to for those files. If the +information about those neighboring files is acquired repeatedly +and reliably, it may be more sensible to report them as +\"foreign\" diagnostics instead. + +Commands such as `flymake-show-project-diagnostics' will include +some of this variable's contents the diagnostic listings.") + +(defvar-local flymake--project-diagnostic-list-project nil) + +(defvar flymake-project-diagnostics-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map flymake-diagnostics-buffer-mode-map) + map)) + +(define-derived-mode flymake-project-diagnostics-mode tabulated-list-mode + "Flymake diagnostics" + "A mode for listing Flymake diagnostics in a project." + :interactive nil + (flymake--tabulated-setup t)) + +(cl-defun flymake--project-diagnostics (&optional (project (project-current))) + "Get all known relevant diagnostics for PROJECT." + (let* ((root (project-root project)) + (visited-buffers (cl-remove-if-not #'buffer-file-name (project-buffers project))) + buffer-annotated-diags + relevant-foreign-diags + list-only-diags + annotated-diag-files) + (setq buffer-annotated-diags + (cl-loop for buf in visited-buffers + for diags = (with-current-buffer buf + (flymake-diagnostics)) + when diags do + (push (buffer-file-name buf) annotated-diag-files) + append (cl-sort diags #'< :key #'flymake-diagnostic-beg))) + (cl-loop + for buf in visited-buffers + do (with-current-buffer buf + (when flymake-mode + (maphash + (lambda (_backend state) + (maphash + (lambda (foreign-file diags) + (setq foreign-file (expand-file-name foreign-file)) + ;; FIXME: This is not right if more than one visited + ;; source targets the same foreign file. Don't + ;; think we can get away without some kind of + ;; `cl-remove-duplicates' here that utilizes + ;; `flymake--equal-diagnostic-p'. + (unless (member foreign-file annotated-diag-files) + (push foreign-file annotated-diag-files) + (setq relevant-foreign-diags + (append relevant-foreign-diags + diags)))) + (flymake--state-foreign-diags state))) + flymake--state)))) + (setq list-only-diags + (cl-loop for (file-name . diags) in flymake-list-only-diagnostics + if (and (string-prefix-p (expand-file-name root) file-name) + (not (member file-name annotated-diag-files))) + append diags)) + (append buffer-annotated-diags relevant-foreign-diags list-only-diags))) + +(defun flymake--project-diagnostics-buffer (root) + (get-buffer-create (format "*Flymake diagnostics for `%s'*" root))) + +(defun flymake-show-project-diagnostics () + "Show a list of Flymake diagnostics for the current project." + (interactive) + (let* ((prj (project-current)) + (root (project-root prj)) + (buffer (flymake--project-diagnostics-buffer root))) + (with-current-buffer buffer + (flymake-project-diagnostics-mode) + (setq-local flymake--project-diagnostic-list-project prj) + (setq next-error-last-buffer (current-buffer)) + (revert-buffer) + (display-buffer (current-buffer) + `((display-buffer-reuse-window + display-buffer-at-bottom) + (window-height . flymake--fit-diagnostics-window)))))) + +(defun flymake--update-diagnostics-listings (buffer) + "Update diagnostics listings somehow relevant to BUFFER." + (dolist (probe (buffer-list)) + (with-current-buffer probe + (when (or (and (eq major-mode 'flymake-project-diagnostics-mode) + flymake--project-diagnostic-list-project + (buffer-file-name buffer) + (memq buffer + (project-buffers flymake--project-diagnostic-list-project))) + (and (eq major-mode 'flymake-diagnostics-buffer-mode) + (eq flymake--diagnostics-buffer-source buffer))) + (revert-buffer))))) + + +;;; Eol overlay helpers +;;; +(defun flymake--update-eol-overlays () + "Update the `display' property of end-of-line overlays." + (save-restriction + (widen) + (dolist (o (overlays-in (point-min) (point-max))) + (when (overlay-get o 'flymake--eol-overlay) + (if-let* ((src-ovs (overlay-get o 'flymake-eol-source-overlays))) + (overlay-put o 'display (flymake--eol-overlay-summary src-ovs)) + (delete-overlay o)))))) + +(defun flymake--eol-overlay-summary (src-ovs) + "Helper function for `flymake--update-eol-overlays'." + (cl-flet ((summarize (d) + (flymake--format-diagnostic d :eol 'eol-face))) + (let* ((diags + (cl-sort + (mapcar (lambda (o) (overlay-get o 'flymake-diagnostic)) src-ovs) + #'> + :key (lambda (d) (flymake--severity (flymake-diagnostic-type d))))) + (summary + (concat + " " + (cond ((eq flymake-show-diagnostics-at-end-of-line 'short) + (concat + (summarize (car diags)) + (and (cdr diags) + (concat + " " + (propertize (format "and %s more" + (1- (length diags))) + 'face 'flymake-eol-information-face))))) + ((eq flymake-show-diagnostics-at-end-of-line 'fancy) + (flymake--eol-draw-fancy diags #'summarize)) + (t + (mapconcat #'summarize diags " "))) + "\n"))) + (put-text-property 0 1 'cursor t summary) + summary))) + +(defun flymake--eol-draw-fancy-1 (text boxdraw-face line-beg-col + height-to-clear + text-beg-col + text-end-col) + (cl-flet ((move (cl) + (let* ((lep (line-end-position)) + (target (+ (point) cl)) + (diff (- target lep))) + (cond ((> diff 0) + (goto-char lep) + (insert (make-string diff ? ))) + (t + (goto-char target))))) + (onward () + (let ((rem (forward-line 1))) + (unless (and (not (eobp)) (zerop rem)) + (goto-char (point-max)) + (insert "\n"))))) + (goto-char (point-min)) + (cl-loop + with fork = (propertize "├" 'face boxdraw-face) + with pipe = (propertize "│" 'face boxdraw-face) + with inhibit-field-text-motion = t + for i from 0 + repeat height-to-clear + do (move line-beg-col) + (let ((c (char-before))) + (delete-char -1) + (insert + (propertize + (cond ;; ((zerop i) "┬") + ((memq c '(?└ ?├)) fork) + (t pipe)) + 'face boxdraw-face))) + (onward)) + (move line-beg-col) + (delete-char -1) + (insert (propertize "└" 'face boxdraw-face)) + (insert (propertize (make-string (- text-beg-col line-beg-col 1) + ?─) + 'face boxdraw-face)) + (insert " ") + (let ((rect (with-temp-buffer + (insert text) + (let ((fill-column (- text-end-col text-beg-col))) + (fill-paragraph) + (forward-line 0) + (move fill-column) + (extract-rectangle (point-min) (point-max)))))) + (insert-rectangle rect) + (+ height-to-clear (length rect))))) + +(defun flymake--eol-draw-fancy (diags summarize-fn) + (with-temp-buffer + (cl-loop + with sorted = (cl-sort diags #'> :key #'flymake-diagnostic-beg) + for diag in sorted + for text = (funcall summarize-fn diag) + for line-beg-col = + (with-current-buffer (flymake-diagnostic-buffer diag) + (save-excursion + (goto-char (flymake-diagnostic-beg diag)) + (1+ (current-column)))) + for height-to-clear = 0 then ret + for i from 0 + for adjust = (* i 2) + for face = `(:foreground + ,(face-attribute + (or (get-text-property 0 'face text) + 'flymake-error) + :foreground nil t)) + for text-beg-col = (max (- (max 30 (+ line-beg-col 5)) adjust) (+ line-beg-col 1)) + for text-end-col = (max 100 (+ text-beg-col 40)) + for ret = (flymake--eol-draw-fancy-1 + text + face + line-beg-col + height-to-clear + text-beg-col + text-end-col)) + (concat " \n" (buffer-string)))) + + +;;; Margins and fringes + +(defvar-local flymake--original-margin-width nil + "Store original margin width. +Used by `flymake--resize-margins' for restoring original margin width +when flymake is turned off.") + +(defun flymake--suitably-fringed-p (&optional window) + "Tell if WINDOW is suitably fringed-up fro Flymake." + (cl-case flymake-fringe-indicator-position + (left-fringe (< 0 (nth 0 (window-fringes window)))) + (right-fringe (< 0 (nth 1 (window-fringes window)))))) + +(defun flymake--bs-display (type where) + "Return a `display' spec for an overlay's `before-string'. +The overlay will represent a diagnostic of type TYPE. WHERE is the +symbol `fringes' or the symbol `margins'." + (let* ((indicator (flymake--lookup-type-property + type + (cl-case where + (fringes 'flymake-bitmap) + (margins 'flymake-margin-string)) + (alist-get 'bitmap (alist-get type ; backward compat + flymake-diagnostic-types-alist)))) + (value (if (symbolp indicator) + (symbol-value indicator) + indicator)) + (valuelist (if (listp value) + value + (list value))) + (indicator-car (car valuelist))) + (cond ((and (symbolp indicator-car) + flymake-fringe-indicator-position) + (cons flymake-fringe-indicator-position valuelist)) + ((and (stringp indicator-car) + flymake-margin-indicator-position) + `((margin ,flymake-margin-indicator-position) + ,(propertize + indicator-car + 'face `(:inherit (,(cdr valuelist) default)) + 'mouse-face 'highlight + 'help-echo "Open Flymake diagnostics" + 'keymap (let ((map (make-sparse-keymap))) + (define-key + map `[,flymake-margin-indicator-position mouse-1] + #'flymake-show-buffer-diagnostics) + map))))))) + +(defun flymake--appropriate-margin () + (if (eq flymake-margin-indicator-position 'left-margin) + 'left-margin-width 'right-margin-width)) + +(defun flymake--restore-margins () + (when flymake--original-margin-width + (set (flymake--appropriate-margin) flymake--original-margin-width)) + (flymake--apply-margins)) + +(defun flymake--suitable-margin-width () + (let* ((indicators + (mapcar (lambda (sym) + (let ((ind (get sym 'flymake-margin-string))) + (when (and (equal (car ind) "‼") + (not (char-displayable-p ?‼))) + (setq ind (cons "!!" (cdr ind))) + (put sym 'flymake-margin-string ind)) + (car ind))) + '(flymake-error flymake-warning flymake-note)))) + (apply #'max (mapcar #'string-width indicators)))) + +(defun flymake--resize-margins () + (let* ((sym (flymake--appropriate-margin)) + (width (flymake--suitable-margin-width)) + (curr (symbol-value sym))) + (unless (eq curr width) + (setq flymake--original-margin-width (symbol-value sym)) + (set sym width) + (flymake--apply-margins)))) + +(defun flymake--apply-margins () + ;; FIXME: this destroys any scroll an inactive window showing + (mapc (lambda (w) + (set-window-buffer w (window-buffer w))) + (get-buffer-window-list nil nil 'visible))) + +(provide 'flymake) + +;;; flymake.el ends here diff --git a/elpa/flymake-1.4.5/flymake.info b/elpa/flymake-1.4.5/flymake.info new file mode 100644 index 00000000..b63c4421 --- /dev/null +++ b/elpa/flymake-1.4.5/flymake.info @@ -0,0 +1,1942 @@ +This is flymake.info, produced by makeinfo version 7.2 from +flymake.texi. + +This manual is for GNU Flymake (version 1.3.4, April 2023). + + Copyright © 2004-2026 Free Software Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with no Invariant Sections, with the Front-Cover Texts + being "A GNU Manual," and with the Back-Cover Texts as in (a) + below. A copy of the license is included in the section entitled + "GNU Free Documentation License". + + (a) The FSF's Back-Cover Text is: "You have the freedom to copy and + modify this GNU manual." +INFO-DIR-SECTION Emacs misc features +START-INFO-DIR-ENTRY +* Flymake: (flymake). A universal on-the-fly syntax checker. +END-INFO-DIR-ENTRY + + +File: flymake.info, Node: Top, Next: Using Flymake, Up: (dir) + +GNU Flymake +*********** + +Flymake is a universal on-the-fly syntax checker for Emacs. When +enabled, Flymake contacts one or more source “backends” to collect +information about problems in the buffer, called “diagnostics”, and +visually annotates them with a special face. The mode line displays +overall status including totals for different types of diagnostics. + + To learn about using Flymake, *note Using Flymake::. + + When the Emacs LSP support mode Eglot is enabled, Flymake will use +that as an additional back-end. *Note (eglot)Eglot Features::. Flymake +is also designed to be easily extended to support new backends via an +Elisp interface. *Note Flymake API::. + + This manual is for GNU Flymake (version 1.3.4, April 2023). + + Copyright © 2004-2026 Free Software Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with no Invariant Sections, with the Front-Cover Texts + being "A GNU Manual," and with the Back-Cover Texts as in (a) + below. A copy of the license is included in the section entitled + "GNU Free Documentation License". + + (a) The FSF's Back-Cover Text is: "You have the freedom to copy and + modify this GNU manual." + +* Menu: + +* Using Flymake:: +* Flymake API:: +* The legacy Proc backend:: +* GNU Free Documentation License:: +* Index:: + + +File: flymake.info, Node: Using Flymake, Next: Flymake API, Prev: Top, Up: Top + +1 Using Flymake +*************** + +Flymake is only useful if at least one “backend” is configured to +provide the buffer-checking service. This is done via the hook +‘flymake-diagnostic-functions’. *Note Hooks: (emacs)Hooks. + + It's possible that some major modes or a third-party package has +already setup this hook for you, by adding “backend functions” to +‘flymake-diagnostic-functions’. If you know Elisp you may also write +your own Flymake backend functions. *Note Backend functions::. + + When the Emacs LSP support mode Eglot is enabled, Flymake will use +that as an additional back-end automatically. *Note (eglot)Eglot +Features::. + +* Menu: + +* Starting Flymake:: +* Finding diagnostics:: +* Mode line status:: +* Troubleshooting:: +* Customizable variables:: + + +File: flymake.info, Node: Starting Flymake, Next: Finding diagnostics, Up: Using Flymake + +1.1 Starting Flymake +==================== + +To use Flymake, activate the minor-mode ‘flymake-mode’. Use the command +‘flymake-mode’ to toggle it on and off. The mode line should indicate +its presence via an indicator (*note Mode line status::). + + Syntax checks happen "on-the-fly". Each check is started whenever: + + • ‘flymake-mode’ is started, unless ‘flymake-start-on-flymake-mode’ + is ‘nil’; + + • the buffer is saved, unless ‘flymake-start-on-save-buffer’ is + ‘nil’; + + • some changes were made to the buffer more than ‘0.5’ seconds ago + (the delay is configurable in ‘flymake-no-changes-timeout’). + + • When the user invokes the command ‘flymake-start’. + + If the check detected errors or warnings, the respective buffer +regions are highlighted. *Note Finding diagnostics::, for how to learn +what the problems are. + + +File: flymake.info, Node: Finding diagnostics, Next: Mode line status, Prev: Starting Flymake, Up: Using Flymake + +1.2 Finding diagnostics +======================= + +If Flymake has highlighted the buffer, you may hover the mouse on the +highlighted regions to learn what the specific problem is. +Alternatively, place point on the highlighted regions and use the +commands ‘eldoc’ or ‘display-local-help’. + + Another easy way to get instant access to the diagnostic text is to +set ‘flymake-show-diagnostics-at-end-of-line’ to a non-‘nil’ value. +This makes the diagnostic messages appear at the end of the line where +the regular annotation is located (*note Customizable variables::) + + If the diagnostics are outside the visible region of the buffer, +‘flymake-goto-next-error’ and ‘flymake-goto-prev-error’ let you navigate +to the next/previous erroneous regions, respectively. It might be a +good idea to map them to ‘M-n’ and ‘M-p’ in ‘flymake-mode’, by adding to +your init file: + + (define-key flymake-mode-map (kbd "M-n") 'flymake-goto-next-error) + (define-key flymake-mode-map (kbd "M-p") 'flymake-goto-prev-error) + + Sometimes it is useful to have a detailed overview of the diagnostics +in your files without having to jump to each one. The commands +‘flymake-show-buffer-diagnostics’ and ‘flymake-show-project-diagnostics’ +are designed to handle this situation. When invoked, they bring up a +separate buffer containing a detailed structured listing of multiple +diagnostics in the current buffer or for the current project, +respectively (*note (emacs)Projects::). + + The listings is continuously updated as you edit source code, adding +or removing lines as you make or correct mistakes. Each line of this +listing includes the type of the diagnostic, its line and column in the +file, as well as the diagnostic message. You may sort the listing by +each of these columns. + + When invoked on a diagnostic (either via the keyboard or a mouse +click) the command ‘flymake-show-buffer-diagnostics’ attempts to reveal +said diagnostic in the listing. + + +File: flymake.info, Node: Mode line status, Next: Troubleshooting, Prev: Finding diagnostics, Up: Using Flymake + +1.3 Mode line status +==================== + +When enabled, Flymake displays its status in the mode line, which +provides a visual summary of diagnostic collection. It may also hint at +certain exceptional situations encountered when communicating with +backends. + + The following statuses are defined: + +[NERRORS Normal operation. NERRORS and NWARNINGS are, +NWARNINGS ...] respectively, the total number of errors and + warnings found during the last buffer check, for all + backends. They may be followed by other totals for + other types of diagnostics + (*note Flymake error types::). + +‘Wait’ Some Flymake backends haven't reported since the + last time they where questioned. It is reasonable + to assume that this is a temporary delay and Flymake + will resume normal operation soon. + +‘!’ All the configured Flymake backends have disabled + themselves: Flymake cannot annotate the buffer and + action from the user is needed to investigate and + remedy the situation (*note Troubleshooting::). + +‘?’ There are no applicable Flymake backends for this + buffer, thus Flymake cannot annotate it. To fix + this, a user may look to extending Flymake and add a + new backend (*note Flymake API::). + + + If you would like to customize the appearance of the mode-line, you +can use the variables ‘flymake-mode-line-format’ and +‘flymake-mode-line-counter-format’ for that purpose. *Note Customizable +variables::. + + +File: flymake.info, Node: Troubleshooting, Next: Customizable variables, Prev: Mode line status, Up: Using Flymake + +1.4 Troubleshooting +=================== + +As Flymake supports multiple simultaneously active external backends, it +becomes useful to monitor their status. For example, some backends may +take longer than others to respond or complete, and some may decide to +_disable_ themselves if they are not suitable for the current buffer or +encounter some unavoidable problem. A disabled backend is not tried +again for future checks of the current buffer. + + The commands ‘flymake-reporting-backends’, ‘flymake-running-backends’ +and ‘flymake-disabled-backends’ show the backends currently used and +those which are disabled. + + Sometimes, re-starting a backend that disabled itself is useful after +some external roadblock has been removed (for example after the user +installed a needed syntax-check program). Invoking ‘flymake-start’ with +a prefix argument is a way to reset the disabled backend list, so that +they will be tried again in the next check. Manually toggling +‘flymake-mode’ off and on again also works. + + Flymake uses a simple logging facility for indicating important +points in the control flow. The logging facility sends logging messages +to the ‘*Flymake log*’ buffer. The logged information can be used for +resolving various problems related to Flymake. For convenience, a +shortcut to this buffer can be found in Flymake's menu, accessible from +the top menu bar or just left of the status indicator. The command +‘flymake-switch-to-log-buffer’ is another alternative. + + Logging output is controlled by the Emacs ‘warning-minimum-log-level’ +and ‘warning-minimum-level’ variables. + + +File: flymake.info, Node: Customizable variables, Prev: Troubleshooting, Up: Using Flymake + +1.5 Customizable variables +========================== + +This section summarizes customization variables used for the +configuration of the Flymake user interface. + +‘flymake-mode-line-lighter’ + The name of the mode. Defaults to ‘Flymake’. + +‘flymake-mode-line-format’ + Format to use for the Flymake mode line indicator. + +‘flymake-mode-line-counter-format’ + mode line construct for formatting Flymake diagnostic counters + inside the Flymake mode line indicator. + +‘flymake-no-changes-timeout’ + If any changes are made to the buffer, syntax check is + automatically started after this many seconds, unless the user + makes another change, which resets the timer. + +‘flymake-start-on-flymake-mode’ + A boolean flag indicating whether to start syntax check immediately + after enabling ‘flymake-mode’. + +‘flymake-start-on-save-buffer’ + A boolean flag indicating whether to start syntax check after + saving the buffer. + +‘flymake-error’ + A custom face for highlighting regions for which an error has been + reported. + +‘flymake-warning’ + A custom face for highlighting regions for which a warning has been + reported. + +‘flymake-note’ + A custom face for highlighting regions for which a note has been + reported. + +‘flymake-indicator-type’ + The indicator type which Flymake should use to indicate lines with + errors or warnings. Depending on your preference, this can either + use ‘fringes’ or ‘margins’ for indicating errors. On text + terminals, only ‘margins’ is available. + +‘flymake-error-bitmap’ + A bitmap used in the fringe to mark lines for which an error has + been reported. + +‘flymake-warning-bitmap’ + A bitmap used in the fringe to mark lines for which a warning has + been reported. + +‘flymake-fringe-indicator-position’ + Which fringe (if any) should show the warning/error bitmaps. + +‘flymake-margin-indicators-string’ + Specifies the string and face to use for the margin indicators, for + each error type. + +‘flymake-margin-indicator-position’ + Which margin (if any) should show the warning/error strings. + +‘flymake-autoresize-margins’ + If non-‘nil’, Flymake will resize the margins when ‘flymake-mode’ + is turned on or off. Only relevant if ‘flymake-indicator-type’ is + set to ‘margins’. + +‘flymake-wrap-around’ + If non-‘nil’, moving to errors with ‘flymake-goto-next-error’ and + ‘flymake-goto-prev-error’ wraps around buffer boundaries. + +‘flymake-show-diagnostics-at-end-of-line’ + If non-‘nil’, show summarized descriptions of diagnostics at the + end of the line. Depending on your preference, this can either be + distracting and easily confused with actual code, or a significant + early aid that relieves you from moving around or reaching for the + mouse to consult an error message. This value may also be set to + ‘fancy’, which will attempt to layout diagnostics below the + affected line using unicode graphics to point to diagnostic locus. + +‘flymake-diagnostic-format-alist’ + Control which parts of a diagnostic to show in various situations. + +‘flymake-error-eol’ + A custom face for summarizing diagnostic error messages. + +‘flymake-warning-eol’ + A custom face for summarizing diagnostic warning messages. + +‘flymake-note-eol’ + A custom face for summarizing diagnostic notes. + + +File: flymake.info, Node: Flymake API, Next: The legacy Proc backend, Prev: Using Flymake, Up: Top + +2 Flymake API +************* + +Flymake's API supports the following use cases: + + 1. Changing the look and feel of the annotations produced by the + different backends. *Note Flymake error types::. + + 2. Adding a new buffer-checking backend. *Note Backend functions::. + + 3. Writing extension to and process Flymake's output. *Note + Inspecting diagnostics::. + + The following sections discuss each approach in detail. + +* Menu: + +* Flymake error types:: +* Backend functions:: +* Inspecting diagnostics:: + + +File: flymake.info, Node: Flymake error types, Next: Backend functions, Up: Flymake API + +2.1 Customizing Flymake error types +=================================== + +To customize the appearance of error types, the user must set properties +on the symbols associated with each diagnostic type. + + The three standard diagnostic keyword symbols - ‘:error’, ‘:warning’ +and ‘:note’ - have pre-configured appearances. However a backend may +define more (*note Backend functions::). + + The following properties can be set: + + • ‘flymake-bitmap’, an image displayed in the fringe according to + ‘flymake-fringe-indicator-position’. The value actually follows + the syntax of ‘flymake-error-bitmap’ (*note Customizable + variables::). It is overridden by any ‘before-string’ overlay + property. + + • ‘flymake-margin-string’, a string displayed in the margin according + to ‘flymake-margin-indicator-position’. The value actually follows + the syntax of ‘flymake-margin-indicators-string’ (*note + Customizable variables::). It is overridden by any ‘before-string’ + overlay property. + + • ‘flymake-overlay-control’, an alist ((OVPROP . VALUE) ...) of + further properties used to affect the appearance of Flymake + annotations. With the exception of ‘category’ and ‘evaporate’, + these properties are applied directly to the created overlay (*note + (elisp)Overlay Properties::). + + As an example, here's how to make diagnostics of the type ‘:note’ + stand out more prominently: + + (push '(face . highlight) (get :note 'flymake-overlay-control)) + + If you push another alist entry in front, it overrides the previous + one. So this effectively removes the face from ‘:note’ + diagnostics: + + (push '(face . nil) (get :note 'flymake-overlay-control)) + + To restore the original look for ‘:note’ types, empty or remove its + ‘flymake-overlay-control’ property: + + (put :note 'flymake-overlay-control '()) + + • ‘severity’ is a non-negative integer specifying the diagnostic's + severity. The higher the value, the more serious is the error. If + the overlay property ‘priority’ is not specified in + ‘flymake-overlay-control’, ‘flymake-severity’ is used to set it and + help sort overlapping overlays. + + • ‘flymake-type-name’ is a string used to succinctly name the error + type, in case the name of the symbol associated with it is very + long. + + • ‘flymake-category’ is a symbol whose property list is considered + the default for missing values of any other properties. + + • ‘mode-line-face’ is a face specifier controlling the appearance of + the indicator of this type of diagnostic in the mode line. + + • ‘echo-face’ is a face specifier controlling the appearance of the + summarized description of this diagnostic when reading diagnostic + messages (*note Finding diagnostics::). + + Three default diagnostic types are predefined: ‘:error’, ‘:warning’, +and ‘:note’. By default, each one of them has a ‘flymake-category’ +property whose value is, respectively, the category symbol +‘flymake-error’, ‘flymake-warning’ and ‘flymake-note’. + + These category symbols' plist is where the values of customizable +variables and faces (such as ‘flymake-error-bitmap’) are found. Thus, +if you change their plists, Flymake may stop honoring these user +customizations. + + The ‘flymake-category’ special property is especially useful for +backends which create diagnostics objects with non-default types that +differ from an existing type by only a few properties (*note Flymake +utility functions::). + + As an example, consider configuring a new diagnostic type +‘:low-priority-note’ that behaves much like ‘:note’, but without an +overlay face. + + (put :low-priority-note 'flymake-overlay-control '((face . nil))) + (put :low-priority-note 'flymake-category 'flymake-note) + + As you might have guessed, Flymake's annotations are implemented as +overlays (*note (elisp)Overlays::). Along with the properties that you +specify for the specific type of diagnostic, Flymake adds the property +‘flymake-diagnostic’ to these overlays, and sets it to the object that +the backend created with ‘flymake-make-diagnostic’. + + Since overlays also support arbitrary keymaps, you can use this along +with the functions ‘flymake-diagnostics’ and ‘flymake-diagnostic-text’ +(*note Flymake utility functions::) to create interactive annotations, +such as in the following example of binding a ‘mouse-3’ event (middle +mouse button click) to an Internet search for the text of a ‘:warning’ +or ‘:error’. + + (defun my-search-for-message (event) + (interactive "e") + (let* ((diags (flymake-diagnostics (posn-point (event-start event)))) + (topmost-diag (car diags))) + (eww-browse-url + (concat + "https://duckduckgo.com/?q=" + (replace-regexp-in-string + " " "+" (flymake-diagnostic-text topmost-diag))) + t))) + + (dolist (type '(:warning :error)) + (push '(mouse-face . highlight) (get type 'flymake-overlay-control)) + (push `(keymap . ,(let ((map (make-sparse-keymap))) + (define-key map [mouse-2] + 'my-search-for-message) + map)) + (get type 'flymake-overlay-control))) + + +File: flymake.info, Node: Backend functions, Next: Inspecting diagnostics, Prev: Flymake error types, Up: Flymake API + +2.2 Backend functions +===================== + +Flymake backends are Lisp functions placed in the special hook +‘flymake-diagnostic-functions’. + + A backend's responsibility is to diagnose the contents of a buffer +for problems, registering the problem's positions, type, and summary +description. This information is collected in the form of diagnostic +objects created by the function ‘flymake-make-diagnostic’ (*note Flymake +utility functions::), and then handed over to Flymake, which proceeds to +annotate the buffer. + + A request for a buffer check, and the subsequent delivery of +diagnostics, are two key events of the interaction between Flymake and +backend. Each such event corresponds to a well-defined function calling +convention: one for calls made by Flymake into the backend via the +backend function, the other in the reverse direction via a callback. To +be usable, backends must adhere to both. + + The first argument passed to a backend function is always REPORT-FN, +a callback function detailed below. Beyond it, functions must be +prepared to accept (and possibly ignore) an arbitrary number of +keyword-value pairs of the form ‘(:KEY VALUE :KEY2 VALUE2...)’. + + Currently, Flymake may pass the following keywords and values to the +backend function: + + • ‘:recent-changes’ The value is a list recent changes since the last + time the backend function was called for the buffer. If the list + is empty, this indicates that no changes have been recorded. If it + is the first time that this backend function is called for this + activation of ‘flymake-mode’, then this argument isn't provided at + all (in other words, it's not merely nil). + + Each element is in the form (BEG END TEXT) where BEG and END are + buffer positions, and TEXT is a string containing the text + contained between those positions (if any), after the change was + performed. + + • ‘:changes-start’ and ‘:changes-end’ The value is, respectively, the + minimum and maximum buffer positions touched by the recent changes. + These are provided for convenience and only if ‘:recent-changes’ is + also provided. + + Whenever Flymake or the user decide to re-check the buffer, backend +functions are called as detailed above, and are expected to initiate +this check, but aren't in any way required to complete it before +exiting: if the computation involved is expensive, as is often the case +with large buffers, that slower task should be scheduled for the future +using asynchronous sub-processes (*note (elisp)Asynchronous Processes::) +or other asynchronous mechanisms. + + In any case, backend functions are expected to return quickly or +signal an error, in which case the backend is disabled (*note +Troubleshooting::). + + If the function returns, Flymake considers the backend to be +“running”. If it has not done so already, the backend is expected to +call the function REPORT-FN passed to it, at which point Flymake +considers the backend to be “reporting”. Backends call REPORT-FN by +passing it a single argument REPORT-ACTION followed by an optional list +of keyword-value pairs of the form +‘(:REPORT-KEY VALUE :REPORT-KEY2 VALUE2...)’. + + Currently accepted values for REPORT-ACTION are: + + • A (possibly empty) list of diagnostic objects created by + ‘flymake-make-diagnostic’, causing Flymake to annotate the buffer + with this information. + + A backend may call REPORT-FN repeatedly in this manner, but only + until Flymake considers that the most recently requested buffer + check is now obsolete, because, say, buffer contents have changed + in the meantime. The backend is only given notice of this via a + renewed call to the backend function. Thus, to prevent making + obsolete reports and wasting resources, backend functions should + first cancel any ongoing processing from previous calls. + + • The symbol ‘:panic’, signaling that the backend has encountered an + exceptional situation and should be disabled. + + Currently accepted REPORT-KEY arguments are: + + • ‘:explanation’, whose value should give user-readable details of + the situation encountered, if any. + + • ‘:force’, whose value should be a boolean suggesting that Flymake + consider the report even if it was somehow unexpected. + + • ‘:region’, a cons (BEG . END) of buffer positions indicating that + the report applies to that region and that previous reports + targeting other parts of the buffer remain valid. + +* Menu: + +* Flymake utility functions:: +* Foreign and list-only diagnostics:: +* An annotated example backend:: + + +File: flymake.info, Node: Flymake utility functions, Next: Foreign and list-only diagnostics, Up: Backend functions + +2.2.1 Flymake utility functions +------------------------------- + +Before delivering them to Flymake, backends create diagnostic objects by +calling the function ‘flymake-make-diagnostic’. + + -- Function: flymake-make-diagnostic locus beg end type info &optional + data + Make a Flymake diagnostic for the region of text in LOCUS's + delimited by BEG and END. TYPE is a diagnostic symbol (*note + Flymake error types::). TEXT can be a string or a list (ORIGIN + CODE MESSAGE) appropriately categorizing and describing the + diagnostic. Most commonly, LOCUS is the buffer object designating + for the current buffer being syntax-checked. However, it may be a + string naming a file relative to the current working directory. + *Note Foreign and list-only diagnostics::, for when this may be + useful. Depending on the type of LOCUS, BEG and END are both + either buffer positions or conses (LINE . COL) which specify the + line and column of the diagnostic's start and end positions, + respectively. + + It is often the case with external syntax tools that a diagnostic's +position is reported in terms of a line number, and sometimes a column +number. To convert this information into a buffer position, backends +can use the following function: + + -- Function: flymake-diag-region buffer line &optional col + Compute BUFFER's region (BEG . END) corresponding to LINE and COL. + If COL is ‘nil’, return a region just for LINE. Return ‘nil’ if + the region is invalid. This function saves match data (*note + (elisp)Saving Match Data::). + + For troubleshooting purposes, backends may record arbitrary +exceptional or erroneous situations into the Flymake log buffer (*note +Troubleshooting::): + + -- Macro: flymake-log level msg &optional args + Log, at level LEVEL, the message MSG formatted with ARGS. LEVEL is + passed to ‘display-warning’ (*note (elisp)Warning Basics::), which + is used to display the warning in Flymake's log buffer. + + +File: flymake.info, Node: Foreign and list-only diagnostics, Next: An annotated example backend, Prev: Flymake utility functions, Up: Backend functions + +2.2.2 Foreign and list-only diagnostics +--------------------------------------- + +It is possible for a given backend's implementation to use +‘flymake-make-diagnostic’ to create diagnostics for buffers or files +other than the "source" buffer where Flymake was enabled. For instance, +this is useful when a given backend has access to information about the +health of neighboring files that are not yet visited or whose +diagnostics depend on the current buffer's state. There are two +alternative ways to go about doing this: + + 1. If the information about neighboring diagnostics is obtained + regularly, like when each syntax-checking iteration of a ‘.c’ file + also reports a number of associated problems in an neighboring ‘.h’ + file, it is better to create so-called "foreign" diagnostics. + + This is done by passing a file name to ‘flymake-make-diagnostic’ + (*note Flymake utility functions::). Then, the resulting object is + simply reported along with the other "domestic" diagnostics for the + source buffer (*note Backend functions::). When the neighboring + file is visited as a buffer and Flymake is active there, a number + of supplemental annotations will appear and automatically update + whenever as the "source" buffer is syntax-checked. + + 2. If information about neighboring diagnostics is obtained + infrequently, like when running a time-consuming and sporadic check + of a large project, it is easier for the backend to modify the + global variable ‘flymake-list-only-diagnostics’. + + Flymake will look up this variable when asked to compile + project-wide lists of diagnostics. The backend should add one or + more alist entries that look like (FILE-NAME . DIAGS). FILE-NAME + is the absolute name of the neighboring file presumed not to be + visited in Emacs already, as that would mean that that buffer + contains more up-to-date information on its diagnostics. DIAGS is + a list of diagnostic objects. When the neighboring file FILE-NAME + is visited as a buffer and Flymake is activated there, the + "list-only" diagnostics will _not_ produce annotations for DIAGS, + as Flymake assumes that the Flymake activation in the new buffer + will take care of that. + + +File: flymake.info, Node: An annotated example backend, Prev: Foreign and list-only diagnostics, Up: Backend functions + +2.2.3 An annotated example backend +---------------------------------- + +This section presents an annotated example of a complete working Flymake +backend. The example illustrates the process of writing a backend as +outlined above. + + The backend in question is used for checking Ruby source files. It +uses asynchronous sub-processes (*note (elisp)Asynchronous Processes::), +a common technique for performing parallel processing in Emacs. + + The following code needs lexical binding (*note (elisp)Using Lexical +Binding::) to be active. + + ;;; ruby-flymake.el --- A ruby Flymake backend -*- lexical-binding: t; -*- + (require 'cl-lib) + (defvar-local ruby--flymake-proc nil) + + (defun ruby-flymake (report-fn &rest _args) + ;; Not having a ruby interpreter is a serious problem which should cause + ;; the backend to disable itself, so an error is signaled. + ;; + (unless (executable-find + "ruby") (error "Cannot find a suitable ruby")) + ;; If a live process launched in an earlier check was found, that + ;; process is killed. When that process's sentinel eventually runs, + ;; it will notice its obsoletion, since it have since reset + ;; `ruby-flymake-proc' to a different value + ;; + (when (process-live-p ruby--flymake-proc) + (kill-process ruby--flymake-proc)) + + ;; Save the current buffer, the narrowing restriction, remove any + ;; narrowing restriction. + ;; + (let ((source (current-buffer))) + (save-restriction + (widen) + ;; Reset the `ruby--flymake-proc' process to a new process + ;; calling the ruby tool. + ;; + (setq + ruby--flymake-proc + (make-process + :name "ruby-flymake" :noquery t :connection-type 'pipe + ;; Make output go to a temporary buffer. + ;; + :buffer (generate-new-buffer " *ruby-flymake*") + :command '("ruby" "-w" "-c") + :sentinel + (lambda (proc _event) + ;; Check that the process has indeed exited, as it might + ;; be simply suspended. + ;; + (when (memq (process-status proc) '(exit signal)) + (unwind-protect + ;; Only proceed if `proc' is the same as + ;; `ruby--flymake-proc', which indicates that + ;; `proc' is not an obsolete process. + ;; + (if (with-current-buffer source (eq proc ruby--flymake-proc)) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + ;; Parse the output buffer for diagnostic's + ;; messages and locations, collect them in a list + ;; of objects, and call `report-fn'. + ;; + (cl-loop + while (search-forward-regexp + "^\\(?:.*\\.rb\\|-\\):\\([0-9]+\\): \\(.*\\)$" + nil t) + for msg = (match-string 2) + for (beg . end) = (flymake-diag-region + source + (string-to-number (match-string 1))) + for type = (if (string-match "^warning" msg) + :warning + :error) + when (and beg end) + collect (flymake-make-diagnostic source + beg + end + type + msg) + into diags + finally (funcall report-fn diags))) + (flymake-log :warning "Canceling obsolete check %s" + proc)) + ;; Cleanup the temporary buffer used to hold the + ;; check's output. + ;; + (kill-buffer (process-buffer proc))))))) + ;; Send the buffer contents to the process's stdin, followed by + ;; an EOF. + ;; + (process-send-region ruby--flymake-proc (point-min) (point-max)) + (process-send-eof ruby--flymake-proc)))) + + (defun ruby-setup-flymake-backend () + (add-hook 'flymake-diagnostic-functions 'ruby-flymake nil t)) + + (add-hook 'ruby-mode-hook 'ruby-setup-flymake-backend) + + +File: flymake.info, Node: Inspecting diagnostics, Prev: Backend functions, Up: Flymake API + +2.3 Inspecting diagnostics +========================== + +When Flymake has called on the backend and collected its diagnostics, it +will annotate the buffer with it. After this happens, Elisp programs +may call ‘flymake-diagnostics’ to collect such objects in a specified +region. + + -- Function: flymake-diagnostics beg end + Get a list of Flymake diagnostics in the region determined by BEG + and END. If neither BEG or END is supplied, use the whole buffer, + otherwise if BEG is non-‘nil’ and END is ‘nil’, consider only + diagnostics at BEG. + + A diagnostic object's properties can be accessed with the functions +‘flymake-diagnostic-backend’, ‘flymake-diagnostic-buffer’, +‘flymake-diagnostic-origin’, ‘flymake-diagnostic-code’ +‘flymake-diagnostic-message’, ‘flymake-diagnostic-beg’, +‘flymake-diagnostic-end’, ‘flymake-diagnostic-type’ and +‘flymake-diagnostic-data’. ‘flymake-diagnostic-text’ will compose the +diagnostic's origin, code and message in a single string. + + +File: flymake.info, Node: The legacy Proc backend, Next: GNU Free Documentation License, Prev: Flymake API, Up: Top + +3 The legacy "Proc" backend +*************************** + +* Menu: + +* Proc customization variables:: +* Adding support for a new syntax check tool:: +* Implementation overview:: +* Making a temporary copy:: +* Locating a master file:: +* Getting the include directories:: +* Locating the buildfile:: +* Starting the syntax check process:: +* Parsing the output:: +* Interaction with other modes:: + +The backend ‘flymake-proc-legacy-flymake’ was originally designed to be +extended for supporting new syntax check tools and error message +patterns. It is also controlled by its own set of customization +variables. + + +File: flymake.info, Node: Proc customization variables, Next: Adding support for a new syntax check tool, Up: The legacy Proc backend + +3.1 Customization variables for the Proc backend +================================================ + +‘flymake-proc-allowed-file-name-masks’ + A list of ‘(filename-regexp, init-function, cleanup-function + getfname-function)’ for configuring syntax check tools. *Note + Adding support for a new syntax check tool::. + +‘flymake-proc-master-file-dirs’ + A list of directories for searching a master file. *Note Locating + a master file::. + +‘flymake-proc-get-project-include-dirs-function’ + A function used for obtaining a list of project include dirs (C/C++ + specific). *Note Getting the include directories::. + +‘flymake-proc-master-file-count-limit’ +‘flymake-proc-check-file-limit’ + Used when looking for a master file. *Note Locating a master + file::. + +‘flymake-proc-err-line-patterns’ + Patterns for error/warning messages in the form ‘(regexp file-idx + line-idx col-idx err-text-idx)’. *Note Parsing the output::. + +‘flymake-proc-diagnostic-type-pred’ + A function to classify a diagnostic text as a particular type of + error. The value of this variable should be a function taking an + error text and returning a diagnostic symbol (*note Flymake error + types::). If it returns a non-‘nil’ value but there is no such + symbol in that table, the text is interpreted as a warning. If the + function returns ‘nil’, the text is assumed to be an error. + + The value of this variable can alternatively be a regular + expression that should match only warnings. + + This variable replaces the old ‘flymake-warning-re’ and + ‘flymake-warning-predicate’. + +‘flymake-proc-compilation-prevents-syntax-check’ + A flag indicating whether compilation and syntax check of the same + file cannot be run simultaneously. *Note Interaction with other + modes::. + + +File: flymake.info, Node: Adding support for a new syntax check tool, Next: Implementation overview, Prev: Proc customization variables, Up: The legacy Proc backend + +3.2 Adding support for a new syntax check tool +============================================== + +* Menu: + +* Example---Configuring a tool called directly:: +* Example---Configuring a tool called via make:: + +Syntax check tools are configured using the +‘flymake-proc-allowed-file-name-masks’ list. Each item of this list has +the following format: + + (filename-regexp, init-function, cleanup-function, getfname-function) + +‘filename-regexp’ + This field is used as a key for locating init/cleanup/getfname + functions for the buffer. Items in + ‘flymake-proc-allowed-file-name-masks’ are searched sequentially. + The first item with ‘filename-regexp’ matching buffer filename is + selected. If no match is found, ‘flymake-mode’ is switched off. + +‘init-function’ + ‘init-function’ is required to initialize the syntax check, usually + by creating a temporary copy of the buffer contents. The function + must return ‘(list cmd-name arg-list)’. If ‘init-function’ returns + null, syntax check is aborted, but ‘flymake-mode’ is not switched + off. + +‘cleanup-function’ + ‘cleanup-function’ is called after the syntax check process is + complete and should take care of proper deinitialization, which is + usually deleting a temporary copy created by the ‘init-function’. + +‘getfname-function’ + This function is used for translating filenames reported by the + syntax check tool into "real" filenames. Filenames reported by the + tool will be different from the real ones, as actually the tool + works with the temporary copy. In most cases, the default + implementation provided by Flymake, + ‘flymake-proc-get-real-file-name’, can be used as + ‘getfname-function’. + + To add support for a new syntax check tool, write the corresponding +‘init-function’ and, optionally, ‘cleanup-function’ and +‘getfname-function’. If the format of error messages reported by the +new tool is not yet supported by Flymake, add a new entry to the +‘flymake-proc-err-line-patterns’ list. + + The following sections contain some examples of configuring Flymake +support for various syntax check tools. + + +File: flymake.info, Node: Example---Configuring a tool called directly, Next: Example---Configuring a tool called via make, Up: Adding support for a new syntax check tool + +3.2.1 Example--Configuring a tool called directly +------------------------------------------------- + +In this example, we will add support for ‘perl’ as a syntax check tool. +‘perl’ supports the ‘-c’ option which does syntax checking. + + First, we write the ‘init-function’: + + (defun flymake-proc-perl-init () + (let* ((temp-file (flymake-proc-init-create-temp-buffer-copy + 'flymake-proc-create-temp-inplace)) + (local-file (file-relative-name + temp-file + (file-name-directory buffer-file-name)))) + (list "perl" (list "-wc " local-file)))) + + ‘flymake-proc-perl-init’ creates a temporary copy of the buffer +contents with the help of ‘flymake-proc-init-create-temp-buffer-copy’, +and builds an appropriate command line. + + Next, we add a new entry to the +‘flymake-proc-allowed-file-name-masks’: + + (setq flymake-proc-allowed-file-name-masks + (cons '(".+\\.pl$" + flymake-proc-perl-init + flymake-proc-simple-cleanup + flymake-proc-get-real-file-name) + flymake-proc-allowed-file-name-masks)) + + Note that we use standard ‘cleanup-function’ and ‘getfname-function’. + + Finally, we add an entry to ‘flymake-proc-err-line-patterns’: + + (setq flymake-proc-err-line-patterns + (cons '("\\(.*\\) at \\([^ \n]+\\) line \\([0-9]+\\)[,.\n]" + 2 3 nil 1) + flymake-proc-err-line-patterns)) + + +File: flymake.info, Node: Example---Configuring a tool called via make, Prev: Example---Configuring a tool called directly, Up: Adding support for a new syntax check tool + +3.2.2 Example--Configuring a tool called via make +------------------------------------------------- + +In this example we will add support for C files syntax checked by ‘gcc’ +called via ‘make’. + + We're not required to write any new functions, as Flymake already has +functions for ‘make’. We just add a new entry to the +‘flymake-proc-allowed-file-name-masks’: + + (setq flymake-proc-allowed-file-name-masks + (cons '(".+\\.c$" + flymake-proc-simple-make-init + flymake-proc-simple-cleanup + flymake-proc-get-real-file-name) + flymake-proc-allowed-file-name-masks)) + + ‘flymake-proc-simple-make-init’ builds the following ‘make’ command +line: + + (list "make" + (list "-s" "-C" + base-dir + (concat "CHK_SOURCES=" source) + "SYNTAX_CHECK_MODE=1" + "check-syntax")) + + ‘base-dir’ is a directory containing the ‘Makefile’, see *note +Locating the buildfile::. + + Thus, ‘Makefile’ must contain the ‘check-syntax’ target. In our case +this target might look like this: + +check-syntax: + gcc -o /dev/null -S ${CHK_SOURCES} || true + +The format of error messages reported by ‘gcc’ is already supported by +Flymake, so we don't have to add a new entry to +‘flymake-err-line-patterns’. Note that if you are using Automake, you +may want to replace ‘gcc’ with the standard Automake variable ‘COMPILE’: + +check-syntax: + $(COMPILE) -o /dev/null -S ${CHK_SOURCES} || true + + +File: flymake.info, Node: Implementation overview, Next: Making a temporary copy, Prev: Adding support for a new syntax check tool, Up: The legacy Proc backend + +3.3 Implementation overview +=========================== + +‘flymake-proc-legacy-flymake’ saves a copy of the buffer in a temporary +file in the buffer's directory (or in the system temporary directory, +for Java files), creates a syntax check command and launches a process +with this command. The output is parsed using a list of error message +patterns, and error information (file name, line number, type and text) +is saved. After the process has finished, Flymake highlights erroneous +lines in the buffer using the accumulated error information. + + Syntax check is considered possible if there's an entry in +‘flymake-proc-allowed-file-name-masks’ matching buffer's filename and +its ‘init-function’ returns non-‘nil’ value. + + Two syntax check modes are distinguished: + + 1. Buffer can be syntax checked in a standalone fashion, that is, the + file (its temporary copy, in fact) can be passed over to the + compiler to do the syntax check. Examples are C/C++ sources (‘.c’, + ‘.cpp’) and Java (‘.java’). + + 2. Buffer can be syntax checked, but additional file, called master + file, is required to perform this operation. A master file is a + file that includes the current file, so that running a syntax check + tool on it will also check syntax in the current file. Examples + are C/C++ headers (‘.h’, ‘.hpp’). + + These modes are handled inside init/cleanup/getfname functions, see +*note Adding support for a new syntax check tool::. + + The Proc backend contains implementations of all functionality +required to support different syntax check modes described above (making +temporary copies, finding master files, etc.), as well as some +tool-specific (routines for Make, Ant, etc.) code. + + +File: flymake.info, Node: Making a temporary copy, Next: Locating a master file, Prev: Implementation overview, Up: The legacy Proc backend + +3.4 Making a temporary copy +=========================== + +After the possibility of the syntax check has been determined, a +temporary copy of the current buffer is made so that the most recent +unsaved changes could be seen by the syntax check tool. Making a copy +is quite straightforward in a standalone case (mode ‘1’), as it's just +saving buffer contents to a temporary file. + + Things get trickier, however, when master file is involved, as it +requires to + + • locate a master file + • patch it to include the current file using its new (temporary) + name. + + Locating a master file is discussed in the following section. + + Patching just changes all appropriate lines of the master file so +that they use the new (temporary) name of the current file. For +example, suppose current file name is ‘file.h’, the master file is +‘file.cpp’, and it includes current file via ‘#include "file.h"’. +Current file's copy is saved to file ‘file_flymake.h’, so the include +line must be changed to ‘#include "file_flymake.h"’. Finally, patched +master file is saved to ‘file_flymake_master.cpp’, and the last one is +passed to the syntax check tool. + + +File: flymake.info, Node: Locating a master file, Next: Getting the include directories, Prev: Making a temporary copy, Up: The legacy Proc backend + +3.5 Locating a master file +========================== + +Master file is located in two steps. + + First, a list of possible master files is built. A simple name +matching is used to find the files. For a C++ header ‘file.h’, the Proc +backend searches for all ‘.cpp’ files in the directories whose relative +paths are stored in a customizable variable +‘flymake-proc-master-file-dirs’, which usually contains something like +‘("." "./src")’. No more than ‘flymake-proc-master-file-count-limit’ +entries is added to the master file list. The list is then sorted to +move files with names ‘file.cpp’ to the top. + + Next, each master file in a list is checked to contain the +appropriate include directives. No more than +‘flymake-proc-check-file-limit’ of each file are parsed. + + For ‘file.h’, the include directives to look for are ‘#include +"file.h"’, ‘#include "../file.h"’, etc. Each include is checked against +a list of include directories (*note Getting the include directories::) +to be sure it points to the correct ‘file.h’. + + First matching master file found stops the search. The master file +is then patched and saved to disk. In case no master file is found, +syntax check is aborted, and corresponding status (‘!’) is reported in +the mode line. *Note Mode line status::. + + +File: flymake.info, Node: Getting the include directories, Next: Locating the buildfile, Prev: Locating a master file, Up: The legacy Proc backend + +3.6 Getting the include directories +=================================== + +Two sets of include directories are distinguished: system include +directories and project include directories. The former is just the +contents of the ‘INCLUDE’ environment variable. The latter is not so +easy to obtain, and the way it can be obtained can vary greatly for +different projects. Therefore, a customizable variable +‘flymake-proc-get-project-include-dirs-function’ is used to provide the +way to implement the desired behavior. + + The default implementation, +‘flymake-proc-get-project-include-dirs-imp’, uses a ‘make’ call. This +requires a correct base directory, that is, a directory containing a +correct ‘Makefile’, to be determined. + + As obtaining the project include directories might be a costly +operation, its return value is cached in the hash table. The cache is +cleared in the beginning of every syntax check attempt. + + +File: flymake.info, Node: Locating the buildfile, Next: Starting the syntax check process, Prev: Getting the include directories, Up: The legacy Proc backend + +3.7 Locating the buildfile +========================== + +The Proc backend can be configured to use different tools for performing +syntax checks. For example, it can use direct compiler call to syntax +check a perl script or a call to ‘make’ for a more complicated case of a +C/C++ source. The general idea is that simple files, like Perl scripts +and HTML pages, can be checked by directly invoking a corresponding +tool. Files that are usually more complex and generally used as part of +larger projects, might require non-trivial options to be passed to the +syntax check tool, like include directories for C++. The latter files +are syntax checked using some build tool, like Make or Ant. + + All Make configuration data is usually stored in a file called +‘Makefile’. To allow for future extensions, Flymake uses a notion of +buildfile to reference the “project configuration” file. + + Special function, ‘flymake-proc-find-buildfile’ is provided for +locating buildfiles. Searching for a buildfile is done in a manner +similar to that of searching for possible master files. In case there's +no build file, the syntax check is aborted. + + Buildfile values are also cached. + + +File: flymake.info, Node: Starting the syntax check process, Next: Parsing the output, Prev: Locating the buildfile, Up: The legacy Proc backend + +3.8 Starting the syntax check process +===================================== + +The command line (command name and the list of arguments) for launching +a process is returned by the initialization function. The Proc backend +then just starts an asynchronous process and configures a process filter +and sentinel, which are used for processing the output of the syntax +check tool. When exiting Emacs, running processes will be killed +without prompting the user. + + +File: flymake.info, Node: Parsing the output, Next: Interaction with other modes, Prev: Starting the syntax check process, Up: The legacy Proc backend + +3.9 Parsing the output +====================== + +The output generated by the syntax check tool is parsed in the process +filter/sentinel using the error message patterns stored in the +‘flymake-proc-err-line-patterns’ variable. This variable contains a +list of items of the form ‘(regexp file-idx line-idx err-text-idx)’, +used to determine whether a particular line is an error message and +extract file name, line number and error text, respectively. Error type +(error/warning) is also guessed by matching error text with the +‘^[wW]arning’ pattern. Anything that was not classified as a warning is +considered an error. Type is then used to sort error menu items, which +shows error messages first. + + The Proc backend is also able to interpret error message patterns +missing err-text-idx information. This is done by merely taking the +rest of the matched line (‘(substring line (match-end 0))’) as error +text. This trick allows making use of a huge collection of error +message line patterns from ‘compile.el’. All these error patterns are +appended to the end of ‘flymake-proc-err-line-patterns’. + + The error information obtained is saved in a buffer local variable. +The buffer for which the process output belongs is determined from the +process-id->buffer mapping updated after every process launch/exit. + + +File: flymake.info, Node: Interaction with other modes, Prev: Parsing the output, Up: The legacy Proc backend + +3.10 Interaction with other modes +================================= + +The only mode the Proc backend currently knows about is ‘compile’. + + The Proc backend can be configured to not start syntax check if it +thinks the compilation is in progress, by testing the +‘compilation-in-progress’ variable. The reason why this might be useful +is saving CPU time in case both syntax check and compilation are very +CPU intensive. The original reason for adding this feature, though, was +working around a locking problem with MS Visual C++ compiler. The +variable in question is +‘flymake-proc-compilation-prevents-syntax-check’. + + The Proc backend also provides an alternative command for starting +compilation, ‘flymake-proc-compile’. It just kills all the active +syntax check processes before calling ‘compile’. + + +File: flymake.info, Node: GNU Free Documentation License, Next: Index, Prev: The legacy Proc backend, Up: Top + +Appendix A GNU Free Documentation License +***************************************** + + Version 1.3, 3 November 2008 + + Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 0. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document “free” in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by others. + + This License is a kind of "copyleft", which means that derivative + works of the document must themselves be free in the same sense. + It complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to + software manuals; it can be used for any textual work, regardless + of subject matter or whether it is published as a printed book. We + recommend this License principally for works whose purpose is + instruction or reference. + + 1. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it can + be distributed under the terms of this License. Such a notice + grants a world-wide, royalty-free license, unlimited in duration, + to use that work under the conditions stated herein. The + "Document", below, refers to any such manual or work. Any member + of the public is a licensee, and is addressed as "you". You accept + the license if you copy, modify or distribute the work in a way + requiring permission under copyright law. + + A "Modified Version" of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A "Secondary Section" is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document's overall + subject (or to related matters) and contains nothing that could + fall directly within that overall subject. (Thus, if the Document + is in part a textbook of mathematics, a Secondary Section may not + explain any mathematics.) The relationship could be a matter of + historical connection with the subject or with related matters, or + of legal, commercial, philosophical, ethical or political position + regarding them. + + The "Invariant Sections" are certain Secondary Sections whose + titles are designated, as being those of Invariant Sections, in the + notice that says that the Document is released under this License. + If a section does not fit the above definition of Secondary then it + is not allowed to be designated as Invariant. The Document may + contain zero Invariant Sections. If the Document does not identify + any Invariant Sections then there are none. + + The "Cover Texts" are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice + that says that the Document is released under this License. A + Front-Cover Text may be at most 5 words, and a Back-Cover Text may + be at most 25 words. + + A "Transparent" copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images composed + of pixels) generic paint programs or (for drawings) some widely + available drawing editor, and that is suitable for input to text + formatters or for automatic translation to a variety of formats + suitable for input to text formatters. A copy made in an otherwise + Transparent file format whose markup, or absence of markup, has + been arranged to thwart or discourage subsequent modification by + readers is not Transparent. An image format is not Transparent if + used for any substantial amount of text. A copy that is not + "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, + SGML or XML using a publicly available DTD, and standard-conforming + simple HTML, PostScript or PDF designed for human modification. + Examples of transparent image formats include PNG, XCF and JPG. + Opaque formats include proprietary formats that can be read and + edited only by proprietary word processors, SGML or XML for which + the DTD and/or processing tools are not generally available, and + the machine-generated HTML, PostScript or PDF produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, "Title + Page" means the text near the most prominent appearance of the + work's title, preceding the beginning of the body of the text. + + The "publisher" means any person or entity that distributes copies + of the Document to the public. + + A section "Entitled XYZ" means a named subunit of the Document + whose title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + "Acknowledgements", "Dedications", "Endorsements", or "History".) + To "Preserve the Title" of such a section when you modify the + Document means that it remains a section "Entitled XYZ" according + to this definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and + has no effect on the meaning of this License. + + 2. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You + may not use technical measures to obstruct or control the reading + or further copying of the copies you make or distribute. However, + you may accept compensation in exchange for copies. If you + distribute a large enough number of copies you must also follow the + conditions in section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + + 3. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly + have printed covers) of the Document, numbering more than 100, and + the Document's license notice requires Cover Texts, you must + enclose the copies in covers that carry, clearly and legibly, all + these Cover Texts: Front-Cover Texts on the front cover, and + Back-Cover Texts on the back cover. Both covers must also clearly + and legibly identify you as the publisher of these copies. The + front cover must present the full title with all words of the title + equally prominent and visible. You may add other material on the + covers in addition. Copying with changes limited to the covers, as + long as they preserve the title of the Document and satisfy these + conditions, can be treated as verbatim copying in other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a machine-readable + Transparent copy along with each Opaque copy, or state in or with + each Opaque copy a computer-network location from which the general + network-using public has access to download using public-standard + network protocols a complete Transparent copy of the Document, free + of added material. If you use the latter option, you must take + reasonably prudent steps, when you begin distribution of Opaque + copies in quantity, to ensure that this Transparent copy will + remain thus accessible at the stated location until at least one + year after the last time you distribute an Opaque copy (directly or + through your agents or retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of copies, + to give them a chance to provide you with an updated version of the + Document. + + 4. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document + under the conditions of sections 2 and 3 above, provided that you + release the Modified Version under precisely this License, with the + Modified Version filling the role of the Document, thus licensing + distribution and modification of the Modified Version to whoever + possesses a copy of it. In addition, you must do these things in + the Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of previous + versions (which should, if there were any, be listed in the + History section of the Document). You may use the same title + as a previous version if the original publisher of that + version gives permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in + the Modified Version, together with at least five of the + principal authors of the Document (all of its principal + authors, if it has fewer than five), unless they release you + from this requirement. + + C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified + Version under the terms of this License, in the form shown in + the Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document's + license notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled "History", Preserve its Title, + and add to it an item stating at least the title, year, new + authors, and publisher of the Modified Version as given on the + Title Page. If there is no section Entitled "History" in the + Document, create one stating the title, year, authors, and + publisher of the Document as given on its Title Page, then add + an item describing the Modified Version as stated in the + previous sentence. + + J. Preserve the network location, if any, given in the Document + for public access to a Transparent copy of the Document, and + likewise the network locations given in the Document for + previous versions it was based on. These may be placed in the + "History" section. You may omit a network location for a work + that was published at least four years before the Document + itself, or if the original publisher of the version it refers + to gives permission. + + K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section + all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, unaltered + in their text and in their titles. Section numbers or the + equivalent are not considered part of the section titles. + + M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled + "Endorsements" or to conflict in title with any Invariant + Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option designate + some or all of these sections as invariant. To do this, add their + titles to the list of Invariant Sections in the Modified Version's + license notice. These titles must be distinct from any other + section titles. + + You may add a section Entitled "Endorsements", provided it contains + nothing but endorsements of your Modified Version by various + parties--for example, statements of peer review or that the text + has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover Text, + and a passage of up to 25 words as a Back-Cover Text, to the end of + the list of Cover Texts in the Modified Version. Only one passage + of Front-Cover Text and one of Back-Cover Text may be added by (or + through arrangements made by) any one entity. If the Document + already includes a cover text for the same cover, previously added + by you or by arrangement made by the same entity you are acting on + behalf of, you may not add another; but you may replace the old + one, on explicit permission from the previous publisher that added + the old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + + 5. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination all + of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice, and that you preserve all + their Warranty Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the + original author or publisher of that section if known, or else a + unique number. Make the same adjustment to the section titles in + the list of Invariant Sections in the license notice of the + combined work. + + In the combination, you must combine any sections Entitled + "History" in the various original documents, forming one section + Entitled "History"; likewise combine any sections Entitled + "Acknowledgements", and any sections Entitled "Dedications". You + must delete all sections Entitled "Endorsements." + + 6. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the documents + in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert + a copy of this License into the extracted document, and follow this + License in all other respects regarding verbatim copying of that + document. + + 7. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of a + storage or distribution medium, is called an "aggregate" if the + copyright resulting from the compilation is not used to limit the + legal rights of the compilation's users beyond what the individual + works permit. When the Document is included in an aggregate, this + License does not apply to the other works in the aggregate which + are not themselves derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document's Cover Texts may be placed + on covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket + the whole aggregate. + + 8. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled "Acknowledgements", + "Dedications", or "History", the requirement (section 4) to + Preserve its Title (section 1) will typically require changing the + actual title. + + 9. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, or distribute it is void, + and will automatically terminate your rights under this License. + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate + the licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, receipt of a copy of some or all of the + same material does not give you any rights to use it. + + 10. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. See + . + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered + version of this License "or any later version" applies to it, you + have the option of following the terms and conditions either of + that specified version or of any later version that has been + published (not as a draft) by the Free Software Foundation. If the + Document does not specify a version number of this License, you may + choose any version ever published (not as a draft) by the Free + Software Foundation. If the Document specifies that a proxy can + decide which future versions of this License can be used, that + proxy's public statement of acceptance of a version permanently + authorizes you to choose that version for the Document. + + 11. RELICENSING + + "Massive Multiauthor Collaboration Site" (or "MMC Site") means any + World Wide Web server that publishes copyrightable works and also + provides prominent facilities for anybody to edit those works. A + public wiki that anybody can edit is an example of such a server. + A "Massive Multiauthor Collaboration" (or "MMC") contained in the + site means any set of copyrightable works thus published on the MMC + site. + + "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 + license published by Creative Commons Corporation, a not-for-profit + corporation with a principal place of business in San Francisco, + California, as well as future copyleft versions of that license + published by that same organization. + + "Incorporate" means to publish or republish a Document, in whole or + in part, as part of another Document. + + An MMC is "eligible for relicensing" if it is licensed under this + License, and if all works that were first published under this + License somewhere other than this MMC, and subsequently + incorporated in whole or in part into the MMC, (1) had no cover + texts or invariant sections, and (2) were thus incorporated prior + to November 1, 2008. + + The operator of an MMC Site may republish an MMC contained in the + site under CC-BY-SA on the same site at any time before August 1, + 2009, provided the MMC is eligible for relicensing. + +ADDENDUM: How to use this License for your documents +==================================================== + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + + Copyright (C) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + + If you have Invariant Sections, Front-Cover Texts and Back-Cover +Texts, replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with + the Front-Cover Texts being LIST, and with the Back-Cover Texts + being LIST. + + If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + + If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of free +software license, such as the GNU General Public License, to permit +their use in free software. + + +File: flymake.info, Node: Index, Prev: GNU Free Documentation License, Up: Top + +Index +***** + +[index] +* Menu: + +* access diagnostic object: Inspecting diagnostics. + (line 17) +* add a log message: Flymake utility functions. + (line 35) +* adding support for a new syntax check tool: Adding support for a new syntax check tool. + (line 6) +* adding support for C (gcc+make): Example---Configuring a tool called via make. + (line 6) +* adding support for perl: Example---Configuring a tool called directly. + (line 6) +* backend exceptions: Troubleshooting. (line 6) +* backend functions: Backend functions. (line 6) +* backend, annotated example: An annotated example backend. + (line 6) +* backends, disabled: Troubleshooting. (line 6) +* bitmap of diagnostic: Flymake error types. (line 15) +* buffer position from line and column number: Flymake utility functions. + (line 24) +* buildfile, locating: Locating the buildfile. + (line 6) +* collect diagnostic objects: Inspecting diagnostics. + (line 11) +* create diagnostic object: Flymake utility functions. + (line 6) +* create diagnostic object for other buffer: Foreign and list-only diagnostics. + (line 6) +* customizable variables: Customizable variables. + (line 6) +* customizing error types: Flymake error types. (line 6) +* disabled backends: Troubleshooting. (line 6) +* domestic diagnostics: Foreign and list-only diagnostics. + (line 14) +* error types, customization: Flymake error types. (line 6) +* example of backend: An annotated example backend. + (line 6) +* extending flymake: Flymake API. (line 6) +* flymake logging: Troubleshooting. (line 24) +* flymake mode line: Mode line status. (line 6) +* flymake-autoresize-margins: Customizable variables. + (line 68) +* flymake-category: Flymake error types. (line 59) +* flymake-diag-region: Flymake utility functions. + (line 29) +* flymake-diagnostic-backend: Flymake error types. (line 91) +* flymake-diagnostic-beg: Flymake error types. (line 91) +* flymake-diagnostic-buffer: Flymake error types. (line 91) +* flymake-diagnostic-end: Flymake error types. (line 91) +* flymake-diagnostic-format-alist: Customizable variables. + (line 86) +* flymake-diagnostic-functions: Backend functions. (line 6) +* flymake-diagnostic-text: Flymake error types. (line 91) +* flymake-diagnostics: Inspecting diagnostics. + (line 11) +* flymake-diagnostics <1>: Flymake error types. (line 91) +* flymake-disabled-backends: Troubleshooting. (line 13) +* flymake-error: Customizable variables. + (line 32) +* flymake-error <1>: Flymake error types. (line 69) +* flymake-error-bitmap: Customizable variables. + (line 50) +* flymake-error-eol: Customizable variables. + (line 89) +* flymake-fringe-indicator-position: Customizable variables. + (line 58) +* flymake-indicator-type: Customizable variables. + (line 44) +* flymake-list-only-diagnostics: Foreign and list-only diagnostics. + (line 27) +* flymake-log: Flymake utility functions. + (line 39) +* flymake-make-diagnostic: Flymake utility functions. + (line 9) +* flymake-margin-indicator-position: Customizable variables. + (line 65) +* flymake-margin-indicators-string: Customizable variables. + (line 61) +* flymake-mode-line-counter-format: Customizable variables. + (line 15) +* flymake-mode-line-format: Customizable variables. + (line 12) +* flymake-mode-line-lighter: Customizable variables. + (line 9) +* flymake-no-changes-timeout: Customizable variables. + (line 19) +* flymake-note: Customizable variables. + (line 40) +* flymake-note <1>: Flymake error types. (line 69) +* flymake-note-eol: Customizable variables. + (line 95) +* flymake-proc-allowed-file-name-masks: Proc customization variables. + (line 6) +* flymake-proc-check-file-limit: Proc customization variables. + (line 20) +* flymake-proc-compilation-prevents-syntax-check: Proc customization variables. + (line 42) +* flymake-proc-compile: Interaction with other modes. + (line 17) +* flymake-proc-diagnostic-type-pred: Proc customization variables. + (line 28) +* flymake-proc-err-line-patterns: Proc customization variables. + (line 24) +* flymake-proc-find-buildfile: Locating the buildfile. + (line 20) +* flymake-proc-get-project-include-dirs-function: Proc customization variables. + (line 15) +* flymake-proc-legacy-flymake: The legacy Proc backend. + (line 19) +* flymake-proc-master-file-count-limit: Proc customization variables. + (line 19) +* flymake-proc-master-file-dirs: Proc customization variables. + (line 11) +* flymake-reporting-backends: Troubleshooting. (line 13) +* flymake-running-backends: Troubleshooting. (line 13) +* flymake-show-diagnostics-at-end-of-line: Customizable variables. + (line 77) +* flymake-start-on-flymake-mode: Customizable variables. + (line 24) +* flymake-start-on-save-buffer: Customizable variables. + (line 28) +* flymake-type-name: Flymake error types. (line 55) +* flymake-warning: Customizable variables. + (line 36) +* flymake-warning <1>: Flymake error types. (line 69) +* flymake-warning-bitmap: Customizable variables. + (line 54) +* flymake-warning-eol: Customizable variables. + (line 92) +* flymake-wrap-around: Customizable variables. + (line 73) +* foreign diagnostics: Foreign and list-only diagnostics. + (line 14) +* include directories (C/C++ specific): Getting the include directories. + (line 6) +* interaction with compile mode, legacy proc backend: Interaction with other modes. + (line 6) +* interaction with other modes, legacy proc backend: Interaction with other modes. + (line 6) +* legacy proc backend: The legacy Proc backend. + (line 6) +* list-only diagnostics: Foreign and list-only diagnostics. + (line 27) +* listing diagnostics: Finding diagnostics. (line 25) +* locating a master file: Locating a master file. + (line 6) +* locating the buildfile: Locating the buildfile. + (line 6) +* logging: Troubleshooting. (line 24) +* makefile, locating: Locating the buildfile. + (line 6) +* margin of diagnostic: Flymake error types. (line 21) +* master file: Implementation overview. + (line 6) +* master file, locating: Locating a master file. + (line 6) +* mode-line appearance of a diagnostic: Flymake error types. (line 62) +* next and previous diagnostic: Finding diagnostics. (line 16) +* overview of flymake: Using Flymake. (line 6) +* parsing the output, legacy proc backend: Parsing the output. (line 6) +* predefined diagnostic types: Flymake error types. (line 69) +* proc backend customization variables: Proc customization variables. + (line 6) +* read diagnostic message: Finding diagnostics. (line 6) +* reset disabled backends: Troubleshooting. (line 17) +* severity of diagnostic: Flymake error types. (line 49) +* starting Flymake: Starting Flymake. (line 6) +* summarized appearance of a diagnostic: Flymake error types. (line 65) +* syntax check models: Implementation overview. + (line 6) +* syntax check process, legacy proc backend: Starting the syntax check process. + (line 6) +* syntax check status: Mode line status. (line 6) +* temporary copy of the buffer: Making a temporary copy. + (line 6) +* troubleshooting: Troubleshooting. (line 6) +* using flymake: Using Flymake. (line 6) +* utility functions: Flymake utility functions. + (line 6) +* variables for customizing flymake: Customizable variables. + (line 6) +* warning-minimum-level: Troubleshooting. (line 32) +* warning-minimum-log-level: Troubleshooting. (line 32) + + +Tag Table: +Node: Top900 +Node: Using Flymake2447 +Node: Starting Flymake3314 +Node: Finding diagnostics4299 +Node: Mode line status6410 +Node: Troubleshooting8311 +Node: Customizable variables10065 +Node: Flymake API13654 +Node: Flymake error types14271 +Node: Backend functions19823 +Node: Flymake utility functions24606 +Node: Foreign and list-only diagnostics26750 +Node: An annotated example backend29193 +Node: Inspecting diagnostics34104 +Node: The legacy Proc backend35235 +Node: Proc customization variables35963 +Node: Adding support for a new syntax check tool37986 +Node: Example---Configuring a tool called directly40376 +Node: Example---Configuring a tool called via make42104 +Node: Implementation overview43841 +Node: Making a temporary copy45761 +Node: Locating a master file47085 +Node: Getting the include directories48572 +Node: Locating the buildfile49664 +Node: Starting the syntax check process51018 +Node: Parsing the output51628 +Node: Interaction with other modes53121 +Node: GNU Free Documentation License54063 +Node: Index79226 + +End Tag Table + + +Local Variables: +coding: utf-8 +Info-documentlanguage: en +End: diff --git a/elpa/flymake-1.4.5/flymake.texi b/elpa/flymake-1.4.5/flymake.texi new file mode 100644 index 00000000..d0983bc7 --- /dev/null +++ b/elpa/flymake-1.4.5/flymake.texi @@ -0,0 +1,1383 @@ +\input texinfo @c -*- mode: texinfo; coding: utf-8 -*- +@comment %**start of header +@setfilename ../../info/flymake.info +@set VERSION 1.3.4 +@set UPDATED April 2023 +@settitle GNU Flymake @value{VERSION} +@documentlanguage en +@include docstyle.texi +@syncodeindex pg cp +@syncodeindex vr cp +@syncodeindex fn cp +@comment %**end of header + +@copying +This manual is for GNU Flymake (version @value{VERSION}, @value{UPDATED}). + +Copyright @copyright{} 2004--2026 Free Software Foundation, Inc. + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,'' +and with the Back-Cover Texts as in (a) below. A copy of the license +is included in the section entitled ``GNU Free Documentation License''. + +(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and +modify this GNU manual.'' +@end quotation +@end copying + +@dircategory Emacs misc features +@direntry +* Flymake: (flymake). A universal on-the-fly syntax checker. +@end direntry + +@titlepage +@title GNU Flymake +@subtitle for version @value{VERSION}, @value{UPDATED} +@author João Távora and Pavel Kobiakov(@email{pk_at_work@@yahoo.com}). +@page +@vskip 0pt plus 1filll +@insertcopying + +@end titlepage + +@contents + +@ifnottex +@node Top +@top GNU Flymake +@end ifnottex + +Flymake is a universal on-the-fly syntax checker for Emacs. When +enabled, Flymake contacts one or more source @dfn{backends} to +collect information about problems in the buffer, called +@dfn{diagnostics}, and visually annotates them with a special face. +The mode line displays overall status including totals for different +types of diagnostics. + +To learn about using Flymake, @pxref{Using Flymake}. + +When the Emacs LSP support mode Eglot is enabled, Flymake will use that +as an additional back-end. @xref{Eglot Features,,, eglot, Eglot: The +Emacs LSP Client}. Flymake is also designed to be easily extended to +support new backends via an Elisp interface. @xref{Flymake API}. + +@ifnottex +@insertcopying +@end ifnottex + +@menu +* Using Flymake:: +* Flymake API:: +* The legacy Proc backend:: +* GNU Free Documentation License:: +* Index:: +@end menu + +@node Using Flymake +@chapter Using Flymake +@cindex overview of flymake +@cindex using flymake + +Flymake is only useful if at least one @dfn{backend} is configured to +provide the buffer-checking service. This is done via the hook +@code{flymake-diagnostic-functions}. @xref{Hooks,Hooks,, emacs, The +Emacs Editor}. + +It's possible that some major modes or a third-party package has +already setup this hook for you, by adding @dfn{backend functions} to +@code{flymake-diagnostic-functions}. If you know Elisp you may also +write your own Flymake backend functions. @xref{Backend functions}. + +When the Emacs LSP support mode Eglot is enabled, Flymake will use +that as an additional back-end automatically. @xref{Eglot Features,,, +eglot, Eglot: The Emacs LSP Client}. + +@menu +* Starting Flymake:: +* Finding diagnostics:: +* Mode line status:: +* Troubleshooting:: +* Customizable variables:: +@end menu + +@node Starting Flymake +@section Starting Flymake +@cindex starting Flymake + +To use Flymake, activate the minor-mode @code{flymake-mode}. +Use the command @kbd{flymake-mode} to toggle it on and off. The +mode line should indicate its presence via an indicator (@pxref{Mode +line status}). + +Syntax checks happen ``on-the-fly''. Each check is started whenever: + +@itemize @bullet +@item +@code{flymake-mode} is started, unless +@code{flymake-start-on-flymake-mode} is @code{nil}; + +@item +the buffer is saved, unless @code{flymake-start-on-save-buffer} is +@code{nil}; + +@item +some changes were made to the buffer more than @code{0.5} seconds ago +(the delay is configurable in @code{flymake-no-changes-timeout}). + +@item +When the user invokes the command @code{flymake-start}. +@end itemize + +If the check detected errors or warnings, the respective buffer +regions are highlighted. @xref{Finding diagnostics}, for how to +learn what the problems are. + +@node Finding diagnostics +@section Finding diagnostics + +@cindex read diagnostic message +If Flymake has highlighted the buffer, you may hover the mouse on the +highlighted regions to learn what the specific problem +is. Alternatively, place point on the highlighted regions and use the +commands @code{eldoc} or @code{display-local-help}. + +Another easy way to get instant access to the diagnostic text is to +set @code{flymake-show-diagnostics-at-end-of-line} to a non-@code{nil} +value. This makes the diagnostic messages appear at the end of the +line where the regular annotation is located (@pxref{Customizable +variables}) + +@cindex next and previous diagnostic +If the diagnostics are outside the visible region of the buffer, +@code{flymake-goto-next-error} and @code{flymake-goto-prev-error} +let you navigate to the next/previous erroneous regions, +respectively. It might be a good idea to map them to @kbd{M-n} and +@kbd{M-p} in @code{flymake-mode}, by adding to your init file: + +@lisp +(define-key flymake-mode-map (kbd "M-n") 'flymake-goto-next-error) +(define-key flymake-mode-map (kbd "M-p") 'flymake-goto-prev-error) +@end lisp + +@cindex listing diagnostics +Sometimes it is useful to have a detailed overview of the diagnostics +in your files without having to jump to each one. The commands +@code{flymake-show-buffer-diagnostics} and +@code{flymake-show-project-diagnostics} are designed to handle this +situation. When invoked, they bring up a separate buffer containing a +detailed structured listing of multiple diagnostics in the current +buffer or for the current project, respectively (@pxref{Projects,,, +emacs, The Emacs Editor}). + +The listings is continuously updated as you edit source code, adding or +removing lines as you make or correct mistakes. Each line of this +listing includes the type of the diagnostic, its line and column in +the file, as well as the diagnostic message. You may sort the listing +by each of these columns. + +When invoked on a diagnostic (either via the keyboard or a mouse click) +the command @code{flymake-show-buffer-diagnostics} attempts to reveal +said diagnostic in the listing. + +@node Mode line status +@section Mode line status +@cindex flymake mode line +@cindex syntax check status + +When enabled, Flymake displays its status in the mode line, which +provides a visual summary of diagnostic collection. It may also hint +at certain exceptional situations encountered when communicating with +backends. + +The following statuses are defined: + +@multitable @columnfractions 0.25 0.75 +@item [@var{nerrors} @var{nwarnings} ...] +@tab Normal operation. @var{nerrors} and @var{nwarnings} are, respectively, +the total number of errors and warnings found during the last buffer +check, for all backends. They may be followed by other totals for +other types of diagnostics (@pxref{Flymake error types}). + +@item @code{Wait} +@tab Some Flymake backends haven't reported since the last time they +where questioned. It is reasonable to assume that this is a temporary +delay and Flymake will resume normal operation soon. + +@item @code{!} +@tab All the configured Flymake backends have disabled themselves: Flymake +cannot annotate the buffer and action from the user is needed to +investigate and remedy the situation (@pxref{Troubleshooting}). + +@item @code{?} +@tab There are no applicable Flymake backends for this buffer, thus Flymake +cannot annotate it. To fix this, a user may look to extending Flymake +and add a new backend (@pxref{Flymake API}). + +@end multitable + +If you would like to customize the appearance of the mode-line, you +can use the variables @code{flymake-mode-line-format} and +@code{flymake-mode-line-counter-format} for that purpose. +@xref{Customizable variables}. + +@node Troubleshooting +@section Troubleshooting +@cindex troubleshooting +@cindex backend exceptions + +@cindex disabled backends +@cindex backends, disabled +As Flymake supports multiple simultaneously active external backends, +it becomes useful to monitor their status. For example, some backends +may take longer than others to respond or complete, and some may +decide to @emph{disable} themselves if they are not suitable for the +current buffer or encounter some unavoidable problem. A disabled +backend is not tried again for future checks of the current buffer. + +@findex flymake-reporting-backends +@findex flymake-running-backends +@findex flymake-disabled-backends +The commands @code{flymake-reporting-backends}, +@code{flymake-running-backends} and @code{flymake-disabled-backends} +show the backends currently used and those which are disabled. + +@cindex reset disabled backends +Sometimes, re-starting a backend that disabled itself is useful after +some external roadblock has been removed (for example after the user +installed a needed syntax-check program). Invoking +@code{flymake-start} with a prefix argument is a way to reset the +disabled backend list, so that they will be tried again in the next +check. Manually toggling @code{flymake-mode} off and on again also +works. + +@cindex logging +@cindex flymake logging +Flymake uses a simple logging facility for indicating important points +in the control flow. The logging facility sends logging messages to +the @file{*Flymake log*} buffer. The logged information can be used +for resolving various problems related to Flymake. For convenience, a +shortcut to this buffer can be found in Flymake's menu, accessible +from the top menu bar or just left of the status indicator. The +command @code{flymake-switch-to-log-buffer} is another alternative. + +@vindex warning-minimum-log-level +@vindex warning-minimum-level +Logging output is controlled by the Emacs @code{warning-minimum-log-level} +and @code{warning-minimum-level} variables. + +@node Customizable variables +@section Customizable variables +@cindex customizable variables +@cindex variables for customizing flymake + +This section summarizes customization variables used for the +configuration of the Flymake user interface. + +@vtable @code +@item flymake-mode-line-lighter +The name of the mode. Defaults to @samp{Flymake}. + +@item flymake-mode-line-format +Format to use for the Flymake mode line indicator. + +@item flymake-mode-line-counter-format +mode line construct for formatting Flymake diagnostic counters inside +the Flymake mode line indicator. + +@item flymake-no-changes-timeout +If any changes are made to the buffer, syntax check is automatically +started after this many seconds, unless the user makes another change, +which resets the timer. + +@item flymake-start-on-flymake-mode +A boolean flag indicating whether to start syntax check immediately +after enabling @code{flymake-mode}. + +@item flymake-start-on-save-buffer +A boolean flag indicating whether to start syntax check after saving +the buffer. + +@item flymake-error +A custom face for highlighting regions for which an error has been +reported. + +@item flymake-warning +A custom face for highlighting regions for which a warning has been +reported. + +@item flymake-note +A custom face for highlighting regions for which a note has been +reported. + +@item flymake-indicator-type +The indicator type which Flymake should use to indicate lines with +errors or warnings. +Depending on your preference, this can either use @code{fringes} or +@code{margins} for indicating errors. On text terminals, only +@code{margins} is available. + +@item flymake-error-bitmap +A bitmap used in the fringe to mark lines for which an error has +been reported. + +@item flymake-warning-bitmap +A bitmap used in the fringe to mark lines for which a warning has +been reported. + +@item flymake-fringe-indicator-position +Which fringe (if any) should show the warning/error bitmaps. + +@item flymake-margin-indicators-string +Specifies the string and face to use for the margin indicators, for +each error type. + +@item flymake-margin-indicator-position +Which margin (if any) should show the warning/error strings. + +@item flymake-autoresize-margins +If non-@code{nil}, Flymake will resize the margins when +@code{flymake-mode} is turned on or off. +Only relevant if @code{flymake-indicator-type} is set to @code{margins}. + +@item flymake-wrap-around +If non-@code{nil}, moving to errors with @code{flymake-goto-next-error} and +@code{flymake-goto-prev-error} wraps around buffer boundaries. + +@item flymake-show-diagnostics-at-end-of-line +If non-@code{nil}, show summarized descriptions of diagnostics at the +end of the line. Depending on your preference, this can either be +distracting and easily confused with actual code, or a significant early +aid that relieves you from moving around or reaching for the mouse to +consult an error message. This value may also be set to @code{fancy}, +which will attempt to layout diagnostics below the affected line using +unicode graphics to point to diagnostic locus. + +@item flymake-diagnostic-format-alist +Control which parts of a diagnostic to show in various situations. + +@item flymake-error-eol +A custom face for summarizing diagnostic error messages. + +@item flymake-warning-eol +A custom face for summarizing diagnostic warning messages. + +@item flymake-note-eol +A custom face for summarizing diagnostic notes. +@end vtable + +@node Flymake API, The legacy Proc backend, Using Flymake, Top +@chapter Flymake API +@cindex extending flymake + +Flymake's API supports the following use cases: + +@enumerate +@item +Changing the look and feel of the annotations produced by the +different backends. @xref{Flymake error types}. + +@item +Adding a new buffer-checking backend. @xref{Backend functions}. + +@item +Writing extension to and process Flymake's output. @xref{Inspecting +diagnostics}. +@end enumerate + +The following sections discuss each approach in detail. + +@menu +* Flymake error types:: +* Backend functions:: +* Inspecting diagnostics:: +@end menu + +@node Flymake error types +@section Customizing Flymake error types +@cindex customizing error types +@cindex error types, customization + +To customize the appearance of error types, the user must set +properties on the symbols associated with each diagnostic type. + +The three standard diagnostic keyword symbols -- @code{:error}, +@code{:warning} and @code{:note} -- have pre-configured appearances. +However a backend may define more (@pxref{Backend functions}). + +The following properties can be set: + +@itemize + +@item +@cindex bitmap of diagnostic +@code{flymake-bitmap}, an image displayed in the fringe according to +@code{flymake-fringe-indicator-position}. The value actually follows +the syntax of @code{flymake-error-bitmap} (@pxref{Customizable +variables}). It is overridden by any @code{before-string} overlay +property. + +@item +@cindex margin of diagnostic +@code{flymake-margin-string}, a string displayed in the margin +according to @code{flymake-margin-indicator-position}. +The value actually follows the syntax of @code{flymake-margin-indicators-string} +(@pxref{Customizable variables}). It is overridden by any +@code{before-string} overlay property. + +@item +@code{flymake-overlay-control}, an alist ((@var{OVPROP} . @var{VALUE}) +@var{...}) of further properties used to affect the appearance of +Flymake annotations. With the exception of @code{category} and +@code{evaporate}, these properties are applied directly to the created +overlay (@pxref{Overlay Properties,,, elisp, The Emacs Lisp Reference +Manual}). + +As an example, here's how to make diagnostics of the type @code{:note} +stand out more prominently: + +@example +(push '(face . highlight) (get :note 'flymake-overlay-control)) +@end example + +If you push another alist entry in front, it overrides the previous +one. So this effectively removes the face from @code{:note} +diagnostics: + +@example +(push '(face . nil) (get :note 'flymake-overlay-control)) +@end example + +To restore the original look for @code{:note} types, empty or remove +its @code{flymake-overlay-control} property: + +@example +(put :note 'flymake-overlay-control '()) +@end example + +@item +@cindex severity of diagnostic +@code{severity} is a non-negative integer specifying the +diagnostic's severity. The higher the value, the more serious is the +error. If the overlay property @code{priority} is not specified in +@code{flymake-overlay-control}, @code{flymake-severity} is used to set +it and help sort overlapping overlays. + +@item +@vindex flymake-type-name +@code{flymake-type-name} is a string used to succinctly name the error +type, in case the name of the symbol associated with it is very long. + +@item +@vindex flymake-category +@code{flymake-category} is a symbol whose property list is considered +the default for missing values of any other properties. + +@item +@cindex mode-line appearance of a diagnostic +@code{mode-line-face} is a face specifier controlling the appearance +of the indicator of this type of diagnostic in the mode line. + +@item +@cindex summarized appearance of a diagnostic +@code{echo-face} is a face specifier controlling the appearance of the +summarized description of this diagnostic when reading diagnostic +messages (@pxref{Finding diagnostics}). +@end itemize + +@cindex predefined diagnostic types +@vindex flymake-error +@vindex flymake-warning +@vindex flymake-note +Three default diagnostic types are predefined: @code{:error}, +@code{:warning}, and @code{:note}. By default, each one of them has a +@code{flymake-category} property whose value is, respectively, the +category symbol @code{flymake-error}, @code{flymake-warning} and +@code{flymake-note}. + +These category symbols' plist is where the values of customizable +variables and faces (such as @code{flymake-error-bitmap}) are found. +Thus, if you change their plists, Flymake may stop honoring these user +customizations. + +The @code{flymake-category} special property is especially useful for +backends which create diagnostics objects with non-default types that +differ from an existing type by only a few properties (@pxref{Flymake +utility functions}). + +As an example, consider configuring a new diagnostic type +@code{:low-priority-note} that behaves much like @code{:note}, but +without an overlay face. + +@example +(put :low-priority-note 'flymake-overlay-control '((face . nil))) +(put :low-priority-note 'flymake-category 'flymake-note) +@end example + +@vindex flymake-diagnostics +@vindex flymake-diagnostic-backend +@vindex flymake-diagnostic-buffer +@vindex flymake-diagnostic-text +@vindex flymake-diagnostic-beg +@vindex flymake-diagnostic-end +As you might have guessed, Flymake's annotations are implemented as +overlays (@pxref{Overlays,,, elisp, The Emacs Lisp Reference Manual}). +Along with the properties that you specify for the specific type of +diagnostic, Flymake adds the property @code{flymake-diagnostic} to +these overlays, and sets it to the object that the backend created +with @code{flymake-make-diagnostic}. + +Since overlays also support arbitrary keymaps, you can use this along +with the functions @code{flymake-diagnostics} and +@code{flymake-diagnostic-text} (@pxref{Flymake utility functions}) to +create interactive annotations, such as in the following example of +binding a @code{mouse-3} event (middle mouse button click) to an +Internet search for the text of a @code{:warning} or @code{:error}. + +@example +(defun my-search-for-message (event) + (interactive "e") + (let* ((diags (flymake-diagnostics (posn-point (event-start event)))) + (topmost-diag (car diags))) + (eww-browse-url + (concat + "https://duckduckgo.com/?q=" + (replace-regexp-in-string + " " "+" (flymake-diagnostic-text topmost-diag))) + t))) + +(dolist (type '(:warning :error)) + (push '(mouse-face . highlight) (get type 'flymake-overlay-control)) + (push `(keymap . ,(let ((map (make-sparse-keymap))) + (define-key map [mouse-2] + 'my-search-for-message) + map)) + (get type 'flymake-overlay-control))) +@end example + +@node Backend functions +@section Backend functions +@cindex backend functions + +@vindex flymake-diagnostic-functions +Flymake backends are Lisp functions placed in the special hook +@code{flymake-diagnostic-functions}. + +A backend's responsibility is to diagnose the contents of a buffer for +problems, registering the problem's positions, type, and summary +description. This information is collected in the form of diagnostic +objects created by the function @code{flymake-make-diagnostic} +(@pxref{Flymake utility functions}), and +then handed over to Flymake, which proceeds to annotate the +buffer. + +A request for a buffer check, and the subsequent delivery of +diagnostics, are two key events of the interaction between Flymake +and backend. Each such event corresponds to a well-defined function +calling convention: one for calls made by Flymake into the backend via +the backend function, the other in the reverse direction via a +callback. To be usable, backends must adhere to both. + +The first argument passed to a backend function is always +@var{report-fn}, a callback function detailed below. Beyond it, +functions must be prepared to accept (and possibly ignore) an +arbitrary number of keyword-value pairs of the form +@w{@code{(@var{:key} @var{value} @var{:key2} @var{value2}...)}}. + +Currently, Flymake may pass the following keywords and values to the +backend function: + +@itemize + +@item @code{:recent-changes} +The value is a list recent changes since the last time the backend +function was called for the buffer. If the list is empty, this +indicates that no changes have been recorded. If it is the first time +that this backend function is called for this activation of +@code{flymake-mode}, then this argument isn't provided at all +(in other words, it's not merely nil). + +Each element is in the form (@var{beg} @var{end} @var{text}) where +@var{beg} and @var{end} are buffer positions, and @var{text} is a +string containing the text contained between those positions (if any), +after the change was performed. + +@item @code{:changes-start} and @code{:changes-end} +The value is, respectively, the minimum and maximum buffer positions +touched by the recent changes. These are provided for convenience and +only if @code{:recent-changes} is also provided. + +@end itemize + +Whenever Flymake or the user decide to re-check the buffer, backend +functions are called as detailed above, and are expected to initiate +this check, but aren't in any way required to complete it before +exiting: if the computation involved is expensive, as +is often the case with large buffers, that slower task should be +scheduled for the future using asynchronous sub-processes +(@pxref{Asynchronous Processes,,, elisp, The Emacs Lisp reference +manual}) or other asynchronous mechanisms. + +In any case, backend functions are expected to return quickly or +signal an error, in which case the backend is disabled +(@pxref{Troubleshooting}). + +If the function returns, Flymake considers the backend to be +@dfn{running}. If it has not done so already, the backend is expected +to call the function @var{report-fn} passed to it, at which point +Flymake considers the backend to be @dfn{reporting}. Backends call +@var{report-fn} by passing it a single argument @var{report-action} +followed by an optional list of keyword-value pairs of the form +@w{@code{(@var{:report-key} @var{value} @var{:report-key2} @var{value2}...)}}. + +Currently accepted values for @var{report-action} are: + +@itemize +@item +A (possibly empty) list of diagnostic objects created by +@code{flymake-make-diagnostic}, causing Flymake to annotate the +buffer with this information. + +A backend may call @var{report-fn} repeatedly in this manner, but only +until Flymake considers that the most recently requested buffer check +is now obsolete, because, say, buffer contents have changed in the +meantime. The backend is only given notice of this via a renewed call +to the backend function. Thus, to prevent making obsolete reports and +wasting resources, backend functions should first cancel any ongoing +processing from previous calls. + +@item +The symbol @code{:panic}, signaling that the backend has encountered +an exceptional situation and should be disabled. +@end itemize + +Currently accepted @var{report-key} arguments are: + +@itemize +@item +@code{:explanation}, whose value should give user-readable +details of the situation encountered, if any. + +@item +@code{:force}, whose value should be a boolean suggesting +that Flymake consider the report even if it was somehow +unexpected. + +@item +@code{:region}, a cons (@var{beg} . @var{end}) of buffer positions +indicating that the report applies to that region and that previous +reports targeting other parts of the buffer remain valid. +@end itemize + +@menu +* Flymake utility functions:: +* Foreign and list-only diagnostics:: +* An annotated example backend:: +@end menu + +@node Flymake utility functions +@subsection Flymake utility functions +@cindex utility functions + +@cindex create diagnostic object +Before delivering them to Flymake, backends create diagnostic objects +by calling the function @code{flymake-make-diagnostic}. + +@deffn Function flymake-make-diagnostic locus beg end type info &optional data +Make a Flymake diagnostic for the region of text in @var{locus}'s +delimited by @var{beg} and @var{end}. @var{type} is a diagnostic symbol +(@pxref{Flymake error types}). @var{text} can be a string or a list +(@var{origin} @var{code} @var{message}) appropriately categorizing and +describing the diagnostic. Most commonly, @var{locus} is the buffer +object designating for the current buffer being syntax-checked. +However, it may be a string naming a file relative to the current +working directory. @xref{Foreign and list-only diagnostics}, for when +this may be useful. Depending on the type of @var{locus}, @var{beg} and +@var{end} are both either buffer positions or conses (@var{line} +. @var{col}) which specify the line and column of the diagnostic's start +and end positions, respectively. +@end deffn + +@cindex buffer position from line and column number +It is often the case with external syntax tools that a diagnostic's +position is reported in terms of a line number, and sometimes a column +number. To convert this information into a buffer position, backends +can use the following function: + +@deffn Function flymake-diag-region buffer line &optional col +Compute @var{buffer}'s region (@var{beg} . @var{end}) corresponding +to @var{line} and @var{col}. If @var{col} is @code{nil}, return a +region just for @var{line}. Return @code{nil} if the region is +invalid. This function saves match data (@pxref{Saving Match Data,,, +elisp, The Emacs Lisp Reference Manual}). +@end deffn + +@cindex add a log message +For troubleshooting purposes, backends may record arbitrary +exceptional or erroneous situations into the Flymake log +buffer (@pxref{Troubleshooting}): + +@deffn Macro flymake-log level msg &optional args +Log, at level @var{level}, the message @var{msg} formatted with +@var{args}. @var{level} is passed to @code{display-warning} +(@pxref{Warning Basics,,, elisp, The Emacs Lisp reference Manual}), which is +used to display the warning in Flymake's log buffer. +@end deffn + +@node Foreign and list-only diagnostics +@subsection Foreign and list-only diagnostics +@cindex create diagnostic object for other buffer + +It is possible for a given backend's implementation to use +@code{flymake-make-diagnostic} to create diagnostics for buffers or +files other than the ``source'' buffer where Flymake was enabled. For +instance, this is useful when a given backend has access to +information about the health of neighboring files that are not yet +visited or whose diagnostics depend on the current buffer's state. +There are two alternative ways to go about doing this: + +@enumerate + +@item +@cindex foreign diagnostics +@cindex domestic diagnostics +If the information about neighboring diagnostics is obtained +regularly, like when each syntax-checking iteration of a @code{.c} +file also reports a number of associated problems in an neighboring +@code{.h} file, it is better to create so-called ``foreign'' +diagnostics. + +This is done by passing a file name to @code{flymake-make-diagnostic} +(@pxref{Flymake utility functions}). Then, the resulting object is +simply reported along with the other ``domestic'' diagnostics for the +source buffer (@pxref{Backend functions}). When the neighboring file +is visited as a buffer and Flymake is active there, a number of +supplemental annotations will appear and automatically update whenever +as the ``source'' buffer is syntax-checked. + +@item +@cindex list-only diagnostics +@vindex flymake-list-only-diagnostics +If information about neighboring diagnostics is obtained infrequently, +like when running a time-consuming and sporadic check of a large +project, it is easier for the backend to modify the global variable +@code{flymake-list-only-diagnostics}. + +Flymake will look up this variable when asked to compile project-wide +lists of diagnostics. The backend should add one or more alist +entries that look like (@var{file-name} . @var{diags}). +@var{file-name} is the absolute name of the neighboring file presumed +not to be visited in Emacs already, as that would mean that that +buffer contains more up-to-date information on its diagnostics. +@var{diags} is a list of diagnostic objects. When the neighboring +file @var{file-name} is visited as a buffer and Flymake is activated +there, the ``list-only'' diagnostics will @emph{not} produce +annotations for @var{diags}, as Flymake assumes that the Flymake +activation in the new buffer will take care of that. +@end enumerate + +@node An annotated example backend +@subsection An annotated example backend +@cindex example of backend +@cindex backend, annotated example + +This section presents an annotated example of a complete working +Flymake backend. The example illustrates the process of writing a +backend as outlined above. + +The backend in question is used for checking Ruby source files. It +uses asynchronous sub-processes (@pxref{Asynchronous Processes,,, elisp, +The Emacs Lisp Reference Manual}), a common technique for performing +parallel processing in Emacs. + +The following code needs lexical binding (@pxref{Using Lexical +Binding,,, elisp, The Emacs Lisp Reference Manual}) to be active. + +@example +@group +;;; ruby-flymake.el --- A ruby Flymake backend -*- lexical-binding: t; -*- +(require 'cl-lib) +(defvar-local ruby--flymake-proc nil) +@end group + +@group +(defun ruby-flymake (report-fn &rest _args) + ;; Not having a ruby interpreter is a serious problem which should cause + ;; the backend to disable itself, so an @code{error} is signaled. + ;; + (unless (executable-find + "ruby") (error "Cannot find a suitable ruby")) + ;; If a live process launched in an earlier check was found, that + ;; process is killed. When that process's sentinel eventually runs, + ;; it will notice its obsoletion, since it have since reset + ;; `ruby-flymake-proc' to a different value + ;; + (when (process-live-p ruby--flymake-proc) + (kill-process ruby--flymake-proc)) +@end group + +@group + ;; Save the current buffer, the narrowing restriction, remove any + ;; narrowing restriction. + ;; + (let ((source (current-buffer))) + (save-restriction + (widen) + ;; Reset the `ruby--flymake-proc' process to a new process + ;; calling the ruby tool. + ;; + (setq + ruby--flymake-proc + (make-process + :name "ruby-flymake" :noquery t :connection-type 'pipe + ;; Make output go to a temporary buffer. + ;; + :buffer (generate-new-buffer " *ruby-flymake*") + :command '("ruby" "-w" "-c") + :sentinel + (lambda (proc _event) + ;; Check that the process has indeed exited, as it might + ;; be simply suspended. + ;; + (when (memq (process-status proc) '(exit signal)) + (unwind-protect + ;; Only proceed if `proc' is the same as + ;; `ruby--flymake-proc', which indicates that + ;; `proc' is not an obsolete process. + ;; + (if (with-current-buffer source (eq proc ruby--flymake-proc)) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + ;; Parse the output buffer for diagnostic's + ;; messages and locations, collect them in a list + ;; of objects, and call `report-fn'. + ;; + (cl-loop + while (search-forward-regexp + "^\\(?:.*\\.rb\\|-\\):\\([0-9]+\\): \\(.*\\)$" + nil t) + for msg = (match-string 2) + for (beg . end) = (flymake-diag-region + source + (string-to-number (match-string 1))) + for type = (if (string-match "^warning" msg) + :warning + :error) + when (and beg end) + collect (flymake-make-diagnostic source + beg + end + type + msg) + into diags + finally (funcall report-fn diags))) + (flymake-log :warning "Canceling obsolete check %s" + proc)) + ;; Cleanup the temporary buffer used to hold the + ;; check's output. + ;; + (kill-buffer (process-buffer proc))))))) + ;; Send the buffer contents to the process's stdin, followed by + ;; an EOF. + ;; + (process-send-region ruby--flymake-proc (point-min) (point-max)) + (process-send-eof ruby--flymake-proc)))) +@end group + +@group +(defun ruby-setup-flymake-backend () + (add-hook 'flymake-diagnostic-functions 'ruby-flymake nil t)) + +(add-hook 'ruby-mode-hook 'ruby-setup-flymake-backend) +@end group +@end example + +@node Inspecting diagnostics +@section Inspecting diagnostics + +When Flymake has called on the backend and collected its diagnostics, it +will annotate the buffer with it. After this happens, Elisp programs +may call @code{flymake-diagnostics} to collect such objects in a +specified region. + +@cindex collect diagnostic objects +@deffn Function flymake-diagnostics beg end +Get a list of Flymake diagnostics in the region determined by +@var{beg} and @var{end}. If neither @var{beg} or @var{end} is +supplied, use the whole buffer, otherwise if @var{beg} is +non-@code{nil} and @var{end} is @code{nil}, consider only diagnostics +at @var{beg}. +@end deffn + +@cindex access diagnostic object +A diagnostic object's properties can be accessed with the functions +@code{flymake-diagnostic-backend}, @code{flymake-diagnostic-buffer}, +@code{flymake-diagnostic-origin}, @code{flymake-diagnostic-code} +@code{flymake-diagnostic-message}, @code{flymake-diagnostic-beg}, +@code{flymake-diagnostic-end}, @code{flymake-diagnostic-type} and +@code{flymake-diagnostic-data}. @code{flymake-diagnostic-text} will +compose the diagnostic's origin, code and message in a single string. + +@node The legacy Proc backend +@chapter The legacy ``Proc'' backend +@cindex legacy proc backend + +@menu +* Proc customization variables:: +* Adding support for a new syntax check tool:: +* Implementation overview:: +* Making a temporary copy:: +* Locating a master file:: +* Getting the include directories:: +* Locating the buildfile:: +* Starting the syntax check process:: +* Parsing the output:: +* Interaction with other modes:: +@end menu + +@findex flymake-proc-legacy-flymake +The backend @code{flymake-proc-legacy-flymake} was originally designed +to be extended for supporting new syntax check tools and error message +patterns. It is also controlled by its own set of customization variables. + +@node Proc customization variables +@section Customization variables for the Proc backend +@cindex proc backend customization variables + +@vtable @code +@item flymake-proc-allowed-file-name-masks +A list of @code{(filename-regexp, init-function, cleanup-function +getfname-function)} for configuring syntax check tools. @xref{Adding +support for a new syntax check tool}. + +@item flymake-proc-master-file-dirs +A list of directories for searching a master file. @xref{Locating a +master file}. + +@item flymake-proc-get-project-include-dirs-function +A function used for obtaining a list of project include dirs (C/C++ +specific). @xref{Getting the include directories}. + +@item flymake-proc-master-file-count-limit +@itemx flymake-proc-check-file-limit +Used when looking for a master file. @xref{Locating a master file}. + +@item flymake-proc-err-line-patterns +Patterns for error/warning messages in the form @code{(regexp file-idx +line-idx col-idx err-text-idx)}. @xref{Parsing the output}. + +@item flymake-proc-diagnostic-type-pred +A function to classify a diagnostic text as a particular type of +error. The value of this variable should be a function taking an +error text and returning a diagnostic symbol (@pxref{Flymake error +types}). If it returns a non-@code{nil} value but there is no such +symbol in that table, the text is interpreted as a warning. If the +function returns @code{nil}, the text is assumed to be an error. + +The value of this variable can alternatively be a regular expression +that should match only warnings. + +This variable replaces the old @code{flymake-warning-re} and +@code{flymake-warning-predicate}. + +@item flymake-proc-compilation-prevents-syntax-check +A flag indicating whether compilation and syntax check of the same +file cannot be run simultaneously. @xref{Interaction with other modes}. +@end vtable + +@node Adding support for a new syntax check tool +@section Adding support for a new syntax check tool +@cindex adding support for a new syntax check tool + +@menu +* Example---Configuring a tool called directly:: +* Example---Configuring a tool called via make:: +@end menu + +Syntax check tools are configured using the +@code{flymake-proc-allowed-file-name-masks} list. Each item of this list +has the following format: + +@lisp +(filename-regexp, init-function, cleanup-function, getfname-function) +@end lisp + +@table @code +@item filename-regexp +This field is used as a key for locating init/cleanup/getfname +functions for the buffer. Items in +@code{flymake-proc-allowed-file-name-masks} are searched sequentially. +The first item with @code{filename-regexp} matching buffer filename is +selected. If no match is found, @code{flymake-mode} is switched off. + +@item init-function +@code{init-function} is required to initialize the syntax check, +usually by creating a temporary copy of the buffer contents. The +function must return @code{(list cmd-name arg-list)}. If +@code{init-function} returns null, syntax check is aborted, but +@code{flymake-mode} is not switched off. + +@item cleanup-function +@code{cleanup-function} is called after the syntax check process is +complete and should take care of proper deinitialization, which is +usually deleting a temporary copy created by the @code{init-function}. + +@item getfname-function +This function is used for translating filenames reported by the syntax +check tool into ``real'' filenames. Filenames reported by the tool +will be different from the real ones, as actually the tool works with +the temporary copy. In most cases, the default implementation +provided by Flymake, @code{flymake-proc-get-real-file-name}, can be +used as @code{getfname-function}. +@end table + +To add support for a new syntax check tool, write the corresponding +@code{init-function} and, optionally, @code{cleanup-function} and +@code{getfname-function}. If the format of error messages reported by +the new tool is not yet supported by Flymake, add a new entry to +the @code{flymake-proc-err-line-patterns} list. + +The following sections contain some examples of configuring Flymake +support for various syntax check tools. + +@node Example---Configuring a tool called directly +@subsection Example---Configuring a tool called directly +@cindex adding support for perl + +In this example, we will add support for @command{perl} as a syntax check +tool. @command{perl} supports the @option{-c} option which does syntax +checking. + +First, we write the @code{init-function}: + +@lisp +(defun flymake-proc-perl-init () + (let* ((temp-file (flymake-proc-init-create-temp-buffer-copy + 'flymake-proc-create-temp-inplace)) + (local-file (file-relative-name + temp-file + (file-name-directory buffer-file-name)))) + (list "perl" (list "-wc " local-file)))) +@end lisp + +@code{flymake-proc-perl-init} creates a temporary copy of the buffer +contents with the help of +@code{flymake-proc-init-create-temp-buffer-copy}, and builds an appropriate +command line. + +Next, we add a new entry to the +@code{flymake-proc-allowed-file-name-masks}: + +@lisp +(setq flymake-proc-allowed-file-name-masks + (cons '(".+\\.pl$" + flymake-proc-perl-init + flymake-proc-simple-cleanup + flymake-proc-get-real-file-name) + flymake-proc-allowed-file-name-masks)) +@end lisp + +Note that we use standard @code{cleanup-function} and +@code{getfname-function}. + +Finally, we add an entry to @code{flymake-proc-err-line-patterns}: + +@lisp +(setq flymake-proc-err-line-patterns + (cons '("\\(.*\\) at \\([^ \n]+\\) line \\([0-9]+\\)[,.\n]" + 2 3 nil 1) + flymake-proc-err-line-patterns)) +@end lisp + +@node Example---Configuring a tool called via make +@subsection Example---Configuring a tool called via make +@cindex adding support for C (gcc+make) + +In this example we will add support for C files syntax checked by +@command{gcc} called via @command{make}. + +We're not required to write any new functions, as Flymake already has +functions for @command{make}. We just add a new entry to the +@code{flymake-proc-allowed-file-name-masks}: + +@lisp +(setq flymake-proc-allowed-file-name-masks + (cons '(".+\\.c$" + flymake-proc-simple-make-init + flymake-proc-simple-cleanup + flymake-proc-get-real-file-name) + flymake-proc-allowed-file-name-masks)) +@end lisp + +@code{flymake-proc-simple-make-init} builds the following @command{make} +command line: + +@lisp +(list "make" + (list "-s" "-C" + base-dir + (concat "CHK_SOURCES=" source) + "SYNTAX_CHECK_MODE=1" + "check-syntax")) +@end lisp + +@code{base-dir} is a directory containing the @file{Makefile}, see +@ref{Locating the buildfile}. + +Thus, @file{Makefile} must contain the @code{check-syntax} target. In +our case this target might look like this: + +@verbatim +check-syntax: + gcc -o /dev/null -S ${CHK_SOURCES} || true +@end verbatim + +@noindent +The format of error messages reported by @command{gcc} is already +supported by Flymake, so we don't have to add a new entry to +@code{flymake-err-line-patterns}. Note that if you are using +Automake, you may want to replace @code{gcc} with the standard +Automake variable @code{COMPILE}: + +@verbatim +check-syntax: + $(COMPILE) -o /dev/null -S ${CHK_SOURCES} || true +@end verbatim + +@node Implementation overview +@section Implementation overview +@cindex syntax check models +@cindex master file + +@code{flymake-proc-legacy-flymake} saves a copy of the buffer in a +temporary file in the buffer's directory (or in the system temporary +directory, for Java files), creates a syntax check command and +launches a process with this command. The output is parsed using a +list of error message patterns, and error information (file name, line +number, type and text) is saved. After the process has finished, +Flymake highlights erroneous lines in the buffer using the accumulated +error information. + +Syntax check is considered possible if there's an entry in +@code{flymake-proc-allowed-file-name-masks} matching buffer's filename and +its @code{init-function} returns non-@code{nil} value. + +Two syntax check modes are distinguished: + +@enumerate + +@item +Buffer can be syntax checked in a standalone fashion, that is, the +file (its temporary copy, in fact) can be passed over to the compiler to +do the syntax check. Examples are C/C@t{++} sources (@file{.c}, +@file{.cpp}) and Java (@file{.java}). + +@item +Buffer can be syntax checked, but additional file, called master file, +is required to perform this operation. A master file is a file that +includes the current file, so that running a syntax check tool on it +will also check syntax in the current file. Examples are C/C@t{++} +headers (@file{.h}, @file{.hpp}). + +@end enumerate + +These modes are handled inside init/cleanup/getfname functions, see +@ref{Adding support for a new syntax check tool}. + +The Proc backend contains implementations of all functionality +required to support different syntax check modes described above +(making temporary copies, finding master files, etc.), as well as some +tool-specific (routines for Make, Ant, etc.)@: code. + + +@node Making a temporary copy +@section Making a temporary copy +@cindex temporary copy of the buffer + +After the possibility of the syntax check has been determined, a +temporary copy of the current buffer is made so that the most recent +unsaved changes could be seen by the syntax check tool. Making a copy +is quite straightforward in a standalone case (mode @code{1}), as it's +just saving buffer contents to a temporary file. + +Things get trickier, however, when master file is involved, as it +requires to + +@itemize @bullet +@item +locate a master file +@item +patch it to include the current file using its new (temporary) name. +@end itemize + +Locating a master file is discussed in the following section. + +Patching just changes all appropriate lines of the master file so that they +use the new (temporary) name of the current file. For example, suppose current +file name is @code{file.h}, the master file is @code{file.cpp}, and +it includes current file via @code{#include "file.h"}. Current file's copy +is saved to file @code{file_flymake.h}, so the include line must be +changed to @code{#include "file_flymake.h"}. Finally, patched master file +is saved to @code{file_flymake_master.cpp}, and the last one is passed to +the syntax check tool. + +@node Locating a master file +@section Locating a master file +@cindex locating a master file +@cindex master file, locating + +Master file is located in two steps. + +First, a list of possible master files is built. A simple name +matching is used to find the files. For a C++ header @file{file.h}, +the Proc backend searches for all @file{.cpp} files in the directories +whose relative paths are stored in a customizable variable +@code{flymake-proc-master-file-dirs}, which usually contains something +like @code{("." "./src")}. No more than +@code{flymake-proc-master-file-count-limit} entries is added to the +master file list. The list is then sorted to move files with names +@file{file.cpp} to the top. + +Next, each master file in a list is checked to contain the appropriate +include directives. No more than @code{flymake-proc-check-file-limit} of each +file are parsed. + +For @file{file.h}, the include directives to look for are +@code{#include "file.h"}, @code{#include "../file.h"}, etc. Each +include is checked against a list of include directories +(@pxref{Getting the include directories}) to be sure it points to the +correct @file{file.h}. + +First matching master file found stops the search. The master file is then +patched and saved to disk. In case no master file is found, syntax check is +aborted, and corresponding status (@samp{!}) is reported in the mode line. +@xref{Mode line status}. + +@node Getting the include directories +@section Getting the include directories +@cindex include directories (C/C++ specific) + +Two sets of include directories are distinguished: system include directories +and project include directories. The former is just the contents of the +@code{INCLUDE} environment variable. The latter is not so easy to obtain, +and the way it can be obtained can vary greatly for different projects. +Therefore, a customizable variable +@code{flymake-proc-get-project-include-dirs-function} is used to provide the +way to implement the desired behavior. + +The default implementation, @code{flymake-proc-get-project-include-dirs-imp}, +uses a @command{make} call. This requires a correct base directory, that is, a +directory containing a correct @file{Makefile}, to be determined. + +As obtaining the project include directories might be a costly operation, its +return value is cached in the hash table. The cache is cleared in the beginning +of every syntax check attempt. + +@node Locating the buildfile +@section Locating the buildfile +@cindex locating the buildfile +@cindex buildfile, locating +@cindex makefile, locating + +The Proc backend can be configured to use different tools for +performing syntax checks. For example, it can use direct compiler +call to syntax check a perl script or a call to @command{make} for a +more complicated case of a C/C@t{++} source. The general idea is +that simple files, like Perl scripts and @acronym{HTML} pages, can be checked by +directly invoking a corresponding tool. Files that are usually more +complex and generally used as part of larger projects, might require +non-trivial options to be passed to the syntax check tool, like +include directories for C@t{++}. The latter files are syntax checked +using some build tool, like Make or Ant. + +All Make configuration data is usually stored in a file called +@file{Makefile}. To allow for future extensions, Flymake uses a notion of +buildfile to reference the @dfn{project configuration} file. + +@findex flymake-proc-find-buildfile +Special function, @code{flymake-proc-find-buildfile} is provided for locating buildfiles. +Searching for a buildfile is done in a manner similar to that of searching +for possible master files. +@ignore +A customizable variable +@code{flymake-proc-buildfile-dirs} holds a list of relative paths to the +buildfile. They are checked sequentially until a buildfile is found. +@end ignore +In case there's no build file, the syntax check is aborted. + +Buildfile values are also cached. + +@node Starting the syntax check process +@section Starting the syntax check process +@cindex syntax check process, legacy proc backend + +The command line (command name and the list of arguments) for +launching a process is returned by the initialization function. The +Proc backend then just starts an asynchronous process and configures a +process filter and sentinel, which are used for processing the output +of the syntax check tool. When exiting Emacs, running processes will +be killed without prompting the user. + +@node Parsing the output +@section Parsing the output +@cindex parsing the output, legacy proc backend + +The output generated by the syntax check tool is parsed in the process +filter/sentinel using the error message patterns stored in the +@code{flymake-proc-err-line-patterns} variable. This variable contains a +list of items of the form @w{@code{(regexp file-idx line-idx +err-text-idx)}}, used to determine whether a particular line is an +error message and extract file name, line number and error text, +respectively. Error type (error/warning) is also guessed by matching +error text with the @samp{^[wW]arning} pattern. Anything that was not +classified as a warning is considered an error. Type is then used to +sort error menu items, which shows error messages first. + +The Proc backend is also able to interpret error message patterns +missing err-text-idx information. This is done by merely taking the +rest of the matched line (@code{(substring line (match-end 0))}) as +error text. This trick allows making use of a huge collection of +error message line patterns from @file{compile.el}. All these error +patterns are appended to the end of +@code{flymake-proc-err-line-patterns}. + +The error information obtained is saved in a buffer local +variable. The buffer for which the process output belongs is +determined from the process-id@w{}->@w{}buffer mapping updated +after every process launch/exit. + +@node Interaction with other modes +@section Interaction with other modes +@cindex interaction with other modes, legacy proc backend +@cindex interaction with compile mode, legacy proc backend + +The only mode the Proc backend currently knows about is +@code{compile}. + +The Proc backend can be configured to not start syntax check if it +thinks the compilation is in progress, by testing the +@code{compilation-in-progress} variable. The reason why this might be +useful is saving CPU time in case both syntax check and compilation +are very CPU intensive. The original reason for adding this feature, +though, was working around a locking problem with MS Visual C++ +compiler. The variable in question is +@code{flymake-proc-compilation-prevents-syntax-check}. + +@findex flymake-proc-compile +The Proc backend also provides an alternative command for starting +compilation, @code{flymake-proc-compile}. It just kills all the active +syntax check processes before calling @code{compile}. + +@node GNU Free Documentation License +@appendix GNU Free Documentation License +@include doclicense.texi + +@node Index +@unnumbered Index + +@printindex cp + +@bye