summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-06-04 03:02:48 +0000
committerNorbert Preining <norbert@preining.info>2021-06-04 03:02:48 +0000
commita5ae129f3aa3a3a0aeaa21c55b75a1d543fe4111 (patch)
treefe5e1e212aec203e668df8581a17374cdde352a1 /support
parentd231c6331f53a048d29c2f847254a9f56d5ee2dd (diff)
CTAN sync 202106040302
Diffstat (limited to 'support')
-rw-r--r--support/TeX4ht/source/tex4ht-html4.tex42
-rw-r--r--support/texlab/CHANGELOG.md18
-rw-r--r--support/texlab/Cargo.lock33
-rw-r--r--support/texlab/Cargo.toml22
-rw-r--r--support/texlab/README.md5
-rw-r--r--support/texlab/docs/options.md36
-rw-r--r--support/texlab/src/citation.rs2
-rw-r--r--support/texlab/src/diagnostics/bibtex.rs12
-rw-r--r--support/texlab/src/diagnostics/latex.rs22
-rw-r--r--support/texlab/src/features/completion.rs36
-rw-r--r--support/texlab/src/features/completion/acronym_ref.rs16
-rw-r--r--support/texlab/src/features/completion/citation.rs74
-rw-r--r--support/texlab/src/features/completion/color.rs11
-rw-r--r--support/texlab/src/features/completion/color_model.rs31
-rw-r--r--support/texlab/src/features/completion/component_environment.rs20
-rw-r--r--support/texlab/src/features/completion/field.rs2
-rw-r--r--support/texlab/src/features/completion/glossary_ref.rs18
-rw-r--r--support/texlab/src/features/completion/import.rs13
-rw-r--r--support/texlab/src/features/completion/include.rs11
-rw-r--r--support/texlab/src/features/completion/label.rs60
-rw-r--r--support/texlab/src/features/completion/theorem.rs21
-rw-r--r--support/texlab/src/features/completion/tikz_library.rs12
-rw-r--r--support/texlab/src/features/completion/types.rs8
-rw-r--r--support/texlab/src/features/completion/user_environment.rs21
-rw-r--r--support/texlab/src/features/cursor.rs110
-rw-r--r--support/texlab/src/features/definition/entry.rs12
-rw-r--r--support/texlab/src/features/definition/label.rs13
-rw-r--r--support/texlab/src/features/formatting.rs6
-rw-r--r--support/texlab/src/features/formatting/bibtex_internal.rs2
-rw-r--r--support/texlab/src/features/formatting/latexindent.rs96
-rw-r--r--support/texlab/src/features/highlight.rs7
-rw-r--r--support/texlab/src/features/highlight/label.rs61
-rw-r--r--support/texlab/src/features/hover/label.rs4
-rw-r--r--support/texlab/src/features/reference/entry.rs10
-rw-r--r--support/texlab/src/features/reference/label.rs2
-rw-r--r--support/texlab/src/features/rename/entry.rs35
-rw-r--r--support/texlab/src/features/rename/label.rs37
-rw-r--r--support/texlab/src/features/symbol/bibtex.rs4
-rw-r--r--support/texlab/src/features/symbol/latex.rs22
-rw-r--r--support/texlab/src/label.rs13
-rw-r--r--support/texlab/src/line_index.rs2
-rw-r--r--support/texlab/src/line_index_ext.rs2
-rw-r--r--support/texlab/src/options.rs28
-rw-r--r--support/texlab/src/syntax/bibtex/cst.rs36
-rw-r--r--support/texlab/src/syntax/bibtex/kind.rs1
-rw-r--r--support/texlab/src/syntax/bibtex/parser.rs14
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_complete_parens.snap3
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields.snap3
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields_missing_comma.snap3
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field.snap3
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_number_key.snap3
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_trailing_comma.snap3
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields.snap3
-rw-r--r--support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields_incomplete.snap3
-rw-r--r--support/texlab/src/syntax/latex/analysis/environment.rs2
-rw-r--r--support/texlab/src/syntax/latex/analysis/explicit_link.rs20
-rw-r--r--support/texlab/src/syntax/latex/analysis/label_name.rs24
-rw-r--r--support/texlab/src/syntax/latex/analysis/label_number.rs2
-rw-r--r--support/texlab/src/syntax/latex/analysis/theorem.rs2
-rw-r--r--support/texlab/src/syntax/latex/analysis/types.rs6
-rw-r--r--support/texlab/src/syntax/latex/cst.rs52
-rw-r--r--support/texlab/src/syntax/latex/parser.rs108
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acronym_declaration.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__bibtex_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_figure.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_missing_brace.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_multiple_keys.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote_postnote.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_redundant_comma.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_star.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_definition_simple.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_reference_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error1.snap15
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error2.snap9
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error3.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_simple.snap18
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested.snap12
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested_missing_braces.snap31
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_simple.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_label_reference_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_begin.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_end.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_definition_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_incomplete.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_simple.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_number.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_multiple.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_error.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_incomplete.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_simple.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_multiple.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__pgf_library_import_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_enum_item.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_options.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_full.snap9
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_counter.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description_and_counter.snap6
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_only_name.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__tikz_library_import_simple.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__verbatim_include_simple.snap3
-rw-r--r--support/texlab/tests/integration/completion.rs34
-rw-r--r--support/texlab/tests/integration/snapshots/integration__completion__latex__citation_multi_word.snap34
-rw-r--r--support/texlab/texlab.pdfbin84894 -> 26161 bytes
-rw-r--r--support/texlab/texlab.tex78
130 files changed, 1120 insertions, 645 deletions
diff --git a/support/TeX4ht/source/tex4ht-html4.tex b/support/TeX4ht/source/tex4ht-html4.tex
index 5e542e34f2..9bf0a4bcab 100644
--- a/support/TeX4ht/source/tex4ht-html4.tex
+++ b/support/TeX4ht/source/tex4ht-html4.tex
@@ -1,4 +1,4 @@
-% $Id: tex4ht-html4.tex 938 2021-05-17 09:38:57Z michal_h21 $
+% $Id: tex4ht-html4.tex 944 2021-06-03 09:29:05Z michal_h21 $
% Compile 4 times: latex tex4ht-html4
% Copy html4.4ht into the work directory before all but the last compilation.
%
@@ -2810,6 +2810,10 @@ such a case, we don't have proper nestings of environments.
li p\string ~ol:last-child{ margin-bottom:0.5em; }}
>>>
+\<list par\><<<
+\par\ShowPar
+>>>
+
\<configure html4 latex\><<<
\ConfigureEnv{trivlist}
{}{|<try env inline par|>}{}{}
@@ -2819,7 +2823,7 @@ such a case, we don't have proper nestings of environments.
{|<recall end:itm|>\EndP\HCode{</dd></dl>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</dd>}\HCode{<dt
class="trivlist">}\bgroup \bf}
- {\egroup\HCode{</dt><dd\Hnewline class="trivlist">}}
+ {\egroup\HCode{</dt><dd\Hnewline class="trivlist">}|<list par|>}
\ConfigureEnv{list}
{}{|<try env inline par|>}{}{}
\ConfigureList{list}%
@@ -2842,7 +2846,7 @@ such a case, we don't have proper nestings of environments.
{|<recall end:itm|>\ifvmode \IgnorePar\fi
\EndP\HCode{</li></ul>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</li>}\DeleteMark}
- {\HCode{<li class="\getClass{li}itemize">}\afterGetClass{li}}
+ {\HCode{<li class="\getClass{li}itemize">}\afterGetClass{li}|<list par|>}
\NewConfigure{itemizeClass}{2}
\Configure{itemizeClass}{}{}
\NewConfigure{liClass}{2}
@@ -2895,7 +2899,7 @@ such a case, we don't have proper nestings of environments.
\EndP\HCode{</dd></dl>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</dd>}\HCode{<dt
class="enumerate">}\bgroup \bf}
- {\egroup\EndP\HCode{</dt><dd\Hnewline class="enumerate">}}
+ {\egroup\EndP\HCode{</dt><dd\Hnewline class="enumerate">}|<list par|>}
\Css{dd.enumerate {margin-left: 2em;}}
\Css{dt.enumerate {float:left;
clear:left;
@@ -2950,7 +2954,7 @@ such a case, we don't have proper nestings of environments.
\<enumerate IV\><<<
\HCode{<li class="enumerate" value="\expandafter\the\csname
- c@enum\romannumeral\the\@enumdepth\endcsname"\Hnewline>}\AnchorLabel
+ c@enum\romannumeral\the\@enumdepth\endcsname"\Hnewline>}|<list par|>\AnchorLabel
>>>
@@ -2959,7 +2963,7 @@ such a case, we don't have proper nestings of environments.
\<enumerate IV-\><<<
{\Configure{Link}{li}{}{ class="enumerate" id=}{}%
- \let\EndLink=\empty \AnchorLabel }%
+ \let\EndLink=\empty|<list par|>\AnchorLabel }%
>>>
@@ -3029,7 +3033,7 @@ to the following text.
|<save end:itm|>\global\let\end:itm=\empty}
{|<recall end:itm|>\EndP\HCode{</li></ul>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</li>}\DeleteMark}
- {\HCode{<li class="itemize">}}
+ {\HCode{<li class="itemize">}|<list par|>}
>>>
\<prosper lists\><<<
@@ -3047,7 +3051,7 @@ to the following text.
{}
{\end:itm \global\def\end:itm{\EndP\Tg</li>}\DeleteMark}
{\HCode{<li class="itemize\ifnum
- \c@item@step>\c@overlaysCount -hide\fi">}}
+ \c@item@step>\c@overlaysCount -hide\fi">}|<list par|>}
\Css{li.itemize-hide {visibility:hidden;}}
>>>
@@ -3088,8 +3092,8 @@ to the following text.
|<save end:itm|>\global\let\end:itm=\empty}
{|<recall end:itm|>\EndP\HCode{</dd></dl>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</dd>}\HCode{<dt
- class="description">}\bgroup \bf}
- {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}}
+ class="description">}\bgroup |<list par|>\bf}
+ {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}|<list par|>}
>>>
\<32,4 report,book\><<<
@@ -3149,7 +3153,7 @@ Latex allows groups like the following, so we need global \verb+\end:itm+
|<save end:itm|>\global\let\end:itm=\empty}
{|<recall end:itm|>\EndP\HCode{</li></ul>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</li>}\DeleteMark}
- {\HCode{<li class="itemize">}}
+ {\HCode{<li class="itemize">}|<list par|>}
\ConfigureEnv{enumerate*}
{}{|<try env inline par|>}{}{}
\ConfigureList{enumerate*}%
@@ -3163,7 +3167,7 @@ Latex allows groups like the following, so we need global \verb+\end:itm+
{|<recall end:itm|>\EndP\HCode{</dd></dl>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</dd>}\HCode{<dt
class="description">}\bgroup \bf}
- {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}}
+ {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}|<list par|>}
\ConfigureList{basedescript}
{\EndP\HCode{<dl \a:LRdir class="basedescript">}%
\PushMacro\end:itm \global\let\end:itm=\empty}
@@ -10052,7 +10056,7 @@ need to change early the catcodes of `\verb'_' and `\verb'^'.
\EndP\HCode{</li></ul>}\ShowPar
}
{\end:itm \gdef\end:itm{\EndP\Tg</li>}\DeleteMark}
- {\HCode{<li class="itemize">}\AnchorLabel }
+ {\HCode{<li class="itemize">}|<list par|>\AnchorLabel }
>>>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -11058,7 +11062,7 @@ a \par b
\EndP\HCode{</dd></dl>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</dd>}\HCode{<dt
class="description">}\bgroup \bf}
- {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}}
+ {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}|<list par|>}
|<quote config|>
\ConfigureEnv{verse}
@@ -11469,19 +11473,19 @@ a \par b
{\IgnorePar\EndP\HCode{<ol\space class="enumerate"\Hnewline>}}
{\IgnorePar\EndP\HCode{</li></ol>}\ShowPar}
{\IgnorePar\EndP\ifnum \itemno>1 \Tg</li>\fi\DeleteMark}
- {\HCode{<li class="enumerate">}}
+ {\HCode{<li class="enumerate">}|<list par|>}
\Configure{itemize}
{\IgnorePar\EndP\HCode{<ul\space\a:LRdir class="itemize"\Hnewline>}}
{\IgnorePar\EndP\HCode{</li></ul>}\ShowPar}
{\IgnorePar\EndP\ifnum \itemno>1 \Tg</li>\fi\DeleteMark}
- {\HCode{<li class="itemize">}}
+ {\HCode{<li class="itemize">}|<list par|>}
\Configure{table}%
{\IgnorePar\EndP\HCode{<dl \a:LRdir class="description">}%
|<save end:itm|>\global\let\end:itm|=\empty}
{|<recall end:itm|>\IgnorePar\EndP\HCode{</dd></dl>}}
{\IgnorePar\end:itm \global\def\end:itm{\EndP\Tg</dd>}\HCode{<dt
class="description">}\bgroup \bf}
- {\egroup\IgnorePar\EndP\HCode{</dt><dd\Hnewline class="description">}}
+ {\egroup\IgnorePar\EndP\HCode{</dt><dd\Hnewline class="description">}|<list par|>}
>>>
\<configure html4 texinfo\><<<
@@ -14078,7 +14082,7 @@ supported formats by tex4ht.
\EndP\HCode{</li></ul>}\ShowPar
|<end pause region|>}
{\end:itm \global\def\end:itm{\EndP\Tg</li>}\DeleteMark}
- {\HCode{<li class="itemize">}}
+ {\HCode{<li class="itemize">}|<list par|>}
>>>
\<configure html4 powerdot\><<<
@@ -14107,7 +14111,7 @@ supported formats by tex4ht.
|<end pause region|>}
{\end:itm \global\def\end:itm{\EndP\Tg</dd>}\HCode{<dt
class="description">}\bgroup \bf}
- {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}}
+ {\egroup\EndP\HCode{</dt><dd\Hnewline class="description">}|<list par|>}
>>>
diff --git a/support/texlab/CHANGELOG.md b/support/texlab/CHANGELOG.md
index df4134084d..885fa24bc5 100644
--- a/support/texlab/CHANGELOG.md
+++ b/support/texlab/CHANGELOG.md
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [3.1.0] - 03.06.2021
+
+### Added
+
+- Add `texlab.latexFormatter` setting to allow turning off `latexindent`.
+ At the moment, `texlab.latexFormatter: texlab` is not implemented yet and does nothing.
+- Expose the `--local` flag of `latexindent` via `texlab.latexindent.local` setting ([#365](https://github.com/latex-lsp/texlab/issues/365))
+- Expose the `--modfiylinebreaks` flag of `latexindent` via `texlab.latexindent.modifyLineBreaks` setting ([#365](https://github.com/latex-lsp/texlab/issues/365))
+- Assign (unique) error codes to static analysis diagnostics.
+
+### Fixed
+
+- Avoid creating defunct `latexindent` processes which clear out the document ([#437](https://github.com/latex-lsp/texlab/issues/437))
+- Allow whitespace in LaTeX identifiers like labels ([#433](https://github.com/latex-lsp/texlab/issues/433))
+- Run CI on Ubuntu 18.04 to allow an older `glibc` version ([#439](https://github.com/latex-lsp/texlab/issues/439)).
+
+### Fixed
+
## [3.0.1] - 22.05.2021
### Fixed
diff --git a/support/texlab/Cargo.lock b/support/texlab/Cargo.lock
index c224bce2d3..8ae7d7e49d 100644
--- a/support/texlab/Cargo.lock
+++ b/support/texlab/Cargo.lock
@@ -605,20 +605,10 @@ dependencies = [
]
[[package]]
-name = "fsevent"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97f347202c95c98805c216f9e1df210e8ebaec9fdb2365700a43c10797a35e63"
-dependencies = [
- "bitflags",
- "fsevent-sys",
-]
-
-[[package]]
name = "fsevent-sys"
-version = "3.1.0"
+version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca6f5e6817058771c10f0eb0f05ddf1e35844266f972004fe8e4b21fda295bd5"
+checksum = "5c0e564d24da983c053beff1bb7178e237501206840a3e6bf4e267b9e8ae734a"
dependencies = [
"libc",
]
@@ -999,9 +989,9 @@ dependencies = [
[[package]]
name = "lsp-types"
-version = "0.89.0"
+version = "0.89.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07731ecd4ee0654728359a5b95e2a254c857876c04b85225496a35d60345daa7"
+checksum = "48b8a871b0a450bcec0e26d74a59583c8173cb9fb7d7f98889e18abb84838e0f"
dependencies = [
"bitflags",
"serde",
@@ -1154,14 +1144,13 @@ dependencies = [
[[package]]
name = "notify"
-version = "5.0.0-pre.8"
+version = "5.0.0-pre.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46bbbcd078f1f00ddb7a9abe70b96e91229b44b0b3afdec610f8e5137f8f014b"
+checksum = "b89869d77edd64db917d7903abeadc166f93686b342c56cc0ca51acb68441d09"
dependencies = [
"bitflags",
"crossbeam-channel 0.5.1",
"filetime",
- "fsevent",
"fsevent-sys",
"inotify",
"libc",
@@ -1697,9 +1686,9 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.5.0"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
+checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg 1.0.1",
"crossbeam-deque 0.8.0",
@@ -1709,9 +1698,9 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.9.0"
+version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
+checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
dependencies = [
"crossbeam-channel 0.5.1",
"crossbeam-deque 0.8.0",
@@ -2167,7 +2156,7 @@ dependencies = [
[[package]]
name = "texlab"
-version = "3.0.1"
+version = "3.1.0"
dependencies = [
"anyhow",
"bibutils-sys",
diff --git a/support/texlab/Cargo.toml b/support/texlab/Cargo.toml
index 56317c7f9c..506b454b4a 100644
--- a/support/texlab/Cargo.toml
+++ b/support/texlab/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "texlab"
description = "LaTeX Language Server"
-version = "3.0.1"
+version = "3.1.0"
license = "GPL-3.0"
readme = "README.md"
authors = [
@@ -17,7 +17,17 @@ doctest = false
[features]
default = ["citation", "completion"]
completion = ["fuzzy-matcher"]
-citation = ["bibutils-sys", "citeproc", "citeproc-db", "citeproc-io", "csl", "fnv", "html2md", "lalrpop-util", "lalrpop"]
+citation = [
+ "bibutils-sys",
+ "citeproc",
+ "citeproc-db",
+ "citeproc-io",
+ "csl",
+ "fnv",
+ "html2md",
+ "lalrpop-util",
+ "lalrpop",
+]
semantic = []
[dependencies]
@@ -45,12 +55,12 @@ lalrpop-util = { version = "0.19.5", optional = true }
log = "0.4.14"
logos = "0.12.0"
lsp-server = "0.5"
-lsp-types = "0.89.0"
+lsp-types = "0.89.1"
multimap = "0.8.3"
-notify = "5.0.0-pre.8"
+notify = "5.0.0-pre.9"
once_cell = "1.7.2"
petgraph = "0.5.1"
-rayon = "1.5.0"
+rayon = "1.5.1"
regex = "1.5.4"
rustc-hash = "1.1.0"
serde = "1.0.126"
@@ -73,4 +83,4 @@ unindent = "0.1.7"
lalrpop = { version = "0.19.5", features = ["lexer"], optional = true }
[profile.release]
-lto = true \ No newline at end of file
+lto = true
diff --git a/support/texlab/README.md b/support/texlab/README.md
index b2edc3f2b4..57351b677b 100644
--- a/support/texlab/README.md
+++ b/support/texlab/README.md
@@ -1,7 +1,6 @@
[![CI](https://github.com/latex-lsp/texlab/workflows/CI/badge.svg)](https://github.com/latex-lsp/texlab/actions)
[![Coverage](https://codecov.io/gh/latex-lsp/texlab/branch/master/graph/badge.svg)](https://codecov.io/gh/latex-lsp/texlab)
-[![Rust](https://img.shields.io/badge/rustc-1.39%2B-blue)](https://blog.rust-lang.org/2019/11/07/Rust-1.39.0.html)
-[![Dependabot](https://api.dependabot.com/badges/status?host=github&repo=latex-lsp/texlab)](https://dependabot.com)
+[![Rust](https://img.shields.io/badge/rustc-1.51%2B-blue)](https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html)
[![GitHub release](https://img.shields.io/github/release/latex-lsp/texlab?label=github)](https://github.com/latex-lsp/texlab/releases)
[![CTAN](https://img.shields.io/ctan/v/texlab)](https://ctan.org/pkg/texlab)
@@ -41,7 +40,7 @@ On Windows, you may need to install [Microsoft Visual C++ Redistributable for Vi
You will need to install the following dependencies to compile the server:
-- A recent, stable version of [Rust](https://rustup.rs/)
+- A recent, stable version of [Rust](https://rustup.rs/) (>= 1.51)
Then run the following command in the project folder:
diff --git a/support/texlab/docs/options.md b/support/texlab/docs/options.md
index 9cabd31062..3cc2edfd8a 100644
--- a/support/texlab/docs/options.md
+++ b/support/texlab/docs/options.md
@@ -143,3 +143,39 @@ Possible values are either `texlab` or `latexindent`.
**Type:** `string`
**Default value:** `texlab`
+
+---
+
+## texlab.latexFormatter
+
+Defines the formatter to use for LaTeX formatting.
+Possible values are either `texlab` or `latexindent`.
+Note that `texlab` is not implemented yet.
+
+**Type:** `string`
+
+**Default value:** `latexindent`
+
+---
+
+## texlab.latexindent.local
+
+Defines the path of a file containing the `latexindent` configuration.
+This corresponds to the `--local=file.yaml` flag of `latexindent`.
+By default the configuration inside the project root directory is used.
+
+**Type:** `string`
+
+**Default value:** `null`
+
+---
+
+## texlab.latexindent.modifyLineBreaks
+
+Modifies linebreaks before, during, and at the end of code blocks
+when formatting with `latexindent`.
+This corresponds to the `--modifylinebreaks` flag of `latexindent`.
+
+**Type:** `boolean`
+
+**Default value:** `false`
diff --git a/support/texlab/src/citation.rs b/support/texlab/src/citation.rs
index e185c14b55..daa4b60997 100644
--- a/support/texlab/src/citation.rs
+++ b/support/texlab/src/citation.rs
@@ -67,7 +67,7 @@ fn convert_to_ris(root: &bibtex::SyntaxNode, key: &str) -> Option<RisReference>
let entry = root
.children()
.filter_map(bibtex::Entry::cast)
- .find(|entry| entry.key().map(|key| key.text()) == Some(key))?;
+ .find(|entry| entry.key().map(|key| key.to_string()).as_deref() == Some(key))?;
bib_code.push_str(&entry.syntax().to_string());
bib_code = bib_code.replace("\\hypen", "-");
diff --git a/support/texlab/src/diagnostics/bibtex.rs b/support/texlab/src/diagnostics/bibtex.rs
index efea141db0..d90bde0c8d 100644
--- a/support/texlab/src/diagnostics/bibtex.rs
+++ b/support/texlab/src/diagnostics/bibtex.rs
@@ -1,7 +1,7 @@
use std::sync::Arc;
use cstree::TextRange;
-use lsp_types::{Diagnostic, DiagnosticSeverity};
+use lsp_types::{Diagnostic, DiagnosticSeverity, NumberOrString};
use multimap::MultiMap;
use crate::{
@@ -42,7 +42,7 @@ fn analyze_entry(
.line_index
.line_col_lsp_range(entry.ty()?.text_range()),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(4)),
code_description: None,
source: Some("texlab".to_string()),
message: "Expecting a curly bracket: \"{\"".to_string(),
@@ -62,7 +62,7 @@ fn analyze_entry(
.line_index
.line_col_lsp_range(entry.left_delimiter()?.text_range()),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(5)),
code_description: None,
source: Some("texlab".to_string()),
message: "Expecting a key".to_string(),
@@ -82,7 +82,7 @@ fn analyze_entry(
.line_index
.line_col_lsp_range(entry.right_delimiter()?.text_range()),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(6)),
code_description: None,
source: Some("texlab".to_string()),
message: "Expecting a curly bracket: \"}\"".to_string(),
@@ -111,7 +111,7 @@ fn analyze_field(
.line_index
.line_col_lsp_range(TextRange::empty(field.name()?.text_range().end())),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(7)),
code_description: None,
source: Some("texlab".to_string()),
message: "Expecting an equality sign: \"=\"".to_string(),
@@ -131,7 +131,7 @@ fn analyze_field(
field.equality_sign()?.text_range().end(),
)),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(8)),
code_description: None,
source: Some("texlab".to_string()),
message: "Expecting a field value".to_string(),
diff --git a/support/texlab/src/diagnostics/latex.rs b/support/texlab/src/diagnostics/latex.rs
index b835f88398..012e9b399f 100644
--- a/support/texlab/src/diagnostics/latex.rs
+++ b/support/texlab/src/diagnostics/latex.rs
@@ -1,7 +1,7 @@
use std::sync::Arc;
use cstree::TextRange;
-use lsp_types::{Diagnostic, DiagnosticSeverity};
+use lsp_types::{Diagnostic, DiagnosticSeverity, NumberOrString};
use multimap::MultiMap;
use crate::{
@@ -31,7 +31,7 @@ pub fn analyze_latex_static(
Diagnostic {
range: document.line_index.line_col_lsp_range(node.text_range()),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(1)),
code_description: None,
source: Some("texlab".to_string()),
message: "Unexpected \"}\"".to_string(),
@@ -56,15 +56,15 @@ fn analyze_environment(
node: &latex::SyntaxNode,
) -> Option<()> {
let environment = latex::Environment::cast(node)?;
- let name1 = environment.begin()?.name()?.word()?;
- let name2 = environment.end()?.name()?.word()?;
- if name1.text() != name2.text() {
+ let name1 = environment.begin()?.name()?.key()?;
+ let name2 = environment.end()?.name()?.key()?;
+ if name1 != name2 {
diagnostics_by_uri.insert(
Arc::clone(&document.uri),
Diagnostic {
- range: document.line_index.line_col_lsp_range(name1.text_range()),
+ range: document.line_index.line_col_lsp_range(name1.small_range()),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(3)),
code_description: None,
source: Some("texlab".to_string()),
message: "Mismatched environment".to_string(),
@@ -98,8 +98,10 @@ fn analyze_curly_group(
.filter_map(latex::Environment::cast)
.filter_map(|env| env.begin())
.filter_map(|begin| begin.name())
- .filter_map(|name| name.word())
- .any(|name| ["asy", "lstlisting", "minted", "verbatim"].contains(&name.text()));
+ .filter_map(|name| name.key())
+ .any(|name| {
+ ["asy", "lstlisting", "minted", "verbatim"].contains(&name.to_string().as_str())
+ });
if !is_inside_verbatim_environment
&& !node
@@ -114,7 +116,7 @@ fn analyze_curly_group(
.line_index
.line_col_lsp_range(TextRange::empty(node.text_range().end())),
severity: Some(DiagnosticSeverity::Error),
- code: None,
+ code: Some(NumberOrString::Number(2)),
code_description: None,
source: Some("texlab".to_string()),
message: "Missing \"}\" inserted".to_string(),
diff --git a/support/texlab/src/features/completion.rs b/support/texlab/src/features/completion.rs
index 13c7aad22b..29559bd808 100644
--- a/support/texlab/src/features/completion.rs
+++ b/support/texlab/src/features/completion.rs
@@ -19,6 +19,8 @@ mod user_command;
mod user_environment;
mod util;
+use std::borrow::Cow;
+
use cancellation::CancellationToken;
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
use lsp_types::{
@@ -144,15 +146,29 @@ fn dedup(items: Vec<InternalCompletionItem>) -> Vec<InternalCompletionItem> {
}
fn score(context: &CursorContext<CompletionParams>, items: &mut Vec<InternalCompletionItem>) {
- let pattern = match &context.cursor {
- Cursor::Latex(token) if token.kind().is_command_name() => token.text().trim_end(),
- Cursor::Latex(token) if token.kind() == latex::WORD => token.text(),
- Cursor::Latex(_) => "",
- Cursor::Bibtex(token) if token.kind().is_type() => token.text(),
- Cursor::Bibtex(token) if token.kind() == bibtex::WORD => token.text(),
- Cursor::Bibtex(token) if token.kind() == bibtex::COMMAND_NAME => token.text().trim_end(),
- Cursor::Bibtex(_) => "",
- Cursor::Nothing => "",
+ let pattern: Cow<str> = match &context.cursor {
+ Cursor::Latex(token) if token.kind().is_command_name() => token.text().trim_end().into(),
+ Cursor::Latex(token) if token.kind() == latex::WORD => {
+ if let Some(key) = latex::Key::cast(token.parent()) {
+ key.to_string().into()
+ } else {
+ token.text().into()
+ }
+ }
+ Cursor::Latex(_) => "".into(),
+ Cursor::Bibtex(token) if token.kind().is_type() => token.text().into(),
+ Cursor::Bibtex(token) if token.kind() == bibtex::WORD => {
+ if let Some(key) = bibtex::Key::cast(token.parent()) {
+ key.to_string().into()
+ } else {
+ token.text().into()
+ }
+ }
+ Cursor::Bibtex(token) if token.kind() == bibtex::COMMAND_NAME => {
+ token.text().trim_end().into()
+ }
+ Cursor::Bibtex(_) => "".into(),
+ Cursor::Nothing => "".into(),
};
let file_pattern = pattern.split('/').last().unwrap();
@@ -211,7 +227,7 @@ fn preselect(
let group = latex::CurlyGroupWord::cast(name.parent())?;
let end = latex::End::cast(group.syntax().parent()?)?;
let environment = latex::Environment::cast(end.syntax().parent()?)?;
- let name = environment.begin()?.name()?.word()?.text();
+ let name = environment.begin()?.name()?.key()?.to_string();
for item in items {
if item.data.label() == name {
diff --git a/support/texlab/src/features/completion/acronym_ref.rs b/support/texlab/src/features/completion/acronym_ref.rs
index 9d8bcc6c5f..db3e34f9eb 100644
--- a/support/texlab/src/features/completion/acronym_ref.rs
+++ b/support/texlab/src/features/completion/acronym_ref.rs
@@ -1,5 +1,4 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
use crate::{
@@ -16,18 +15,9 @@ pub fn complete_acronyms<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let group = latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
-
+ let (_, range, group) = context.find_curly_group_word()?;
latex::AcronymReference::cast(group.syntax().parent()?)?;
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
-
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_latex() {
for name in data
@@ -35,8 +25,8 @@ pub fn complete_acronyms<'a>(
.descendants()
.filter_map(latex::AcronymDefinition::cast)
.filter_map(|node| node.name())
- .filter_map(|name| name.word())
- .map(|name| name.text())
+ .filter_map(|name| name.key())
+ .map(|name| name.to_string())
{
items.push(InternalCompletionItem::new(
range,
diff --git a/support/texlab/src/features/completion/citation.rs b/support/texlab/src/features/completion/citation.rs
index 6df3364099..0a7cc26b10 100644
--- a/support/texlab/src/features/completion/citation.rs
+++ b/support/texlab/src/features/completion/citation.rs
@@ -26,12 +26,14 @@ pub fn complete_citations<'a>(
let token = context.cursor.as_latex()?;
let range = if token.kind() == latex::WORD {
- token.text_range()
+ latex::Key::cast(token.parent())
+ .map(|key| key.small_range())
+ .or_else(|| latex::Text::cast(token.parent()).map(|text| text.small_range()))?
} else {
TextRange::empty(context.offset)
};
- check_citation(context, token).or_else(|| check_acronym(token))?;
+ check_citation(context).or_else(|| check_acronym(context))?;
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_bibtex() {
for entry in data.root.children().filter_map(bibtex::Entry::cast) {
@@ -46,20 +48,17 @@ pub fn complete_citations<'a>(
Some(())
}
-fn check_citation(
- context: &CursorContext<CompletionParams>,
- token: &latex::SyntaxToken,
-) -> Option<()> {
- let group = latex::CurlyGroupWordList::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
+fn check_citation(context: &CursorContext<CompletionParams>) -> Option<()> {
+ let (_, _, group) = context.find_curly_group_word_list()?;
latex::Citation::cast(group.syntax().parent()?)?;
Some(())
}
-fn check_acronym(token: &latex::SyntaxToken) -> Option<()> {
+fn check_acronym(context: &CursorContext<CompletionParams>) -> Option<()> {
+ let token = context.cursor.as_latex()?;
+
let pair = token.ancestors().find_map(latex::KeyValuePair::cast)?;
- let mut key_words = pair.key()?.words();
- if key_words.next()?.text() != "cite" || key_words.next().is_some() {
+ if pair.key()?.to_string() != "cite" {
return None;
}
@@ -72,7 +71,7 @@ fn make_item<'a>(
entry: bibtex::Entry<'a>,
range: TextRange,
) -> Option<InternalCompletionItem<'a>> {
- let key = entry.key()?.text();
+ let key = entry.key()?.to_string();
let ty = LANGUAGE_DATA
.find_entry_type(&entry.ty()?.text()[1..])
.map(|ty| Structure::Entry(ty.category))
@@ -98,7 +97,7 @@ fn make_item<'a>(
range,
InternalCompletionItemData::Citation {
uri: Arc::clone(&document.uri),
- key: key.into(),
+ key,
text,
ty,
},
@@ -171,6 +170,29 @@ mod tests {
}
#[test]
+ fn test_latex_two_words() {
+ let request = FeatureTester::builder()
+ .files(vec![
+ ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"),
+ ("main.bib", "@article{foo bar,}"),
+ ])
+ .main("main.tex")
+ .line(1)
+ .character(6)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_citations(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(32.into(), 35.into()));
+ }
+ }
+
+ #[test]
fn test_latex_open_brace() {
let request = FeatureTester::builder()
.files(vec![
@@ -241,4 +263,30 @@ mod tests {
assert_eq!(item.range, TextRange::new(54.into(), 54.into()));
}
}
+
+ #[test]
+ fn test_latex_acronym_two_words() {
+ let request = FeatureTester::builder()
+ .files(vec![
+ (
+ "main.tex",
+ "\\addbibresource{main.bib}\n\\DeclareAcronym{foo}{cite={\na b}}",
+ ),
+ ("main.bib", "@article{foo,}"),
+ ])
+ .main("main.tex")
+ .line(2)
+ .character(0)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_citations(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(54.into(), 57.into()));
+ }
+ }
}
diff --git a/support/texlab/src/features/completion/color.rs b/support/texlab/src/features/completion/color.rs
index 0e94af15fe..15a7c341f5 100644
--- a/support/texlab/src/features/completion/color.rs
+++ b/support/texlab/src/features/completion/color.rs
@@ -1,5 +1,4 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
use crate::{
@@ -17,15 +16,7 @@ pub fn complete_colors<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
-
- let group = latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
+ let (_, range, group) = context.find_curly_group_word()?;
latex::ColorReference::cast(group.syntax().parent()?)?;
for name in &LANGUAGE_DATA.colors {
diff --git a/support/texlab/src/features/completion/color_model.rs b/support/texlab/src/features/completion/color_model.rs
index f7f09b6367..a24953caa5 100644
--- a/support/texlab/src/features/completion/color_model.rs
+++ b/support/texlab/src/features/completion/color_model.rs
@@ -18,15 +18,7 @@ pub fn complete_color_models<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
-
- check_color_definition(context, token)
- .or_else(|| check_color_definition_set(context, token))?;
+ let range = check_color_definition(context).or_else(|| check_color_definition_set(context))?;
for name in MODEL_NAMES {
items.push(InternalCompletionItem::new(
@@ -38,30 +30,23 @@ pub fn complete_color_models<'a>(
Some(())
}
-fn check_color_definition(
- context: &CursorContext<CompletionParams>,
- token: &latex::SyntaxToken,
-) -> Option<()> {
- let group = latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
+fn check_color_definition(context: &CursorContext<CompletionParams>) -> Option<TextRange> {
+ let (_, range, group) = context.find_curly_group_word()?;
+
let definition = latex::ColorDefinition::cast(group.syntax().parent()?)?;
definition
.model()
.filter(|model| model.syntax().text_range() == group.syntax().text_range())?;
- Some(())
+ Some(range)
}
-fn check_color_definition_set(
- context: &CursorContext<CompletionParams>,
- token: &latex::SyntaxToken,
-) -> Option<()> {
- let group = latex::CurlyGroupWordList::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
+fn check_color_definition_set(context: &CursorContext<CompletionParams>) -> Option<TextRange> {
+ let (_, range, group) = context.find_curly_group_word_list()?;
let definition = latex::ColorSetDefinition::cast(group.syntax().parent()?)?;
definition
.model_list()
.filter(|model| model.syntax().text_range() == group.syntax().text_range())?;
- Some(())
+ Some(range)
}
#[cfg(test)]
diff --git a/support/texlab/src/features/completion/component_environment.rs b/support/texlab/src/features/completion/component_environment.rs
index fca9d03780..d4340a160a 100644
--- a/support/texlab/src/features/completion/component_environment.rs
+++ b/support/texlab/src/features/completion/component_environment.rs
@@ -1,12 +1,7 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
-use crate::{
- component_db::COMPONENT_DATABASE,
- features::cursor::CursorContext,
- syntax::{latex, CstNode},
-};
+use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext};
use super::types::{InternalCompletionItem, InternalCompletionItemData};
@@ -17,18 +12,7 @@ pub fn complete_component_environments<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let group = latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
- if !matches!(group.syntax().parent()?.kind(), latex::BEGIN | latex::END) {
- return None;
- }
-
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
+ let (_, range) = context.find_environment_name()?;
for component in COMPONENT_DATABASE.linked_components(&context.request.subset) {
cancellation_token.result().ok()?;
diff --git a/support/texlab/src/features/completion/field.rs b/support/texlab/src/features/completion/field.rs
index d7297b481b..ad1042b04d 100644
--- a/support/texlab/src/features/completion/field.rs
+++ b/support/texlab/src/features/completion/field.rs
@@ -26,7 +26,7 @@ pub fn complete_fields<'a>(
let parent = token.parent();
if let Some(entry) = bibtex::Entry::cast(parent) {
- if entry.key()?.text_range() == token.text_range() {
+ if entry.key()?.small_range() == token.text_range() {
return None;
}
} else {
diff --git a/support/texlab/src/features/completion/glossary_ref.rs b/support/texlab/src/features/completion/glossary_ref.rs
index 4529129fd7..66d20e46ff 100644
--- a/support/texlab/src/features/completion/glossary_ref.rs
+++ b/support/texlab/src/features/completion/glossary_ref.rs
@@ -1,5 +1,4 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
use crate::{
@@ -16,15 +15,8 @@ pub fn complete_glossary_entries<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let group = latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
+ let (_, range, group) = context.find_curly_group_word()?;
latex::GlossaryEntryReference::cast(group.syntax().parent()?)?;
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_latex() {
@@ -33,8 +25,8 @@ pub fn complete_glossary_entries<'a>(
if let Some(name) = latex::GlossaryEntryDefinition::cast(node)
.and_then(|entry| entry.name())
- .and_then(|name| name.word())
- .map(|name| name.text())
+ .and_then(|name| name.key())
+ .map(|name| name.to_string())
{
items.push(InternalCompletionItem::new(
range,
@@ -42,8 +34,8 @@ pub fn complete_glossary_entries<'a>(
));
} else if let Some(name) = latex::AcronymDefinition::cast(node)
.and_then(|entry| entry.name())
- .and_then(|name| name.word())
- .map(|name| name.text())
+ .and_then(|name| name.key())
+ .map(|name| name.to_string())
{
items.push(InternalCompletionItem::new(
range,
diff --git a/support/texlab/src/features/completion/import.rs b/support/texlab/src/features/completion/import.rs
index ac5f2e6e40..da4c12c02b 100644
--- a/support/texlab/src/features/completion/import.rs
+++ b/support/texlab/src/features/completion/import.rs
@@ -1,5 +1,4 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
use rustc_hash::FxHashSet;
use smol_str::SmolStr;
@@ -17,15 +16,7 @@ pub fn complete_imports<'a>(
items: &mut Vec<InternalCompletionItem<'a>>,
cancellation_token: &CancellationToken,
) -> Option<()> {
- let token = context.cursor.as_latex()?;
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
-
- let group = latex::CurlyGroupWordList::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
+ let (_, range, group) = context.find_curly_group_word_list()?;
let (extension, mut factory): (
&str,
@@ -76,6 +67,8 @@ pub fn complete_imports<'a>(
#[cfg(test)]
mod tests {
+ use cstree::TextRange;
+
use crate::features::testing::FeatureTester;
use super::*;
diff --git a/support/texlab/src/features/completion/include.rs b/support/texlab/src/features/completion/include.rs
index c711ea5ce7..4a8e561866 100644
--- a/support/texlab/src/features/completion/include.rs
+++ b/support/texlab/src/features/completion/include.rs
@@ -25,15 +25,8 @@ pub fn complete_includes<'a>(
return None;
}
- let token = context.cursor.as_latex()?;
- let (path_text, path_range) = if token.kind() == latex::WORD {
- (token.text(), token.text_range())
- } else {
- ("", TextRange::empty(context.offset))
- };
+ let (path_text, path_range, group) = context.find_curly_group_word_list()?;
- let group = latex::CurlyGroupWordList::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
let include = group.syntax().parent()?;
let (include_extension, extensions): (bool, &[&str]) = match include.kind() {
latex::PACKAGE_INCLUDE => (false, &["sty"]),
@@ -62,7 +55,7 @@ pub fn complete_includes<'a>(
TextRange::new(start, path_range.end())
};
- let current_dir = current_dir(context, path_text)?;
+ let current_dir = current_dir(context, &path_text)?;
for entry in fs::read_dir(current_dir).ok()?.filter_map(Result::ok) {
let mut path = entry.path();
diff --git a/support/texlab/src/features/completion/label.rs b/support/texlab/src/features/completion/label.rs
index 2f7e2d8f77..3efb168d0d 100644
--- a/support/texlab/src/features/completion/label.rs
+++ b/support/texlab/src/features/completion/label.rs
@@ -18,26 +18,7 @@ pub fn complete_labels<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let is_math = latex::CurlyGroupWordList::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))
- .and_then(|group| group.syntax().parent())
- .and_then(|reference| latex::LabelReference::cast(reference))
- .and_then(|refernce| refernce.command())
- .map(|reference| reference.text() == "\\eqref")
- .or_else(|| {
- latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))
- .and_then(|group| group.syntax().parent())
- .and_then(|reference| latex::LabelReferenceRange::cast(reference))
- .map(|_| false)
- })?;
-
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
+ let (range, is_math) = find_reference(context).or_else(|| find_reference_range(context))?;
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_latex() {
@@ -49,10 +30,10 @@ pub fn complete_labels<'a>(
{
if let Some(name) = label
.name()
- .and_then(|name| name.word())
- .map(|name| name.text())
+ .and_then(|name| name.key())
+ .map(|name| name.to_string())
{
- match render_label(&context.request.subset, name, Some(label)) {
+ match render_label(&context.request.subset, &name, Some(label)) {
Some(rendered_label) => {
let kind = match &rendered_label.object {
LabelledObject::Section { .. } => Structure::Section,
@@ -112,6 +93,19 @@ pub fn complete_labels<'a>(
Some(())
}
+fn find_reference(context: &CursorContext<CompletionParams>) -> Option<(TextRange, bool)> {
+ let (_, range, group) = context.find_curly_group_word_list()?;
+ let reference = latex::LabelReference::cast(group.syntax().parent()?)?;
+ let is_math = reference.command()?.text() == "\\eqref";
+ Some((range, is_math))
+}
+
+fn find_reference_range(context: &CursorContext<CompletionParams>) -> Option<(TextRange, bool)> {
+ let (_, range, group) = context.find_curly_group_word()?;
+ latex::LabelReferenceRange::cast(group.syntax().parent()?)?;
+ Some((range, false))
+}
+
#[cfg(test)]
mod tests {
use cstree::TextRange;
@@ -193,4 +187,24 @@ mod tests {
assert_eq!(item.range, TextRange::new(11.into(), 11.into()));
}
}
+
+ #[test]
+ fn test_multi_word() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", "\\ref{foo}\\label{foo bar}")])
+ .main("main.tex")
+ .line(0)
+ .character(8)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_labels(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(5.into(), 8.into()));
+ }
+ }
}
diff --git a/support/texlab/src/features/completion/theorem.rs b/support/texlab/src/features/completion/theorem.rs
index 54db031a4b..25eea87ab7 100644
--- a/support/texlab/src/features/completion/theorem.rs
+++ b/support/texlab/src/features/completion/theorem.rs
@@ -1,11 +1,7 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
-use crate::{
- features::cursor::CursorContext,
- syntax::{latex, CstNode},
-};
+use crate::features::cursor::CursorContext;
use super::types::{InternalCompletionItem, InternalCompletionItemData};
@@ -18,18 +14,7 @@ pub fn complete_theorem_environments<'a>(
return None;
}
- let token = context.cursor.as_latex()?;
- let group = latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
- if !matches!(group.syntax().parent()?.kind(), latex::BEGIN | latex::END) {
- return None;
- }
-
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
+ let (_, range) = context.find_environment_name()?;
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_latex() {
@@ -49,6 +34,8 @@ pub fn complete_theorem_environments<'a>(
#[cfg(test)]
mod tests {
+ use cstree::TextRange;
+
use crate::features::testing::FeatureTester;
use super::*;
diff --git a/support/texlab/src/features/completion/tikz_library.rs b/support/texlab/src/features/completion/tikz_library.rs
index da2a26cc9b..b9c5e3ec7a 100644
--- a/support/texlab/src/features/completion/tikz_library.rs
+++ b/support/texlab/src/features/completion/tikz_library.rs
@@ -1,5 +1,4 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
use crate::{
@@ -17,15 +16,8 @@ pub fn complete_tikz_libraries<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
+ let (_, range, group) = context.find_curly_group_word_list()?;
- let group = latex::CurlyGroupWordList::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
let import = latex::TikzLibraryImport::cast(group.syntax().parent()?)?;
if import.command()?.text() == "\\usepgflibrary" {
@@ -49,6 +41,8 @@ pub fn complete_tikz_libraries<'a>(
#[cfg(test)]
mod tests {
+ use cstree::TextRange;
+
use crate::features::testing::FeatureTester;
use super::*;
diff --git a/support/texlab/src/features/completion/types.rs b/support/texlab/src/features/completion/types.rs
index b58a155fc4..b7e5c09592 100644
--- a/support/texlab/src/features/completion/types.rs
+++ b/support/texlab/src/features/completion/types.rs
@@ -40,7 +40,7 @@ pub enum InternalCompletionItemData<'a> {
BeginCommand,
Citation {
uri: Arc<Uri>,
- key: &'a str,
+ key: String,
text: String,
ty: Structure,
},
@@ -67,10 +67,10 @@ pub enum InternalCompletionItemData<'a> {
name: &'a str,
},
Acronym {
- name: &'a str,
+ name: String,
},
GlossaryEntry {
- name: &'a str,
+ name: String,
},
File {
name: SmolStr,
@@ -79,7 +79,7 @@ pub enum InternalCompletionItemData<'a> {
name: SmolStr,
},
Label {
- name: &'a str,
+ name: String,
kind: Structure,
header: Option<String>,
footer: Option<String>,
diff --git a/support/texlab/src/features/completion/user_environment.rs b/support/texlab/src/features/completion/user_environment.rs
index a1a5701fac..5529143adc 100644
--- a/support/texlab/src/features/completion/user_environment.rs
+++ b/support/texlab/src/features/completion/user_environment.rs
@@ -1,11 +1,7 @@
use cancellation::CancellationToken;
-use cstree::TextRange;
use lsp_types::CompletionParams;
-use crate::{
- features::cursor::CursorContext,
- syntax::{latex, CstNode},
-};
+use crate::features::cursor::CursorContext;
use super::types::{InternalCompletionItem, InternalCompletionItemData};
@@ -16,18 +12,7 @@ pub fn complete_user_environments<'a>(
) -> Option<()> {
cancellation_token.result().ok()?;
- let token = context.cursor.as_latex()?;
- let group = latex::CurlyGroupWord::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
- if !matches!(group.syntax().parent()?.kind(), latex::BEGIN | latex::END) {
- return None;
- }
-
- let range = if token.kind() == latex::WORD {
- token.text_range()
- } else {
- TextRange::empty(context.offset)
- };
+ let (name, range) = context.find_environment_name()?;
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_latex() {
@@ -35,7 +20,7 @@ pub fn complete_user_environments<'a>(
.extras
.environment_names
.iter()
- .filter(|name| name.as_str() != token.text())
+ .filter(|n| n.as_str() != name)
{
cancellation_token.result().ok()?;
items.push(InternalCompletionItem::new(
diff --git a/support/texlab/src/features/cursor.rs b/support/texlab/src/features/cursor.rs
index 19079b841b..6e8719987a 100644
--- a/support/texlab/src/features/cursor.rs
+++ b/support/texlab/src/features/cursor.rs
@@ -1,7 +1,7 @@
use cstree::{TextRange, TextSize};
use lsp_types::{
- CompletionParams, GotoDefinitionParams, HoverParams, Position, ReferenceParams, RenameParams,
- TextDocumentPositionParams,
+ CompletionParams, DocumentHighlightParams, GotoDefinitionParams, HoverParams, Position,
+ ReferenceParams, RenameParams, TextDocumentPositionParams,
};
use crate::{
@@ -42,6 +42,14 @@ impl Cursor {
return Some(Self::Latex(right));
}
+ if left.kind() == latex::WHITESPACE && left.parent().kind() == latex::KEY {
+ return Some(Self::Latex(left));
+ }
+
+ if right.kind() == latex::WHITESPACE && right.parent().kind() == latex::KEY {
+ return Some(Self::Latex(right));
+ }
+
Some(Self::Latex(right))
}
@@ -149,66 +157,116 @@ impl<P: HasPosition> CursorContext<P> {
group.small_range().contains(self.offset) || group.right_curly().is_none()
}
- pub fn find_citation_key_word(&self) -> Option<(&str, TextRange)> {
- let key = self
+ pub fn find_citation_key_word(&self) -> Option<(String, TextRange)> {
+ let word = self
.cursor
.as_latex()
.filter(|token| token.kind() == latex::WORD)?;
- let group = latex::CurlyGroupWordList::cast(key.parent())?;
+ let key = latex::Key::cast(word.parent())?;
+
+ let group = latex::CurlyGroupWordList::cast(key.syntax().parent()?)?;
latex::Citation::cast(group.syntax().parent()?)?;
- Some((key.text(), key.text_range()))
+ Some((key.to_string(), key.small_range()))
}
- pub fn find_citation_key_command(&self) -> Option<(&str, TextRange)> {
+ pub fn find_citation_key_command(&self) -> Option<(String, TextRange)> {
let command = self.cursor.as_latex()?;
let citation = latex::Citation::cast(command.parent())?;
- let key = citation.key_list()?.words().next()?;
- Some((key.text(), key.text_range()))
+ let key = citation.key_list()?.keys().next()?;
+ Some((key.to_string(), key.small_range()))
}
- pub fn find_entry_key(&self) -> Option<(&str, TextRange)> {
- let key = self
+ pub fn find_entry_key(&self) -> Option<(String, TextRange)> {
+ let word = self
.cursor
.as_bibtex()
.filter(|token| token.kind() == bibtex::WORD)?;
- bibtex::Entry::cast(key.parent())?;
- Some((key.text(), key.text_range()))
+ let key = bibtex::Key::cast(word.parent())?;
+
+ bibtex::Entry::cast(key.syntax().parent()?)?;
+ Some((key.to_string(), key.small_range()))
}
- pub fn find_label_name_word(&self) -> Option<(&str, TextRange)> {
+ pub fn find_label_name_key(&self) -> Option<(String, TextRange)> {
let name = self
.cursor
.as_latex()
.filter(|token| token.kind() == latex::WORD)?;
+ let key = latex::Key::cast(name.parent())?;
+
if matches!(
- name.parent().parent()?.kind(),
+ key.syntax().parent()?.parent()?.kind(),
latex::LABEL_DEFINITION | latex::LABEL_REFERENCE | latex::LABEL_REFERENCE_RANGE
) {
- Some((name.text(), name.text_range()))
+ Some((key.to_string(), key.small_range()))
} else {
None
}
}
- pub fn find_label_name_command(&self) -> Option<(&str, TextRange)> {
+ pub fn find_label_name_command(&self) -> Option<(String, TextRange)> {
let node = self.cursor.as_latex()?.parent();
if let Some(label) = latex::LabelDefinition::cast(node) {
- let name = label.name()?.word()?;
- Some((name.text(), name.text_range()))
+ let name = label.name()?.key()?;
+ Some((name.to_string(), name.small_range()))
} else if let Some(label) = latex::LabelReference::cast(node) {
- let name = label.name_list()?.words().next()?;
- Some((name.text(), name.text_range()))
+ let name = label.name_list()?.keys().next()?;
+ Some((name.to_string(), name.small_range()))
} else if let Some(label) = latex::LabelReferenceRange::cast(node) {
- let name = label.from()?.word()?;
- Some((name.text(), name.text_range()))
+ let name = label.from()?.key()?;
+ Some((name.to_string(), name.small_range()))
} else {
None
}
}
+
+ pub fn find_environment_name(&self) -> Option<(String, TextRange)> {
+ let (name, range, group) = self.find_curly_group_word()?;
+
+ if !matches!(group.syntax().parent()?.kind(), latex::BEGIN | latex::END) {
+ return None;
+ }
+
+ Some((name, range))
+ }
+
+ pub fn find_curly_group_word(&self) -> Option<(String, TextRange, latex::CurlyGroupWord)> {
+ let token = self.cursor.as_latex()?;
+ let key = latex::Key::cast(token.parent());
+
+ let group = key
+ .as_ref()
+ .and_then(|key| key.syntax().parent())
+ .unwrap_or(token.parent());
+
+ let group =
+ latex::CurlyGroupWord::cast(group).filter(|group| self.is_inside_latex_curly(group))?;
+
+ key.map(|key| (key.to_string(), key.small_range(), group))
+ .or_else(|| Some((String::new(), TextRange::empty(self.offset), group)))
+ }
+
+ pub fn find_curly_group_word_list(
+ &self,
+ ) -> Option<(String, TextRange, latex::CurlyGroupWordList)> {
+ let token = self.cursor.as_latex()?;
+ let key = latex::Key::cast(token.parent());
+
+ let group = key
+ .as_ref()
+ .and_then(|key| key.syntax().parent())
+ .unwrap_or(token.parent());
+
+ let group = latex::CurlyGroupWordList::cast(group)
+ .filter(|group| self.is_inside_latex_curly(group))?;
+
+ key.map(|key| (key.to_string(), key.small_range(), group))
+ .or_else(|| Some((String::new(), TextRange::empty(self.offset), group)))
+ }
}
pub trait HasPosition {
@@ -250,3 +308,9 @@ impl HasPosition for GotoDefinitionParams {
self.text_document_position_params.position
}
}
+
+impl HasPosition for DocumentHighlightParams {
+ fn position(&self) -> Position {
+ self.text_document_position_params.position
+ }
+}
diff --git a/support/texlab/src/features/definition/entry.rs b/support/texlab/src/features/definition/entry.rs
index 7f489ec848..b04490dc32 100644
--- a/support/texlab/src/features/definition/entry.rs
+++ b/support/texlab/src/features/definition/entry.rs
@@ -13,29 +13,31 @@ pub fn goto_entry_definition(
) -> Option<Vec<LocationLink>> {
let main_document = context.request.main_document();
- let key = context
+ let word = context
.cursor
.as_latex()
.filter(|token| token.kind() == latex::WORD)?;
- latex::Citation::cast(key.parent().parent()?)?;
+ let key = latex::Key::cast(word.parent())?;
+
+ latex::Citation::cast(key.syntax().parent()?.parent()?)?;
let origin_selection_range = main_document
.line_index
- .line_col_lsp_range(key.text_range());
+ .line_col_lsp_range(key.small_range());
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_bibtex() {
for entry in data.root.children().filter_map(bibtex::Entry::cast) {
cancellation_token.result().ok()?;
- if let Some(key) = entry.key().filter(|k| k.text() == key.text()) {
+ if let Some(key) = entry.key().filter(|k| k.to_string() == key.to_string()) {
return Some(vec![LocationLink {
origin_selection_range: Some(origin_selection_range),
target_uri: document.uri.as_ref().clone().into(),
target_selection_range: document
.line_index
- .line_col_lsp_range(key.text_range()),
+ .line_col_lsp_range(key.small_range()),
target_range: document.line_index.line_col_lsp_range(entry.small_range()),
}]);
}
diff --git a/support/texlab/src/features/definition/label.rs b/support/texlab/src/features/definition/label.rs
index 65f0981de0..fd30b1fbc5 100644
--- a/support/texlab/src/features/definition/label.rs
+++ b/support/texlab/src/features/definition/label.rs
@@ -1,7 +1,10 @@
use cancellation::CancellationToken;
use lsp_types::{GotoDefinitionParams, LocationLink};
-use crate::{features::cursor::CursorContext, find_label_definition, render_label, LineIndexExt};
+use crate::{
+ features::cursor::CursorContext, find_label_definition, render_label, syntax::CstNode,
+ LineIndexExt,
+};
pub fn goto_label_definition(
context: &CursorContext<GotoDefinitionParams>,
@@ -10,7 +13,7 @@ pub fn goto_label_definition(
let main_document = context.request.main_document();
let (name_text, name_range) = context
- .find_label_name_word()
+ .find_label_name_key()
.or_else(|| context.find_label_name_command())?;
let origin_selection_range = main_document.line_index.line_col_lsp_range(name_range);
@@ -18,10 +21,10 @@ pub fn goto_label_definition(
for document in &context.request.subset.documents {
cancellation_token.result().ok()?;
if let Some(data) = document.data.as_latex() {
- if let Some(definition) = find_label_definition(&data.root, name_text) {
- let target_selection_range = definition.name()?.word()?.text_range();
+ if let Some(definition) = find_label_definition(&data.root, &name_text) {
+ let target_selection_range = definition.name()?.key()?.small_range();
let target_range =
- render_label(&context.request.subset, name_text, Some(definition))
+ render_label(&context.request.subset, &name_text, Some(definition))
.map(|label| label.range)
.unwrap_or(target_selection_range);
diff --git a/support/texlab/src/features/formatting.rs b/support/texlab/src/features/formatting.rs
index 4492a0532d..c7c2dc410a 100644
--- a/support/texlab/src/features/formatting.rs
+++ b/support/texlab/src/features/formatting.rs
@@ -4,7 +4,7 @@ mod latexindent;
use cancellation::CancellationToken;
use lsp_types::{DocumentFormattingParams, TextEdit};
-use crate::BibtexFormatter;
+use crate::{BibtexFormatter, LatexFormatter};
use self::{bibtex_internal::format_bibtex_internal, latexindent::format_with_latexindent};
@@ -19,6 +19,10 @@ pub fn format_source_code(
edits = edits.or_else(|| format_bibtex_internal(&request, cancellation_token));
}
+ if request.context.options.read().unwrap().latex_formatter == LatexFormatter::Texlab {
+ edits = edits.or_else(|| Some(vec![]));
+ }
+
edits = edits.or_else(|| format_with_latexindent(&request, cancellation_token));
edits
}
diff --git a/support/texlab/src/features/formatting/bibtex_internal.rs b/support/texlab/src/features/formatting/bibtex_internal.rs
index 8481f561e7..641bee0cfe 100644
--- a/support/texlab/src/features/formatting/bibtex_internal.rs
+++ b/support/texlab/src/features/formatting/bibtex_internal.rs
@@ -148,7 +148,7 @@ impl<'a> Formatter<'a> {
self.visit_token_lowercase(entry.ty().unwrap());
self.output.push('{');
if let Some(key) = entry.key() {
- self.output.push_str(key.text());
+ self.output.push_str(&key.to_string());
self.output.push(',');
self.output.push('\n');
for field in entry.fields() {
diff --git a/support/texlab/src/features/formatting/latexindent.rs b/support/texlab/src/features/formatting/latexindent.rs
index f603728a5d..300f512578 100644
--- a/support/texlab/src/features/formatting/latexindent.rs
+++ b/support/texlab/src/features/formatting/latexindent.rs
@@ -1,50 +1,98 @@
use std::{
- io::{BufWriter, Write},
+ fs,
process::{Command, Stdio},
};
use cancellation::CancellationToken;
use cstree::{TextLen, TextRange};
use lsp_types::{DocumentFormattingParams, TextEdit};
+use tempfile::tempdir;
-use crate::{features::FeatureRequest, LineIndexExt};
+use crate::{features::FeatureRequest, DocumentLanguage, LineIndexExt};
pub fn format_with_latexindent(
request: &FeatureRequest<DocumentFormattingParams>,
_cancellation_token: &CancellationToken,
) -> Option<Vec<TextEdit>> {
+ let directory = tempdir().ok()?;
let document = request.main_document();
- let current_dir = &request.context.current_directory;
let options = request.context.options.read().unwrap();
- let current_dir = match &options.root_directory {
- Some(root_directory) => current_dir.join(root_directory),
- None => current_dir.clone(),
+ let current_dir = options
+ .root_directory
+ .as_ref()
+ .cloned()
+ .or_else(|| {
+ if document.uri.scheme() == "file" {
+ document
+ .uri
+ .to_file_path()
+ .unwrap()
+ .parent()
+ .map(ToOwned::to_owned)
+ } else {
+ None
+ }
+ })
+ .unwrap_or_else(|| ".".into());
+
+ let local = match &options.latexindent.local {
+ Some(local) => format!("--local={}", local),
+ None => "-l".to_string(),
};
+
+ let modify_line_breaks = options.latexindent.modify_line_breaks;
+
drop(options);
- let mut process = Command::new("latexindent")
- .arg("-l")
+ let path = directory.path();
+ let _ = fs::copy(
+ current_dir.join("localSettings.yaml"),
+ path.join("localSettings.yaml"),
+ );
+ let _ = fs::copy(
+ current_dir.join(".localSettings.yaml"),
+ path.join(".localSettings.yaml"),
+ );
+ let _ = fs::copy(
+ current_dir.join("latexindent.yaml"),
+ path.join("latexindent.yaml"),
+ );
+
+ let name = if document.language() == DocumentLanguage::Bibtex {
+ "file.bib"
+ } else {
+ "file.tex"
+ };
+
+ fs::write(directory.path().join(name), &document.text).ok()?;
+
+ let mut args = Vec::new();
+ if modify_line_breaks {
+ args.push("--modifylinebreaks");
+ }
+ args.push(&local);
+ args.push(name);
+
+ let output = Command::new("latexindent")
+ .args(&args)
.current_dir(current_dir)
- .stdin(Stdio::piped())
+ .stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::null())
- .spawn()
+ .current_dir(directory.path())
+ .output()
.ok()?;
- let stdin = process.stdin.take()?;
- let mut stdin = BufWriter::new(stdin);
- stdin.write_all(document.text.as_bytes()).ok()?;
- drop(stdin);
-
- let output = process.wait_with_output().ok()?;
-
let new_text = String::from_utf8_lossy(&output.stdout).into_owned();
-
- Some(vec![TextEdit {
- range: document
- .line_index
- .line_col_lsp_range(TextRange::new(0.into(), document.text.text_len())),
- new_text,
- }])
+ if new_text.is_empty() {
+ None
+ } else {
+ Some(vec![TextEdit {
+ range: document
+ .line_index
+ .line_col_lsp_range(TextRange::new(0.into(), document.text.text_len())),
+ new_text,
+ }])
+ }
}
diff --git a/support/texlab/src/features/highlight.rs b/support/texlab/src/features/highlight.rs
index e1aea6e2ad..386018f353 100644
--- a/support/texlab/src/features/highlight.rs
+++ b/support/texlab/src/features/highlight.rs
@@ -5,11 +5,12 @@ use lsp_types::{DocumentHighlight, DocumentHighlightParams};
use self::label::find_label_highlights;
-use super::FeatureRequest;
+use super::{cursor::CursorContext, FeatureRequest};
pub fn find_document_highlights(
request: FeatureRequest<DocumentHighlightParams>,
- token: &CancellationToken,
+ cancellation_token: &CancellationToken,
) -> Option<Vec<DocumentHighlight>> {
- find_label_highlights(&request, token)
+ let context = CursorContext::new(request);
+ find_label_highlights(&context, cancellation_token)
}
diff --git a/support/texlab/src/features/highlight/label.rs b/support/texlab/src/features/highlight/label.rs
index 4c94180f2a..9694993033 100644
--- a/support/texlab/src/features/highlight/label.rs
+++ b/support/texlab/src/features/highlight/label.rs
@@ -2,48 +2,32 @@ use cancellation::CancellationToken;
use lsp_types::{DocumentHighlight, DocumentHighlightKind, DocumentHighlightParams};
use crate::{
- features::FeatureRequest,
+ features::cursor::CursorContext,
syntax::{latex, CstNode},
LineIndexExt,
};
pub fn find_label_highlights(
- request: &FeatureRequest<DocumentHighlightParams>,
- token: &CancellationToken,
+ context: &CursorContext<DocumentHighlightParams>,
+ cancellation_token: &CancellationToken,
) -> Option<Vec<DocumentHighlight>> {
- let main_document = request.main_document();
-
- let offset = main_document
- .line_index
- .offset_lsp(request.params.text_document_position_params.position);
+ let (name_text, _) = context.find_label_name_key()?;
+ let main_document = context.request.main_document();
let data = main_document.data.as_latex()?;
- let name = data.root.token_at_offset(offset).right_biased()?;
- if name.kind() != latex::WORD {
- return None;
- }
-
- if !matches!(
- name.parent().parent()?.kind(),
- latex::LABEL_DEFINITION | latex::LABEL_REFERENCE | latex::LABEL_REFERENCE_RANGE
- ) {
- return None;
- }
let mut highlights = Vec::new();
for node in data.root.descendants() {
- if token.is_canceled() {
- return None;
- }
+ cancellation_token.result().ok()?;
if let Some(label_name) = latex::LabelDefinition::cast(node)
.and_then(|label| label.name())
- .and_then(|label_name| label_name.word())
- .filter(|label_name| label_name.text() == name.text())
+ .and_then(|label_name| label_name.key())
+ .filter(|label_name| label_name.to_string() == name_text)
{
let range = main_document
.line_index
- .line_col_lsp_range(label_name.text_range());
+ .line_col_lsp_range(label_name.small_range());
highlights.push(DocumentHighlight {
range,
@@ -53,12 +37,12 @@ pub fn find_label_highlights(
for label_name in label
.name_list()
.into_iter()
- .flat_map(|name| name.words())
- .filter(|label_name| label_name.text() == name.text())
+ .flat_map(|name| name.keys())
+ .filter(|label_name| label_name.to_string() == name_text)
{
let range = main_document
.line_index
- .line_col_lsp_range(label_name.text_range());
+ .line_col_lsp_range(label_name.small_range());
highlights.push(DocumentHighlight {
range,
@@ -68,12 +52,12 @@ pub fn find_label_highlights(
} else if let Some(label) = latex::LabelReferenceRange::cast(node) {
if let Some(label_name) = label
.from()
- .and_then(|label_name| label_name.word())
- .filter(|label_name| label_name.text() == name.text())
+ .and_then(|label_name| label_name.key())
+ .filter(|label_name| label_name.to_string() == name_text)
{
let range = main_document
.line_index
- .line_col_lsp_range(label_name.text_range());
+ .line_col_lsp_range(label_name.small_range());
highlights.push(DocumentHighlight {
range,
@@ -83,12 +67,12 @@ pub fn find_label_highlights(
if let Some(label_name) = label
.to()
- .and_then(|label_name| label_name.word())
- .filter(|label_name| label_name.text() == name.text())
+ .and_then(|label_name| label_name.key())
+ .filter(|label_name| label_name.to_string() == name_text)
{
let range = main_document
.line_index
- .line_col_lsp_range(label_name.text_range());
+ .line_col_lsp_range(label_name.small_range());
highlights.push(DocumentHighlight {
range,
@@ -118,8 +102,9 @@ mod tests {
.character(0)
.build()
.highlight();
+ let context = CursorContext::new(request);
- let actual_links = find_label_highlights(&request, CancellationToken::none());
+ let actual_links = find_label_highlights(&context, CancellationToken::none());
assert!(actual_links.is_none());
}
@@ -133,8 +118,9 @@ mod tests {
.character(0)
.build()
.highlight();
+ let context = CursorContext::new(request);
- let actual_links = find_label_highlights(&request, CancellationToken::none());
+ let actual_links = find_label_highlights(&context, CancellationToken::none());
assert!(actual_links.is_none());
}
@@ -148,8 +134,9 @@ mod tests {
.character(7)
.build();
let request = tester.highlight();
+ let context = CursorContext::new(request);
- let actual_highlights = find_label_highlights(&request, CancellationToken::none()).unwrap();
+ let actual_highlights = find_label_highlights(&context, CancellationToken::none()).unwrap();
let expected_highlights = vec![
DocumentHighlight {
diff --git a/support/texlab/src/features/hover/label.rs b/support/texlab/src/features/hover/label.rs
index 79afe7d250..26477feb7c 100644
--- a/support/texlab/src/features/hover/label.rs
+++ b/support/texlab/src/features/hover/label.rs
@@ -10,10 +10,10 @@ pub fn find_label_hover(
let main_document = context.request.main_document();
let (name_text, name_range) = context
- .find_label_name_word()
+ .find_label_name_key()
.or_else(|| context.find_label_name_command())?;
- let label = render_label(&context.request.subset, name_text, None)?;
+ let label = render_label(&context.request.subset, &name_text, None)?;
Some(Hover {
range: Some(main_document.line_index.line_col_lsp_range(name_range)),
diff --git a/support/texlab/src/features/reference/entry.rs b/support/texlab/src/features/reference/entry.rs
index fbbcbdb4cc..a9e15ba5b6 100644
--- a/support/texlab/src/features/reference/entry.rs
+++ b/support/texlab/src/features/reference/entry.rs
@@ -26,9 +26,9 @@ pub fn find_entry_references(
.descendants()
.filter_map(latex::Citation::cast)
.filter_map(|citation| citation.key_list())
- .flat_map(|keys| keys.words())
- .filter(|key| key.text() == key_text)
- .map(|key| document.line_index.line_col_lsp_range(key.text_range()))
+ .flat_map(|keys| keys.keys())
+ .filter(|key| key.to_string() == key_text)
+ .map(|key| document.line_index.line_col_lsp_range(key.small_range()))
.for_each(|range| {
references.push(Location::new(document.uri.as_ref().clone().into(), range));
});
@@ -38,8 +38,8 @@ pub fn find_entry_references(
.children()
.filter_map(bibtex::Entry::cast)
.filter_map(|entry| entry.key())
- .filter(|key| key.text() == key_text)
- .map(|key| document.line_index.line_col_lsp_range(key.text_range()))
+ .filter(|key| key.to_string() == key_text)
+ .map(|key| document.line_index.line_col_lsp_range(key.small_range()))
.for_each(|range| {
references.push(Location::new(document.uri.as_ref().clone().into(), range));
});
diff --git a/support/texlab/src/features/reference/label.rs b/support/texlab/src/features/reference/label.rs
index e9aa3a8510..45c6b90137 100644
--- a/support/texlab/src/features/reference/label.rs
+++ b/support/texlab/src/features/reference/label.rs
@@ -11,7 +11,7 @@ pub fn find_label_references(
cancellation_token.result().ok()?;
let (name_text, _) = context
- .find_label_name_word()
+ .find_label_name_key()
.or_else(|| context.find_label_name_command())?;
for document in &context.request.subset.documents {
diff --git a/support/texlab/src/features/rename/entry.rs b/support/texlab/src/features/rename/entry.rs
index 14fbfd42d7..35a77d926e 100644
--- a/support/texlab/src/features/rename/entry.rs
+++ b/support/texlab/src/features/rename/entry.rs
@@ -4,7 +4,7 @@ use cancellation::CancellationToken;
use lsp_types::{Range, RenameParams, TextEdit, WorkspaceEdit};
use crate::{
- features::cursor::{Cursor, CursorContext, HasPosition},
+ features::cursor::{CursorContext, HasPosition},
syntax::{bibtex, latex, CstNode},
DocumentData, LineIndexExt,
};
@@ -13,18 +13,9 @@ pub fn prepare_entry_rename<P: HasPosition>(
context: &CursorContext<P>,
_cancellation_token: &CancellationToken,
) -> Option<Range> {
- let range = match &context.cursor {
- Cursor::Latex(token) if token.kind() == latex::WORD => {
- let group = latex::CurlyGroupWordList::cast(token.parent())?;
- latex::Citation::cast(group.syntax().parent()?)?;
- token.text_range()
- }
- Cursor::Bibtex(token) if token.kind() == bibtex::WORD => {
- bibtex::Entry::cast(token.parent())?;
- token.text_range()
- }
- _ => return None,
- };
+ let (_, range) = context
+ .find_citation_key_word()
+ .or_else(|| context.find_entry_key())?;
Some(
context
@@ -41,11 +32,9 @@ pub fn rename_entry(
) -> Option<WorkspaceEdit> {
cancellation_token.result().ok()?;
prepare_entry_rename(context, cancellation_token)?;
- let key_text = context
- .cursor
- .as_latex()
- .map(|token| token.text())
- .or_else(|| context.cursor.as_bibtex().map(|token| token.text()))?;
+ let (key_text, _) = context
+ .find_citation_key_word()
+ .or_else(|| context.find_entry_key())?;
let mut changes = HashMap::new();
for document in &context.request.subset.documents {
@@ -57,9 +46,9 @@ pub fn rename_entry(
.descendants()
.filter_map(latex::Citation::cast)
.filter_map(|citation| citation.key_list())
- .flat_map(|keys| keys.words())
- .filter(|key| key.text() == key_text)
- .map(|key| document.line_index.line_col_lsp_range(key.text_range()))
+ .flat_map(|keys| keys.keys())
+ .filter(|key| key.to_string() == key_text)
+ .map(|key| document.line_index.line_col_lsp_range(key.small_range()))
.map(|range| TextEdit::new(range, context.request.params.new_name.clone()))
.collect();
changes.insert(document.uri.as_ref().clone().into(), edits);
@@ -70,8 +59,8 @@ pub fn rename_entry(
.descendants()
.filter_map(bibtex::Entry::cast)
.filter_map(|entry| entry.key())
- .filter(|key| key.text() == key_text)
- .map(|key| document.line_index.line_col_lsp_range(key.text_range()))
+ .filter(|key| key.to_string() == key_text)
+ .map(|key| document.line_index.line_col_lsp_range(key.small_range()))
.map(|range| TextEdit::new(range, context.request.params.new_name.clone()))
.collect();
changes.insert(document.uri.as_ref().clone().into(), edits);
diff --git a/support/texlab/src/features/rename/label.rs b/support/texlab/src/features/rename/label.rs
index 11b414ccfa..a73a0064bf 100644
--- a/support/texlab/src/features/rename/label.rs
+++ b/support/texlab/src/features/rename/label.rs
@@ -13,20 +13,14 @@ pub fn prepare_label_rename<P: HasPosition>(
context: &CursorContext<P>,
_cancellation_token: &CancellationToken,
) -> Option<Range> {
- let name = context.cursor.as_latex()?;
- name.parent().parent().filter(|node| {
- matches!(
- node.kind(),
- latex::LABEL_DEFINITION | latex::LABEL_REFERENCE | latex::LABEL_REFERENCE_RANGE
- )
- })?;
+ let (_, range) = context.find_label_name_key()?;
Some(
context
.request
.main_document()
.line_index
- .line_col_lsp_range(name.text_range()),
+ .line_col_lsp_range(range),
)
}
@@ -35,7 +29,8 @@ pub fn rename_label(
cancellation_token: &CancellationToken,
) -> Option<WorkspaceEdit> {
prepare_label_rename(context, cancellation_token)?;
- let name_text = context.cursor.as_latex()?.text();
+ let (name_text, _) = context.find_label_name_key()?;
+
let mut changes = HashMap::new();
for document in &context.request.subset.documents {
cancellation_token.result().ok()?;
@@ -44,9 +39,9 @@ pub fn rename_label(
for node in data.root.descendants() {
if let Some(range) = latex::LabelDefinition::cast(node)
.and_then(|label| label.name())
- .and_then(|name| name.word())
- .filter(|name| name.text() == name_text)
- .map(|name| document.line_index.line_col_lsp_range(name.text_range()))
+ .and_then(|name| name.key())
+ .filter(|name| name.to_string() == name_text)
+ .map(|name| document.line_index.line_col_lsp_range(name.small_range()))
{
edits.push(TextEdit::new(
range,
@@ -57,9 +52,9 @@ pub fn rename_label(
latex::LabelReference::cast(node)
.and_then(|label| label.name_list())
.into_iter()
- .flat_map(|label| label.words())
- .filter(|name| name.text() == name_text)
- .map(|name| document.line_index.line_col_lsp_range(name.text_range()))
+ .flat_map(|label| label.keys())
+ .filter(|name| name.to_string() == name_text)
+ .map(|name| document.line_index.line_col_lsp_range(name.small_range()))
.for_each(|range| {
edits.push(TextEdit::new(
range,
@@ -70,22 +65,22 @@ pub fn rename_label(
if let Some(label) = latex::LabelReferenceRange::cast(node) {
if let Some(name1) = label
.from()
- .and_then(|name| name.word())
- .filter(|name| name.text() == name_text)
+ .and_then(|name| name.key())
+ .filter(|name| name.to_string() == name_text)
{
edits.push(TextEdit::new(
- document.line_index.line_col_lsp_range(name1.text_range()),
+ document.line_index.line_col_lsp_range(name1.small_range()),
context.request.params.new_name.clone(),
));
}
if let Some(name2) = label
.from()
- .and_then(|name| name.word())
- .filter(|name| name.text() == name_text)
+ .and_then(|name| name.key())
+ .filter(|name| name.to_string() == name_text)
{
edits.push(TextEdit::new(
- document.line_index.line_col_lsp_range(name2.text_range()),
+ document.line_index.line_col_lsp_range(name2.small_range()),
context.request.params.new_name.clone(),
));
}
diff --git a/support/texlab/src/features/symbol/bibtex.rs b/support/texlab/src/features/symbol/bibtex.rs
index e030195880..db555a7176 100644
--- a/support/texlab/src/features/symbol/bibtex.rs
+++ b/support/texlab/src/features/symbol/bibtex.rs
@@ -68,7 +68,7 @@ pub fn find_bibtex_symbols(
.unwrap_or(BibtexEntryTypeCategory::Misc);
buf.push(InternalSymbol {
- name: key.text().to_string(),
+ name: key.to_string(),
label: None,
kind: InternalSymbolKind::Entry(category),
deprecated: false,
@@ -77,7 +77,7 @@ pub fn find_bibtex_symbols(
.line_col_lsp_range(entry.small_range()),
selection_range: main_document
.line_index
- .line_col_lsp_range(key.text_range()),
+ .line_col_lsp_range(key.small_range()),
children,
});
}
diff --git a/support/texlab/src/features/symbol/latex.rs b/support/texlab/src/features/symbol/latex.rs
index ce584c0c76..ec549c87fe 100644
--- a/support/texlab/src/features/symbol/latex.rs
+++ b/support/texlab/src/features/symbol/latex.rs
@@ -59,25 +59,25 @@ fn visit(context: &mut Context, node: &latex::SyntaxNode) -> Vec<InternalSymbol>
latex::ENVIRONMENT => latex::Environment::cast(node)
.and_then(|env| env.begin())
.and_then(|begin| begin.name())
- .and_then(|name| name.word())
- .map(|name| name.text())
+ .and_then(|name| name.key())
+ .map(|name| name.to_string())
.and_then(|name| {
if LANGUAGE_DATA
.math_environments
.iter()
- .any(|env| env == name)
+ .any(|env| env == &name)
{
visit_equation_environment(context, node)
} else if LANGUAGE_DATA
.enum_environments
.iter()
- .any(|env| env == name)
+ .any(|env| env == &name)
{
- visit_enumeration(context, node, name)
- } else if let Ok(float_kind) = LabelledFloatKind::from_str(name) {
+ visit_enumeration(context, node, &name)
+ } else if let Ok(float_kind) = LabelledFloatKind::from_str(&name) {
visit_float(context, node, float_kind)
} else {
- visit_theorem(context, node, name)
+ visit_theorem(context, node, &name)
}
}),
_ => None,
@@ -161,12 +161,12 @@ fn visit_enum_item(context: &mut Context, node: &latex::SyntaxNode) -> Option<In
.filter_map(latex::Environment::cast)
.filter_map(|environment| environment.begin())
.filter_map(|begin| begin.name())
- .filter_map(|name| name.word())
+ .filter_map(|name| name.key())
.any(|name| {
LANGUAGE_DATA
.enum_environments
.iter()
- .any(|e| e == name.text())
+ .any(|e| e == &name.to_string())
})
{
return None;
@@ -471,7 +471,7 @@ fn find_label_by_parent(
) -> Option<NumberedLabel> {
let node = parent.children().find_map(latex::LabelDefinition::cast)?;
- let name = node.name()?.word()?.text();
+ let name = node.name()?.key()?.to_string();
let range = context
.subset
.documents
@@ -479,7 +479,7 @@ fn find_label_by_parent(
.line_index
.line_col_lsp_range(node.small_range());
- let number = find_label_number(&context.subset, name);
+ let number = find_label_number(&context.subset, &name);
Some(NumberedLabel {
name: name.to_string(),
range,
diff --git a/support/texlab/src/label.rs b/support/texlab/src/label.rs
index eead07814e..3d40b1620c 100644
--- a/support/texlab/src/label.rs
+++ b/support/texlab/src/label.rs
@@ -157,8 +157,9 @@ pub fn find_label_definition<'a>(
.find(|label| {
label
.name()
- .and_then(|name| name.word())
- .map(|name| name.text())
+ .and_then(|name| name.key())
+ .map(|name| name.to_string())
+ .as_deref()
== Some(label_name)
})
}
@@ -178,7 +179,7 @@ fn render_label_float(
number: &mut Option<String>,
) -> Option<RenderedLabel> {
let environment = latex::Environment::cast(parent)?;
- let environment_name = environment.begin()?.name()?.word()?.text();
+ let environment_name = environment.begin()?.name()?.key()?.to_string();
let kind = LabelledFloatKind::from_str(&environment_name).ok()?;
let caption = find_caption_by_parent(&parent)?;
Some(RenderedLabel {
@@ -235,12 +236,12 @@ fn render_label_equation(
number: &mut Option<String>,
) -> Option<RenderedLabel> {
let environment = latex::Environment::cast(parent)?;
- let environment_name = environment.begin()?.name()?.word()?.text();
+ let environment_name = environment.begin()?.name()?.key()?.to_string();
if !LANGUAGE_DATA
.math_environments
.iter()
- .any(|name| name == environment_name)
+ .any(|name| name == &environment_name)
{
return None;
}
@@ -261,7 +262,7 @@ fn render_label_theorem(
let begin = environment.begin()?;
let description = begin.options().and_then(|options| options.content_text());
- let environment_name = begin.name()?.word()?.text();
+ let environment_name = begin.name()?.key()?.to_string();
let theorem = subset.documents.iter().find_map(|document| {
document.data.as_latex().and_then(|data| {
diff --git a/support/texlab/src/line_index.rs b/support/texlab/src/line_index.rs
index 868fe41232..3b36cd6802 100644
--- a/support/texlab/src/line_index.rs
+++ b/support/texlab/src/line_index.rs
@@ -214,4 +214,4 @@ where
}
left
-} \ No newline at end of file
+}
diff --git a/support/texlab/src/line_index_ext.rs b/support/texlab/src/line_index_ext.rs
index 8e28207edd..8c8f83f7b4 100644
--- a/support/texlab/src/line_index_ext.rs
+++ b/support/texlab/src/line_index_ext.rs
@@ -30,7 +30,7 @@ impl LineIndexExt for LineIndex {
fn line_col_lsp(&self, offset: TextSize) -> Position {
let position = self.line_col(offset);
- let LineColUtf16 { line , col } = self.to_utf16(position);
+ let LineColUtf16 { line, col } = self.to_utf16(position);
Position::new(line, col)
}
diff --git a/support/texlab/src/options.rs b/support/texlab/src/options.rs
index 09eea1110f..2626143e18 100644
--- a/support/texlab/src/options.rs
+++ b/support/texlab/src/options.rs
@@ -12,6 +12,9 @@ pub struct Options {
#[serde(default)]
pub bibtex_formatter: BibtexFormatter,
+ #[serde(default)]
+ pub latex_formatter: LatexFormatter,
+
pub formatter_line_length: Option<i32>,
pub diagnostics_delay: Option<u64>,
@@ -22,6 +25,9 @@ pub struct Options {
#[serde(default)]
pub chktex: ChktexOptions,
+ #[serde(default)]
+ pub latexindent: LatexindentOptions,
+
pub forward_search: Option<ForwardSearchOptions>,
}
@@ -38,6 +44,28 @@ impl Default for BibtexFormatter {
}
}
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum LatexFormatter {
+ Texlab,
+ Latexindent,
+}
+
+impl Default for LatexFormatter {
+ fn default() -> Self {
+ Self::Latexindent
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct LatexindentOptions {
+ pub local: Option<String>,
+
+ #[serde(default)]
+ pub modify_line_breaks: bool,
+}
+
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BuildOptions {
diff --git a/support/texlab/src/syntax/bibtex/cst.rs b/support/texlab/src/syntax/bibtex/cst.rs
index 7f824681dc..ba860c1ee7 100644
--- a/support/texlab/src/syntax/bibtex/cst.rs
+++ b/support/texlab/src/syntax/bibtex/cst.rs
@@ -1,4 +1,5 @@
use cstree::TextRange;
+use itertools::{EitherOrBoth, Itertools};
use crate::syntax::CstNode;
@@ -159,15 +160,42 @@ impl<'a> HasType<'a> for Entry<'a> {}
impl<'a> HasDelimiters<'a> for Entry<'a> {}
impl<'a> Entry<'a> {
- pub fn key(&self) -> Option<&'a SyntaxToken> {
+ pub fn key(&self) -> Option<Key<'a>> {
+ self.syntax().children().find_map(Key::cast)
+ }
+
+ pub fn fields(&self) -> impl Iterator<Item = Field<'a>> {
+ self.syntax().children().filter_map(Field::cast)
+ }
+}
+
+cst_node!(Key, KEY);
+
+impl<'a> Key<'a> {
+ pub fn words(&self) -> impl Iterator<Item = &'a SyntaxToken> {
self.syntax()
.children_with_tokens()
.filter_map(|node| node.into_token())
- .find(|node| node.kind() == WORD)
+ .filter(|node| node.kind() == WORD)
}
+}
- pub fn fields(&self) -> impl Iterator<Item = Field<'a>> {
- self.syntax().children().filter_map(Field::cast)
+impl<'a> PartialEq for Key<'a> {
+ fn eq(&self, other: &Self) -> bool {
+ self.words()
+ .zip_longest(other.words())
+ .all(|result| match result {
+ EitherOrBoth::Both(left, right) => left.text() == right.text(),
+ EitherOrBoth::Left(_) | EitherOrBoth::Right(_) => false,
+ })
+ }
+}
+
+impl<'a> Eq for Key<'a> {}
+
+impl<'a> ToString for Key<'a> {
+ fn to_string(&self) -> std::string::String {
+ self.words().map(|word| word.text()).join(" ")
}
}
diff --git a/support/texlab/src/syntax/bibtex/kind.rs b/support/texlab/src/syntax/bibtex/kind.rs
index fcb26b69bd..91f62fd3b8 100644
--- a/support/texlab/src/syntax/bibtex/kind.rs
+++ b/support/texlab/src/syntax/bibtex/kind.rs
@@ -26,6 +26,7 @@ pub enum SyntaxKind {
STRING,
COMMENT,
ENTRY,
+ KEY,
FIELD,
VALUE,
TOKEN,
diff --git a/support/texlab/src/syntax/bibtex/parser.rs b/support/texlab/src/syntax/bibtex/parser.rs
index ffdb1c94a0..6e8c4b3b59 100644
--- a/support/texlab/src/syntax/bibtex/parser.rs
+++ b/support/texlab/src/syntax/bibtex/parser.rs
@@ -174,7 +174,7 @@ impl<'a> Parser<'a> {
self.builder.finish_node();
return;
}
- self.eat();
+ self.key();
while let Some(kind) = self.peek() {
match kind {
@@ -190,6 +190,18 @@ impl<'a> Parser<'a> {
self.builder.finish_node();
}
+ fn key(&mut self) {
+ self.builder.start_node(KEY.into());
+ while self
+ .peek()
+ .filter(|&kind| matches!(kind, WORD | WHITESPACE))
+ .is_some()
+ {
+ self.eat();
+ }
+ self.builder.finish_node();
+ }
+
fn field(&mut self) {
self.builder.start_node(FIELD.into());
self.eat();
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_complete_parens.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_complete_parens.snap
index cfd469f161..d86d2fb035 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_complete_parens.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_complete_parens.snap
@@ -7,7 +7,8 @@ ROOT@0..50
ENTRY@0..50
ENTRY_TYPE@0..8 "@article"
L_PAREN@8..9 "("
- WORD@9..12 "foo"
+ KEY@9..12
+ WORD@9..12 "foo"
COMMA@12..13 ","
WHITESPACE@13..14 " "
FIELD@14..32
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields.snap
index a98df7e382..e5df412782 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields.snap
@@ -7,7 +7,8 @@ ROOT@0..14
ENTRY@0..14
ENTRY_TYPE@0..8 "@article"
L_CURLY@8..9 "{"
- WORD@9..12 "foo"
+ KEY@9..12
+ WORD@9..12 "foo"
COMMA@12..13 ","
R_CURLY@13..14 "}"
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields_missing_comma.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields_missing_comma.snap
index b83037aae0..b15c871298 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields_missing_comma.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_no_fields_missing_comma.snap
@@ -7,6 +7,7 @@ ROOT@0..13
ENTRY@0..13
ENTRY_TYPE@0..8 "@article"
L_CURLY@8..9 "{"
- WORD@9..12 "foo"
+ KEY@9..12
+ WORD@9..12 "foo"
R_CURLY@12..13 "}"
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field.snap
index 704cbbbd47..0bd43ac612 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field.snap
@@ -7,7 +7,8 @@ ROOT@0..33
ENTRY@0..33
ENTRY_TYPE@0..8 "@article"
L_CURLY@8..9 "{"
- WORD@9..12 "foo"
+ KEY@9..12
+ WORD@9..12 "foo"
COMMA@12..13 ","
WHITESPACE@13..14 " "
FIELD@14..32
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_number_key.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_number_key.snap
index 8f00c5ee1c..09bb00872f 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_number_key.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_number_key.snap
@@ -7,7 +7,8 @@ ROOT@0..37
ENTRY@0..37
ENTRY_TYPE@0..8 "@article"
L_CURLY@8..9 "{"
- WORD@9..16 "foo2021"
+ KEY@9..16
+ WORD@9..16 "foo2021"
COMMA@16..17 ","
WHITESPACE@17..18 " "
FIELD@18..36
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_trailing_comma.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_trailing_comma.snap
index af8b1593df..51adbbc275 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_trailing_comma.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_one_field_trailing_comma.snap
@@ -7,7 +7,8 @@ ROOT@0..34
ENTRY@0..34
ENTRY_TYPE@0..8 "@article"
L_CURLY@8..9 "{"
- WORD@9..12 "foo"
+ KEY@9..12
+ WORD@9..12 "foo"
COMMA@12..13 ","
WHITESPACE@13..14 " "
FIELD@14..32
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields.snap
index f47b3b6917..384d582ef9 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields.snap
@@ -7,7 +7,8 @@ ROOT@0..56
ENTRY@0..56
ENTRY_TYPE@0..8 "@article"
L_CURLY@8..9 "{"
- WORD@9..12 "foo"
+ KEY@9..12
+ WORD@9..12 "foo"
COMMA@12..13 ","
WHITESPACE@13..14 " "
FIELD@14..32
diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields_incomplete.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields_incomplete.snap
index 34a9019582..cbe00beff5 100644
--- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields_incomplete.snap
+++ b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__parser__tests__entry_two_fields_incomplete.snap
@@ -7,7 +7,8 @@ ROOT@0..36
ENTRY@0..36
ENTRY_TYPE@0..8 "@article"
L_CURLY@8..9 "{"
- WORD@9..12 "foo"
+ KEY@9..12
+ WORD@9..12 "foo"
COMMA@12..13 ","
WHITESPACE@13..14 " "
FIELD@14..32
diff --git a/support/texlab/src/syntax/latex/analysis/environment.rs b/support/texlab/src/syntax/latex/analysis/environment.rs
index 3b83b40b2f..7cda0c126b 100644
--- a/support/texlab/src/syntax/latex/analysis/environment.rs
+++ b/support/texlab/src/syntax/latex/analysis/environment.rs
@@ -4,7 +4,7 @@ use super::LatexAnalyzerContext;
pub fn analyze_begin(context: &mut LatexAnalyzerContext, node: &latex::SyntaxNode) -> Option<()> {
let begin = latex::Begin::cast(node)?;
- let name = begin.name()?.word()?.text();
+ let name = begin.name()?.key()?.to_string();
let extras = &mut context.extras;
extras.environment_names.insert(name.into());
Some(())
diff --git a/support/texlab/src/syntax/latex/analysis/explicit_link.rs b/support/texlab/src/syntax/latex/analysis/explicit_link.rs
index 363a576aaa..f177354ac7 100644
--- a/support/texlab/src/syntax/latex/analysis/explicit_link.rs
+++ b/support/texlab/src/syntax/latex/analysis/explicit_link.rs
@@ -23,22 +23,22 @@ pub fn analyze_include(context: &mut LatexAnalyzerContext, node: &latex::SyntaxN
ExplicitLinkKind::Class => &["cls"],
};
- for path in include.path_list()?.words() {
- let stem = path.text();
- let mut targets = vec![Arc::new(context.base_uri.join(stem).ok()?.into())];
+ for path in include.path_list()?.keys() {
+ let stem = path.to_string();
+ let mut targets = vec![Arc::new(context.base_uri.join(&stem).ok()?.into())];
for extension in extensions {
let path = format!("{}.{}", stem, extension);
targets.push(Arc::new(context.base_uri.join(&path).ok()?.into()));
}
- resolve_distro_file(&context.inner.resolver.lock().unwrap(), stem, extensions)
+ resolve_distro_file(&context.inner.resolver.lock().unwrap(), &stem, extensions)
.into_iter()
.for_each(|target| targets.push(Arc::new(target)));
context.extras.explicit_links.push(ExplicitLink {
kind,
stem: stem.into(),
- stem_range: path.text_range(),
+ stem_range: path.small_range(),
targets,
});
}
@@ -52,19 +52,19 @@ pub fn analyze_import(context: &mut LatexAnalyzerContext, node: &latex::SyntaxNo
let mut targets = Vec::new();
let directory = context
.base_uri
- .join(import.directory()?.word()?.text())
+ .join(&import.directory()?.key()?.to_string())
.ok()?;
- let file = import.file()?.word()?;
- let stem = file.text();
- targets.push(Arc::new(directory.join(stem).ok()?.into()));
+ let file = import.file()?.key()?;
+ let stem = file.to_string();
+ targets.push(Arc::new(directory.join(&stem).ok()?.into()));
targets.push(Arc::new(
directory.join(&format!("{}.tex", stem)).ok()?.into(),
));
context.extras.explicit_links.push(ExplicitLink {
stem: stem.into(),
- stem_range: file.text_range(),
+ stem_range: file.small_range(),
targets,
kind: ExplicitLinkKind::Latex,
});
diff --git a/support/texlab/src/syntax/latex/analysis/label_name.rs b/support/texlab/src/syntax/latex/analysis/label_name.rs
index d0410b953c..e5ff6829cd 100644
--- a/support/texlab/src/syntax/latex/analysis/label_name.rs
+++ b/support/texlab/src/syntax/latex/analysis/label_name.rs
@@ -18,10 +18,10 @@ fn analyze_label_definition_name(
node: &latex::SyntaxNode,
) -> Option<()> {
let label = latex::LabelDefinition::cast(node)?;
- let name = label.name()?.word()?;
+ let name = label.name()?.key()?;
context.extras.label_names.push(LabelName {
- text: name.text().into(),
- range: name.text_range(),
+ text: name.to_string().into(),
+ range: name.small_range(),
is_definition: true,
});
Some(())
@@ -32,10 +32,10 @@ fn analyze_label_reference_name(
node: &latex::SyntaxNode,
) -> Option<()> {
let label = latex::LabelReference::cast(node)?;
- for name in label.name_list()?.words() {
+ for name in label.name_list()?.keys() {
context.extras.label_names.push(LabelName {
- text: name.text().into(),
- range: name.text_range(),
+ text: name.to_string().into(),
+ range: name.small_range(),
is_definition: false,
});
}
@@ -47,18 +47,18 @@ fn analyze_label_reference_range_name(
node: &latex::SyntaxNode,
) -> Option<()> {
let label = LabelReferenceRange::cast(node)?;
- if let Some(name1) = label.from().and_then(|name| name.word()) {
+ if let Some(name1) = label.from().and_then(|name| name.key()) {
context.extras.label_names.push(LabelName {
- text: name1.text().into(),
- range: name1.text_range(),
+ text: name1.to_string().into(),
+ range: name1.small_range(),
is_definition: false,
});
}
- if let Some(name2) = label.to().and_then(|name| name.word()) {
+ if let Some(name2) = label.to().and_then(|name| name.key()) {
context.extras.label_names.push(LabelName {
- text: name2.text().into(),
- range: name2.text_range(),
+ text: name2.to_string().into(),
+ range: name2.small_range(),
is_definition: false,
});
}
diff --git a/support/texlab/src/syntax/latex/analysis/label_number.rs b/support/texlab/src/syntax/latex/analysis/label_number.rs
index de8d0dc1e1..93ad09523f 100644
--- a/support/texlab/src/syntax/latex/analysis/label_number.rs
+++ b/support/texlab/src/syntax/latex/analysis/label_number.rs
@@ -7,7 +7,7 @@ pub fn analyze_label_number(
node: &latex::SyntaxNode,
) -> Option<()> {
let number = latex::LabelNumber::cast(node)?;
- let name = number.name()?.word()?.text().into();
+ let name = number.name()?.key()?.to_string();
let text = number
.text()?
.syntax()
diff --git a/support/texlab/src/syntax/latex/analysis/theorem.rs b/support/texlab/src/syntax/latex/analysis/theorem.rs
index 0c365f0ef5..50236e24a5 100644
--- a/support/texlab/src/syntax/latex/analysis/theorem.rs
+++ b/support/texlab/src/syntax/latex/analysis/theorem.rs
@@ -10,7 +10,7 @@ pub fn analyze_theorem_definition(
node: &latex::SyntaxNode,
) -> Option<()> {
let theorem = latex::TheoremDefinition::cast(node)?;
- let name = theorem.name()?.word()?.text().into();
+ let name = theorem.name()?.key()?.to_string();
let description = theorem.description()?;
let description = description.content_text()?;
diff --git a/support/texlab/src/syntax/latex/analysis/types.rs b/support/texlab/src/syntax/latex/analysis/types.rs
index f089721397..bd2789b3b7 100644
--- a/support/texlab/src/syntax/latex/analysis/types.rs
+++ b/support/texlab/src/syntax/latex/analysis/types.rs
@@ -20,9 +20,9 @@ pub struct Extras {
pub explicit_links: Vec<ExplicitLink>,
pub has_document_environment: bool,
pub command_names: FxHashSet<SmolStr>,
- pub environment_names: FxHashSet<SmolStr>,
+ pub environment_names: FxHashSet<String>,
pub label_names: Vec<LabelName>,
- pub label_numbers_by_name: FxHashMap<SmolStr, String>,
+ pub label_numbers_by_name: FxHashMap<String, String>,
pub theorem_environments: Vec<TheoremEnvironment>,
}
@@ -61,7 +61,7 @@ impl ExplicitLink {
#[derive(Debug, PartialEq, Eq, Clone, Default, Hash)]
pub struct TheoremEnvironment {
- pub name: SmolStr,
+ pub name: String,
pub description: String,
}
diff --git a/support/texlab/src/syntax/latex/cst.rs b/support/texlab/src/syntax/latex/cst.rs
index 0b839b706d..a800236ebf 100644
--- a/support/texlab/src/syntax/latex/cst.rs
+++ b/support/texlab/src/syntax/latex/cst.rs
@@ -1,4 +1,5 @@
use cstree::TextRange;
+use itertools::{EitherOrBoth, Itertools};
use crate::syntax::CstNode;
@@ -6,7 +7,7 @@ use super::{Language, SyntaxKind::*, SyntaxNode, SyntaxToken};
macro_rules! cst_node {
($name:ident, $($kind:pat),+) => {
- #[derive(Clone)]
+ #[derive(Clone, Copy)]
#[repr(transparent)]
pub struct $name<'a>(&'a SyntaxNode);
@@ -45,6 +46,15 @@ macro_rules! cst_node {
cst_node!(Text, TEXT);
+impl<'a> Text<'a> {
+ pub fn words(&self) -> impl Iterator<Item = &'a SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(|node| node.into_token())
+ .filter(|node| node.kind() == WORD)
+ }
+}
+
pub trait HasCurly<'a>: CstNode<'a, Lang = Language> {
fn left_curly(&self) -> Option<&'a SyntaxToken> {
self.syntax()
@@ -168,11 +178,8 @@ cst_node!(CurlyGroupWord, CURLY_GROUP_WORD);
impl<'a> HasCurly<'a> for CurlyGroupWord<'a> {}
impl<'a> CurlyGroupWord<'a> {
- pub fn word(&self) -> Option<&'a SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(|node| node.into_token())
- .find(|node| node.kind() == WORD)
+ pub fn key(&self) -> Option<Key<'a>> {
+ self.syntax().children().find_map(Key::cast)
}
}
@@ -181,11 +188,8 @@ cst_node!(BrackGroupWord, BRACK_GROUP_WORD);
impl<'a> HasBrack<'a> for BrackGroupWord<'a> {}
impl<'a> BrackGroupWord<'a> {
- pub fn word(&self) -> Option<&'a SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(|node| node.into_token())
- .find(|node| node.kind() == WORD)
+ pub fn key(&self) -> Option<Key<'a>> {
+ self.syntax().children().find_map(Key::cast)
}
}
@@ -194,11 +198,8 @@ cst_node!(CurlyGroupWordList, CURLY_GROUP_WORD_LIST);
impl<'a> HasCurly<'a> for CurlyGroupWordList<'a> {}
impl<'a> CurlyGroupWordList<'a> {
- pub fn words(&self) -> impl Iterator<Item = &'a SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(|node| node.into_token())
- .filter(|node| node.kind() == WORD)
+ pub fn keys(&self) -> impl Iterator<Item = Key<'a>> {
+ self.syntax().children().filter_map(Key::cast)
}
}
@@ -226,6 +227,25 @@ impl<'a> Key<'a> {
}
}
+impl<'a> PartialEq for Key<'a> {
+ fn eq(&self, other: &Self) -> bool {
+ self.words()
+ .zip_longest(other.words())
+ .all(|result| match result {
+ EitherOrBoth::Both(left, right) => left.text() == right.text(),
+ EitherOrBoth::Left(_) | EitherOrBoth::Right(_) => false,
+ })
+ }
+}
+
+impl<'a> Eq for Key<'a> {}
+
+impl<'a> ToString for Key<'a> {
+ fn to_string(&self) -> String {
+ self.words().map(|word| word.text()).join(" ")
+ }
+}
+
cst_node!(Value, VALUE);
cst_node!(KeyValuePair, KEY_VALUE_PAIR);
diff --git a/support/texlab/src/syntax/latex/parser.rs b/support/texlab/src/syntax/latex/parser.rs
index 4333235ba5..a21674f51d 100644
--- a/support/texlab/src/syntax/latex/parser.rs
+++ b/support/texlab/src/syntax/latex/parser.rs
@@ -173,20 +173,6 @@ impl<'a> Parser<'a> {
self.builder.finish_node();
}
- fn group_with_token(
- &mut self,
- node_kind: SyntaxKind,
- content_kind: SyntaxKind,
- right_kind: SyntaxKind,
- ) {
- self.builder.start_node(node_kind.into());
- self.eat();
- self.trivia();
- self.expect(content_kind);
- self.expect(right_kind);
- self.builder.finish_node();
- }
-
fn curly_group(&mut self) {
self.builder.start_node(CURLY_GROUP.into());
self.eat();
@@ -219,7 +205,23 @@ impl<'a> Parser<'a> {
}
fn curly_group_word(&mut self) {
- self.group_with_token(CURLY_GROUP_WORD, WORD, R_CURLY);
+ self.builder.start_node(CURLY_GROUP_WORD.into());
+ self.eat();
+ self.trivia();
+ match self.peek() {
+ Some(WORD) => {
+ self.key();
+ }
+ Some(PARAMETER) => {
+ self.eat();
+ self.trivia();
+ }
+ Some(_) | None => {
+ self.builder.token(MISSING.into(), "");
+ }
+ }
+ self.expect(R_CURLY);
+ self.builder.finish_node();
}
fn curly_group_word_list(&mut self) {
@@ -228,10 +230,14 @@ impl<'a> Parser<'a> {
while self
.peek()
- .filter(|&kind| matches!(kind, WHITESPACE | COMMENT | WORD | COMMA))
+ .filter(|&kind| matches!(kind, WHITESPACE | COMMENT | WORD | COMMA | PARAMETER))
.is_some()
{
- self.eat();
+ if self.peek() == Some(WORD) {
+ self.key();
+ } else {
+ self.eat();
+ }
}
self.expect(R_CURLY);
@@ -239,7 +245,24 @@ impl<'a> Parser<'a> {
}
fn curly_group_command(&mut self) {
- self.group_with_token(CURLY_GROUP_COMMAND, GENERIC_COMMAND_NAME, R_CURLY);
+ self.builder.start_node(CURLY_GROUP_COMMAND.into());
+ self.eat();
+ self.trivia();
+ match self.peek() {
+ Some(kind) if kind.is_command_name() => {
+ self.eat();
+ self.trivia();
+ }
+ Some(PARAMETER) => {
+ self.eat();
+ self.trivia();
+ }
+ Some(_) | None => {
+ self.builder.token(MISSING.into(), "");
+ }
+ }
+ self.expect(R_CURLY);
+ self.builder.finish_node();
}
fn brack_group(&mut self) {
@@ -271,37 +294,24 @@ impl<'a> Parser<'a> {
}
fn brack_group_word(&mut self) {
- self.group_with_token(BRACK_GROUP_WORD, WORD, R_BRACK);
- }
-
- // fn paren_group(&mut self) {
- // self.builder.start_node(PAREN_GROUP.into());
- // self.eat();
- // while self
- // .peek()
- // .filter(|&kind| {
- // !matches!(
- // kind,
- // R_CURLY
- // | R_BRACK
- // | R_PAREN
- // | PART_NAME
- // | CHAPTER_NAME
- // | SECTION_NAME
- // | SUBSECTION_NAME
- // | PARAGRAPH_NAME
- // | SUBPARAGRAPH_NAME
- // | ENUM_ITEM_NAME
- // | END_ENVIRONMENT_NAME
- // )
- // })
- // .is_some()
- // {
- // self.content();
- // }
- // self.expect(R_PAREN);
- // self.builder.finish_node();
- // }
+ self.builder.start_node(BRACK_GROUP_WORD.into());
+ self.eat();
+ self.trivia();
+ match self.peek() {
+ Some(WORD) => {
+ self.key();
+ }
+ Some(PARAMETER) => {
+ self.eat();
+ self.trivia();
+ }
+ Some(_) | None => {
+ self.builder.token(MISSING.into(), "");
+ }
+ }
+ self.expect(R_BRACK);
+ self.builder.finish_node();
+ }
fn mixed_group(&mut self) {
self.builder.start_node(MIXED_GROUP.into());
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acronym_declaration.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acronym_declaration.snap
index dfd05750d3..a92180efb3 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acronym_declaration.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acronym_declaration.snap
@@ -9,7 +9,8 @@ ROOT@0..64
ACRONYM_DECLARATION_NAME@0..15 "\\DeclareAcronym"
CURLY_GROUP_WORD@15..19
L_CURLY@15..16 "{"
- WORD@16..18 "eg"
+ KEY@16..18
+ WORD@16..18 "eg"
R_CURLY@18..19 "}"
CURLY_GROUP_KEY_VALUE@19..64
L_CURLY@19..20 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_options.snap
index 1838e80f9a..80043c18e7 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_options.snap
@@ -27,7 +27,8 @@ ROOT@0..76
R_BRACK@42..43 "]"
CURLY_GROUP_WORD@43..53
L_CURLY@43..44 "{"
- WORD@44..52 "fpsLabel"
+ KEY@44..52
+ WORD@44..52 "fpsLabel"
R_CURLY@52..53 "}"
CURLY_GROUP@53..58
L_CURLY@53..54 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_simple.snap
index 1d32bed249..74ae2219de 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_simple.snap
@@ -9,7 +9,8 @@ ROOT@0..44
ACRONYM_DEFINITION_NAME@0..11 "\\newacronym"
CURLY_GROUP_WORD@11..21
L_CURLY@11..12 "{"
- WORD@12..20 "fpsLabel"
+ KEY@12..20
+ WORD@12..20 "fpsLabel"
R_CURLY@20..21 "}"
CURLY_GROUP@21..26
L_CURLY@21..22 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_options.snap
index ce5b85c1cf..6a1c2cdcbe 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_options.snap
@@ -24,6 +24,7 @@ ROOT@0..32
R_BRACK@21..22 "]"
CURLY_GROUP_WORD@22..32
L_CURLY@22..23 "{"
- WORD@23..31 "fpsLabel"
+ KEY@23..31
+ WORD@23..31 "fpsLabel"
R_CURLY@31..32 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_simple.snap
index 5df8059f1b..9924c7175c 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..19
ACRONYM_REFERENCE_NAME@0..9 "\\acrshort"
CURLY_GROUP_WORD@9..19
L_CURLY@9..10 "{"
- WORD@10..18 "fpsLabel"
+ KEY@10..18
+ WORD@10..18 "fpsLabel"
R_CURLY@18..19 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_options.snap
index c910699363..3189cabd46 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_options.snap
@@ -25,6 +25,7 @@ ROOT@0..42
R_BRACK@28..29 "]"
CURLY_GROUP_WORD_LIST@29..42
L_CURLY@29..30 "{"
- WORD@30..41 "foo/bar.bib"
+ KEY@30..41
+ WORD@30..41 "foo/bar.bib"
R_CURLY@41..42 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_simple.snap
index 3549b985c4..3166d13aff 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..28
BIBLATEX_INCLUDE_NAME@0..15 "\\addbibresource"
CURLY_GROUP_WORD_LIST@15..28
L_CURLY@15..16 "{"
- WORD@16..27 "foo/bar.bib"
+ KEY@16..27
+ WORD@16..27 "foo/bar.bib"
R_CURLY@27..28 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__bibtex_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__bibtex_include_simple.snap
index f0d30ebfa3..db58621c75 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__bibtex_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__bibtex_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..22
BIBTEX_INCLUDE_NAME@0..13 "\\bibliography"
CURLY_GROUP_WORD_LIST@13..22
L_CURLY@13..14 "{"
- WORD@14..21 "foo/bar"
+ KEY@14..21
+ WORD@14..21 "foo/bar"
R_CURLY@21..22 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_figure.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_figure.snap
index 4b963caabd..b3bf7589d8 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_figure.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_figure.snap
@@ -10,7 +10,8 @@ ROOT@0..39
BEGIN_ENVIRONMENT_NAME@0..6 "\\begin"
CURLY_GROUP_WORD@6..14
L_CURLY@6..7 "{"
- WORD@7..13 "figure"
+ KEY@7..13
+ WORD@7..13 "figure"
R_CURLY@13..14 "}"
CAPTION@14..27
CAPTION_NAME@14..22 "\\caption"
@@ -23,6 +24,7 @@ ROOT@0..39
END_ENVIRONMENT_NAME@27..31 "\\end"
CURLY_GROUP_WORD@31..39
L_CURLY@31..32 "{"
- WORD@32..38 "figure"
+ KEY@32..38
+ WORD@32..38 "figure"
R_CURLY@38..39 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_missing_brace.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_missing_brace.snap
index 363f8b0142..61cd6d8f0b 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_missing_brace.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_missing_brace.snap
@@ -9,6 +9,7 @@ ROOT@0..9
CITATION_NAME@0..5 "\\cite"
CURLY_GROUP_WORD_LIST@5..9
L_CURLY@5..6 "{"
- WORD@6..9 "foo"
+ KEY@6..9
+ WORD@6..9 "foo"
MISSING@9..9 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_multiple_keys.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_multiple_keys.snap
index dafc826a97..7195e8992e 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_multiple_keys.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_multiple_keys.snap
@@ -9,9 +9,11 @@ ROOT@0..15
CITATION_NAME@0..5 "\\cite"
CURLY_GROUP_WORD_LIST@5..15
L_CURLY@5..6 "{"
- WORD@6..9 "foo"
+ KEY@6..9
+ WORD@6..9 "foo"
COMMA@9..10 ","
WHITESPACE@10..11 " "
- WORD@11..14 "bar"
+ KEY@11..14
+ WORD@11..14 "bar"
R_CURLY@14..15 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote.snap
index 93d83bb448..b5d92886aa 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote.snap
@@ -14,6 +14,7 @@ ROOT@0..15
R_BRACK@9..10 "]"
CURLY_GROUP_WORD_LIST@10..15
L_CURLY@10..11 "{"
- WORD@11..14 "bar"
+ KEY@11..14
+ WORD@11..14 "bar"
R_CURLY@14..15 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote_postnote.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote_postnote.snap
index 3acaafea3b..ba99b66e35 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote_postnote.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote_postnote.snap
@@ -19,6 +19,7 @@ ROOT@0..20
R_BRACK@14..15 "]"
CURLY_GROUP_WORD_LIST@15..20
L_CURLY@15..16 "{"
- WORD@16..19 "baz"
+ KEY@16..19
+ WORD@16..19 "baz"
R_CURLY@19..20 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_redundant_comma.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_redundant_comma.snap
index 12f34f16ae..9062479f7a 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_redundant_comma.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_redundant_comma.snap
@@ -10,7 +10,8 @@ ROOT@0..12
CURLY_GROUP_WORD_LIST@5..12
L_CURLY@5..6 "{"
COMMA@6..7 ","
- WORD@7..10 "foo"
+ KEY@7..10
+ WORD@7..10 "foo"
COMMA@10..11 ","
R_CURLY@11..12 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_simple.snap
index a22129f85f..335b9d461c 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..10
CITATION_NAME@0..5 "\\cite"
CURLY_GROUP_WORD_LIST@5..10
L_CURLY@5..6 "{"
- WORD@6..9 "foo"
+ KEY@6..9
+ WORD@6..9 "foo"
R_CURLY@9..10 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_star.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_star.snap
index 4388596dfd..e6d5dad128 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_star.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_star.snap
@@ -9,6 +9,7 @@ ROOT@0..10
CITATION_NAME@0..7 "\\nocite"
CURLY_GROUP_WORD_LIST@7..10
L_CURLY@7..8 "{"
- WORD@8..9 "*"
+ KEY@8..9
+ WORD@8..9 "*"
R_CURLY@9..10 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_options.snap
index 0d0eb1b250..ac20c4b8ac 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_options.snap
@@ -32,6 +32,7 @@ ROOT@0..44
R_BRACK@34..35 "]"
CURLY_GROUP_WORD_LIST@35..44
L_CURLY@35..36 "{"
- WORD@36..43 "article"
+ KEY@36..43
+ WORD@36..43 "article"
R_CURLY@43..44 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_simple.snap
index 85e21b47a8..07c426101e 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..23
CLASS_INCLUDE_NAME@0..14 "\\documentclass"
CURLY_GROUP_WORD_LIST@14..23
L_CURLY@14..15 "{"
- WORD@15..22 "article"
+ KEY@15..22
+ WORD@15..22 "article"
R_CURLY@22..23 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_definition_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_definition_simple.snap
index e4adfd534c..64eee4351b 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_definition_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_definition_simple.snap
@@ -9,11 +9,13 @@ ROOT@0..33
COLOR_DEFINITION_NAME@0..12 "\\definecolor"
CURLY_GROUP_WORD@12..17
L_CURLY@12..13 "{"
- WORD@13..16 "foo"
+ KEY@13..16
+ WORD@13..16 "foo"
R_CURLY@16..17 "}"
CURLY_GROUP_WORD@17..22
L_CURLY@17..18 "{"
- WORD@18..21 "rgb"
+ KEY@18..21
+ WORD@18..21 "rgb"
R_CURLY@21..22 "}"
CURLY_GROUP@22..33
L_CURLY@22..23 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_reference_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_reference_simple.snap
index 41a3700122..cb0ee151b9 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_reference_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_reference_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..13
COLOR_REFERENCE_NAME@0..6 "\\color"
CURLY_GROUP_WORD@6..13
L_CURLY@6..7 "{"
- WORD@7..12 "black"
+ KEY@7..12
+ WORD@7..12 "black"
R_CURLY@12..13 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error1.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error1.snap
index 42095ff974..59688f0902 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error1.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error1.snap
@@ -9,21 +9,26 @@ ROOT@0..39
COLOR_SET_DEFINITION_NAME@0..15 "\\definecolorset"
BRACK_GROUP_WORD@15..19
L_BRACK@15..16 "["
- WORD@16..18 "ty"
+ KEY@16..18
+ WORD@16..18 "ty"
R_BRACK@18..19 "]"
CURLY_GROUP_WORD_LIST@19..29
L_CURLY@19..20 "{"
- WORD@20..23 "rgb"
+ KEY@20..23
+ WORD@20..23 "rgb"
COMMA@23..24 ","
- WORD@24..28 "HTML"
+ KEY@24..28
+ WORD@24..28 "HTML"
R_CURLY@28..29 "}"
CURLY_GROUP_WORD@29..34
L_CURLY@29..30 "{"
- WORD@30..33 "foo"
+ KEY@30..33
+ WORD@30..33 "foo"
R_CURLY@33..34 "}"
CURLY_GROUP_WORD@34..39
L_CURLY@34..35 "{"
- WORD@35..38 "bar"
+ KEY@35..38
+ WORD@35..38 "bar"
R_CURLY@38..39 "}"
MISSING@39..39 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error2.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error2.snap
index 718d49a3e3..cbbeacb649 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error2.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error2.snap
@@ -9,13 +9,16 @@ ROOT@0..30
COLOR_SET_DEFINITION_NAME@0..15 "\\definecolorset"
CURLY_GROUP_WORD_LIST@15..25
L_CURLY@15..16 "{"
- WORD@16..19 "rgb"
+ KEY@16..19
+ WORD@16..19 "rgb"
COMMA@19..20 ","
- WORD@20..24 "HTML"
+ KEY@20..24
+ WORD@20..24 "HTML"
R_CURLY@24..25 "}"
CURLY_GROUP_WORD@25..30
L_CURLY@25..26 "{"
- WORD@26..29 "foo"
+ KEY@26..29
+ WORD@26..29 "foo"
R_CURLY@29..30 "}"
MISSING@30..30 ""
MISSING@30..30 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error3.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error3.snap
index f92d813123..826bea28b6 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error3.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error3.snap
@@ -9,9 +9,11 @@ ROOT@0..25
COLOR_SET_DEFINITION_NAME@0..15 "\\definecolorset"
CURLY_GROUP_WORD_LIST@15..25
L_CURLY@15..16 "{"
- WORD@16..19 "rgb"
+ KEY@16..19
+ WORD@16..19 "rgb"
COMMA@19..20 ","
- WORD@20..24 "HTML"
+ KEY@20..24
+ WORD@20..24 "HTML"
R_CURLY@24..25 "}"
MISSING@25..25 ""
MISSING@25..25 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_simple.snap
index f9a736c65f..9d32e127ef 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_simple.snap
@@ -9,24 +9,30 @@ ROOT@0..44
COLOR_SET_DEFINITION_NAME@0..15 "\\definecolorset"
BRACK_GROUP_WORD@15..19
L_BRACK@15..16 "["
- WORD@16..18 "ty"
+ KEY@16..18
+ WORD@16..18 "ty"
R_BRACK@18..19 "]"
CURLY_GROUP_WORD_LIST@19..29
L_CURLY@19..20 "{"
- WORD@20..23 "rgb"
+ KEY@20..23
+ WORD@20..23 "rgb"
COMMA@23..24 ","
- WORD@24..28 "HTML"
+ KEY@24..28
+ WORD@24..28 "HTML"
R_CURLY@28..29 "}"
CURLY_GROUP_WORD@29..34
L_CURLY@29..30 "{"
- WORD@30..33 "foo"
+ KEY@30..33
+ WORD@30..33 "foo"
R_CURLY@33..34 "}"
CURLY_GROUP_WORD@34..39
L_CURLY@34..35 "{"
- WORD@35..38 "bar"
+ KEY@35..38
+ WORD@35..38 "bar"
R_CURLY@38..39 "}"
CURLY_GROUP_WORD@39..44
L_CURLY@39..40 "{"
- WORD@40..43 "baz"
+ KEY@40..43
+ WORD@40..43 "baz"
R_CURLY@43..44 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_simple.snap
index e5f2377fcf..b0d9b225d0 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_simple.snap
@@ -10,7 +10,8 @@ ROOT@0..23
MISSING@11..11 ""
BRACK_GROUP_WORD@11..14
L_BRACK@11..12 "["
- WORD@12..13 "1"
+ KEY@12..13
+ WORD@12..13 "1"
R_BRACK@13..14 "]"
CURLY_GROUP@14..19
L_CURLY@14..15 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition.snap
index df3c0d56fb..982d3b8667 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition.snap
@@ -9,11 +9,13 @@ ROOT@0..47
ENVIRONMENT_DEFINIITION_NAME@0..15 "\\newenvironment"
CURLY_GROUP_WORD@15..20
L_CURLY@15..16 "{"
- WORD@16..19 "bar"
+ KEY@16..19
+ WORD@16..19 "bar"
R_CURLY@19..20 "}"
BRACK_GROUP_WORD@20..23
L_BRACK@20..21 "["
- WORD@21..22 "1"
+ KEY@21..22
+ WORD@21..22 "1"
R_BRACK@22..23 "]"
CURLY_GROUP@23..36
L_CURLY@23..24 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested.snap
index a5c566f773..3a65af3a2b 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested.snap
@@ -10,7 +10,8 @@ ROOT@0..43
BEGIN_ENVIRONMENT_NAME@0..6 "\\begin"
CURLY_GROUP_WORD@6..12
L_CURLY@6..7 "{"
- WORD@7..10 "foo"
+ KEY@7..10
+ WORD@7..10 "foo"
R_CURLY@10..11 "}"
WHITESPACE@11..12 " "
ENVIRONMENT@12..34
@@ -18,20 +19,23 @@ ROOT@0..43
BEGIN_ENVIRONMENT_NAME@12..18 "\\begin"
CURLY_GROUP_WORD@18..24
L_CURLY@18..19 "{"
- WORD@19..22 "qux"
+ KEY@19..22
+ WORD@19..22 "qux"
R_CURLY@22..23 "}"
WHITESPACE@23..24 " "
END@24..34
END_ENVIRONMENT_NAME@24..28 "\\end"
CURLY_GROUP_WORD@28..34
L_CURLY@28..29 "{"
- WORD@29..32 "baz"
+ KEY@29..32
+ WORD@29..32 "baz"
R_CURLY@32..33 "}"
WHITESPACE@33..34 " "
END@34..43
END_ENVIRONMENT_NAME@34..38 "\\end"
CURLY_GROUP_WORD@38..43
L_CURLY@38..39 "{"
- WORD@39..42 "bar"
+ KEY@39..42
+ WORD@39..42 "bar"
R_CURLY@42..43 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested_missing_braces.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested_missing_braces.snap
index 9ff76605d6..973e6e9a9f 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested_missing_braces.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested_missing_braces.snap
@@ -10,33 +10,36 @@ ROOT@0..52
BEGIN_ENVIRONMENT_NAME@0..6 "\\begin"
CURLY_GROUP_WORD@6..11
L_CURLY@6..7 "{"
- WORD@7..10 "foo"
- WHITESPACE@10..11 " "
+ KEY@7..11
+ WORD@7..10 "foo"
+ WHITESPACE@10..11 " "
MISSING@11..11 ""
ENVIRONMENT@11..44
- BEGIN@11..22
+ BEGIN@11..34
BEGIN_ENVIRONMENT_NAME@11..17 "\\begin"
- CURLY_GROUP_WORD@17..22
+ CURLY_GROUP_WORD@17..34
L_CURLY@17..18 "{"
- WORD@18..21 "qux"
- WHITESPACE@21..22 " "
- MISSING@22..22 ""
- TEXT@22..34
- WORD@22..27 "Hello"
- WHITESPACE@27..28 " "
- WORD@28..33 "World"
- WHITESPACE@33..34 " "
+ KEY@18..34
+ WORD@18..21 "qux"
+ WHITESPACE@21..22 " "
+ WORD@22..27 "Hello"
+ WHITESPACE@27..28 " "
+ WORD@28..33 "World"
+ WHITESPACE@33..34 " "
+ MISSING@34..34 ""
END@34..44
END_ENVIRONMENT_NAME@34..38 "\\end"
CURLY_GROUP_WORD@38..44
L_CURLY@38..39 "{"
- WORD@39..42 "baz"
+ KEY@39..42
+ WORD@39..42 "baz"
R_CURLY@42..43 "}"
WHITESPACE@43..44 " "
END@44..52
END_ENVIRONMENT_NAME@44..48 "\\end"
CURLY_GROUP_WORD@48..52
L_CURLY@48..49 "{"
- WORD@49..52 "bar"
+ KEY@49..52
+ WORD@49..52 "bar"
MISSING@52..52 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_simple.snap
index d58f5b26c4..b8b85f1348 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_simple.snap
@@ -10,7 +10,8 @@ ROOT@0..33
BEGIN_ENVIRONMENT_NAME@0..6 "\\begin"
CURLY_GROUP_WORD@6..12
L_CURLY@6..7 "{"
- WORD@7..10 "foo"
+ KEY@7..10
+ WORD@7..10 "foo"
R_CURLY@10..11 "}"
WHITESPACE@11..12 " "
TEXT@12..24
@@ -22,6 +23,7 @@ ROOT@0..33
END_ENVIRONMENT_NAME@24..28 "\\end"
CURLY_GROUP_WORD@28..33
L_CURLY@28..29 "{"
- WORD@29..32 "bar"
+ KEY@29..32
+ WORD@29..32 "bar"
R_CURLY@32..33 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_label_reference_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_label_reference_simple.snap
index 7a851233ef..9123fafcf2 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_label_reference_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_label_reference_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..11
LABEL_REFERENCE_NAME@0..6 "\\eqref"
CURLY_GROUP_WORD_LIST@6..11
L_CURLY@6..7 "{"
- WORD@7..10 "foo"
+ KEY@7..10
+ WORD@7..10 "foo"
R_CURLY@10..11 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_begin.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_begin.snap
index fe065667c3..9a2af78417 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_begin.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_begin.snap
@@ -10,7 +10,8 @@ ROOT@0..28
BEGIN_ENVIRONMENT_NAME@0..6 "\\begin"
CURLY_GROUP_WORD@6..10
L_CURLY@6..7 "{"
- WORD@7..8 "a"
+ KEY@7..8
+ WORD@7..8 "a"
R_CURLY@8..9 "}"
WHITESPACE@9..10 " "
TEXT@10..18
@@ -25,6 +26,7 @@ ROOT@0..28
END_ENVIRONMENT_NAME@21..25 "\\end"
CURLY_GROUP_WORD@25..28
L_CURLY@25..26 "{"
- WORD@26..27 "b"
+ KEY@26..27
+ WORD@26..27 "b"
R_CURLY@27..28 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_end.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_end.snap
index f7b6205ffb..3085037fac 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_end.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_end.snap
@@ -10,7 +10,8 @@ ROOT@0..28
BEGIN_ENVIRONMENT_NAME@0..6 "\\begin"
CURLY_GROUP_WORD@6..10
L_CURLY@6..7 "{"
- WORD@7..8 "a"
+ KEY@7..8
+ WORD@7..8 "a"
R_CURLY@8..9 "}"
WHITESPACE@9..10 " "
EQUATION@10..21
@@ -26,6 +27,7 @@ ROOT@0..28
END_ENVIRONMENT_NAME@21..25 "\\end"
CURLY_GROUP_WORD@25..28
L_CURLY@25..26 "{"
- WORD@26..27 "b"
+ KEY@26..27
+ WORD@26..27 "b"
R_CURLY@27..28 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_definition_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_definition_simple.snap
index d1b31e275a..519abf75e8 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_definition_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_definition_simple.snap
@@ -9,7 +9,8 @@ ROOT@0..39
GLOSSARY_ENTRY_DEFINITION_NAME@0..17 "\\newglossaryentry"
CURLY_GROUP_WORD@17..22
L_CURLY@17..18 "{"
- WORD@18..21 "foo"
+ KEY@18..21
+ WORD@18..21 "foo"
R_CURLY@21..22 "}"
CURLY_GROUP_KEY_VALUE@22..39
L_CURLY@22..23 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_options.snap
index ad5c44885a..494c0be0a0 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_options.snap
@@ -27,6 +27,7 @@ ROOT@0..25
R_BRACK@19..20 "]"
CURLY_GROUP_WORD@20..25
L_CURLY@20..21 "{"
- WORD@21..24 "baz"
+ KEY@21..24
+ WORD@21..24 "baz"
R_CURLY@24..25 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_simple.snap
index 2a6b845733..94af3796fc 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..9
GLOSSARY_ENTRY_REFERENCE_NAME@0..4 "\\gls"
CURLY_GROUP_WORD@4..9
L_CURLY@4..5 "{"
- WORD@5..8 "foo"
+ KEY@5..8
+ WORD@5..8 "foo"
R_CURLY@8..9 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_options.snap
index 910a4848ef..14e2413323 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_options.snap
@@ -20,6 +20,7 @@ ROOT@0..39
R_BRACK@25..26 "]"
CURLY_GROUP_WORD_LIST@26..39
L_CURLY@26..27 "{"
- WORD@27..38 "foo/bar.pdf"
+ KEY@27..38
+ WORD@27..38 "foo/bar.pdf"
R_CURLY@38..39 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_simple.snap
index fa6fbf1a14..f4c640bca8 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..29
GRAPHICS_INCLUDE_NAME@0..16 "\\includegraphics"
CURLY_GROUP_WORD_LIST@16..29
L_CURLY@16..17 "{"
- WORD@17..28 "foo/bar.pdf"
+ KEY@17..28
+ WORD@17..28 "foo/bar.pdf"
R_CURLY@28..29 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_incomplete.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_incomplete.snap
index 3dae1f433a..c8634d6269 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_incomplete.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_incomplete.snap
@@ -9,7 +9,8 @@ ROOT@0..11
IMPORT_NAME@0..7 "\\import"
CURLY_GROUP_WORD@7..11
L_CURLY@7..8 "{"
- WORD@8..11 "foo"
+ KEY@8..11
+ WORD@8..11 "foo"
MISSING@11..11 ""
MISSING@11..11 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_simple.snap
index 6e21f65cbf..c94f34eb3f 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_simple.snap
@@ -9,10 +9,12 @@ ROOT@0..17
IMPORT_NAME@0..7 "\\import"
CURLY_GROUP_WORD@7..12
L_CURLY@7..8 "{"
- WORD@8..11 "foo"
+ KEY@8..11
+ WORD@8..11 "foo"
R_CURLY@11..12 "}"
CURLY_GROUP_WORD@12..17
L_CURLY@12..13 "{"
- WORD@13..16 "bar"
+ KEY@13..16
+ WORD@13..16 "bar"
R_CURLY@16..17 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_options.snap
index d1fd2df652..8b95509be6 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_options.snap
@@ -20,6 +20,7 @@ ROOT@0..30
R_BRACK@20..21 "]"
CURLY_GROUP_WORD_LIST@21..30
L_CURLY@21..22 "{"
- WORD@22..29 "foo/bar"
+ KEY@22..29
+ WORD@22..29 "foo/bar"
R_CURLY@29..30 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_simple.snap
index 59f50c36d3..e3d1f9bdfd 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..20
SVG_INCLUDE_NAME@0..11 "\\includesvg"
CURLY_GROUP_WORD_LIST@11..20
L_CURLY@11..12 "{"
- WORD@12..19 "foo/bar"
+ KEY@12..19
+ WORD@12..19 "foo/bar"
R_CURLY@19..20 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_simple.snap
index 7eacd65c59..2d15533f87 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..11
LABEL_DEFINITION_NAME@0..6 "\\label"
CURLY_GROUP_WORD@6..11
L_CURLY@6..7 "{"
- WORD@7..10 "foo"
+ KEY@7..10
+ WORD@7..10 "foo"
R_CURLY@10..11 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_number.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_number.snap
index 46392d7574..a63752d80e 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_number.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_number.snap
@@ -9,7 +9,8 @@ ROOT@0..21
LABEL_NUMBER_NAME@0..9 "\\newlabel"
CURLY_GROUP_WORD@9..14
L_CURLY@9..10 "{"
- WORD@10..13 "foo"
+ KEY@10..13
+ WORD@10..13 "foo"
R_CURLY@13..14 "}"
CURLY_GROUP@14..21
L_CURLY@14..15 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_multiple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_multiple.snap
index e399397e09..0176c770e8 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_multiple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_multiple.snap
@@ -9,9 +9,11 @@ ROOT@0..14
LABEL_REFERENCE_NAME@0..4 "\\ref"
CURLY_GROUP_WORD_LIST@4..14
L_CURLY@4..5 "{"
- WORD@5..8 "foo"
+ KEY@5..8
+ WORD@5..8 "foo"
COMMA@8..9 ","
WHITESPACE@9..10 " "
- WORD@10..13 "bar"
+ KEY@10..13
+ WORD@10..13 "bar"
R_CURLY@13..14 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_error.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_error.snap
index 2894a9c2ec..ee65f8a02f 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_error.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_error.snap
@@ -9,10 +9,12 @@ ROOT@0..19
LABEL_REFERENCE_RANGE_NAME@0..10 "\\crefrange"
CURLY_GROUP_WORD@10..14
L_CURLY@10..11 "{"
- WORD@11..14 "foo"
+ KEY@11..14
+ WORD@11..14 "foo"
MISSING@14..14 ""
CURLY_GROUP_WORD@14..19
L_CURLY@14..15 "{"
- WORD@15..18 "bar"
+ KEY@15..18
+ WORD@15..18 "bar"
R_CURLY@18..19 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_incomplete.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_incomplete.snap
index 0a1753867e..3dbe4bbab6 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_incomplete.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_incomplete.snap
@@ -9,7 +9,8 @@ ROOT@0..15
LABEL_REFERENCE_RANGE_NAME@0..10 "\\crefrange"
CURLY_GROUP_WORD@10..15
L_CURLY@10..11 "{"
- WORD@11..14 "foo"
+ KEY@11..14
+ WORD@11..14 "foo"
R_CURLY@14..15 "}"
MISSING@15..15 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_simple.snap
index c06c31c1b7..094d0e2870 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_simple.snap
@@ -9,10 +9,12 @@ ROOT@0..20
LABEL_REFERENCE_RANGE_NAME@0..10 "\\crefrange"
CURLY_GROUP_WORD@10..15
L_CURLY@10..11 "{"
- WORD@11..14 "foo"
+ KEY@11..14
+ WORD@11..14 "foo"
R_CURLY@14..15 "}"
CURLY_GROUP_WORD@15..20
L_CURLY@15..16 "{"
- WORD@16..19 "bar"
+ KEY@16..19
+ WORD@16..19 "bar"
R_CURLY@19..20 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_simple.snap
index ed06f5dfc1..9b6e622ef9 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..9
LABEL_REFERENCE_NAME@0..4 "\\ref"
CURLY_GROUP_WORD_LIST@4..9
L_CURLY@4..5 "{"
- WORD@5..8 "foo"
+ KEY@5..8
+ WORD@5..8 "foo"
R_CURLY@8..9 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_simple.snap
index 34565aa072..dbdeaad2f7 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..17
LATEX_INCLUDE_NAME@0..8 "\\include"
CURLY_GROUP_WORD_LIST@8..17
L_CURLY@8..9 "{"
- WORD@9..16 "foo/bar"
+ KEY@9..16
+ WORD@9..16 "foo/bar"
R_CURLY@16..17 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap
index 208e898407..efa0d9b675 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..19
LATEX_INCLUDE_NAME@0..6 "\\input"
CURLY_GROUP_WORD_LIST@6..19
L_CURLY@6..7 "{"
- WORD@7..18 "foo/bar.tex"
+ KEY@7..18
+ WORD@7..18 "foo/bar.tex"
R_CURLY@18..19 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_multiple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_multiple.snap
index e68b98d1b5..2df92fd909 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_multiple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_multiple.snap
@@ -9,9 +9,11 @@ ROOT@0..28
PACKAGE_INCLUDE_NAME@0..11 "\\usepackage"
CURLY_GROUP_WORD_LIST@11..28
L_CURLY@11..12 "{"
- WORD@12..19 "amsmath"
+ KEY@12..19
+ WORD@12..19 "amsmath"
COMMA@19..20 ","
WHITESPACE@20..21 " "
- WORD@21..27 "lipsum"
+ KEY@21..27
+ WORD@21..27 "lipsum"
R_CURLY@27..28 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_options.snap
index a33c4e0bd7..0f87570023 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_options.snap
@@ -32,6 +32,7 @@ ROOT@0..41
R_BRACK@31..32 "]"
CURLY_GROUP_WORD_LIST@32..41
L_CURLY@32..33 "{"
- WORD@33..40 "amsmath"
+ KEY@33..40
+ WORD@33..40 "amsmath"
R_CURLY@40..41 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_simple.snap
index 00c075fdfe..a28dd39a13 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..20
PACKAGE_INCLUDE_NAME@0..11 "\\usepackage"
CURLY_GROUP_WORD_LIST@11..20
L_CURLY@11..12 "{"
- WORD@12..19 "amsmath"
+ KEY@12..19
+ WORD@12..19 "amsmath"
R_CURLY@19..20 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__pgf_library_import_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__pgf_library_import_simple.snap
index 8f289f97a4..c36bf857bb 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__pgf_library_import_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__pgf_library_import_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..19
TIKZ_LIBRARY_IMPORT_NAME@0..14 "\\usepgflibrary"
CURLY_GROUP_WORD_LIST@14..19
L_CURLY@14..15 "{"
- WORD@15..18 "foo"
+ KEY@15..18
+ WORD@15..18 "foo"
R_CURLY@18..19 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_enum_item.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_enum_item.snap
index 43dcae1987..0ca7421ac6 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_enum_item.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_enum_item.snap
@@ -10,7 +10,8 @@ ROOT@0..60
BEGIN_ENVIRONMENT_NAME@0..6 "\\begin"
CURLY_GROUP_WORD@6..18
L_CURLY@6..7 "{"
- WORD@7..16 "enumerate"
+ KEY@7..16
+ WORD@7..16 "enumerate"
R_CURLY@16..17 "}"
WHITESPACE@17..18 " "
ENUM_ITEM@18..26
@@ -40,6 +41,7 @@ ROOT@0..60
END_ENVIRONMENT_NAME@45..49 "\\end"
CURLY_GROUP_WORD@49..60
L_CURLY@49..50 "{"
- WORD@50..59 "enumerate"
+ KEY@50..59
+ WORD@50..59 "enumerate"
R_CURLY@59..60 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_options.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_options.snap
index 863f27cf56..3140282630 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_options.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_options.snap
@@ -20,6 +20,7 @@ ROOT@0..34
R_BRACK@20..21 "]"
CURLY_GROUP_WORD_LIST@21..34
L_CURLY@21..22 "{"
- WORD@22..33 "foo/bar.svg"
+ KEY@22..33
+ WORD@22..33 "foo/bar.svg"
R_CURLY@33..34 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_simple.snap
index 02db942d99..2cf133b4d0 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..24
SVG_INCLUDE_NAME@0..11 "\\includesvg"
CURLY_GROUP_WORD_LIST@11..24
L_CURLY@11..12 "{"
- WORD@12..23 "foo/bar.svg"
+ KEY@12..23
+ WORD@12..23 "foo/bar.svg"
R_CURLY@23..24 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_full.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_full.snap
index d8fe3816ad..7f21c0ef52 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_full.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_full.snap
@@ -9,11 +9,13 @@ ROOT@0..31
THEOREM_DEFINITION_NAME@0..11 "\\newtheorem"
CURLY_GROUP_WORD@11..16
L_CURLY@11..12 "{"
- WORD@12..15 "foo"
+ KEY@12..15
+ WORD@12..15 "foo"
R_CURLY@15..16 "}"
BRACK_GROUP_WORD@16..21
L_BRACK@16..17 "["
- WORD@17..20 "bar"
+ KEY@17..20
+ WORD@17..20 "bar"
R_BRACK@20..21 "]"
CURLY_GROUP@21..26
L_CURLY@21..22 "{"
@@ -22,6 +24,7 @@ ROOT@0..31
R_CURLY@25..26 "}"
BRACK_GROUP_WORD@26..31
L_BRACK@26..27 "["
- WORD@27..30 "baz"
+ KEY@27..30
+ WORD@27..30 "baz"
R_BRACK@30..31 "]"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_counter.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_counter.snap
index 9e550b19a4..d7bb29bf58 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_counter.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_counter.snap
@@ -9,11 +9,13 @@ ROOT@0..21
THEOREM_DEFINITION_NAME@0..11 "\\newtheorem"
CURLY_GROUP_WORD@11..16
L_CURLY@11..12 "{"
- WORD@12..15 "foo"
+ KEY@12..15
+ WORD@12..15 "foo"
R_CURLY@15..16 "}"
BRACK_GROUP_WORD@16..21
L_BRACK@16..17 "["
- WORD@17..20 "bar"
+ KEY@17..20
+ WORD@17..20 "bar"
R_BRACK@20..21 "]"
MISSING@21..21 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description.snap
index 356dc079f1..7c8b49efa1 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description.snap
@@ -9,7 +9,8 @@ ROOT@0..21
THEOREM_DEFINITION_NAME@0..11 "\\newtheorem"
CURLY_GROUP_WORD@11..16
L_CURLY@11..12 "{"
- WORD@12..15 "foo"
+ KEY@12..15
+ WORD@12..15 "foo"
R_CURLY@15..16 "}"
CURLY_GROUP@16..21
L_CURLY@16..17 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description_and_counter.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description_and_counter.snap
index cc6e34d378..3322a9a116 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description_and_counter.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description_and_counter.snap
@@ -9,11 +9,13 @@ ROOT@0..26
THEOREM_DEFINITION_NAME@0..11 "\\newtheorem"
CURLY_GROUP_WORD@11..16
L_CURLY@11..12 "{"
- WORD@12..15 "foo"
+ KEY@12..15
+ WORD@12..15 "foo"
R_CURLY@15..16 "}"
BRACK_GROUP_WORD@16..21
L_BRACK@16..17 "["
- WORD@17..20 "bar"
+ KEY@17..20
+ WORD@17..20 "bar"
R_BRACK@20..21 "]"
CURLY_GROUP@21..26
L_CURLY@21..22 "{"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_only_name.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_only_name.snap
index 27a040b7ff..0ba62df76c 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_only_name.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_only_name.snap
@@ -9,7 +9,8 @@ ROOT@0..16
THEOREM_DEFINITION_NAME@0..11 "\\newtheorem"
CURLY_GROUP_WORD@11..16
L_CURLY@11..12 "{"
- WORD@12..15 "foo"
+ KEY@12..15
+ WORD@12..15 "foo"
R_CURLY@15..16 "}"
MISSING@16..16 ""
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__tikz_library_import_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__tikz_library_import_simple.snap
index 4915306c55..4cd63e6728 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__tikz_library_import_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__tikz_library_import_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..20
TIKZ_LIBRARY_IMPORT_NAME@0..15 "\\usetikzlibrary"
CURLY_GROUP_WORD_LIST@15..20
L_CURLY@15..16 "{"
- WORD@16..19 "foo"
+ KEY@16..19
+ WORD@16..19 "foo"
R_CURLY@19..20 "}"
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__verbatim_include_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__verbatim_include_simple.snap
index 399e16d791..48d6b816f3 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__verbatim_include_simple.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__verbatim_include_simple.snap
@@ -9,6 +9,7 @@ ROOT@0..27
VERBATIM_INCLUDE_NAME@0..14 "\\verbatiminput"
CURLY_GROUP_WORD_LIST@14..27
L_CURLY@14..15 "{"
- WORD@15..26 "foo/bar.txt"
+ KEY@15..26
+ WORD@15..26 "foo/bar.txt"
R_CURLY@26..27 "}"
diff --git a/support/texlab/tests/integration/completion.rs b/support/texlab/tests/integration/completion.rs
index 33af77f003..488415e2d6 100644
--- a/support/texlab/tests/integration/completion.rs
+++ b/support/texlab/tests/integration/completion.rs
@@ -239,6 +239,40 @@ mod latex {
}
#[test]
+ fn test_citation_multi_word() -> Result<()> {
+ let server = ServerTester::launch_new_instance()?;
+ server.initialize(ClientCapabilities::default(), None)?;
+ let tex_uri = server.open(
+ "main.tex",
+ r#"
+ \documentclass{article}
+ \bibliography{main}
+ \begin{document}
+ \cite{foo 2
+ \end{document}
+ "#,
+ "latex",
+ false,
+ )?;
+ server.open(
+ "main.bib",
+ r#"
+ @article{foo 2019,
+ author = {Foo Bar},
+ title = {Baz Qux},
+ year = {2019},
+ }
+
+ @article{bar:2005,}
+ "#,
+ "bibtex",
+ false,
+ )?;
+ assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 6)?);
+ Ok(())
+ }
+
+ #[test]
fn test_citation_after() -> Result<()> {
let server = ServerTester::launch_new_instance()?;
server.initialize(ClientCapabilities::default(), None)?;
diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_multi_word.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_multi_word.snap
new file mode 100644
index 0000000000..2ce23ae3fa
--- /dev/null
+++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_multi_word.snap
@@ -0,0 +1,34 @@
+---
+source: tests/integration/completion.rs
+expression: "complete_and_resolve(&server, tex_uri, 3, 6)?"
+
+---
+{
+ "isIncomplete": false,
+ "items": [
+ {
+ "label": "foo 2019",
+ "kind": 1,
+ "documentation": {
+ "kind": "markdown",
+ "value": "Bar, F. (2019). *Baz Qux*."
+ },
+ "preselect": false,
+ "sortText": "00 foo 2019 @articlefoo 2019 author Foo Bar title Baz Qux year 2019",
+ "filterText": "foo 2019 @articlefoo 2019 author Foo Bar title Baz Qux year 2019",
+ "textEdit": {
+ "range": {
+ "start": {
+ "line": 3,
+ "character": 6
+ },
+ "end": {
+ "line": 3,
+ "character": 11
+ }
+ },
+ "newText": "foo 2019"
+ }
+ }
+ ]
+}
diff --git a/support/texlab/texlab.pdf b/support/texlab/texlab.pdf
index bf485f9295..27f915c944 100644
--- a/support/texlab/texlab.pdf
+++ b/support/texlab/texlab.pdf
Binary files differ
diff --git a/support/texlab/texlab.tex b/support/texlab/texlab.tex
new file mode 100644
index 0000000000..7faff8b122
--- /dev/null
+++ b/support/texlab/texlab.tex
@@ -0,0 +1,78 @@
+\documentclass{article}
+\usepackage[utf8]{inputenc}
+\usepackage{hyperref}
+
+\date{\today}
+\author{Eric Förster \and Patrick Förster}
+\title{\TeX{}Lab}
+
+\begin{document}
+
+\maketitle{}
+
+\section{Introduction}
+
+TexLab is a cross-platform implementation of the
+\href{https://microsoft.github.io/language-server-protocol/specifications/specification-current/}{Language Server Protocol}
+for the \LaTeX{} typesetting system.
+It aims to produce high quality code completion results.
+The server may be used with any editor that implements the Language Server Protocol.
+It is written in Rust, a blazingly fast systems programming language.
+
+\section{Features}
+
+The language server implements most of the Language Server Protocol specification.
+In addition to that, it implements additional functionality like
+building and forward search.
+
+\section{Availability}
+
+TexLab is available on \href{https://github.com/latex-lsp/texlab}{GitHub},
+various package managers and CTAN\@.
+Pre-compiled binaries are available on the
+\href{https://github.com/latex-lsp/texlab/releases}{GitHub Releases} page.
+Some editor extensions are able to automatically download TexLab.
+
+\section{Installation}
+
+There are various ways to install TexLab:
+\begin{itemize}
+ \item
+ TexLab is included in some package managers like \texttt{brew},
+ \texttt{pacman} and \texttt{scoop}.
+ Please refer to the badges in the README to see if your package manager
+ includes TexLab.
+ \item
+ You can download a pre-compiled binary from our
+ \href{https://github.com/latex-lsp/texlab/releases}{GitHub Releases} page.
+ \item
+ Some extensions like the Visual Studio Code extension or
+ \texttt{coc-texlab} can automatically download the server for you.
+ \item
+ You can download the sources from either GitHub or CTAN
+ and compile the server with \texttt{cargo build --release}.
+ The \texttt{texlab} binary can be found inside \texttt{target/release}.
+\end{itemize}
+
+\section{Usage}
+
+\subsection{Synopsis}
+
+\texttt{texlab [FLAGS] [OPTIONS]}
+
+\subsection{Flags}
+
+\begin{itemize}
+ \item \texttt{-h}, \texttt{--help} Prints help information
+ \item \texttt{-q}, \texttt{--quiet} No output printed to stderr
+ \item \texttt{-V}, \texttt{--version} Prints version information
+ \item \texttt{-v}, \texttt{--verbosity} Increase message verbosity (\texttt{-vvvv} for max verbosity)
+\end{itemize}
+
+\subsection{Options}
+
+\begin{itemize}
+ \item \texttt{--log-file <FILE>} WRite the logging output to \texttt{FILE}
+\end{itemize}
+
+\end{document} \ No newline at end of file