summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
Diffstat (limited to 'support')
-rw-r--r--support/TeX4ht/source/ChangeLog35
-rw-r--r--support/TeX4ht/source/tex4ht-4ht.tex52
-rw-r--r--support/TeX4ht/source/tex4ht-cpright.tex4
-rw-r--r--support/TeX4ht/source/tex4ht-html4.tex20
-rwxr-xr-xsupport/epstopdf/epstopdf.pl10
-rw-r--r--support/mf2pt1/ChangeLog19
-rw-r--r--support/mf2pt1/README2
-rw-r--r--support/mf2pt1/mf2pt1.mp2
-rw-r--r--support/mf2pt1/mf2pt1.pdfbin183116 -> 182727 bytes
-rwxr-xr-xsupport/mf2pt1/mf2pt1.pl8
-rw-r--r--support/mf2pt1/mf2pt1.texi16
-rw-r--r--support/pdfjam/VERSION2
-rwxr-xr-xsupport/pdfjam/bin/pdfjam4
-rw-r--r--support/texlab/CHANGELOG.md32
-rw-r--r--support/texlab/Cargo.lock123
-rw-r--r--support/texlab/crates/base-db/Cargo.toml8
-rw-r--r--support/texlab/crates/base-db/src/deps/graph.rs81
-rw-r--r--support/texlab/crates/base-db/src/document.rs17
-rw-r--r--support/texlab/crates/base-db/src/semantics/tex.rs68
-rw-r--r--support/texlab/crates/bibtex-utils/Cargo.toml4
-rw-r--r--support/texlab/crates/citeproc/Cargo.toml4
-rw-r--r--support/texlab/crates/commands/Cargo.toml12
-rw-r--r--support/texlab/crates/commands/src/dep_graph.rs1
-rw-r--r--support/texlab/crates/completion-data/Cargo.toml8
-rw-r--r--support/texlab/crates/completion/Cargo.toml3
-rw-r--r--support/texlab/crates/completion/src/lib.rs2
-rw-r--r--support/texlab/crates/completion/src/providers/label_ref.rs46
-rw-r--r--support/texlab/crates/completion/src/tests.rs213
-rw-r--r--support/texlab/crates/definition/Cargo.toml4
-rw-r--r--support/texlab/crates/diagnostics/Cargo.toml8
-rw-r--r--support/texlab/crates/distro/Cargo.toml2
-rw-r--r--support/texlab/crates/distro/src/language.rs2
-rw-r--r--support/texlab/crates/inlay-hints/Cargo.toml2
-rw-r--r--support/texlab/crates/ipc/Cargo.toml8
-rw-r--r--support/texlab/crates/line-index/Cargo.toml2
-rw-r--r--support/texlab/crates/parser/Cargo.toml8
-rw-r--r--support/texlab/crates/parser/src/bibtex.rs54
-rw-r--r--support/texlab/crates/parser/src/bibtex/tests.rs277
-rw-r--r--support/texlab/crates/parser/src/config.rs26
-rw-r--r--support/texlab/crates/parser/src/file_list.rs44
-rw-r--r--support/texlab/crates/parser/src/latex/lexer/types.rs49
-rw-r--r--support/texlab/crates/parser/src/lib.rs6
-rw-r--r--support/texlab/crates/parser/src/util.rs52
-rw-r--r--support/texlab/crates/references/Cargo.toml2
-rw-r--r--support/texlab/crates/rename/Cargo.toml3
-rw-r--r--support/texlab/crates/rename/src/command.rs5
-rw-r--r--support/texlab/crates/rename/src/entry.rs2
-rw-r--r--support/texlab/crates/rename/src/label.rs47
-rw-r--r--support/texlab/crates/rename/src/lib.rs22
-rw-r--r--support/texlab/crates/rename/src/tests.rs111
-rw-r--r--support/texlab/crates/symbols/Cargo.toml4
-rw-r--r--support/texlab/crates/symbols/src/document.rs1
-rw-r--r--support/texlab/crates/syntax/Cargo.toml3
-rw-r--r--support/texlab/crates/syntax/src/file_list.rs10
-rw-r--r--support/texlab/crates/syntax/src/lib.rs1
-rw-r--r--support/texlab/crates/texlab/Cargo.toml18
-rw-r--r--support/texlab/crates/texlab/src/features/formatting.rs3
-rw-r--r--support/texlab/crates/texlab/src/server/options.rs6
-rw-r--r--support/texlab/crates/texlab/src/util.rs59
-rw-r--r--support/texlab/crates/texlab/src/util/client_flags.rs6
-rw-r--r--support/texlab/crates/texlab/src/util/from_proto.rs28
-rw-r--r--support/texlab/crates/texlab/src/util/to_proto.rs11
-rw-r--r--support/texlab/texlab.14
-rw-r--r--support/texlab/texlab.pdfbin26420 -> 26472 bytes
64 files changed, 1379 insertions, 307 deletions
diff --git a/support/TeX4ht/source/ChangeLog b/support/TeX4ht/source/ChangeLog
index dd7c62fc27..6bf8ba7fce 100644
--- a/support/TeX4ht/source/ChangeLog
+++ b/support/TeX4ht/source/ChangeLog
@@ -1,8 +1,41 @@
+2024-07-06 Michal Hoftich <michal.h21@gmail.com>
+
+ * tex4ht-html4.tex (html4.4ht): added itemize+ option. It will keep
+ original characters for itemize bullets.
+ https://tex.stackexchange.com/a/722062/2891
+
+2024-07-03 Michal Hoftich <michal.h21@gmail.com>
+
+ * tex4ht-4ht.tex (fontawesome5.4ht): use icon name as the alt text.
+
+2024-06-21 Michal Hoftich <michal.h21@gmail.com>
+
+ * tex4ht-4ht.tex (arydshln.4ht): fixed clash between Colortbl and
+ Arydshln packages.
+ https://tex.stackexchange.com/a/721185/2891
+
+2024-06-23 Karl Berry <karl@freefriends.org>
+
+ * tex4ht-cpright.tex: https for urls.
+
+2024-06-21 Michal Hoftich <michal.h21@gmail.com>
+
+ * tex4ht-html4.tex (html4.4ht): don't use picture name as alt in
+ \epsfbox, it can lead to spurious characters in the resulting HTML.
+ Thanks to Rolf Brigola
+
+2024-06-20 Michal Hoftich <michal.h21@gmail.com>
+
+ * tex4ht-4ht.tex (footmisc.4ht): fixed handling of footnote counter
+ reset.
+ https://tex.stackexchange.com/a/720989/2891
+
+
2024-06-17 Michal Hoftich <michal.h21@gmail.com>
* tex4ht-4ht.tex (tabularray.4ht): updated names of token lists that
holds rowspan and colspan.
- https://tex.stackexchange.com/a/720800/2891
+ https://tex.stackexchange.com/a/720800/2891
2024-06-15 Michal Hoftich <michal.h21@gmail.com>
diff --git a/support/TeX4ht/source/tex4ht-4ht.tex b/support/TeX4ht/source/tex4ht-4ht.tex
index 0fd6e45cba..f3617f3757 100644
--- a/support/TeX4ht/source/tex4ht-4ht.tex
+++ b/support/TeX4ht/source/tex4ht-4ht.tex
@@ -1,4 +1,4 @@
-% $Id: tex4ht-4ht.tex 1531 2024-06-17 19:40:15Z michal_h21 $
+% $Id: tex4ht-4ht.tex 1536 2024-07-03 12:08:13Z michal_h21 $
% tex tex4ht-4ht or ht tex tex4ht-4ht
%
% Copyright 2009-2024 TeX Users Group
@@ -4265,18 +4265,19 @@ icons to pictures by TeX4ht conversion.
\<fontawesome5.4ht\><<<
% fontawesome5.4ht (|version), generated from |jobname.tex
-% Copyright 2021 TeX Users Group
+% Copyright 2021-2024 TeX Users Group
|<TeX4ht license text|>
\NewConfigure{fontawesome}{2}
\ExplSyntaxOn
\cs_new_protected:Nn\temp:nn{%
+\def\:fontawesomeicon{#2}% to be used in the alt text
\a:fontawesome%
\o:fontawesome_use_icon:nn:{#1}{#2}
\b:fontawesome}
\HLet\fontawesome_use_icon:nn\temp:nn
\ExplSyntaxOff
-\Configure{fontawesome}{\Picture+{}}{\EndPicture}
+\Configure{fontawesome}{\Picture+[icon: \:fontawesomeicon]{}}{\EndPicture}
\Hinput{fontawesome5}
\endinput
>>> \AddFile{9}{fontawesome5}
@@ -11225,12 +11226,13 @@ compilation errors
\<arydshln.4ht\><<<
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% arydshln.4ht (|version), generated from |jobname.tex
-% Copyright 2022 TeX Users Group
+% Copyright 2022-2024 TeX Users Group
|<TeX4ht license text|>
% this is a copy of code that arydshln inserts to \@array
\def\:new:array{\adl@everyvbox\everyvbox
\everyvbox{\adl@arrayinit \the\adl@everyvbox \everyvbox\adl@everyvbox}%
- \ifadl@inactive \adl@inactivate \else \adl@activate \fi
+ % this line may lead to errors if the document uses Colortbl:
+ % \ifadl@inactive \adl@inactivate \else \adl@activate \fi
\let\adl@noalign\noalign}
\ifcsname n:@array:\endcsname% if \@array was already patched by TeX4ht
\let\orig:n@array\n:@array:
@@ -37900,9 +37902,39 @@ Use
\<footmisc.4ht\><<<
% footmisc.4ht (|version), generated from |jobname.tex
-% Copyright 2019 TeX Users Group
+% Copyright 2019-2024 TeX Users Group
|<TeX4ht license text|>
+|<footmisc footnote counter|>
+|<footmisc footnotetext|>
+|<footmisc symbols|>
+
+
+\Hinput{footmisc}
+\endinput
+>>> \AddFile{9}{footmisc}
+
+Footmisc can reset the normal footnote counter on every page. Footnote links are
+then wrong, as they point to an earlier footnote. My solution is to use a global
+counter that gives each footnote unique number and which doesn't rely on the footnote
+symbol.
+
+\<footmisc footnote counter\><<<
+\newcounter{:footnotes}
+
+\def\FNnum{\the\:footnotes}
+\HRestore\footnote
+
+\def\:tempc{%
+ \HAssign\FNnum = \csname c@:footnotes\endcsname%
+ \stepcounter{:footnotes}%
+ \HAdvance\FNnum by 1%
+ \o:footnote:%
+}
+\HLet\footnote=\:tempc
+>>>
+
+\<footmisc footnotetext\><<<
\long\def\@footnotetext#1{\leavevmode
\vbox{%\IgnorePar
\leftskip0pt {\ht:everypar{}\parindent0pt\leavevmode}%
@@ -37921,6 +37953,9 @@ Use
\color@endgroup
\ht:special{t4ht@[}}\ht:special{t4ht@]}}
+>>>
+
+\<footmisc symbols\><<<
% detect if the symbol or symbol* option were used
% we can detect that by testing of \thefootnote macro
@@ -37937,10 +37972,7 @@ Use
\newcommand\p@footmisc@footnote[1]{\p@footnote{#1}}
\fi
\fi
-
-\Hinput{footmisc}
-\endinput
->>> \AddFile{9}{footmisc}
+>>>
%%%%%%%%%%%%%%%
\Section{tablefootnote}
diff --git a/support/TeX4ht/source/tex4ht-cpright.tex b/support/TeX4ht/source/tex4ht-cpright.tex
index 3527690921..c15155fcc5 100644
--- a/support/TeX4ht/source/tex4ht-cpright.tex
+++ b/support/TeX4ht/source/tex4ht-cpright.tex
@@ -4,14 +4,14 @@
% conditions of the LaTeX Project Public License, either
% version 1.3c of this license or (at your option) any
% later version. The latest version of this license is in
-% http://www.latex-project.org/lppl.txt
+% https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions
% of LaTeX version 2005/12/01 or later.
%
% This work has the LPPL maintenance status "maintained".
%
% The Current Maintainer of this work
-% is the TeX4ht Project <http://tug.org/tex4ht>.
+% is the TeX4ht Project <https://tug.org/tex4ht>.
%
% If you modify this program, changing the
% version identification would be appreciated.>>>
diff --git a/support/TeX4ht/source/tex4ht-html4.tex b/support/TeX4ht/source/tex4ht-html4.tex
index a2f3a57781..13bf280c88 100644
--- a/support/TeX4ht/source/tex4ht-html4.tex
+++ b/support/TeX4ht/source/tex4ht-html4.tex
@@ -1,4 +1,4 @@
-% $Id: tex4ht-html4.tex 1526 2024-05-28 19:03:35Z michal_h21 $
+% $Id: tex4ht-html4.tex 1537 2024-07-06 19:48:42Z michal_h21 $
% Compile 4 times: latex tex4ht-html4
% Copy html4.4ht into the work directory before all but the last compilation.
%
@@ -2950,6 +2950,22 @@ such a case, we don't have proper nestings of environments.
\EndP\HCode{</li></ul>}\ShowPar}
{\end:itm \global\def\end:itm{\EndP\Tg</li>}\DeleteMark}
{\HCode{<li class="\getClass{li}itemize">}\afterGetClass{li}|<list par|>}
+
+\:CheckOption{itemize+}\if:Option
+\ConfigureList{itemize}%
+ {\EndP\HCode{<ul \a:LRdir
+ class="\getClass{itemize}itemize\expandafter\the
+ \csname @itemdepth\endcsname">}%
+ \afterGetClass{itemize}%
+ |<save end:itm|>\global\let\end:itm=\empty}
+ {|<recall end:itm|>\ifvmode \IgnorePar\fi
+ \EndP\HCode{</li></ul>}\ShowPar}
+ {\end:itm \global\def\end:itm{\EndP\Tg</li>}\HCode{<li class="\getClass{li}itemize"><span class="itemizeHead" aria-hidden="true">}\afterGetClass{li}}
+ {\HCode{</span>}|<list par|>}
+\Css{.itemizeHead{float: left; margin-left: -1em; width: 1em;}}
+\Css{li.itemize{list-style: none;}}
+\fi
+
\NewConfigure{itemizeClass}{2}
\Configure{itemizeClass}{}{}
\NewConfigure{liClass}{2}
@@ -13824,7 +13840,7 @@ for margin pars.
\<configure html4 epsf\><<<
\Configure{epsfsetgraph}
- {\Picture+[\PicName]{}}
+ {\Picture+[]{}}
{\EndPicture}
>>>
diff --git a/support/epstopdf/epstopdf.pl b/support/epstopdf/epstopdf.pl
index df768ef815..1a59965017 100755
--- a/support/epstopdf/epstopdf.pl
+++ b/support/epstopdf/epstopdf.pl
@@ -1,6 +1,6 @@
#!/usr/bin/env perl
use warnings;
-# $Id: epstopdf.pl 71121 2024-04-29 17:27:25Z karl $
+# $Id: epstopdf.pl 71584 2024-06-21 22:40:28Z karl $
# (Copyright lines below.)
#
# Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,9 @@ use warnings;
#
# emacs-page
#
-my $ver = "2.34";
+my $ver = "2.35";
+# 2024/06/21 2.35 (Karl Berry)
+# * path_sep for OS/2 is also ";".
# 2024/04/29 2.34 (Karl Berry)
# * if --debug is first argument, give more output.
# * do not check for kpsewhich in PATH unless restricted.
@@ -226,7 +228,7 @@ my $ver = "2.34";
### emacs-page
### program identification
my $program = "epstopdf";
-my $ident = '($Id: epstopdf.pl 71121 2024-04-29 17:27:25Z karl $)' . " $ver";
+my $ident = '($Id: epstopdf.pl 71584 2024-06-21 22:40:28Z karl $)' . " $ver";
my $copyright = <<END_COPYRIGHT ;
Copyright 2009-2024 Karl Berry et al.
Copyright 2002-2009 Gerben Wierda et al.
@@ -258,7 +260,7 @@ debug " on_cygwin=$on_cygwin, on_msys=$on_msys";
# Split PATH and use / as directory separator.
#
-my $path_sep = ( ($^O =~ /^MSWin/) ? ';' : ':' ); # not msys
+my $path_sep = ($^O =~ /^(OS2|MSWin)i/) ? ';' : ':'; # not msys
my @pdirs = split($path_sep, $ENV{"PATH"});
# Normalize directory separators to /. Always valid on Windows.
if ($on_windows_or_cygwin) {
diff --git a/support/mf2pt1/ChangeLog b/support/mf2pt1/ChangeLog
index a8e6d2d910..6df8f95067 100644
--- a/support/mf2pt1/ChangeLog
+++ b/support/mf2pt1/ChangeLog
@@ -1,4 +1,15 @@
-2021-12-04 Scott Pakin <pakin@pakin.org>
+2024-07-06 Scott Pakin <scott+mf@pakin.org>
+
+ * README, mf2pt1.texi, mf2pt1.mp, mf2pt1.pl: Updated the copyright
+ year to 2024.
+
+ * mf2pt1.pl: Applied a patch from Werner Lemberg <wl@gnu.org> that
+ adds extrema later in the FontForge postprocessing script. This
+ patch originally was submitted as a LilyPond merge request
+ (https://gitlab.com/lilypond/lilypond/-/merge_requests/2374).
+ Updated the program version to 2.8.
+
+2021-12-04 Scott Pakin <scott+mf@pakin.org>
* README, mf2pt1.texi: Updated the copyright year to 2021.
@@ -7,7 +18,7 @@
already exist. Updated the copyright year to 2021. Updated the
version to 2.7.
-2021-11-28 Scott Pakin <pakin@pakin.org>
+2021-11-28 Scott Pakin <scott+mf@pakin.org>
* Makefile, mf2pt1.pl, mf2pt1.texi:
Documented that environment variables for programs can now include
@@ -18,13 +29,13 @@
commands to be overridden by environment variables that can also
include program parameters.
-2021-11-27 Scott Pakin <pakin@pakin.org>
+2021-11-27 Scott Pakin <scott+mf@pakin.org>
* mf2pt1.pl:
Introduced a --save-temps option to suppress deletion of intermediate
files.
-2020-11-27 Scott Pakin <pakin@pakin.org>
+2020-11-27 Scott Pakin <scott+mf@pakin.org>
* ChangeLog, README, mf2pt1.mp, mf2pt1.pl, mf2pt1.texi:
mf2pt1 no longer generates a UniqueID automatically, only when
diff --git a/support/mf2pt1/README b/support/mf2pt1/README
index 0eb57ca8fc..e101952ff9 100644
--- a/support/mf2pt1/README
+++ b/support/mf2pt1/README
@@ -27,7 +27,7 @@ For installation instructions, see the mf2pt1 manual (mf2pt1.pdf).
Copyright and license
---------------------
-Copyright (C) 2005-2021 Scott Pakin, scott+mf@pakin.org
+Copyright (C) 2005-2024 Scott Pakin, scott+mf@pakin.org
This package may be distributed and/or modified under the conditions
of the LaTeX Project Public License, either version 1.3c of this
diff --git a/support/mf2pt1/mf2pt1.mp b/support/mf2pt1/mf2pt1.mp
index 3ef56f9ab9..e5cbc9474f 100644
--- a/support/mf2pt1/mf2pt1.mp
+++ b/support/mf2pt1/mf2pt1.mp
@@ -10,7 +10,7 @@
%%%% ==================================================================== %%%%
%%%% mf2pt1 %%%%
-%%%% Copyright (C) 2005-2020 Scott Pakin %%%%
+%%%% Copyright (C) 2005-2024 Scott Pakin %%%%
%%%% %%%%
%%%% This program may be distributed and/or modified under the conditions %%%%
%%%% of the LaTeX Project Public License, either version 1.3c of this %%%%
diff --git a/support/mf2pt1/mf2pt1.pdf b/support/mf2pt1/mf2pt1.pdf
index a28895171a..e702482c74 100644
--- a/support/mf2pt1/mf2pt1.pdf
+++ b/support/mf2pt1/mf2pt1.pdf
Binary files differ
diff --git a/support/mf2pt1/mf2pt1.pl b/support/mf2pt1/mf2pt1.pl
index a9ee8b74fc..982f8c98be 100755
--- a/support/mf2pt1/mf2pt1.pl
+++ b/support/mf2pt1/mf2pt1.pl
@@ -7,7 +7,7 @@
########################################################################
# mf2pt1 #
-# Copyright (C) 2005-2021 Scott Pakin #
+# Copyright (C) 2005-2024 Scott Pakin #
# #
# This program may be distributed and/or modified under the conditions #
# of the LaTeX Project Public License, either version 1.3c of this #
@@ -21,7 +21,7 @@
# version 2006/05/20 or later. #
########################################################################
-our $VERSION = "2.7"; # mf2pt1 version number
+our $VERSION = "2.8"; # mf2pt1 version number
require 5.6.1; # I haven't tested mf2pt1 with older Perl versions
use Cwd;
@@ -161,7 +161,7 @@ my $filedir;
my $filenoext;
my $versionmsg = "mf2pt1 version $VERSION
-Copyright (C) 2005-2021 Scott Pakin
+Copyright (C) 2005-2024 Scott Pakin
This program may be distributed and/or modified under the conditions
of the LaTeX Project Public License, either version 1.3c of this
@@ -1006,9 +1006,9 @@ else {
Open($1);
SelectAll();
RemoveOverlap();
-AddExtrema();
Simplify(0, 2);
CorrectDirection();
+AddExtrema(1);
Simplify(0, 2);
RoundToInt();
AutoHint();
diff --git a/support/mf2pt1/mf2pt1.texi b/support/mf2pt1/mf2pt1.texi
index 9260689d18..f18ed6694c 100644
--- a/support/mf2pt1/mf2pt1.texi
+++ b/support/mf2pt1/mf2pt1.texi
@@ -11,7 +11,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 2005--2021 Scott Pakin
+Copyright @copyright{} 2005--2024 Scott Pakin
@sp 2
@@ -30,8 +30,8 @@ version 2006/05/20 or later.
@end copying
-@set VERSION 2.7
-@set DATE 4 December 2021
+@set VERSION 2.8
+@set DATE 6 July 2024
@c Define some fonts we intend to use.
@iftex
@@ -679,9 +679,9 @@ parameters that @command{mf2pt1} accepts:
@noindent
@b{if} known @i{ps_output}:
-@multitable {@b{if}} {@b{font_underline_thickness}} {@t{"Copyright (C) 2021 Scott Pakin.";}}
+@multitable {@b{if}} {@b{font_underline_thickness}} {@t{"Copyright (C) 2005-2024 Scott Pakin.";}}
@item @tab @b{font_coding_scheme} @tab @t{"ot1"};
-@item @tab @b{font_comment} @tab @t{"Copyright (C) 2021 Scott Pakin."};
+@item @tab @b{font_comment} @tab @t{"Copyright (C) 2005-2024 Scott Pakin."};
@item @tab @b{font_family} @tab @t{"Kerplotz"};
@item @tab @b{font_fixed_pitch} @tab @b{false};
@item @tab @b{font_identifier} @tab @t{"Kerplotz Light Oblique"};
@@ -708,7 +708,7 @@ The same parameters can also be specified on the command line as
follows:
@example
-mf2pt1 --encoding=ot1 --comment="Copyright (C) 2021 Scott Pakin."
+mf2pt1 --encoding=ot1 --comment="Copyright (C) 2005-2024 Scott Pakin."
--family=Kerplotz --nofixedpitch --fullname="Kerplotz Light Oblique"
--name=Kerplotz-LightOblique --designsize=10 --italicangle=-9.5
--underpos=-100 --underthick=50 --uniqueid=4112233 --version=002.005
@@ -881,7 +881,7 @@ character position the current encoding has designated for the
@section Restoring @file{mfplain} defaults
@command{mf2pt1} normally redefines @strong{filldraw} as @strong{fill}
-and @strong{unfilldraw} and @strong{unfill} because @w{Type 1} fonts
+and @strong{unfilldraw} as @strong{unfill} because @w{Type 1} fonts
don't allow overlapping curves. Similarly, @command{mf2pt1} redefines
@strong{pencircle} as a 20-gon to coerce MetaPost into drawing it
using a filled instead of a stroked PostScript path.
@@ -957,7 +957,7 @@ more robust way to dump @file{mf2pt1.mem}; for directing me to the
overlap-removal code mentioned in @ref{Restrictions}; for supplying
the @emph{crossproduct}, @emph{makeline}, and @emph{is_clockwise}
functions used by @file{mf2pt1.mp}; for proposing the @copt{bpppix}
-command-line option; and for suggesting various features and
+command-line option; and for suggesting numerous features and
improvements to @command{mf2pt1}. Thanks also go to Werner Lemberg
and
@iftex
diff --git a/support/pdfjam/VERSION b/support/pdfjam/VERSION
index ab9bd6936f..cd7061f818 100644
--- a/support/pdfjam/VERSION
+++ b/support/pdfjam/VERSION
@@ -1 +1 @@
-This is pdfjam 3.11
+This is pdfjam 3.12
diff --git a/support/pdfjam/bin/pdfjam b/support/pdfjam/bin/pdfjam
index 814da49599..ff9a0123cd 100755
--- a/support/pdfjam/bin/pdfjam
+++ b/support/pdfjam/bin/pdfjam
@@ -1,5 +1,5 @@
#!/bin/sh
-version=3.11
+version=3.12
#########################################################################
## ##
## pdfjam: A shell-script interface to the "pdfpages" LaTeX package ##
@@ -1144,7 +1144,7 @@ do
then
if tty -s ; then
error_exit \
- "tty is connected to connected to stdin, no PDF/JPG/PNG file found" \
+ "tty is connected to stdin, no PDF/JPG/PNG file found" \
$E_NOINPUT
fi
cat > "$uniqueName"
diff --git a/support/texlab/CHANGELOG.md b/support/texlab/CHANGELOG.md
index 8008720d9b..f2fa8d96cf 100644
--- a/support/texlab/CHANGELOG.md
+++ b/support/texlab/CHANGELOG.md
@@ -5,6 +5,38 @@ 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).
+## [5.19.0] - 2024-07-08
+
+### Added
+
+- Add `texlab.build.useFileList` setting to allow controlling whether to use the `.fls` files
+
+### Changed
+
+- Disable using `.fls` files for project detection by default
+
+## [5.18.0] - 2024-07-06
+
+### Added
+
+- Parse `.fls` files to make the project detection more reliable ([#1145](https://github.com/latex-lsp/texlab/issues/1145))
+
+### Fixed
+
+- Fix parsing commands with unicode characters inside BibTeX entries
+ ([#1147](https://github.com/latex-lsp/texlab/issues/1147))
+- Improve detection of included files when non-ASCII characters are used ([#923](https://github.com/latex-lsp/texlab/issues/923))
+- Fix resolving includes starting from files included using `\subimport` ([#1145](https://github.com/latex-lsp/texlab/issues/1145))
+
+## [5.17.0] - 2024-06-23
+
+### Added
+
+- Add label commands from `zref` and `zref-clever` to the list of default label commands
+ ([#1140](https://github.com/latex-lsp/texlab/pull/1140))
+- Add `texlab.experimental.labelDefinitionPrefixes` and
+ `texlab.experimental.labelReferencePrefixes` options ([#1139](https://github.com/latex-lsp/texlab/pull/1139))
+
## [5.16.1] - 2024-05-25
### Fixed
diff --git a/support/texlab/Cargo.lock b/support/texlab/Cargo.lock
index 9d651234e1..ead2473278 100644
--- a/support/texlab/Cargo.lock
+++ b/support/texlab/Cargo.lock
@@ -90,7 +90,7 @@ dependencies = [
"bibtex-utils",
"dirs",
"distro",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"line-index",
"log",
"notify",
@@ -99,7 +99,7 @@ dependencies = [
"percent-encoding",
"regex",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"shellexpand",
"syntax",
"titlecase",
@@ -130,10 +130,10 @@ dependencies = [
"chrono",
"expect-test",
"human_name",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"parser",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"unicode-normalization",
]
@@ -232,10 +232,10 @@ dependencies = [
"bibtex-utils",
"expect-test",
"isocountry",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"parser",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"titlecase",
"unicode-normalization",
@@ -244,9 +244,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.4"
+version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
dependencies = [
"clap_builder",
"clap_derive",
@@ -254,9 +254,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.2"
+version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
dependencies = [
"anstream",
"anstyle",
@@ -266,9 +266,9 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.4"
+version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
dependencies = [
"heck",
"proc-macro2",
@@ -298,11 +298,11 @@ dependencies = [
"crossbeam-channel",
"distro",
"expect-test",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"libc",
"log",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"test-utils",
"thiserror",
@@ -334,9 +334,10 @@ dependencies = [
"expect-test",
"fuzzy-matcher",
"line-index",
+ "parser",
"rayon",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"test-utils",
"url",
@@ -347,9 +348,9 @@ name = "completion-data"
version = "0.0.0"
dependencies = [
"flate2",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"once_cell",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"serde",
"serde_json",
]
@@ -407,9 +408,9 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
-version = "0.5.12"
+version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
dependencies = [
"crossbeam-utils",
]
@@ -449,9 +450,9 @@ name = "definition"
version = "0.0.0"
dependencies = [
"base-db",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"test-utils",
]
@@ -464,14 +465,14 @@ dependencies = [
"encoding_rs",
"encoding_rs_io",
"expect-test",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"line-index",
"log",
"multimap",
"once_cell",
"regex",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"test-utils",
"url",
@@ -509,7 +510,7 @@ name = "distro"
version = "0.0.0"
dependencies = [
"anyhow",
- "rustc-hash",
+ "rustc-hash 2.0.0",
]
[[package]]
@@ -741,7 +742,7 @@ dependencies = [
"base-db",
"expect-test",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"test-utils",
]
@@ -810,9 +811,9 @@ dependencies = [
[[package]]
name = "itertools"
-version = "0.12.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
@@ -860,15 +861,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.154"
+version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "line-index"
version = "0.0.0"
dependencies = [
- "rustc-hash",
+ "rustc-hash 2.0.0",
"text-size",
]
@@ -899,9 +900,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.21"
+version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "logos"
@@ -1094,9 +1095,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "parking_lot"
-version = "0.12.2"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -1126,7 +1127,7 @@ dependencies = [
"pathdiff",
"regex",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"tempfile",
"versions",
@@ -1298,16 +1299,16 @@ version = "0.0.0"
dependencies = [
"base-db",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"test-utils",
]
[[package]]
name = "regex"
-version = "1.10.4"
+version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
@@ -1337,8 +1338,9 @@ name = "rename"
version = "0.0.0"
dependencies = [
"base-db",
+ "parser",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"test-utils",
]
@@ -1352,7 +1354,7 @@ dependencies = [
"countme",
"hashbrown",
"memoffset",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"text-size",
]
@@ -1363,6 +1365,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
+name = "rustc-hash"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
+
+[[package]]
name = "rustix"
version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1404,18 +1412,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
-version = "1.0.202"
+version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
+checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.202"
+version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
+checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
@@ -1424,9 +1432,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.117"
+version = "1.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
+checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0"
dependencies = [
"itoa",
"ryu",
@@ -1494,7 +1502,7 @@ dependencies = [
"base-db",
"distro",
"expect-test",
- "itertools 0.12.1",
+ "itertools 0.13.0",
"line-index",
"regex",
"rowan",
@@ -1519,8 +1527,9 @@ dependencies = [
name = "syntax"
version = "0.0.0"
dependencies = [
- "itertools 0.12.1",
+ "itertools 0.13.0",
"rowan",
+ "rustc-hash 2.0.0",
]
[[package]]
@@ -1548,7 +1557,7 @@ dependencies = [
[[package]]
name = "texlab"
-version = "5.16.1"
+version = "5.19.0"
dependencies = [
"anyhow",
"base-db",
@@ -1582,7 +1591,7 @@ dependencies = [
"regex",
"rename",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"serde",
"serde_json",
"serde_regex",
@@ -1601,18 +1610,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
[[package]]
name = "thiserror"
-version = "1.0.59"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
+checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.59"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
+checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
@@ -1742,11 +1751,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "versions"
-version = "6.2.0"
+version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38a8931f8d167b6448076020e70b9de46dcf5ea1731212481a092d0071c4ac5b"
+checksum = "5fc28d1172a20e32754969ea1a873c2c6e68e36c449c6056aa3e2ee5fe69a794"
dependencies = [
- "itertools 0.12.1",
+ "itertools 0.13.0",
"nom",
]
diff --git a/support/texlab/crates/base-db/Cargo.toml b/support/texlab/crates/base-db/Cargo.toml
index ca477c496c..547ba2ad77 100644
--- a/support/texlab/crates/base-db/Cargo.toml
+++ b/support/texlab/crates/base-db/Cargo.toml
@@ -10,16 +10,16 @@ rust-version.workspace = true
bibtex-utils = { path = "../bibtex-utils" }
dirs = "5.0.1"
distro = { path = "../distro" }
-itertools = "0.12.1"
+itertools = "0.13.0"
line-index = { path = "../line-index" }
-log = "0.4.21"
+log = "0.4.22"
notify = "6.0.1"
once_cell = "1.19.0"
parser = { path = "../parser" }
percent-encoding = "2.3.0"
-regex = "1.10.4"
+regex = "1.10.5"
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
shellexpand = "3.1.0"
syntax = { path = "../syntax" }
titlecase = "3.0.0"
diff --git a/support/texlab/crates/base-db/src/deps/graph.rs b/support/texlab/crates/base-db/src/deps/graph.rs
index 4b2399b7f8..0d8252688d 100644
--- a/support/texlab/crates/base-db/src/deps/graph.rs
+++ b/support/texlab/crates/base-db/src/deps/graph.rs
@@ -1,4 +1,4 @@
-use std::{ffi::OsStr, path::PathBuf, rc::Rc};
+use std::{ffi::OsStr, path::PathBuf, rc::Rc, sync::Arc};
use distro::Language;
use itertools::Itertools;
@@ -23,6 +23,7 @@ pub struct Edge {
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum EdgeData {
DirectLink(Box<DirectLinkData>),
+ FileList(Arc<ProjectRoot>),
AdditionalFiles,
Artifact,
}
@@ -74,6 +75,7 @@ impl Graph {
if visited.insert(edge.target.clone()) {
let new_root = match &edge.data {
EdgeData::DirectLink(data) => data.new_root.clone(),
+ EdgeData::FileList(root) => Some(root.as_ref().clone()),
_ => None,
};
@@ -101,6 +103,10 @@ impl Graph {
self.add_direct_links(workspace, start);
self.add_artifacts(workspace, start);
self.add_additional_files(workspace, start);
+
+ if workspace.config().syntax.use_file_list {
+ self.add_file_list_links(workspace, start);
+ }
}
fn add_additional_files(&mut self, workspace: &Workspace, start: Start) {
@@ -120,6 +126,43 @@ impl Graph {
}
}
+ fn add_file_list_links(&mut self, workspace: &Workspace, start: Start) -> Option<()> {
+ let file_list = start.source.data.as_file_list()?;
+ let home_dir = HOME_DIR.as_deref();
+
+ let working_dir = file_list
+ .working_dir
+ .as_deref()
+ .and_then(|dir| Url::from_directory_path(dir).ok());
+
+ let working_dir = working_dir.as_ref().unwrap_or(&start.source.dir);
+ let new_root = Arc::new(ProjectRoot::from_config(workspace, working_dir));
+
+ for target_uri in file_list
+ .inputs
+ .iter()
+ .chain(file_list.outputs.iter())
+ .filter(|path| {
+ path.is_relative()
+ || Language::from_path(&path) == Some(Language::Bib)
+ || home_dir.map_or(false, |home_dir| path.starts_with(home_dir))
+ })
+ .filter_map(|path| working_dir.join(path.to_str()?).ok())
+ {
+ if workspace.lookup(&target_uri).is_some() {
+ self.edges.push(Edge {
+ source: start.source.uri.clone(),
+ target: target_uri,
+ data: EdgeData::FileList(Arc::clone(&new_root)),
+ });
+ } else {
+ self.missing.push(target_uri);
+ }
+ }
+
+ Some(())
+ }
+
fn add_direct_links(&mut self, workspace: &Workspace, start: Start) -> Option<()> {
let data = start.source.data.as_tex()?;
@@ -169,7 +212,7 @@ impl Graph {
.base_dir
.as_deref()
.and_then(|path| start.root.src_dir.join(path).ok())
- .map(|dir| ProjectRoot::walk_and_find(workspace, &dir));
+ .map(|dir| ProjectRoot::from_config(workspace, &dir));
let link_data = DirectLinkData {
link: link.clone(),
@@ -197,27 +240,33 @@ impl Graph {
}
let root = start.root;
- let relative_path = root.compile_dir.make_relative(&start.source.uri).unwrap();
-
- self.add_artifact(
- workspace,
- start.source,
- &root.aux_dir.join(&relative_path).unwrap(),
- "aux",
- );
+ self.add_artifact_group(workspace, start, &root.aux_dir, "aux");
+ self.add_artifact_group(workspace, start, &root.log_dir, "log");
+ self.add_artifact_group(workspace, start, &root.aux_dir, "fls");
+ }
- self.add_artifact(workspace, start.source, &root.aux_dir, "aux");
- self.add_artifact(workspace, start.source, &root.compile_dir, "aux");
+ fn add_artifact_group(
+ &mut self,
+ workspace: &Workspace,
+ start: Start,
+ dir: &Url,
+ extension: &str,
+ ) {
+ let relative_path = start
+ .root
+ .compile_dir
+ .make_relative(&start.source.uri)
+ .unwrap();
self.add_artifact(
workspace,
start.source,
- &root.log_dir.join(&relative_path).unwrap(),
- "log",
+ &dir.join(&relative_path).unwrap(),
+ extension,
);
- self.add_artifact(workspace, start.source, &root.log_dir, "log");
- self.add_artifact(workspace, start.source, &root.compile_dir, "log");
+ self.add_artifact(workspace, start.source, &dir, extension);
+ self.add_artifact(workspace, start.source, &start.root.compile_dir, extension);
}
fn add_artifact(
diff --git a/support/texlab/crates/base-db/src/document.rs b/support/texlab/crates/base-db/src/document.rs
index 7a388129fd..6fdcf30c16 100644
--- a/support/texlab/crates/base-db/src/document.rs
+++ b/support/texlab/crates/base-db/src/document.rs
@@ -3,7 +3,7 @@ use std::path::PathBuf;
use distro::Language;
use line_index::{LineCol, LineIndex};
use rowan::TextRange;
-use syntax::{bibtex, latex, latexmkrc::LatexmkrcData, BuildError};
+use syntax::{bibtex, file_list::FileList, latex, latexmkrc::LatexmkrcData, BuildError};
use url::Url;
use crate::{semantics, Config};
@@ -56,7 +56,10 @@ impl Document {
Language::Tex => {
let green = parser::parse_latex(&text, &params.config.syntax);
let mut semantics = semantics::tex::Semantics::default();
- semantics.process_root(&latex::SyntaxNode::new_root(green.clone()));
+ semantics.process_root(
+ &params.config.syntax,
+ &latex::SyntaxNode::new_root(green.clone()),
+ );
DocumentData::Tex(TexDocumentData { green, semantics })
}
Language::Bib => {
@@ -86,6 +89,7 @@ impl Document {
DocumentData::Latexmkrc(data)
}
Language::Tectonic => DocumentData::Tectonic,
+ Language::FileList => DocumentData::FileList(parser::parse_file_list(&text)),
};
Self {
@@ -143,6 +147,7 @@ pub enum DocumentData {
Root,
Latexmkrc(LatexmkrcData),
Tectonic,
+ FileList(FileList),
}
impl DocumentData {
@@ -185,6 +190,14 @@ impl DocumentData {
None
}
}
+
+ pub fn as_file_list(&self) -> Option<&FileList> {
+ if let DocumentData::FileList(data) = self {
+ Some(data)
+ } else {
+ None
+ }
+ }
}
#[derive(Debug, Clone)]
diff --git a/support/texlab/crates/base-db/src/semantics/tex.rs b/support/texlab/crates/base-db/src/semantics/tex.rs
index 7e4c926f5d..a1301091d4 100644
--- a/support/texlab/crates/base-db/src/semantics/tex.rs
+++ b/support/texlab/crates/base-db/src/semantics/tex.rs
@@ -3,7 +3,28 @@ use rustc_hash::FxHashSet;
use syntax::latex::{self, HasBrack, HasCurly};
use titlecase::titlecase;
+use parser::SyntaxConfig;
+
use super::Span;
+use crate::semantics::tex::latex::SyntaxToken;
+
+fn maybe_prepend_prefix(
+ map: &Vec<(String, String)>,
+ command: &Option<SyntaxToken>,
+ name: &Span,
+) -> Span {
+ match command {
+ Some(x) => Span::new(
+ map.iter()
+ .find_map(|(k, v)| if k == &x.text()[1..] { Some(v) } else { None })
+ .unwrap_or(&String::new())
+ .to_owned()
+ + &name.text,
+ name.range,
+ ),
+ None => name.clone(),
+ }
+}
#[derive(Debug, Clone, Default)]
pub struct Semantics {
@@ -19,11 +40,11 @@ pub struct Semantics {
}
impl Semantics {
- pub fn process_root(&mut self, root: &latex::SyntaxNode) {
+ pub fn process_root(&mut self, conf: &SyntaxConfig, root: &latex::SyntaxNode) {
for node in root.descendants_with_tokens() {
match node {
latex::SyntaxElement::Node(node) => {
- self.process_node(&node);
+ self.process_node(conf, &node);
}
latex::SyntaxElement::Token(token) => {
if token.kind() == latex::COMMAND_NAME {
@@ -40,17 +61,17 @@ impl Semantics {
.any(|link| link.kind == LinkKind::Cls && link.path.text == "subfiles");
}
- fn process_node(&mut self, node: &latex::SyntaxNode) {
+ fn process_node(&mut self, conf: &SyntaxConfig, node: &latex::SyntaxNode) {
if let Some(include) = latex::Include::cast(node.clone()) {
self.process_include(include);
} else if let Some(import) = latex::Import::cast(node.clone()) {
self.process_import(import);
} else if let Some(label) = latex::LabelDefinition::cast(node.clone()) {
- self.process_label_definition(label);
+ self.process_label_definition(conf, label);
} else if let Some(label) = latex::LabelReference::cast(node.clone()) {
- self.process_label_reference(label);
+ self.process_label_reference(conf, label);
} else if let Some(label) = latex::LabelReferenceRange::cast(node.clone()) {
- self.process_label_reference_range(label);
+ self.process_label_reference_range(conf, label);
} else if let Some(citation) = latex::Citation::cast(node.clone()) {
self.process_citation(citation);
} else if let Some(environment) = latex::Environment::cast(node.clone()) {
@@ -111,7 +132,7 @@ impl Semantics {
});
}
- fn process_label_definition(&mut self, label: latex::LabelDefinition) {
+ fn process_label_definition(&mut self, conf: &SyntaxConfig, label: latex::LabelDefinition) {
let Some(name) = label.name().and_then(|group| group.key()) else {
return;
};
@@ -190,13 +211,14 @@ impl Semantics {
self.labels.push(Label {
kind: LabelKind::Definition,
- name,
+ cmd: label.command().map(|x| x.text()[1..].to_string()),
+ name: maybe_prepend_prefix(&conf.label_definition_prefixes, &label.command(), &name),
targets: objects,
full_range,
});
}
- fn process_label_reference(&mut self, label: latex::LabelReference) {
+ fn process_label_reference(&mut self, conf: &SyntaxConfig, label: latex::LabelReference) {
let Some(name_list) = label.name_list() else {
return;
};
@@ -207,7 +229,12 @@ impl Semantics {
if !name.text.contains('#') {
self.labels.push(Label {
kind: LabelKind::Reference,
- name,
+ cmd: label.command().map(|x| x.text()[1..].to_string()),
+ name: maybe_prepend_prefix(
+ &conf.label_reference_prefixes,
+ &label.command(),
+ &name,
+ ),
targets: Vec::new(),
full_range,
});
@@ -215,14 +242,23 @@ impl Semantics {
}
}
- fn process_label_reference_range(&mut self, label: latex::LabelReferenceRange) {
+ fn process_label_reference_range(
+ &mut self,
+ conf: &SyntaxConfig,
+ label: latex::LabelReferenceRange,
+ ) {
let full_range = latex::small_range(&label);
if let Some(from) = label.from().and_then(|group| group.key()) {
let name = Span::from(&from);
if !name.text.contains('#') {
self.labels.push(Label {
kind: LabelKind::ReferenceRange,
- name,
+ cmd: label.command().map(|x| x.text()[1..].to_string()),
+ name: maybe_prepend_prefix(
+ &conf.label_reference_prefixes,
+ &label.command(),
+ &name,
+ ),
targets: Vec::new(),
full_range,
});
@@ -234,7 +270,12 @@ impl Semantics {
if !name.text.contains('#') {
self.labels.push(Label {
kind: LabelKind::ReferenceRange,
- name,
+ cmd: label.command().map(|x| x.text()[1..].to_string()),
+ name: maybe_prepend_prefix(
+ &conf.label_reference_prefixes,
+ &label.command(),
+ &name,
+ ),
targets: Vec::new(),
full_range,
});
@@ -336,6 +377,7 @@ pub enum LabelKind {
#[derive(Debug, Clone)]
pub struct Label {
pub kind: LabelKind,
+ pub cmd: Option<String>,
pub name: Span,
pub targets: Vec<LabelTarget>,
pub full_range: TextRange,
diff --git a/support/texlab/crates/bibtex-utils/Cargo.toml b/support/texlab/crates/bibtex-utils/Cargo.toml
index c20508107c..88ba2d3a37 100644
--- a/support/texlab/crates/bibtex-utils/Cargo.toml
+++ b/support/texlab/crates/bibtex-utils/Cargo.toml
@@ -9,9 +9,9 @@ rust-version.workspace = true
[dependencies]
chrono = { version = "0.4.38", default-features = false, features = ["std"] }
human_name = "2.0.3"
-itertools = "0.12.1"
+itertools = "0.13.0"
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
unicode-normalization = "0.1.23"
diff --git a/support/texlab/crates/citeproc/Cargo.toml b/support/texlab/crates/citeproc/Cargo.toml
index 9e187f88e6..c87ab14b0e 100644
--- a/support/texlab/crates/citeproc/Cargo.toml
+++ b/support/texlab/crates/citeproc/Cargo.toml
@@ -10,9 +10,9 @@ rust-version.workspace = true
bibtex-utils = { path = "../bibtex-utils" }
base-db = { path = "../base-db" }
isocountry = "0.3.2"
-itertools = "0.12.1"
+itertools = "0.13.0"
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
titlecase = "3.0.0"
unicode-normalization = "0.1.23"
diff --git a/support/texlab/crates/commands/Cargo.toml b/support/texlab/crates/commands/Cargo.toml
index 095828fbc5..6507efb3b8 100644
--- a/support/texlab/crates/commands/Cargo.toml
+++ b/support/texlab/crates/commands/Cargo.toml
@@ -10,14 +10,14 @@ rust-version.workspace = true
anyhow = "1.0.86"
base-db = { path = "../base-db" }
bstr = "1.9.1"
-crossbeam-channel = "0.5.12"
-itertools = "0.12.1"
-libc = "0.2.154"
-log = "0.4.21"
+crossbeam-channel = "0.5.13"
+itertools = "0.13.0"
+libc = "0.2.155"
+log = "0.4.22"
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
-thiserror = "1.0.59"
+thiserror = "1.0.61"
url = "2.5.0"
[dev-dependencies]
diff --git a/support/texlab/crates/commands/src/dep_graph.rs b/support/texlab/crates/commands/src/dep_graph.rs
index fe9ff3829c..86b49da0ac 100644
--- a/support/texlab/crates/commands/src/dep_graph.rs
+++ b/support/texlab/crates/commands/src/dep_graph.rs
@@ -48,6 +48,7 @@ pub fn show_dependency_graph(workspace: &Workspace) -> Result<String> {
base_db::deps::EdgeData::DirectLink(data) => &data.link.path.text,
base_db::deps::EdgeData::AdditionalFiles => "<project>",
base_db::deps::EdgeData::Artifact => "<artifact>",
+ base_db::deps::EdgeData::FileList(_) => "<fls>",
};
writeln!(&mut writer, "\t{source} -> {target} [label=\"{label}\"];")?;
diff --git a/support/texlab/crates/completion-data/Cargo.toml b/support/texlab/crates/completion-data/Cargo.toml
index 970cd6a578..6dbb7d4086 100644
--- a/support/texlab/crates/completion-data/Cargo.toml
+++ b/support/texlab/crates/completion-data/Cargo.toml
@@ -8,11 +8,11 @@ rust-version.workspace = true
[dependencies]
flate2 = "1.0.30"
-itertools = "0.12.1"
+itertools = "0.13.0"
once_cell = "1.19.0"
-rustc-hash = "1.1.0"
-serde = { version = "1.0.202", features = ["derive"] }
-serde_json = "1.0.117"
+rustc-hash = "2.0.0"
+serde = { version = "1.0.203", features = ["derive"] }
+serde_json = "1.0.119"
[lib]
doctest = false
diff --git a/support/texlab/crates/completion/Cargo.toml b/support/texlab/crates/completion/Cargo.toml
index e28e04dfc7..f98f12260b 100644
--- a/support/texlab/crates/completion/Cargo.toml
+++ b/support/texlab/crates/completion/Cargo.toml
@@ -13,7 +13,7 @@ fuzzy-matcher = { version = "0.3.7", features = ["compact"] }
line-index = { path = "../line-index" }
rayon = "1.10.0"
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
url = "2.5.0"
@@ -22,6 +22,7 @@ criterion = "0.5.1"
distro = { path = "../distro" }
expect-test = "1.5.0"
test-utils = { path = "../test-utils" }
+parser = { path = "../parser" }
[lib]
doctest = false
diff --git a/support/texlab/crates/completion/src/lib.rs b/support/texlab/crates/completion/src/lib.rs
index b1050052f0..5bfd94d944 100644
--- a/support/texlab/crates/completion/src/lib.rs
+++ b/support/texlab/crates/completion/src/lib.rs
@@ -72,7 +72,7 @@ impl<'a> CompletionItemData<'a> {
Self::Citation(data) => &data.entry.name.text,
Self::Environment(data) => data.name,
Self::GlossaryEntry(data) => &data.name,
- Self::Label(data) => data.name,
+ Self::Label(data) => &data.name,
Self::Color(name) => name,
Self::ColorModel(name) => name,
Self::File(name) => name,
diff --git a/support/texlab/crates/completion/src/providers/label_ref.rs b/support/texlab/crates/completion/src/providers/label_ref.rs
index 6f71ae3241..8b262f13ca 100644
--- a/support/texlab/crates/completion/src/providers/label_ref.rs
+++ b/support/texlab/crates/completion/src/providers/label_ref.rs
@@ -11,12 +11,30 @@ use crate::{
CompletionItem, CompletionItemData, CompletionParams,
};
+fn trim_prefix<'a>(prefix: Option<&'a str>, text: &'a str) -> &'a str {
+ prefix
+ .and_then(|pref| text.strip_prefix(pref))
+ .unwrap_or(text)
+}
+
pub fn complete_label_references<'a>(
params: &'a CompletionParams<'a>,
builder: &mut CompletionBuilder<'a>,
) -> Option<()> {
- let FindResult { cursor, is_math } =
- find_reference(params).or_else(|| find_reference_range(params))?;
+ let FindResult {
+ cursor,
+ is_math,
+ command,
+ } = find_reference(params).or_else(|| find_reference_range(params))?;
+ let ref_pref = params
+ .feature
+ .workspace
+ .config()
+ .syntax
+ .label_reference_prefixes
+ .iter()
+ .find_map(|(k, v)| if *k == command { Some(v) } else { None })
+ .map(|x| x.as_str());
for document in &params.feature.project.documents {
let DocumentData::Tex(data) = &document.data else {
@@ -29,6 +47,10 @@ pub fn complete_label_references<'a>(
.iter()
.filter(|label| label.kind == LabelKind::Definition)
{
+ if ref_pref.map_or(false, |pref| !label.name.text.starts_with(pref)) {
+ continue;
+ }
+ let labeltext = trim_prefix(ref_pref, &label.name.text);
match render_label(params.feature.workspace, &params.feature.project, label) {
Some(rendered_label) => {
if is_math && !matches!(rendered_label.object, RenderedObject::Equation) {
@@ -41,11 +63,12 @@ pub fn complete_label_references<'a>(
_ => None,
};
- let keywords = format!("{} {}", label.name.text, rendered_label.reference());
+ let keywords = format!("{} {}", labeltext, rendered_label.reference());
if let Some(score) = builder.matcher.score(&keywords, &cursor.text) {
+ let name = trim_prefix(ref_pref, &label.name.text);
let data = CompletionItemData::Label(crate::LabelData {
- name: &label.name.text,
+ name,
header,
footer,
object: Some(rendered_label.object),
@@ -59,12 +82,13 @@ pub fn complete_label_references<'a>(
}
None => {
if let Some(score) = builder.matcher.score(&label.name.text, &cursor.text) {
+ let name = trim_prefix(ref_pref, &label.name.text);
let data = CompletionItemData::Label(crate::LabelData {
- name: &label.name.text,
+ name,
header: None,
footer: None,
object: None,
- keywords: label.name.text.clone(),
+ keywords: labeltext.to_string(),
});
builder
@@ -82,20 +106,26 @@ pub fn complete_label_references<'a>(
struct FindResult {
cursor: Span,
is_math: bool,
+ command: String,
}
fn find_reference(params: &CompletionParams) -> Option<FindResult> {
let (cursor, group) = find_curly_group_word_list(params)?;
let reference = latex::LabelReference::cast(group.syntax().parent()?)?;
let is_math = reference.command()?.text() == "\\eqref";
- Some(FindResult { cursor, is_math })
+ Some(FindResult {
+ cursor,
+ is_math,
+ command: reference.command()?.text()[1..].to_string(),
+ })
}
fn find_reference_range(params: &CompletionParams) -> Option<FindResult> {
let (cursor, group) = find_curly_group_word(params)?;
- latex::LabelReferenceRange::cast(group.syntax().parent()?)?;
+ let refrange = latex::LabelReferenceRange::cast(group.syntax().parent()?)?;
Some(FindResult {
cursor,
is_math: false,
+ command: refrange.command()?.text()[1..].to_string(),
})
}
diff --git a/support/texlab/crates/completion/src/tests.rs b/support/texlab/crates/completion/src/tests.rs
index c6bed6e08e..8c68b71dd9 100644
--- a/support/texlab/crates/completion/src/tests.rs
+++ b/support/texlab/crates/completion/src/tests.rs
@@ -1,11 +1,17 @@
-use base_db::FeatureParams;
+use base_db::{Config, FeatureParams};
use expect_test::{expect, Expect};
+use parser::SyntaxConfig;
use rowan::TextRange;
use crate::CompletionParams;
-fn check(input: &str, expect: Expect) {
- let fixture = test_utils::fixture::Fixture::parse(input);
+fn check_with_syntax_config(config: SyntaxConfig, input: &str, expect: Expect) {
+ let mut fixture = test_utils::fixture::Fixture::parse(input);
+ fixture.workspace.set_config(Config {
+ syntax: config,
+ ..Config::default()
+ });
+ let fixture = fixture;
let (offset, spec) = fixture
.documents
@@ -37,6 +43,10 @@ fn check(input: &str, expect: Expect) {
expect.assert_debug_eq(&items);
}
+fn check(input: &str, expect: Expect) {
+ check_with_syntax_config(SyntaxConfig::default(), input, expect)
+}
+
#[test]
fn acronym_ref_simple() {
check(
@@ -2134,3 +2144,200 @@ fn issue_885() {
"#]],
);
}
+
+#[test]
+fn test_custom_label_prefix_ref() {
+ let mut config = SyntaxConfig::default();
+ config.label_definition_commands.insert("asm".to_string());
+ config
+ .label_definition_prefixes
+ .push(("asm".to_string(), "asm:".to_string()));
+
+ check_with_syntax_config(
+ config,
+ r#"
+%! main.tex
+ \begin{enumerate}\label{baz}
+ \asm{foo}{what}
+ \end{enumerate}
+
+ \ref{}
+ |
+% Comment"#,
+ expect![[r#"
+ [
+ Label(
+ LabelData {
+ name: "asm:foo",
+ header: None,
+ footer: None,
+ object: None,
+ keywords: "asm:foo",
+ },
+ ),
+ Label(
+ LabelData {
+ name: "baz",
+ header: None,
+ footer: None,
+ object: None,
+ keywords: "baz",
+ },
+ ),
+ ]
+ "#]],
+ );
+}
+
+#[test]
+fn test_custom_label_prefix_custom_ref() {
+ let mut config = SyntaxConfig::default();
+ config.label_definition_commands.insert("asm".to_string());
+ config
+ .label_definition_prefixes
+ .push(("asm".to_string(), "asm:".to_string()));
+ config.label_reference_commands.insert("asmref".to_string());
+ config
+ .label_reference_prefixes
+ .push(("asmref".to_string(), "asm:".to_string()));
+
+ check_with_syntax_config(
+ config,
+ r#"
+%! main.tex
+ \begin{enumerate}\label{baz}
+ \asm{foo}{what}
+ \end{enumerate}
+
+ \asmref{}
+ |
+% Comment"#,
+ expect![[r#"
+ [
+ Label(
+ LabelData {
+ name: "foo",
+ header: None,
+ footer: None,
+ object: None,
+ keywords: "foo",
+ },
+ ),
+ ]
+ "#]],
+ );
+}
+
+#[test]
+fn test_custom_label_multiple_prefix_custom_ref() {
+ let mut config = SyntaxConfig::default();
+ config
+ .label_definition_commands
+ .extend(vec!["asm", "goal"].into_iter().map(String::from));
+ config.label_definition_prefixes.extend(
+ vec![("asm", "asm:"), ("goal", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+ config
+ .label_reference_commands
+ .extend(vec!["asmref", "goalref"].into_iter().map(String::from));
+ config.label_reference_prefixes.extend(
+ vec![("asmref", "asm:"), ("goalref", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+
+ check_with_syntax_config(
+ config,
+ r#"
+%! main.tex
+ \begin{enumerate}\label{baz}
+ \asm{foo}{what}
+ \goal{foo}{what}
+ \end{enumerate}
+
+ \goalref{}
+ |
+% Comment"#,
+ expect![[r#"
+ [
+ Label(
+ LabelData {
+ name: "foo",
+ header: None,
+ footer: None,
+ object: None,
+ keywords: "foo",
+ },
+ ),
+ ]
+ "#]],
+ );
+}
+
+#[test]
+fn test_custom_label_multiple_prefix_ref() {
+ let mut config = SyntaxConfig::default();
+ config
+ .label_definition_commands
+ .extend(vec!["asm", "goal"].into_iter().map(String::from));
+ config.label_definition_prefixes.extend(
+ vec![("asm", "asm:"), ("goal", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+ config
+ .label_reference_commands
+ .extend(vec!["asmref", "goalref"].into_iter().map(String::from));
+ config.label_reference_prefixes.extend(
+ vec![("asmref", "asm:"), ("goalref", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+
+ check_with_syntax_config(
+ config,
+ r#"
+%! main.tex
+ \begin{enumerate}\label{baz}
+ \asm{foo}{what}
+ \goal{foo}{what}
+ \end{enumerate}
+
+ \ref{}
+ |
+% Comment"#,
+ expect![[r#"
+ [
+ Label(
+ LabelData {
+ name: "asm:foo",
+ header: None,
+ footer: None,
+ object: None,
+ keywords: "asm:foo",
+ },
+ ),
+ Label(
+ LabelData {
+ name: "baz",
+ header: None,
+ footer: None,
+ object: None,
+ keywords: "baz",
+ },
+ ),
+ Label(
+ LabelData {
+ name: "goal:foo",
+ header: None,
+ footer: None,
+ object: None,
+ keywords: "goal:foo",
+ },
+ ),
+ ]
+ "#]],
+ );
+}
diff --git a/support/texlab/crates/definition/Cargo.toml b/support/texlab/crates/definition/Cargo.toml
index 63ba15c308..254bea0314 100644
--- a/support/texlab/crates/definition/Cargo.toml
+++ b/support/texlab/crates/definition/Cargo.toml
@@ -9,11 +9,11 @@ rust-version.workspace = true
[dependencies]
base-db = { path = "../base-db" }
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
[dev-dependencies]
-itertools = "0.12.1"
+itertools = "0.13.0"
test-utils = { path = "../test-utils" }
[lib]
diff --git a/support/texlab/crates/diagnostics/Cargo.toml b/support/texlab/crates/diagnostics/Cargo.toml
index 1cb09fdec9..37e39280ad 100644
--- a/support/texlab/crates/diagnostics/Cargo.toml
+++ b/support/texlab/crates/diagnostics/Cargo.toml
@@ -10,14 +10,14 @@ rust-version.workspace = true
base-db = { path = "../base-db" }
encoding_rs = "0.8.34"
encoding_rs_io = "0.1.7"
-itertools = "0.12.1"
+itertools = "0.13.0"
line-index = { path = "../line-index" }
-log = "0.4.21"
+log = "0.4.22"
multimap = "0.10.0"
once_cell = "1.19.0"
-regex = "1.10.4"
+regex = "1.10.5"
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
url = "2.5.0"
diff --git a/support/texlab/crates/distro/Cargo.toml b/support/texlab/crates/distro/Cargo.toml
index dea6a56979..c81288e86e 100644
--- a/support/texlab/crates/distro/Cargo.toml
+++ b/support/texlab/crates/distro/Cargo.toml
@@ -8,7 +8,7 @@ rust-version.workspace = true
[dependencies]
anyhow = "1.0.86"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
[lib]
doctest = false
diff --git a/support/texlab/crates/distro/src/language.rs b/support/texlab/crates/distro/src/language.rs
index 201ed0702b..0a94a93604 100644
--- a/support/texlab/crates/distro/src/language.rs
+++ b/support/texlab/crates/distro/src/language.rs
@@ -9,6 +9,7 @@ pub enum Language {
Root,
Latexmkrc,
Tectonic,
+ FileList,
}
impl Language {
@@ -32,6 +33,7 @@ impl Language {
"bib" | "bibtex" => Some(Self::Bib),
"aux" => Some(Self::Aux),
"log" => Some(Self::Log),
+ "fls" => Some(Self::FileList),
_ => None,
}
}
diff --git a/support/texlab/crates/inlay-hints/Cargo.toml b/support/texlab/crates/inlay-hints/Cargo.toml
index ede4ca6188..94651ef4c7 100644
--- a/support/texlab/crates/inlay-hints/Cargo.toml
+++ b/support/texlab/crates/inlay-hints/Cargo.toml
@@ -9,7 +9,7 @@ rust-version.workspace = true
[dependencies]
base-db = { path = "../base-db" }
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
[dev-dependencies]
test-utils = { path = "../test-utils" }
diff --git a/support/texlab/crates/ipc/Cargo.toml b/support/texlab/crates/ipc/Cargo.toml
index 1e1ff7a822..92afbba876 100644
--- a/support/texlab/crates/ipc/Cargo.toml
+++ b/support/texlab/crates/ipc/Cargo.toml
@@ -7,10 +7,10 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-crossbeam-channel = "0.5.12"
-serde = "1.0.202"
-serde_json = "1.0.117"
-log = "0.4.21"
+crossbeam-channel = "0.5.13"
+serde = "1.0.203"
+serde_json = "1.0.119"
+log = "0.4.22"
uds_windows = "1.1.0"
[lib]
diff --git a/support/texlab/crates/line-index/Cargo.toml b/support/texlab/crates/line-index/Cargo.toml
index 73d2766d60..58e2fa9e16 100644
--- a/support/texlab/crates/line-index/Cargo.toml
+++ b/support/texlab/crates/line-index/Cargo.toml
@@ -7,7 +7,7 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
text-size = "1.1.1"
[lib]
diff --git a/support/texlab/crates/parser/Cargo.toml b/support/texlab/crates/parser/Cargo.toml
index 39fa34ef63..2faadcb262 100644
--- a/support/texlab/crates/parser/Cargo.toml
+++ b/support/texlab/crates/parser/Cargo.toml
@@ -7,16 +7,16 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-log = "0.4.21"
+log = "0.4.22"
logos = "0.14.0"
once_cell = "1.19.0"
pathdiff = "0.2.1"
-regex = "1.10.4"
+regex = "1.10.5"
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
tempfile = "3.10.1"
-versions = "6.2.0"
+versions = "6.3.0"
[dev-dependencies]
expect-test = "1.5.0"
diff --git a/support/texlab/crates/parser/src/bibtex.rs b/support/texlab/crates/parser/src/bibtex.rs
index e2cde27dec..4d1e561dbe 100644
--- a/support/texlab/crates/parser/src/bibtex.rs
+++ b/support/texlab/crates/parser/src/bibtex.rs
@@ -2,6 +2,8 @@ use logos::Logos;
use rowan::{GreenNode, GreenNodeBuilder};
use syntax::bibtex::SyntaxKind::{self, *};
+use crate::util::lex_command_name;
+
pub fn parse_bibtex(input: &str) -> GreenNode {
let mut ptr = TokenPtr {
builder: GreenNodeBuilder::new(),
@@ -135,8 +137,8 @@ fn curly_group(mut ptr: TokenPtr<ContentToken>) -> TokenPtr<ContentToken> {
| ContentToken::Quote
| ContentToken::Word => ptr.bump(),
ContentToken::LCurly => ptr = curly_group(ptr),
- ContentToken::AccentName => ptr = accent(ptr),
- ContentToken::CommandName => ptr = command(ptr),
+ ContentToken::CommandName(CommandName::Accent) => ptr = accent(ptr),
+ ContentToken::CommandName(CommandName::Generic) => ptr = command(ptr),
};
}
@@ -160,8 +162,8 @@ fn quote_group(mut ptr: TokenPtr<ContentToken>) -> TokenPtr<ContentToken> {
| ContentToken::Integer
| ContentToken::Word => ptr.bump(),
ContentToken::LCurly => ptr = curly_group(ptr),
- ContentToken::AccentName => ptr = accent(ptr),
- ContentToken::CommandName => ptr = command(ptr),
+ ContentToken::CommandName(CommandName::Accent) => ptr = accent(ptr),
+ ContentToken::CommandName(CommandName::Generic) => ptr = command(ptr),
};
}
@@ -181,7 +183,7 @@ fn accent(mut ptr: TokenPtr<ContentToken>) -> TokenPtr<ContentToken> {
ptr.expect(ContentToken::Whitespace);
}
- if ptr.at(ContentToken::Word) || ptr.at(ContentToken::CommandName) {
+ if ptr.at(ContentToken::Word) || ptr.at(ContentToken::CommandName(CommandName::Generic)) {
ptr.bump();
}
@@ -355,31 +357,29 @@ enum ContentToken {
#[token(r#"~"#)]
Nbsp,
- #[token(r#"\`"#)]
- #[token(r#"\'"#)]
- #[token(r#"\^"#)]
- #[token(r#"\""#)]
- #[token(r#"\H"#)]
- #[token(r#"\~"#)]
- #[token(r#"\c"#)]
- #[token(r#"\k"#)]
- #[token(r#"\="#)]
- #[token(r#"\b"#)]
- #[token(r#"\."#)]
- #[token(r#"\d"#)]
- #[token(r#"\r"#)]
- #[token(r#"\u"#)]
- #[token(r#"\v"#)]
- #[token(r#"\t"#)]
- AccentName,
-
- #[regex(r"\\([^\r\n]|[@a-zA-Z:_]+\*?)?")]
- CommandName,
+ #[regex(r"\\", |lexer| { CommandName::from(lex_command_name(lexer)) })]
+ CommandName(CommandName),
#[regex(r#"[^\s"\{\}\\~,]+"#)]
Word,
}
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
+enum CommandName {
+ Generic,
+ Accent,
+}
+
+impl From<&str> for CommandName {
+ fn from(value: &str) -> Self {
+ match value {
+ "`" | "'" | "^" | "\"" | "H" | "~" | "c" | "k" | "=" | "b" | "." | "d" | "r" | "u"
+ | "v" | "t" => CommandName::Accent,
+ _ => CommandName::Generic,
+ }
+ }
+}
+
impl From<RootToken> for SyntaxKind {
fn from(token: RootToken) -> Self {
match token {
@@ -428,8 +428,8 @@ impl From<ContentToken> for SyntaxKind {
ContentToken::Quote => QUOTE,
ContentToken::Integer => INTEGER,
ContentToken::Nbsp => NBSP,
- ContentToken::AccentName => ACCENT_NAME,
- ContentToken::CommandName => COMMAND_NAME,
+ ContentToken::CommandName(CommandName::Accent) => ACCENT_NAME,
+ ContentToken::CommandName(CommandName::Generic) => COMMAND_NAME,
ContentToken::Word => WORD,
}
}
diff --git a/support/texlab/crates/parser/src/bibtex/tests.rs b/support/texlab/crates/parser/src/bibtex/tests.rs
index e2bb1314d8..f0872b4ca6 100644
--- a/support/texlab/crates/parser/src/bibtex/tests.rs
+++ b/support/texlab/crates/parser/src/bibtex/tests.rs
@@ -3992,3 +3992,280 @@ fn test_rivest_1978() {
"#]],
);
}
+
+#[test]
+fn test_cuesta_2002() {
+ check(
+ r#"@INPROCEEDINGS{Cuesta02,
+ author = {Cuesta, Carlos E. and de la Fuente, Pablo and Barrio-Sol\órzano, Manuel and Beato, Encarnaci\ón},
+ title = {{Coordination in a Reflective Architecture Description Language}},
+ booktitle = {{Proceedings of the 5th International Conference on Coordination Models and Languages (COORDINATION'02)}},
+ year = 2002,
+ editor = {Arbab, Fahrad and Talcott, Carolyn},
+ pages = {141--148},
+ address = {York, United Kingdom},
+ organization = {},
+ publisher = {Springer},
+ volume = {},
+ number = {},
+ series = {Lecture Notes in Computer Science 2315},
+ month = apr,
+ note = {}
+}"#,
+ expect![[r#"
+ ROOT@0..617
+ ENTRY@0..617
+ TYPE@0..14 "@INPROCEEDINGS"
+ L_DELIM@14..15 "{"
+ NAME@15..23 "Cuesta02"
+ COMMA@23..24 ","
+ WHITESPACE@24..27 "\n "
+ FIELD@27..136
+ NAME@27..33 "author"
+ WHITESPACE@33..34 " "
+ EQ@34..35 "="
+ WHITESPACE@35..36 " "
+ CURLY_GROUP@36..135
+ L_CURLY@36..37 "{"
+ WORD@37..43 "Cuesta"
+ COMMA@43..44 ","
+ WHITESPACE@44..45 " "
+ WORD@45..51 "Carlos"
+ WHITESPACE@51..52 " "
+ WORD@52..54 "E."
+ WHITESPACE@54..55 " "
+ WORD@55..58 "and"
+ WHITESPACE@58..59 " "
+ WORD@59..61 "de"
+ WHITESPACE@61..62 " "
+ WORD@62..64 "la"
+ WHITESPACE@64..65 " "
+ WORD@65..71 "Fuente"
+ COMMA@71..72 ","
+ WHITESPACE@72..73 " "
+ WORD@73..78 "Pablo"
+ WHITESPACE@78..79 " "
+ WORD@79..82 "and"
+ WHITESPACE@82..83 " "
+ WORD@83..93 "Barrio-Sol"
+ COMMAND@93..101
+ COMMAND_NAME@93..101 "\\órzano"
+ COMMA@101..102 ","
+ WHITESPACE@102..103 " "
+ WORD@103..109 "Manuel"
+ WHITESPACE@109..110 " "
+ WORD@110..113 "and"
+ WHITESPACE@113..114 " "
+ WORD@114..119 "Beato"
+ COMMA@119..120 ","
+ WHITESPACE@120..121 " "
+ WORD@121..130 "Encarnaci"
+ COMMAND@130..134
+ COMMAND_NAME@130..134 "\\ón"
+ R_CURLY@134..135 "}"
+ COMMA@135..136 ","
+ WHITESPACE@136..139 "\n "
+ FIELD@139..214
+ NAME@139..144 "title"
+ WHITESPACE@144..145 " "
+ EQ@145..146 "="
+ WHITESPACE@146..147 " "
+ CURLY_GROUP@147..213
+ L_CURLY@147..148 "{"
+ CURLY_GROUP@148..212
+ L_CURLY@148..149 "{"
+ WORD@149..161 "Coordination"
+ WHITESPACE@161..162 " "
+ WORD@162..164 "in"
+ WHITESPACE@164..165 " "
+ WORD@165..166 "a"
+ WHITESPACE@166..167 " "
+ WORD@167..177 "Reflective"
+ WHITESPACE@177..178 " "
+ WORD@178..190 "Architecture"
+ WHITESPACE@190..191 " "
+ WORD@191..202 "Description"
+ WHITESPACE@202..203 " "
+ WORD@203..211 "Language"
+ R_CURLY@211..212 "}"
+ R_CURLY@212..213 "}"
+ COMMA@213..214 ","
+ WHITESPACE@214..217 "\n "
+ FIELD@217..336
+ NAME@217..226 "booktitle"
+ WHITESPACE@226..227 " "
+ EQ@227..228 "="
+ WHITESPACE@228..229 " "
+ CURLY_GROUP@229..335
+ L_CURLY@229..230 "{"
+ CURLY_GROUP@230..334
+ L_CURLY@230..231 "{"
+ WORD@231..242 "Proceedings"
+ WHITESPACE@242..243 " "
+ WORD@243..245 "of"
+ WHITESPACE@245..246 " "
+ WORD@246..249 "the"
+ WHITESPACE@249..250 " "
+ WORD@250..253 "5th"
+ WHITESPACE@253..254 " "
+ WORD@254..267 "International"
+ WHITESPACE@267..268 " "
+ WORD@268..278 "Conference"
+ WHITESPACE@278..279 " "
+ WORD@279..281 "on"
+ WHITESPACE@281..282 " "
+ WORD@282..294 "Coordination"
+ WHITESPACE@294..295 " "
+ WORD@295..301 "Models"
+ WHITESPACE@301..302 " "
+ WORD@302..305 "and"
+ WHITESPACE@305..306 " "
+ WORD@306..315 "Languages"
+ WHITESPACE@315..316 " "
+ WORD@316..333 "(COORDINATION'02)"
+ R_CURLY@333..334 "}"
+ R_CURLY@334..335 "}"
+ COMMA@335..336 ","
+ WHITESPACE@336..339 "\n "
+ FIELD@339..351
+ NAME@339..343 "year"
+ WHITESPACE@343..344 " "
+ EQ@344..345 "="
+ WHITESPACE@345..346 " "
+ LITERAL@346..350
+ INTEGER@346..350 "2002"
+ COMMA@350..351 ","
+ WHITESPACE@351..354 "\n "
+ FIELD@354..400
+ NAME@354..360 "editor"
+ WHITESPACE@360..361 " "
+ EQ@361..362 "="
+ WHITESPACE@362..363 " "
+ CURLY_GROUP@363..399
+ L_CURLY@363..364 "{"
+ WORD@364..369 "Arbab"
+ COMMA@369..370 ","
+ WHITESPACE@370..371 " "
+ WORD@371..377 "Fahrad"
+ WHITESPACE@377..378 " "
+ WORD@378..381 "and"
+ WHITESPACE@381..382 " "
+ WORD@382..389 "Talcott"
+ COMMA@389..390 ","
+ WHITESPACE@390..391 " "
+ WORD@391..398 "Carolyn"
+ R_CURLY@398..399 "}"
+ COMMA@399..400 ","
+ WHITESPACE@400..403 "\n "
+ FIELD@403..422
+ NAME@403..408 "pages"
+ WHITESPACE@408..409 " "
+ EQ@409..410 "="
+ WHITESPACE@410..411 " "
+ CURLY_GROUP@411..421
+ L_CURLY@411..412 "{"
+ WORD@412..420 "141--148"
+ R_CURLY@420..421 "}"
+ COMMA@421..422 ","
+ WHITESPACE@422..425 "\n "
+ FIELD@425..458
+ NAME@425..432 "address"
+ WHITESPACE@432..433 " "
+ EQ@433..434 "="
+ WHITESPACE@434..435 " "
+ CURLY_GROUP@435..457
+ L_CURLY@435..436 "{"
+ WORD@436..440 "York"
+ COMMA@440..441 ","
+ WHITESPACE@441..442 " "
+ WORD@442..448 "United"
+ WHITESPACE@448..449 " "
+ WORD@449..456 "Kingdom"
+ R_CURLY@456..457 "}"
+ COMMA@457..458 ","
+ WHITESPACE@458..461 "\n "
+ FIELD@461..479
+ NAME@461..473 "organization"
+ WHITESPACE@473..474 " "
+ EQ@474..475 "="
+ WHITESPACE@475..476 " "
+ CURLY_GROUP@476..478
+ L_CURLY@476..477 "{"
+ R_CURLY@477..478 "}"
+ COMMA@478..479 ","
+ WHITESPACE@479..482 "\n "
+ FIELD@482..505
+ NAME@482..491 "publisher"
+ WHITESPACE@491..492 " "
+ EQ@492..493 "="
+ WHITESPACE@493..494 " "
+ CURLY_GROUP@494..504
+ L_CURLY@494..495 "{"
+ WORD@495..503 "Springer"
+ R_CURLY@503..504 "}"
+ COMMA@504..505 ","
+ WHITESPACE@505..508 "\n "
+ FIELD@508..520
+ NAME@508..514 "volume"
+ WHITESPACE@514..515 " "
+ EQ@515..516 "="
+ WHITESPACE@516..517 " "
+ CURLY_GROUP@517..519
+ L_CURLY@517..518 "{"
+ R_CURLY@518..519 "}"
+ COMMA@519..520 ","
+ WHITESPACE@520..523 "\n "
+ FIELD@523..535
+ NAME@523..529 "number"
+ WHITESPACE@529..530 " "
+ EQ@530..531 "="
+ WHITESPACE@531..532 " "
+ CURLY_GROUP@532..534
+ L_CURLY@532..533 "{"
+ R_CURLY@533..534 "}"
+ COMMA@534..535 ","
+ WHITESPACE@535..538 "\n "
+ FIELD@538..588
+ NAME@538..544 "series"
+ WHITESPACE@544..545 " "
+ EQ@545..546 "="
+ WHITESPACE@546..547 " "
+ CURLY_GROUP@547..587
+ L_CURLY@547..548 "{"
+ WORD@548..555 "Lecture"
+ WHITESPACE@555..556 " "
+ WORD@556..561 "Notes"
+ WHITESPACE@561..562 " "
+ WORD@562..564 "in"
+ WHITESPACE@564..565 " "
+ WORD@565..573 "Computer"
+ WHITESPACE@573..574 " "
+ WORD@574..581 "Science"
+ WHITESPACE@581..582 " "
+ INTEGER@582..586 "2315"
+ R_CURLY@586..587 "}"
+ COMMA@587..588 ","
+ WHITESPACE@588..591 "\n "
+ FIELD@591..603
+ NAME@591..596 "month"
+ WHITESPACE@596..597 " "
+ EQ@597..598 "="
+ WHITESPACE@598..599 " "
+ LITERAL@599..602
+ NAME@599..602 "apr"
+ COMMA@602..603 ","
+ WHITESPACE@603..606 "\n "
+ FIELD@606..616
+ NAME@606..610 "note"
+ WHITESPACE@610..611 " "
+ EQ@611..612 "="
+ WHITESPACE@612..613 " "
+ CURLY_GROUP@613..615
+ L_CURLY@613..614 "{"
+ R_CURLY@614..615 "}"
+ WHITESPACE@615..616 "\n"
+ R_DELIM@616..617 "}"
+
+ "#]],
+ )
+}
diff --git a/support/texlab/crates/parser/src/config.rs b/support/texlab/crates/parser/src/config.rs
index f81083f132..2c5380448f 100644
--- a/support/texlab/crates/parser/src/config.rs
+++ b/support/texlab/crates/parser/src/config.rs
@@ -3,12 +3,15 @@ use rustc_hash::FxHashSet;
#[derive(Debug)]
pub struct SyntaxConfig {
pub follow_package_links: bool,
+ pub use_file_list: bool,
pub math_environments: FxHashSet<String>,
pub enum_environments: FxHashSet<String>,
pub verbatim_environments: FxHashSet<String>,
pub citation_commands: FxHashSet<String>,
pub label_definition_commands: FxHashSet<String>,
+ pub label_definition_prefixes: Vec<(String, String)>,
pub label_reference_commands: FxHashSet<String>,
+ pub label_reference_prefixes: Vec<(String, String)>,
}
impl Default for SyntaxConfig {
@@ -38,19 +41,32 @@ impl Default for SyntaxConfig {
.map(ToString::to_string)
.collect();
+ let label_definition_prefixes = DEFAULT_LABEL_DEFINITION_PREFIXES
+ .iter()
+ .map(|(x, y)| (ToString::to_string(x), ToString::to_string(y)))
+ .collect();
+
let label_reference_commands = DEFAULT_LABEL_REFERENCE_COMMANDS
.iter()
.map(ToString::to_string)
.collect();
+ let label_reference_prefixes = DEFAULT_LABEL_REFERENCE_PREFIXES
+ .iter()
+ .map(|(x, y)| (ToString::to_string(x), ToString::to_string(y)))
+ .collect();
+
Self {
follow_package_links: false,
+ use_file_list: false,
math_environments,
enum_environments,
verbatim_environments,
citation_commands,
label_definition_commands,
+ label_definition_prefixes,
label_reference_commands,
+ label_reference_prefixes,
}
}
}
@@ -170,7 +186,9 @@ static DEFAULT_CITATION_COMMANDS: &[&str] = &[
"citeA*",
];
-static DEFAULT_LABEL_DEFINITION_COMMANDS: &[&str] = &["label"];
+static DEFAULT_LABEL_DEFINITION_COMMANDS: &[&str] = &["label", "zlabel"];
+
+static DEFAULT_LABEL_DEFINITION_PREFIXES: &[(&str, &str)] = &[];
static DEFAULT_LABEL_REFERENCE_COMMANDS: &[&str] = &[
"ref",
@@ -182,6 +200,10 @@ static DEFAULT_LABEL_REFERENCE_COMMANDS: &[&str] = &[
"cref*",
"Cref",
"Cref*",
+ "zcref",
+ "zcref*",
+ "zcpageref",
+ "zcpageref*",
"namecref",
"nameCref",
"lcnamecref",
@@ -192,3 +214,5 @@ static DEFAULT_LABEL_REFERENCE_COMMANDS: &[&str] = &[
"labelcpageref",
"eqref",
];
+
+static DEFAULT_LABEL_REFERENCE_PREFIXES: &[(&str, &str)] = &[];
diff --git a/support/texlab/crates/parser/src/file_list.rs b/support/texlab/crates/parser/src/file_list.rs
new file mode 100644
index 0000000000..c892ebfeef
--- /dev/null
+++ b/support/texlab/crates/parser/src/file_list.rs
@@ -0,0 +1,44 @@
+use syntax::file_list::FileList;
+
+pub fn parse_file_list(input: &str) -> FileList {
+ let mut file_list = FileList::default();
+ for line in input.lines() {
+ if let Some(working_dir) = line.strip_prefix("PWD ") {
+ file_list.working_dir = Some(working_dir.into());
+ } else if let Some(input) = line.strip_prefix("INPUT ") {
+ file_list.inputs.insert(input.into());
+ } else if let Some(output) = line.strip_prefix("OUTPUT ") {
+ file_list.outputs.insert(output.into());
+ }
+ }
+
+ file_list
+}
+
+#[cfg(test)]
+mod tests {
+ use rustc_hash::FxHashSet;
+
+ use super::*;
+
+ #[test]
+ fn test_parse_file_list() {
+ let input = r#"
+PWD /home/user
+INPUT file1.tex
+INPUT file1.tex
+OUTPUT file2.pdf"#;
+
+ let expected_file_list = FileList {
+ working_dir: Some("/home/user".into()),
+ inputs: FxHashSet::from_iter(["file1.tex".into()]),
+ outputs: FxHashSet::from_iter(["file2.pdf".into()]),
+ };
+ let actual_file_list = parse_file_list(input);
+ assert_eq!(actual_file_list, expected_file_list);
+
+ assert_eq!(actual_file_list.working_dir, Some("/home/user".into()));
+ assert_eq!(actual_file_list.inputs.len(), 1);
+ assert_eq!(actual_file_list.outputs.len(), 1);
+ }
+}
diff --git a/support/texlab/crates/parser/src/latex/lexer/types.rs b/support/texlab/crates/parser/src/latex/lexer/types.rs
index 896ce01c05..85e542792b 100644
--- a/support/texlab/crates/parser/src/latex/lexer/types.rs
+++ b/support/texlab/crates/parser/src/latex/lexer/types.rs
@@ -1,5 +1,7 @@
use logos::Logos;
+use crate::util::lex_command_name;
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)]
pub enum Token {
#[regex(r"[\r\n]+", priority = 2)]
@@ -44,55 +46,10 @@ pub enum Token {
#[regex(r"\$\$?")]
Dollar,
- #[regex(r"\\", lex_command_name)]
+ #[regex(r"\\", |lexer| { lex_command_name(lexer); CommandName::Generic } )]
CommandName(CommandName),
}
-fn lex_command_name(lexer: &mut logos::Lexer<Token>) -> CommandName {
- let input = &lexer.source()[lexer.span().end..];
-
- let mut chars = input.chars().peekable();
- let Some(c) = chars.next() else {
- return CommandName::Generic;
- };
-
- if c.is_whitespace() {
- return CommandName::Generic;
- }
-
- lexer.bump(c.len_utf8());
- if !c.is_alphanumeric() && c != '@' {
- return CommandName::Generic;
- }
-
- while let Some(c) = chars.next() {
- match c {
- '*' => {
- lexer.bump(c.len_utf8());
- break;
- }
- c if c.is_alphanumeric() => {
- lexer.bump(c.len_utf8());
- }
- '_' => {
- if !matches!(chars.peek(), Some(c) if c.is_alphanumeric()) {
- break;
- }
-
- lexer.bump(c.len_utf8());
- }
- '@' | ':' => {
- lexer.bump(c.len_utf8());
- }
- _ => {
- break;
- }
- }
- }
-
- CommandName::Generic
-}
-
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum CommandName {
Generic,
diff --git a/support/texlab/crates/parser/src/lib.rs b/support/texlab/crates/parser/src/lib.rs
index 2a4190b7e2..b3952d6ea5 100644
--- a/support/texlab/crates/parser/src/lib.rs
+++ b/support/texlab/crates/parser/src/lib.rs
@@ -1,10 +1,12 @@
mod bibtex;
mod build_log;
mod config;
+mod file_list;
mod latex;
mod latexmkrc;
+pub(crate) mod util;
pub use self::{
- bibtex::parse_bibtex, build_log::parse_build_log, config::*, latex::parse_latex,
- latexmkrc::parse_latexmkrc,
+ bibtex::parse_bibtex, build_log::parse_build_log, config::*, file_list::parse_file_list,
+ latex::parse_latex, latexmkrc::parse_latexmkrc,
};
diff --git a/support/texlab/crates/parser/src/util.rs b/support/texlab/crates/parser/src/util.rs
new file mode 100644
index 0000000000..cb147c493b
--- /dev/null
+++ b/support/texlab/crates/parser/src/util.rs
@@ -0,0 +1,52 @@
+use std::ops::{Index, Range};
+
+use logos::{Logos, Source};
+
+pub fn lex_command_name<'a, T>(lexer: &mut logos::Lexer<'a, T>) -> &'a str
+where
+ T: Logos<'a>,
+ T::Source: Index<Range<usize>, Output = str>,
+{
+ let start = lexer.span().end;
+ let input = &lexer.source()[start..lexer.source().len()];
+
+ let mut chars = input.chars().peekable();
+ let Some(c) = chars.next() else {
+ return "";
+ };
+
+ if c.is_whitespace() {
+ return "";
+ }
+
+ lexer.bump(c.len_utf8());
+
+ if c.is_alphanumeric() || c == '@' {
+ while let Some(c) = chars.next() {
+ match c {
+ '*' => {
+ lexer.bump(c.len_utf8());
+ break;
+ }
+ c if c.is_alphanumeric() => {
+ lexer.bump(c.len_utf8());
+ }
+ '_' => {
+ if !matches!(chars.peek(), Some(c) if c.is_alphanumeric()) {
+ break;
+ }
+
+ lexer.bump(c.len_utf8());
+ }
+ '@' | ':' => {
+ lexer.bump(c.len_utf8());
+ }
+ _ => {
+ break;
+ }
+ }
+ }
+ }
+
+ &lexer.source()[start..lexer.span().end]
+}
diff --git a/support/texlab/crates/references/Cargo.toml b/support/texlab/crates/references/Cargo.toml
index e78e84ea4c..8d4e3a6936 100644
--- a/support/texlab/crates/references/Cargo.toml
+++ b/support/texlab/crates/references/Cargo.toml
@@ -9,7 +9,7 @@ rust-version.workspace = true
[dependencies]
base-db = { path = "../base-db" }
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
[dev-dependencies]
diff --git a/support/texlab/crates/rename/Cargo.toml b/support/texlab/crates/rename/Cargo.toml
index 1b2b91ee2a..592bafb474 100644
--- a/support/texlab/crates/rename/Cargo.toml
+++ b/support/texlab/crates/rename/Cargo.toml
@@ -9,11 +9,12 @@ rust-version.workspace = true
[dependencies]
base-db = { path = "../base-db" }
rowan = "0.15.15"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
syntax = { path = "../syntax" }
[dev-dependencies]
test-utils = { path = "../test-utils" }
+parser = { path = "../parser" }
[lib]
doctest = false
diff --git a/support/texlab/crates/rename/src/command.rs b/support/texlab/crates/rename/src/command.rs
index 7b17d4271c..037e09e4ca 100644
--- a/support/texlab/crates/rename/src/command.rs
+++ b/support/texlab/crates/rename/src/command.rs
@@ -35,7 +35,10 @@ pub(super) fn rename(builder: &mut RenameBuilder) -> Option<()> {
}
}
- builder.result.changes.insert(*document, edits);
+ builder
+ .result
+ .changes
+ .insert(*document, edits.iter().map(|&x| x.into()).collect());
}
Some(())
diff --git a/support/texlab/crates/rename/src/entry.rs b/support/texlab/crates/rename/src/entry.rs
index 5bed4ae613..d35d9e9e84 100644
--- a/support/texlab/crates/rename/src/entry.rs
+++ b/support/texlab/crates/rename/src/entry.rs
@@ -42,7 +42,7 @@ pub(super) fn rename(builder: &mut RenameBuilder) -> Option<()> {
for (document, range) in citations.chain(entries) {
let entry = builder.result.changes.entry(document);
- entry.or_default().push(range);
+ entry.or_default().push(range.into());
}
Some(())
diff --git a/support/texlab/crates/rename/src/label.rs b/support/texlab/crates/rename/src/label.rs
index b21e1b795e..1d82f5e2b4 100644
--- a/support/texlab/crates/rename/src/label.rs
+++ b/support/texlab/crates/rename/src/label.rs
@@ -3,22 +3,65 @@ use base_db::{
util::queries::{self, Object},
};
-use crate::{RenameBuilder, RenameParams};
+use crate::{RenameBuilder, RenameInformation, RenameParams};
+
+struct PrefixInformation<'a> {
+ def_prefixes: &'a Vec<(String, String)>,
+ ref_prefixes: &'a Vec<(String, String)>,
+}
+
+fn label_has_prefix(pref_info: &PrefixInformation, label: &tex::Label) -> Option<String> {
+ match label.kind {
+ tex::LabelKind::Definition => pref_info.def_prefixes.iter(),
+ _ => pref_info.ref_prefixes.iter(),
+ }
+ .find_map(|(k, v)| {
+ if k == &label.cmd.clone().unwrap_or(String::new()) {
+ Some(v)
+ } else {
+ None
+ }
+ })
+ .cloned()
+}
+
+fn find_prefix_in_any(
+ builder: &mut RenameBuilder,
+ pref_info: &PrefixInformation,
+ name: &str,
+) -> Option<String> {
+ let project = &builder.params.feature.project;
+ queries::objects_with_name::<tex::Label>(project, name)
+ .find_map(|(_, label)| label_has_prefix(&pref_info, label))
+}
pub(super) fn prepare_rename(params: &RenameParams) -> Option<Span> {
let data = params.feature.document.data.as_tex()?;
let labels = &data.semantics.labels;
let label = queries::object_at_cursor(labels, params.offset, queries::SearchMode::Name)?;
+
Some(Span::new(label.object.name.text.clone(), label.range))
}
pub(super) fn rename(builder: &mut RenameBuilder) -> Option<()> {
let name = prepare_rename(&builder.params)?;
+ let syn = &builder.params.feature.workspace.config().syntax;
+ let pref_info = PrefixInformation {
+ def_prefixes: &syn.label_definition_prefixes,
+ ref_prefixes: &syn.label_reference_prefixes,
+ };
+ let prefix = find_prefix_in_any(builder, &pref_info, &name.text);
+
let project = &builder.params.feature.project;
for (document, label) in queries::objects_with_name::<tex::Label>(project, &name.text) {
+ let prefix = label_has_prefix(&pref_info, label).map_or(prefix.clone(), |_| None);
+
let entry = builder.result.changes.entry(document);
- entry.or_default().push(label.name_range());
+ entry.or_default().push(RenameInformation {
+ range: label.name_range(),
+ prefix: prefix.clone(),
+ });
}
Some(())
diff --git a/support/texlab/crates/rename/src/lib.rs b/support/texlab/crates/rename/src/lib.rs
index bf9023ddef..e6c05ad268 100644
--- a/support/texlab/crates/rename/src/lib.rs
+++ b/support/texlab/crates/rename/src/lib.rs
@@ -13,8 +13,14 @@ pub struct RenameParams<'a> {
}
#[derive(Debug, Default)]
+pub struct RenameInformation {
+ pub range: TextRange,
+ pub prefix: Option<String>,
+}
+
+#[derive(Debug, Default)]
pub struct RenameResult<'a> {
- pub changes: FxHashMap<&'a Document, Vec<TextRange>>,
+ pub changes: FxHashMap<&'a Document, Vec<RenameInformation>>,
}
struct RenameBuilder<'a> {
@@ -22,6 +28,20 @@ struct RenameBuilder<'a> {
result: RenameResult<'a>,
}
+impl From<TextRange> for RenameInformation {
+ fn from(range: TextRange) -> Self {
+ RenameInformation {
+ range,
+ prefix: None,
+ }
+ }
+}
+impl PartialEq for RenameInformation {
+ fn eq(&self, other: &Self) -> bool {
+ self.range == other.range
+ }
+}
+
pub fn prepare_rename(params: &RenameParams) -> Option<TextRange> {
command::prepare_rename(params)
.or_else(|| entry::prepare_rename(params))
diff --git a/support/texlab/crates/rename/src/tests.rs b/support/texlab/crates/rename/src/tests.rs
index 0f4263033e..4da866fb08 100644
--- a/support/texlab/crates/rename/src/tests.rs
+++ b/support/texlab/crates/rename/src/tests.rs
@@ -1,23 +1,37 @@
use rustc_hash::FxHashMap;
-use crate::RenameParams;
+use base_db::Config;
+use parser::SyntaxConfig;
-fn check(input: &str) {
- let fixture = test_utils::fixture::Fixture::parse(input);
+use crate::{RenameInformation, RenameParams};
+
+fn check_with_syntax_config(config: SyntaxConfig, input: &str) {
+ let mut fixture = test_utils::fixture::Fixture::parse(input);
+ fixture.workspace.set_config(Config {
+ syntax: config,
+ ..Config::default()
+ });
+ let fixture = fixture;
- let mut expected = FxHashMap::default();
+ let mut expected: FxHashMap<_, Vec<RenameInformation>> = FxHashMap::default();
for spec in &fixture.documents {
if !spec.ranges.is_empty() {
let document = fixture.workspace.lookup(&spec.uri).unwrap();
- expected.insert(document, spec.ranges.clone());
+ expected.insert(
+ document,
+ spec.ranges.iter().map(|r| r.clone().into()).collect(),
+ );
}
}
-
let (feature, offset) = fixture.make_params().unwrap();
let actual = crate::rename(RenameParams { feature, offset });
assert_eq!(actual.changes, expected);
}
+fn check(input: &str) {
+ check_with_syntax_config(SyntaxConfig::default(), input)
+}
+
#[test]
fn test_command() {
check(
@@ -78,12 +92,97 @@ fn test_label() {
|
^^^
+%! baz.tex
+\ref{foo}
+
%! bar.tex
\ref{foo}
^^^
+"#,
+ )
+}
+
+#[test]
+fn test_custom_label_ref() {
+ let mut config = SyntaxConfig::default();
+ config
+ .label_definition_commands
+ .extend(vec!["asm", "goal"].into_iter().map(String::from));
+ config.label_definition_prefixes.extend(
+ vec![("asm", "asm:"), ("goal", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+ config
+ .label_reference_commands
+ .extend(vec!["asmref", "goalref"].into_iter().map(String::from));
+ config.label_reference_prefixes.extend(
+ vec![("asmref", "asm:"), ("goalref", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+ check_with_syntax_config(
+ config,
+ r#"
+%! foo.tex
+\goal{foo}
+
+\asm{foo}\include{bar}\include{baz}
+ |
+ ^^^
+
+%! bar.tex
+\asmref{foo}
+ ^^^
+
+%! baz.tex
+\ref{foo}
+
+\ref{asm:foo}
+ ^^^^^^^
+
+"#,
+ )
+}
+
+#[test]
+fn test_custom_label_def() {
+ let mut config = SyntaxConfig::default();
+ config
+ .label_definition_commands
+ .extend(vec!["asm", "goal"].into_iter().map(String::from));
+ config.label_definition_prefixes.extend(
+ vec![("asm", "asm:"), ("goal", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+ config
+ .label_reference_commands
+ .extend(vec!["asmref", "goalref"].into_iter().map(String::from));
+ config.label_reference_prefixes.extend(
+ vec![("asmref", "asm:"), ("goalref", "goal:")]
+ .into_iter()
+ .map(|(x, y)| (String::from(x), String::from(y))),
+ );
+ check_with_syntax_config(
+ config,
+ r#"
+%! foo.tex
+\goal{foo}
+
+\label{asm:foo}\include{bar}\include{baz}
+ |
+ ^^^^^^^
+
+%! bar.tex
+\asmref{foo}
+ ^^^
%! baz.tex
\ref{foo}
+
+\ref{asm:foo}
+ ^^^^^^^
"#,
)
}
diff --git a/support/texlab/crates/symbols/Cargo.toml b/support/texlab/crates/symbols/Cargo.toml
index 65db0fc0bd..c44f120153 100644
--- a/support/texlab/crates/symbols/Cargo.toml
+++ b/support/texlab/crates/symbols/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
[dependencies]
base-db = { path = "../base-db" }
distro = { path = "../distro" }
-itertools = "0.12.1"
+itertools = "0.13.0"
line-index = { path = "../line-index" }
rowan = "0.15.15"
syntax = { path = "../syntax" }
@@ -20,6 +20,6 @@ titlecase = "3.0.0"
url = "2.5.0"
[dev-dependencies]
-regex = "1.10.4"
+regex = "1.10.5"
test-utils = { path = "../test-utils" }
expect-test = "1.5.0"
diff --git a/support/texlab/crates/symbols/src/document.rs b/support/texlab/crates/symbols/src/document.rs
index 791f119919..611a7e0370 100644
--- a/support/texlab/crates/symbols/src/document.rs
+++ b/support/texlab/crates/symbols/src/document.rs
@@ -23,6 +23,7 @@ pub fn document_symbols(workspace: &Workspace, document: &Document) -> Vec<Symbo
| DocumentData::Log(_)
| DocumentData::Root
| DocumentData::Latexmkrc(_)
+ | DocumentData::FileList(_)
| DocumentData::Tectonic => Vec::new(),
};
diff --git a/support/texlab/crates/syntax/Cargo.toml b/support/texlab/crates/syntax/Cargo.toml
index a2d3d866b6..14dfffe380 100644
--- a/support/texlab/crates/syntax/Cargo.toml
+++ b/support/texlab/crates/syntax/Cargo.toml
@@ -7,8 +7,9 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-itertools = "0.12.1"
+itertools = "0.13.0"
rowan = "0.15.15"
+rustc-hash = "2.0.0"
[lib]
doctest = false
diff --git a/support/texlab/crates/syntax/src/file_list.rs b/support/texlab/crates/syntax/src/file_list.rs
new file mode 100644
index 0000000000..cd32e787da
--- /dev/null
+++ b/support/texlab/crates/syntax/src/file_list.rs
@@ -0,0 +1,10 @@
+use std::path::PathBuf;
+
+use rustc_hash::FxHashSet;
+
+#[derive(Debug, PartialEq, Eq, Clone, Default)]
+pub struct FileList {
+ pub working_dir: Option<PathBuf>,
+ pub inputs: FxHashSet<PathBuf>,
+ pub outputs: FxHashSet<PathBuf>,
+}
diff --git a/support/texlab/crates/syntax/src/lib.rs b/support/texlab/crates/syntax/src/lib.rs
index 35f1bb8c52..d3e2098757 100644
--- a/support/texlab/crates/syntax/src/lib.rs
+++ b/support/texlab/crates/syntax/src/lib.rs
@@ -1,4 +1,5 @@
pub mod bibtex;
+pub mod file_list;
pub mod latex;
pub mod latexmkrc;
diff --git a/support/texlab/crates/texlab/Cargo.toml b/support/texlab/crates/texlab/Cargo.toml
index a2fb78e11f..f4cb2d3283 100644
--- a/support/texlab/crates/texlab/Cargo.toml
+++ b/support/texlab/crates/texlab/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "texlab"
description = "LaTeX Language Server"
-version = "5.16.1"
+version = "5.19.0"
license.workspace = true
readme = "README.md"
authors.workspace = true
@@ -26,11 +26,11 @@ anyhow = "1.0.86"
base-db = { path = "../base-db" }
bibfmt = { path = "../bibfmt" }
citeproc = { path = "../citeproc" }
-clap = { version = "4.5.4", features = ["derive"] }
+clap = { version = "4.5.8", features = ["derive"] }
commands = { path = "../commands" }
completion = { path = "../completion" }
completion-data = { path = "../completion-data" }
-crossbeam-channel = "0.5.12"
+crossbeam-channel = "0.5.13"
definition = { path = "../definition" }
diagnostics = { path = "../diagnostics" }
distro = { path = "../distro" }
@@ -42,20 +42,20 @@ inlay-hints = { path = "../inlay-hints" }
ipc = { path = "../ipc" }
line-index = { path = "../line-index" }
links = { path = "../links" }
-log = "0.4.21"
+log = "0.4.22"
lsp-server = "0.7.6"
lsp-types = "0.95.1"
notify = "6.1.1"
notify-debouncer-full = "0.3.1"
-parking_lot = "0.12.2"
+parking_lot = "0.12.3"
parser = { path = "../parser" }
references = { path = "../references" }
-regex = "1.10.4"
+regex = "1.10.5"
rename = { path = "../rename" }
rowan = "0.15.15"
-rustc-hash = "1.1.0"
-serde = "1.0.202"
-serde_json = "1.0.117"
+rustc-hash = "2.0.0"
+serde = "1.0.203"
+serde_json = "1.0.119"
serde_regex = "1.1.0"
serde_repr = "0.1.19"
symbols = { path = "../symbols" }
diff --git a/support/texlab/crates/texlab/src/features/formatting.rs b/support/texlab/crates/texlab/src/features/formatting.rs
index 3fcd66e39b..9d152f6e8b 100644
--- a/support/texlab/crates/texlab/src/features/formatting.rs
+++ b/support/texlab/crates/texlab/src/features/formatting.rs
@@ -27,6 +27,7 @@ pub fn format_source_code(
| Language::Log
| Language::Root
| Language::Latexmkrc
- | Language::Tectonic => None,
+ | Language::Tectonic
+ | Language::FileList => None,
}
}
diff --git a/support/texlab/crates/texlab/src/server/options.rs b/support/texlab/crates/texlab/src/server/options.rs
index 3f50faefd7..f4853d7cb9 100644
--- a/support/texlab/crates/texlab/src/server/options.rs
+++ b/support/texlab/crates/texlab/src/server/options.rs
@@ -1,6 +1,7 @@
-use regex::Regex;
use serde::{Deserialize, Serialize};
+use regex::Regex;
+
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(default)]
@@ -69,6 +70,7 @@ pub struct BuildOptions {
pub log_directory: Option<String>,
pub pdf_directory: Option<String>,
pub filename: Option<String>,
+ pub use_file_list: bool,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
@@ -125,7 +127,9 @@ pub struct ExperimentalOptions {
pub verbatim_environments: Vec<String>,
pub citation_commands: Vec<String>,
pub label_definition_commands: Vec<String>,
+ pub label_definition_prefixes: Vec<(String, String)>,
pub label_reference_commands: Vec<String>,
+ pub label_reference_prefixes: Vec<(String, String)>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
diff --git a/support/texlab/crates/texlab/src/util.rs b/support/texlab/crates/texlab/src/util.rs
index c301dc7722..87e41a78ae 100644
--- a/support/texlab/crates/texlab/src/util.rs
+++ b/support/texlab/crates/texlab/src/util.rs
@@ -18,9 +18,28 @@ pub fn normalize_uri(uri: &mut lsp_types::Url) {
}
}
+ uri.set_path(&normalize_percent_encoding(uri.path()));
uri.set_fragment(None);
}
+fn normalize_percent_encoding(input: &str) -> String {
+ let mut output = String::new();
+ let mut i = 0;
+ for c in input.chars() {
+ if c == '%' && i == 0 {
+ output.push(c);
+ i = 2;
+ } else if i > 0 {
+ output.push(c.to_ascii_uppercase());
+ i -= 1;
+ } else {
+ output.push(c);
+ }
+ }
+
+ output
+}
+
fn fix_drive_letter(text: &str) -> Option<String> {
if !text.is_ascii() || text.is_empty() {
return None;
@@ -59,4 +78,44 @@ mod tests {
normalize_uri(&mut uri);
assert_eq!(uri.as_str(), "foo:///bar/baz.txt");
}
+
+ #[test]
+ #[cfg(unix)]
+ fn test_lowercase_percent_encoding_unix() {
+ let mut uri1 = Url::parse("file:///foo/%c3%a4.tex").unwrap();
+ let uri2 = Url::from_file_path("/foo/ä.tex").unwrap();
+
+ normalize_uri(&mut uri1);
+ assert_eq!(uri1, uri2);
+ }
+
+ #[test]
+ #[cfg(unix)]
+ fn test_uppercase_percent_encoding_unix() {
+ let mut uri1 = Url::parse("file:///foo/%C3%A4.tex").unwrap();
+ let uri2 = Url::from_file_path("/foo/ä.tex").unwrap();
+
+ normalize_uri(&mut uri1);
+ assert_eq!(uri1, uri2);
+ }
+
+ #[test]
+ #[cfg(windows)]
+ fn test_lowercase_percent_encoding_windows() {
+ let mut uri1 = Url::parse("file:///c%3a/foo/%c3%a4.tex").unwrap();
+ let uri2 = Url::from_file_path("C:/foo/ä.tex").unwrap();
+
+ normalize_uri(&mut uri1);
+ assert_eq!(uri1, uri2);
+ }
+
+ #[test]
+ #[cfg(windows)]
+ fn test_uppercase_percent_encoding_windows() {
+ let mut uri1 = Url::parse("file:///c%3A/foo/%C3%A4.tex").unwrap();
+ let uri2 = Url::from_file_path("C:/foo/ä.tex").unwrap();
+
+ normalize_uri(&mut uri1);
+ assert_eq!(uri1, uri2);
+ }
}
diff --git a/support/texlab/crates/texlab/src/util/client_flags.rs b/support/texlab/crates/texlab/src/util/client_flags.rs
index 842dbb1eae..2829041832 100644
--- a/support/texlab/crates/texlab/src/util/client_flags.rs
+++ b/support/texlab/crates/texlab/src/util/client_flags.rs
@@ -20,18 +20,12 @@ pub struct ClientFlags {
/// If not set, then fuzzy citation completion will not work.
pub completion_always_incomplete: bool,
- /// If `true`, the server can include markdown in hover responses.
- pub hover_markdown: bool,
-
/// If `true`, the server can pull the configuration from the client.
pub configuration_pull: bool,
/// If `true`, the client notifies the server when the configuration changes.
pub configuration_push: bool,
- /// If `true`, the client can return `LocationLink` instead of `Location`.
- pub definition_link: bool,
-
/// If `true`, the server can return custom kinds like `section`.
pub folding_custom_kinds: bool,
diff --git a/support/texlab/crates/texlab/src/util/from_proto.rs b/support/texlab/crates/texlab/src/util/from_proto.rs
index 789edbf9c3..b55e3cb0e3 100644
--- a/support/texlab/crates/texlab/src/util/from_proto.rs
+++ b/support/texlab/crates/texlab/src/util/from_proto.rs
@@ -56,15 +56,6 @@ pub fn client_flags(
let completion_always_incomplete = info.map_or(false, |info| info.name == "Visual Studio Code");
- let hover_markdown = capabilities
- .text_document
- .as_ref()
- .and_then(|cap| cap.hover.as_ref())
- .and_then(|cap| cap.content_format.as_ref())
- .map_or(false, |formats| {
- formats.contains(&lsp_types::MarkupKind::Markdown)
- });
-
let configuration_pull = capabilities
.workspace
.as_ref()
@@ -78,13 +69,6 @@ pub fn client_flags(
.and_then(|cap| cap.dynamic_registration)
.unwrap_or(false);
- let definition_link = capabilities
- .text_document
- .as_ref()
- .and_then(|cap| cap.definition)
- .and_then(|cap| cap.link_support)
- .unwrap_or(false);
-
let folding_custom_kinds = capabilities
.text_document
.as_ref()
@@ -111,10 +95,8 @@ pub fn client_flags(
completion_snippets,
completion_kinds,
completion_always_incomplete,
- hover_markdown,
configuration_pull,
configuration_push,
- definition_link,
folding_custom_kinds,
progress,
show_document,
@@ -358,8 +340,18 @@ pub fn config(value: Options) -> Config {
config
.syntax
+ .label_definition_prefixes
+ .extend(value.experimental.label_definition_prefixes);
+
+ config
+ .syntax
.label_reference_commands
.extend(value.experimental.label_reference_commands);
config
+ .syntax
+ .label_reference_prefixes
+ .extend(value.experimental.label_reference_prefixes);
+
+ config
}
diff --git a/support/texlab/crates/texlab/src/util/to_proto.rs b/support/texlab/crates/texlab/src/util/to_proto.rs
index f5cf2edf8b..d2c261c8fb 100644
--- a/support/texlab/crates/texlab/src/util/to_proto.rs
+++ b/support/texlab/crates/texlab/src/util/to_proto.rs
@@ -396,8 +396,15 @@ pub fn workspace_edit(result: RenameResult, new_name: &str) -> lsp_types::Worksp
let mut edits = Vec::new();
ranges
.into_iter()
- .filter_map(|range| document.line_index.line_col_lsp_range(range))
- .for_each(|range| edits.push(lsp_types::TextEdit::new(range, new_name.into())));
+ .filter_map(|info| {
+ document.line_index.line_col_lsp_range(info.range).map(|i| {
+ (
+ i,
+ info.prefix.map_or(new_name.into(), |p| p + new_name.into()),
+ )
+ })
+ })
+ .for_each(|(range, new_name)| edits.push(lsp_types::TextEdit::new(range, new_name)));
changes.insert(document.uri.clone(), edits);
}
diff --git a/support/texlab/texlab.1 b/support/texlab/texlab.1
index 69f16a0bf9..852d37051e 100644
--- a/support/texlab/texlab.1
+++ b/support/texlab/texlab.1
@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1.
-.TH TEXLAB "1" "May 2024" "texlab 5.16.1" "User Commands"
+.TH TEXLAB "1" "July 2024" "texlab 5.19.0" "User Commands"
.SH NAME
-texlab \- manual page for texlab 5.16.1
+texlab \- manual page for texlab 5.19.0
.SH SYNOPSIS
.B texlab
[\fI\,OPTIONS\/\fR] [\fI\,COMMAND\/\fR]
diff --git a/support/texlab/texlab.pdf b/support/texlab/texlab.pdf
index 8731c5ef78..55922ca427 100644
--- a/support/texlab/texlab.pdf
+++ b/support/texlab/texlab.pdf
Binary files differ