mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-04 08:47:11 +00:00
365e01cc9f
Run "TZ=UTC0 admin/update-copyright $(git ls-files)".
1160 lines
43 KiB
Plaintext
1160 lines
43 KiB
Plaintext
\input texinfo @c -*-texinfo; coding: utf-8 -*-
|
|
@comment %**start of header
|
|
@setfilename ../../info/flymake.info
|
|
@set VERSION 1.0
|
|
@set UPDATED June 2018
|
|
@settitle GNU Flymake @value{VERSION}
|
|
@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}),
|
|
which is a universal on-the-fly syntax checker for GNU Emacs.
|
|
|
|
Copyright @copyright{} 2004--2020 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
|
|
@insertcopying
|
|
@end ifnottex
|
|
|
|
@menu
|
|
* Using Flymake::
|
|
* Extending Flymake::
|
|
* 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 a universal on-the-fly buffer checker implemented as an
|
|
Emacs minor mode. To use Flymake, you must first activate
|
|
@code{flymake-mode} by using the command @kbd{flymake-mode}.
|
|
|
|
When enabled, Flymake collects information about problems in the
|
|
buffer, called @dfn{diagnostics}, from one or more different sources,
|
|
or @dfn{backends}, and then visually annotates the buffer by
|
|
highlighting problematic buffer regions with a special face.
|
|
|
|
It also displays an overall buffer status in the mode line containing
|
|
totals for different types of diagnostics.
|
|
|
|
Syntax check is done ``on-the-fly''. It is started whenever
|
|
|
|
@itemize @bullet
|
|
@item
|
|
@code{flymake-mode} is started, unless
|
|
@code{flymake-start-on-flymake-mode} is nil;
|
|
|
|
@item
|
|
the buffer is saved, unless @code{flymake-start-on-save-buffer} is
|
|
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}).
|
|
@end itemize
|
|
|
|
Syntax check can also be started manually by typing the @kbd{M-x
|
|
flymake-start @key{RET}} command.
|
|
|
|
If the check detected errors or warnings, the respective buffer
|
|
regions are highlighted. You can place point on those regions and use
|
|
@kbd{C-h .} (@code{display-local-help}) to see what the specific
|
|
problem was. Alternatively, hovering the mouse on those regions
|
|
should also display a tool-tip with the same information.
|
|
|
|
@code{flymake-goto-next-error} and @code{flymake-goto-prev-error} are
|
|
commands that allow easy navigation to the next/previous erroneous
|
|
regions, respectively. If 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
|
|
|
|
Flymake is a universal syntax checker in the sense that it's easily
|
|
extended to support new backends (@pxref{Extending Flymake}).
|
|
|
|
Historically, Flymake used to accept diagnostics from a single
|
|
backend, albeit a reasonably flexible one.
|
|
|
|
This backend isn't (yet) obsolete, and so is still available as a
|
|
fallback and active by default (@pxref{The legacy Proc backend}). It works by
|
|
selecting a syntax check tool from a preconfigured list (compiler for
|
|
C@t{++} files, @command{perl} for Perl files, etc.), and executing it in the
|
|
background, passing it a temporary file which is a copy of the current
|
|
buffer, and parsing the output for known error/warning message
|
|
patterns.
|
|
|
|
@menu
|
|
* Syntax check statuses::
|
|
* Backend exceptions::
|
|
* Customizable variables::
|
|
@end menu
|
|
|
|
@node Syntax check statuses
|
|
@section Syntax check statuses
|
|
@cindex Syntax check statuses
|
|
|
|
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{Backend exceptions}).
|
|
|
|
@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{Extending Flymake}).
|
|
|
|
@end multitable
|
|
|
|
@node Backend exceptions
|
|
@section Backend exceptions
|
|
@cindex backend exceptions
|
|
|
|
@cindex disabled backends
|
|
@cindex backends, disabled
|
|
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
|
|
Toggling @code{flymake-mode} off and on again, or invoking
|
|
@code{flymake-start} with a prefix argument is one way to reset the
|
|
disabled backend list, so that they will be tried again in the next check.
|
|
|
|
@cindex logging
|
|
@cindex flymake logging
|
|
Flymake also 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 information logged
|
|
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.
|
|
|
|
@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-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-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-wrap-around
|
|
If non-nil, moving to errors with @code{flymake-goto-next-error} and
|
|
@code{flymake-goto-prev-error} wraps around buffer boundaries.
|
|
@end vtable
|
|
|
|
@node Extending Flymake
|
|
@chapter Extending Flymake
|
|
@cindex extending flymake
|
|
|
|
Flymake can primarily be extended in one of two ways:
|
|
|
|
@enumerate
|
|
@item
|
|
By changing the look and feel of the annotations produced by the
|
|
different backends.
|
|
|
|
@item
|
|
By adding a new buffer-checking backend.
|
|
@end enumerate
|
|
|
|
The following sections discuss each approach in detail.
|
|
|
|
@menu
|
|
* Flymake error types::
|
|
* Backend functions::
|
|
@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, set properties on the
|
|
symbols associated with each diagnostic type. The standard diagnostic
|
|
symbols are @code{:error}, @code{:warning} and @code{:note} (though
|
|
the 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
|
|
@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{flymake-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.
|
|
@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
|
|
(i.e. 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, repectively, 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{Backend exceptions}).
|
|
|
|
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::
|
|
* 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 buffer beg end type text
|
|
Make a Flymake diagnostic for @var{buffer}'s region from @var{beg} to
|
|
@var{end}. @var{type} is a diagnostic symbol (@pxref{Flymake error
|
|
types}), and @var{text} is a description of the problem detected in
|
|
this region. Currently, it is unspecified behavior to make
|
|
diagnostics for buffers other than the buffer that the Flymake backend
|
|
is responsible for.
|
|
@end deffn
|
|
|
|
@cindex access diagnostic object
|
|
These objects' properties can be accessed with the functions
|
|
@code{flymake-diagnostic-backend}, @code{flymake-diagnostic-buffer},
|
|
@code{flymake-diagnostic-text}, @code{flymake-diagnostic-beg},
|
|
@code{flymake-diagnostic-end} and @code{flymake-diagnostic-type}.
|
|
|
|
Additionally, the function @code{flymake-diagnostics} will collect
|
|
such objects in the region you specify.
|
|
|
|
@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 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.
|
|
@end deffn
|
|
|
|
@cindex add a log message
|
|
For troubleshooting purposes, backends may record arbitrary
|
|
exceptional or erroneous situations into the Flymake log
|
|
buffer (@pxref{Backend exceptions}):
|
|
|
|
@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 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
|
|
;;; ruby-flymake.el --- A ruby Flymake backend -*- lexical-binding: t; -*-
|
|
(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 @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))
|
|
|
|
;; 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 (eq 'exit (process-status proc))
|
|
(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)
|
|
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)
|
|
@end example
|
|
|
|
@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-backend
|
|
The backend @code{flymake-proc-legacy-backend} 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 particular type of error.
|
|
Should be a function taking an error text and returning a diagnostic
|
|
symbol (@pxref{Flymake error types}). If non-nil is returned but
|
|
there is no such symbol in that table, a warning is assumed. If nil
|
|
is returned, an error is assumed. Can also 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-backend} 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
|
|
(see @ref{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{Syntax check statuses}.
|
|
|
|
@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
|