|
|
11 bulan lalu | |
|---|---|---|
| .. | ||
| README.md | 3 tahun lalu | |
| errors-to-diagnostics.ts | 11 bulan lalu | |
| latex-linter.ts | 11 bulan lalu | |
| latex-linter.worker.ts | 11 bulan lalu | |
| merge-overlapping-diagnostics.ts | 3 tahun lalu | |
The purpose of the linter is to check the following
\begin .. \end$ ... $ # inline math$$ ... $$ # display math{ ... } # grouping commands\left .. \right # bracket commands (in math-mode only)\alpha, ^ and _)\chapter should not be used in math-mode)The general approach of the ace linter is as following
The implementation has two main phases
The linter returns errors found in the InterpretTokens phase.
The tokenizer starts from the beginning of the file, searching repeatedly for the next special character: ['\', '{', '}', '$', '&', '#', '^', '_', '~', '%'].
When a special character is found, it is inspected and additional characters consumed according to the following TeX rules:
'\' escape character: Handle TeX control sequences (\foo) and control symbols (\@).
[a-zA-Z]+: it's a control sequence, consume whitespace after it['{', '}', '$', '&', '#', '^', '_', '~']: push it as a token'%' comment: consume up to next newline.
Special cases:
%novalidate disable validation in this file%begin novalidate, %end novalidate disable validation in a regionThe content between special characters, and not consumed by any rules above or below, is marked as a Text token.
After this stage, we have a list of the tokens (with their positions) and text regions.
This function iterates over the tokens, looking for groups or environments to match. Each environment command is pushed onto the Environments array. As part of this process other commands are interpreted in order to skip over them (for example \newcommand{\foo}{\begin{equation}} is valid and should not trigger an "unmatched environment" error.). We consume these commands using custom argument functions.
When we push an entry onto the Environments array we also keep track of the math mode (either null, inline, or display), and for some commands the mode of the next argument (nextGroupMathMode). For example, \hbox has nextGroupMathMode false since the next group is its argument {...} which will always be text.
Tokens may be followed by various arguments, which can be optional. These are consumed by custom functions which look for the correct format:
read1arg: read an argument FOO to a either form of command \newcommand\FOO... or \newcommand{\FOO}.... Also support optional * form \newcommand*.readLetDefinition: read a let command (the equals sign is optional) \let\foo=\bar, \let\foo=TOKEN, \let\foo\bar, \let\foo\TOKEN.read1name: read an environemt name FOO in \newenvironment{FOO}..., also handle names like FOO_BAR.read1filename: read a filename like foo_bar.tex (may include _)readOptionalParams: read an optional parameter [N] where N is a number, used for \newcommand{\foo}[2]... meaning 2 parameters. Allow for additional arguments like [1][key=value,key=value] and skip over arbitrary arguments [xxx][yyy][\foo{zzz}]{... up to the first {..readOptionalGeneric: read a single optional parameter [foo]readOptionalDef:skip over the optional arguments of a definition \def\foo#1.#2(#3){this is the macro #1 #2 #3} to start looking at text immediately after \def command.readDefinition: read a definition as in \newcommand{\FOO}{DEFN} or \newcommand{\FOO} {DEF} (optional whitespace). Look ahead for argument, consuming whitespace, the definition is read looking for balanced { ... } braces.readVerb: read a verbatim argument \verb@foo@ or \verb*@foo@ where @ is any character except * for \verb, foo is any sequence excluding end-of-line and the delimiter. A space does work for @, contrary to latex documentation. Note: this is only an approximation, because we have already tokenised the input stream, and we should really do that taking into account the effect of verb. For example \verb|%| will get confused because % is then a character.readUrl: read a url argument \url|foo|, \url{foo} Note: this is only an approximation, because we have already tokenised the input stream, so anything after a comment character % on the current line will not be present in the input stream.The following tokens trigger special handling, either by starting or closing a group or environment, being a command that must be intepreted (to skip over arguments) or having special properties (such as only being permissible in certain environments).
{ and } handle open and close group as a type of environment\begin and \end followed by a text token, taken as the environment name
_ (e.g like \begin{new_major_theorem})\left and \right must be followed by one of (){}[]<>/|\.\( ... \) and \[ ... \] handle open and close math-modes as a type of environment\newcommand{\foo}{\begin{equation}} is valid and should not trigger an "unmatched environment" error.
newcommand, renewcommand, DeclareRobustCommand: read1arg readOptionalParams readDefinitiondef: read1arg readOptionalDef readDefinitionlet: readLetDefinitionnewcolumntype read1name readOptionalParams readDefinitionnewenvironment, renewenvironment read1name readOptionalParams readDefinition(open) readDefinition(close)verb: readVerb (\verb|....| where | is any char)url: readUrl (\url{...} or \url|....| where | is any char)input: read1filenamehbox, text, mbox, footnote, intertext, shortintertext, textnormal, tag, reflectbox, textrmtikz: readOptionalGenericrotatebox, scalebox, feynmandiagram: readOptionalGeneric readDefinitionresizebox: readOptionalGeneric readDefinition(width) readDefinition(height)DeclareMathOperator: readDefinition(first arg) readDefinition(second arg)DeclarePairedDelimiter: readDefinition(first arg) readDefinition(second arg) readDefinition(third arg)(alpha|beta|gamma|delta|epsilon|varepsilon|zeta|eta|theta|vartheta|iota|kappa|lambda|mu|nu|xi|pi|varpi|rho|varrho|sigma|varsigma|tau|upsilon|phi|varphi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega): can only be used in math mode(chapter|section|subsection|subsubsection): cannot be used in math mode\[a-z]+: if we see an unknown command \foo{...}{...} put the math mode for the next group into the 'undefined' state, because we do not know what math mode an arbitrary macro will use for its arguments. In the math mode 'undefined' state we don't report errors when we encounter math or text commands.$$ - display math environment$ - inline math environment^ and _: check for mathmode assuming environments are correct(document|figure|center|enumerate|itemize|table|abstract|proof|lemma|theorem|definition|proposition|corollary|remark|notation|thebibliography)(array|gathered|split|aligned|alignedat)\*?(math|displaymath|equation|eqnarray|multline|align|gather|flalign|alignat)\*?(verbatim|boxedverbatim|lstlisting|minted|Verbatim). Any errors occurring in a verbatim environment are ignored.If we encounter any tokens matching (be|beq|beqa|bea) or (ee|eeq|eeqn|eeqa|eeqan|eea) we filter out all errors relating to math-mode violations, since these are common user-defined macros to replace \begin{equation} etc.