summaryrefslogtreecommitdiff
path: root/support/texlab
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab')
-rw-r--r--support/texlab/CHANGELOG.md15
-rw-r--r--support/texlab/Cargo.lock38
-rw-r--r--support/texlab/Cargo.toml6
-rw-r--r--support/texlab/crates/base-db/src/config.rs1
-rw-r--r--support/texlab/crates/base-db/src/deps/discover.rs2
-rw-r--r--support/texlab/crates/base-db/src/deps/graph.rs8
-rw-r--r--support/texlab/crates/base-db/src/deps/root.rs6
-rw-r--r--support/texlab/crates/base-db/src/document.rs4
-rw-r--r--support/texlab/crates/base-db/src/semantics/auxiliary.rs36
-rw-r--r--support/texlab/crates/base-db/src/semantics/tex.rs15
-rw-r--r--support/texlab/crates/bibtex-utils/Cargo.toml2
-rw-r--r--support/texlab/crates/commands/Cargo.toml2
-rw-r--r--support/texlab/crates/commands/src/build.rs6
-rw-r--r--support/texlab/crates/commands/src/clean.rs6
-rw-r--r--support/texlab/crates/commands/src/fwd_search.rs6
-rw-r--r--support/texlab/crates/completion/src/providers/include.rs2
-rw-r--r--support/texlab/crates/diagnostics/src/chktex.rs2
-rw-r--r--support/texlab/crates/diagnostics/src/citations.rs46
-rw-r--r--support/texlab/crates/distro/src/lib.rs17
-rw-r--r--support/texlab/crates/parser/Cargo.toml2
-rw-r--r--support/texlab/crates/parser/src/latex.rs62
-rw-r--r--support/texlab/crates/parser/src/latex/lexer/commands.rs3
-rw-r--r--support/texlab/crates/parser/src/latex/lexer/types.rs3
-rw-r--r--support/texlab/crates/references/src/command.rs4
-rw-r--r--support/texlab/crates/references/src/tests.rs40
-rw-r--r--support/texlab/crates/symbols/src/document/tests.rs72
-rw-r--r--support/texlab/crates/symbols/src/document/tex.rs25
-rw-r--r--support/texlab/crates/syntax/src/latex/cst.rs40
-rw-r--r--support/texlab/crates/syntax/src/latex/kind.rs3
-rw-r--r--support/texlab/crates/texlab/Cargo.toml6
-rw-r--r--support/texlab/crates/texlab/src/features/formatting/latexindent.rs11
-rw-r--r--support/texlab/crates/texlab/src/server/options.rs1
-rw-r--r--support/texlab/crates/texlab/src/util/from_proto.rs1
-rw-r--r--support/texlab/texlab.14
-rw-r--r--support/texlab/texlab.pdfbin26335 -> 26339 bytes
35 files changed, 386 insertions, 111 deletions
diff --git a/support/texlab/CHANGELOG.md b/support/texlab/CHANGELOG.md
index 6af6af2186..526ec6889c 100644
--- a/support/texlab/CHANGELOG.md
+++ b/support/texlab/CHANGELOG.md
@@ -5,6 +5,21 @@ 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.21.0] - 2024-10-26
+
+### Added
+
+- Support starred variants in "Go to References" ([#1234](https://github.com/latex-lsp/texlab/issues/1234))
+- Add `texlab.latexindent.replacement` setting to allow passing a replacement flag to `latexindent` ([#1222](https://github.com/latex-lsp/texlab/issues/1222))
+- Don't require a label to show section numbers for document symbols ([#910](https://github.com/latex-lsp/texlab/issues/910))
+- Support navigating to files that are part of the `TEXINPUTS` similar to `BIBINPUTS` ([#1228](https://github.com/latex-lsp/texlab/discussions/1228))
+
+### Fixed
+
+- Fix opening `untitled` documents ([#1242](https://github.com/latex-lsp/texlab/issues/1242))
+- Handle `\bibitem` when checking for undefined references ([#1171](https://github.com/latex-lsp/texlab/issues/1171))
+- Fix false-positive syntax error when using a command inside a `\label` ([#879](https://github.com/latex-lsp/texlab/issues/879))
+
## [5.20.0] - 2024-10-08
### Added
diff --git a/support/texlab/Cargo.lock b/support/texlab/Cargo.lock
index e1587e07d5..aca7dcd943 100644
--- a/support/texlab/Cargo.lock
+++ b/support/texlab/Cargo.lock
@@ -73,9 +73,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.89"
+version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
+checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95"
[[package]]
name = "autocfg"
@@ -244,9 +244,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.19"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615"
+checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
"clap_builder",
"clap_derive",
@@ -254,9 +254,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.19"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b"
+checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
"anstream",
"anstyle",
@@ -565,9 +565,9 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
name = "fern"
-version = "0.6.2"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee"
+checksum = "69ff9c9d5fb3e6da8ac2f77ab76fe7e8087d512ce095200f8f29ac5b656cf6dc"
dependencies = [
"log",
]
@@ -714,9 +714,9 @@ dependencies = [
[[package]]
name = "human_name"
-version = "2.0.3"
+version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d40d3a11bc31949eb1d5070deb0cbb481bbd17d9423ecd3afdb3db5d81499b9"
+checksum = "fbd70ad9620f3a33a270cedfa47114c9566660c28ff8d0b3772b5c8dc1dac085"
dependencies = [
"compact_str",
"crossbeam-utils",
@@ -867,9 +867,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.159"
+version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
+checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "line-index"
@@ -1050,9 +1050,9 @@ dependencies = [
[[package]]
name = "notify-debouncer-full"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f5dab59c348b9b50cf7f261960a20e389feb2713636399cd9082cd4b536154"
+checksum = "fb7fd166739789c9ff169e654dc1501373db9d80a4c3f972817c8a4d7cf8f34e"
dependencies = [
"crossbeam-channel",
"file-id",
@@ -1141,9 +1141,9 @@ dependencies = [
[[package]]
name = "pathdiff"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361"
[[package]]
name = "percent-encoding"
@@ -1437,9 +1437,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.128"
+version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
+checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [
"itoa",
"memchr",
@@ -1564,7 +1564,7 @@ dependencies = [
[[package]]
name = "texlab"
-version = "5.20.0"
+version = "5.21.0"
dependencies = [
"anyhow",
"base-db",
diff --git a/support/texlab/Cargo.toml b/support/texlab/Cargo.toml
index 393ecdcfcf..c898466e4e 100644
--- a/support/texlab/Cargo.toml
+++ b/support/texlab/Cargo.toml
@@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"
[workspace.package]
-version = "5.20.0"
+version = "5.21.0"
license = "GPL-3.0"
authors = [
"Eric Förster <eric.foerster@outlook.com>",
@@ -13,7 +13,7 @@ edition = "2021"
rust-version = "1.80"
[workspace.dependencies]
-anyhow = "1.0.89"
+anyhow = "1.0.90"
criterion = "0.5.1"
crossbeam-channel = "0.5.13"
expect-test = "1.5.0"
@@ -25,7 +25,7 @@ regex = "1.11.0"
rowan = "0.15.16"
rustc-hash = "2.0.0"
serde = { version = "1.0.210", features = ["derive"] }
-serde_json = "1.0.128"
+serde_json = "1.0.132"
tempfile = "3.13.0"
titlecase = "3.3.0"
unicode-normalization = "0.1.24"
diff --git a/support/texlab/crates/base-db/src/config.rs b/support/texlab/crates/base-db/src/config.rs
index 455fdc2a6c..5774f2a0ec 100644
--- a/support/texlab/crates/base-db/src/config.rs
+++ b/support/texlab/crates/base-db/src/config.rs
@@ -68,6 +68,7 @@ pub enum Formatter {
pub struct LatexIndentConfig {
pub local: Option<String>,
pub modify_line_breaks: bool,
+ pub replacement: Option<String>,
}
#[derive(Debug, Default)]
diff --git a/support/texlab/crates/base-db/src/deps/discover.rs b/support/texlab/crates/base-db/src/deps/discover.rs
index cbcab4d8fb..3039d7b0f4 100644
--- a/support/texlab/crates/base-db/src/deps/discover.rs
+++ b/support/texlab/crates/base-db/src/deps/discover.rs
@@ -15,7 +15,7 @@ pub fn watch(
) {
let roots = workspace
.iter()
- .map(|document| &document.dir)
+ .filter_map(|document| document.dir.as_ref())
.filter(|dir| dir.scheme() == "file")
.unique()
.map(|dir| ProjectRoot::walk_and_find(workspace, dir));
diff --git a/support/texlab/crates/base-db/src/deps/graph.rs b/support/texlab/crates/base-db/src/deps/graph.rs
index 0d8252688d..aec5cea92b 100644
--- a/support/texlab/crates/base-db/src/deps/graph.rs
+++ b/support/texlab/crates/base-db/src/deps/graph.rs
@@ -55,7 +55,11 @@ impl Graph {
start: start.uri.clone(),
};
- let root = ProjectRoot::walk_and_find(workspace, &start.dir);
+ let Some(start_dir) = &start.dir else {
+ return graph;
+ };
+
+ let root = ProjectRoot::walk_and_find(workspace, start_dir);
let mut stack = vec![(start, Rc::new(root))];
let mut visited = FxHashSet::default();
@@ -135,7 +139,7 @@ impl Graph {
.as_deref()
.and_then(|dir| Url::from_directory_path(dir).ok());
- let working_dir = working_dir.as_ref().unwrap_or(&start.source.dir);
+ let working_dir = working_dir.as_ref().or(start.source.dir.as_ref())?;
let new_root = Arc::new(ProjectRoot::from_config(workspace, working_dir));
for target_uri in file_list
diff --git a/support/texlab/crates/base-db/src/deps/root.rs b/support/texlab/crates/base-db/src/deps/root.rs
index 03fd41a9a0..aa3969353d 100644
--- a/support/texlab/crates/base-db/src/deps/root.rs
+++ b/support/texlab/crates/base-db/src/deps/root.rs
@@ -45,7 +45,7 @@ impl ProjectRoot {
pub fn from_tectonic(workspace: &Workspace, dir: &Url) -> Option<Self> {
let exists = workspace
.iter()
- .filter(|document| document.dir == *dir)
+ .filter(|document| document.dir.as_ref() == Some(dir))
.any(|document| matches!(document.data, DocumentData::Tectonic));
if !exists {
@@ -77,7 +77,7 @@ impl ProjectRoot {
let config = workspace.config();
let rcfile = workspace
.iter()
- .filter(|document| document.dir == *dir)
+ .filter(|document| document.dir.as_ref() == Some(dir))
.find_map(|document| document.data.as_latexmkrc())?;
let compile_dir = dir.clone();
@@ -121,7 +121,7 @@ impl ProjectRoot {
pub fn from_rootfile(workspace: &Workspace, dir: &Url) -> Option<Self> {
let exists = workspace
.iter()
- .filter(|document| document.dir == *dir)
+ .filter(|document| document.dir.as_ref() == Some(dir))
.any(|document| matches!(document.data, DocumentData::Root));
if !exists {
diff --git a/support/texlab/crates/base-db/src/document.rs b/support/texlab/crates/base-db/src/document.rs
index 6fdcf30c16..0b81fa2871 100644
--- a/support/texlab/crates/base-db/src/document.rs
+++ b/support/texlab/crates/base-db/src/document.rs
@@ -28,7 +28,7 @@ pub struct DocumentParams<'a> {
#[derive(Clone)]
pub struct Document {
pub uri: Url,
- pub dir: Url,
+ pub dir: Option<Url>,
pub path: Option<PathBuf>,
pub text: String,
pub line_index: LineIndex,
@@ -42,7 +42,7 @@ impl Document {
pub fn parse(params: DocumentParams) -> Self {
let DocumentParams { uri, text, .. } = params;
- let dir = uri.join(".").unwrap();
+ let dir = uri.join(".").ok();
let path = if uri.scheme() == "file" {
uri.to_file_path().ok()
diff --git a/support/texlab/crates/base-db/src/semantics/auxiliary.rs b/support/texlab/crates/base-db/src/semantics/auxiliary.rs
index 8c9fe012e6..bb9a2c065c 100644
--- a/support/texlab/crates/base-db/src/semantics/auxiliary.rs
+++ b/support/texlab/crates/base-db/src/semantics/auxiliary.rs
@@ -5,6 +5,7 @@ use syntax::latex::{self, HasCurly};
#[derive(Debug, Clone, Default)]
pub struct Semantics {
pub label_numbers: FxHashMap<String, String>,
+ pub section_numbers: FxHashMap<String, String>,
}
impl Semantics {
@@ -18,6 +19,9 @@ impl Semantics {
if let Some(label_number) = latex::LabelNumber::cast(node.clone()) {
self.process_label_number(&label_number);
}
+ if let Some(toc_line) = latex::TocContentsLine::cast(node.clone()) {
+ self.process_toc_line(&toc_line);
+ }
}
fn process_label_number(&mut self, label_number: &latex::LabelNumber) -> Option<()> {
@@ -40,4 +44,36 @@ impl Semantics {
self.label_numbers.insert(name, text);
Some(())
}
+
+ fn process_toc_line(&mut self, toc_line: &latex::TocContentsLine) -> Option<()> {
+ let unit = toc_line.unit().and_then(|u| u.content_text())?.to_string();
+
+ if [
+ "part",
+ "chapter",
+ "section",
+ "subsection",
+ "subsubsection",
+ "paragraph",
+ "subparagraph",
+ ]
+ .contains(&unit.as_str())
+ {
+ let line = toc_line.line()?;
+ let name = line.syntax().children().find_map(|child| {
+ latex::Text::cast(child.clone())?;
+ Some(child)
+ })?;
+ let name = name.to_string();
+
+ let num_line = line
+ .syntax()
+ .children()
+ .find_map(|child| latex::TocNumberLine::cast(child.clone()))?;
+ let number = num_line.number()?;
+ let number = number.content_text()?.replace(['{', '}'], "");
+ self.section_numbers.insert(name, number);
+ }
+ Some(())
+ }
}
diff --git a/support/texlab/crates/base-db/src/semantics/tex.rs b/support/texlab/crates/base-db/src/semantics/tex.rs
index acd94b6056..7d150fc4b3 100644
--- a/support/texlab/crates/base-db/src/semantics/tex.rs
+++ b/support/texlab/crates/base-db/src/semantics/tex.rs
@@ -38,6 +38,7 @@ pub struct Semantics {
pub can_be_root: bool,
pub can_be_compiled: bool,
pub diagnostic_suppressions: Vec<TextRange>,
+ pub bibitems: FxHashSet<Span>,
}
impl Semantics {
@@ -49,7 +50,7 @@ impl Semantics {
}
latex::SyntaxElement::Token(token) => match token.kind() {
latex::COMMAND_NAME => {
- self.commands.push(Span::command(&token));
+ self.commands.push(Span::command(&token));
}
latex::COMMENT if token.text().contains("texlab: ignore") => {
self.diagnostic_suppressions.push(token.text_range());
@@ -85,6 +86,8 @@ impl Semantics {
self.process_theorem_definition(theorem_def);
} else if let Some(graphics_path) = latex::GraphicsPath::cast(node.clone()) {
self.process_graphics_path(graphics_path);
+ } else if let Some(bibitem) = latex::BibItem::cast(node.clone()) {
+ self.process_bibitem(bibitem);
}
}
@@ -334,6 +337,16 @@ impl Semantics {
self.graphics_paths.insert(path.to_string());
}
}
+
+ fn process_bibitem(&mut self, bibitem: latex::BibItem) {
+ if let Some(name) = bibitem.name() {
+ if let Some(key) = name.key() {
+ self.bibitems.insert(
+ Span::from(&key)
+ );
+ }
+ }
+ }
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
diff --git a/support/texlab/crates/bibtex-utils/Cargo.toml b/support/texlab/crates/bibtex-utils/Cargo.toml
index 8ab72e39d8..1271823eac 100644
--- a/support/texlab/crates/bibtex-utils/Cargo.toml
+++ b/support/texlab/crates/bibtex-utils/Cargo.toml
@@ -8,7 +8,7 @@ rust-version.workspace = true
[dependencies]
chrono = { version = "0.4.38", default-features = false, features = ["std"] }
-human_name = "2.0.3"
+human_name = "2.0.4"
itertools.workspace = true
rowan.workspace = true
rustc-hash.workspace = true
diff --git a/support/texlab/crates/commands/Cargo.toml b/support/texlab/crates/commands/Cargo.toml
index ddd7db2991..b348ad2b87 100644
--- a/support/texlab/crates/commands/Cargo.toml
+++ b/support/texlab/crates/commands/Cargo.toml
@@ -12,7 +12,7 @@ base-db = { path = "../base-db" }
bstr = "1.10.0"
crossbeam-channel.workspace = true
itertools.workspace = true
-libc = "0.2.159"
+libc = "0.2.161"
log.workspace = true
rowan.workspace = true
rustc-hash.workspace = true
diff --git a/support/texlab/crates/commands/src/build.rs b/support/texlab/crates/commands/src/build.rs
index 34d39f26e4..23a6e16b7b 100644
--- a/support/texlab/crates/commands/src/build.rs
+++ b/support/texlab/crates/commands/src/build.rs
@@ -47,6 +47,10 @@ impl BuildCommand {
.next()
.unwrap_or(document);
+ let Some(document_dir) = &document.dir else {
+ return Err(BuildError::NotLocal(document.uri.clone()));
+ };
+
let Some(path) = document.path.as_deref().and_then(Path::to_str) else {
return Err(BuildError::NotLocal(document.uri.clone()));
};
@@ -55,7 +59,7 @@ impl BuildCommand {
let program = config.program.clone();
let args = replace_placeholders(&config.args, &[('f', path)]);
- let root = ProjectRoot::walk_and_find(workspace, &document.dir);
+ let root = ProjectRoot::walk_and_find(workspace, document_dir);
let Ok(working_dir) = root.compile_dir.to_file_path() else {
return Err(BuildError::NotLocal(document.uri.clone()));
diff --git a/support/texlab/crates/commands/src/clean.rs b/support/texlab/crates/commands/src/clean.rs
index d4ec6b24f4..e429d1afa2 100644
--- a/support/texlab/crates/commands/src/clean.rs
+++ b/support/texlab/crates/commands/src/clean.rs
@@ -21,7 +21,11 @@ impl CleanCommand {
anyhow::bail!("document '{}' is not a local file", document.uri)
};
- let root = ProjectRoot::walk_and_find(workspace, &document.dir);
+ let Some(document_dir) = &document.dir else {
+ anyhow::bail!("document '{}' is not a local file", document.uri)
+ };
+
+ let root = ProjectRoot::walk_and_find(workspace, document_dir);
let flag = match target {
CleanTarget::Auxiliary => "-c",
diff --git a/support/texlab/crates/commands/src/fwd_search.rs b/support/texlab/crates/commands/src/fwd_search.rs
index f3480ef3e2..8b6227d8c2 100644
--- a/support/texlab/crates/commands/src/fwd_search.rs
+++ b/support/texlab/crates/commands/src/fwd_search.rs
@@ -84,7 +84,11 @@ impl ForwardSearch {
}
fn find_pdf(workspace: &Workspace, document: &Document) -> Result<PathBuf, ForwardSearchError> {
- let root = ProjectRoot::walk_and_find(workspace, &document.dir);
+ let Some(document_dir) = &document.dir else {
+ return Err(ForwardSearchError::NotLocal(document.uri.clone()));
+ };
+
+ let root = ProjectRoot::walk_and_find(workspace, document_dir);
log::debug!("[FwdSearch] root={root:#?}");
diff --git a/support/texlab/crates/completion/src/providers/include.rs b/support/texlab/crates/completion/src/providers/include.rs
index d0a042252f..f3deb3a108 100644
--- a/support/texlab/crates/completion/src/providers/include.rs
+++ b/support/texlab/crates/completion/src/providers/include.rs
@@ -118,7 +118,7 @@ fn current_dir(
.next()
.map_or(params.document, Clone::clone);
- let root = ProjectRoot::walk_and_find(workspace, &parent.dir);
+ let root = ProjectRoot::walk_and_find(workspace, parent.dir.as_ref()?);
let mut path = PathBuf::new();
if let Some(graphics_path) = graphics_path {
diff --git a/support/texlab/crates/diagnostics/src/chktex.rs b/support/texlab/crates/diagnostics/src/chktex.rs
index a3f539440d..b7cd80d67b 100644
--- a/support/texlab/crates/diagnostics/src/chktex.rs
+++ b/support/texlab/crates/diagnostics/src/chktex.rs
@@ -36,7 +36,7 @@ impl Command {
return None;
}
- let root = ProjectRoot::walk_and_find(workspace, &parent.dir);
+ let root = ProjectRoot::walk_and_find(workspace, parent.dir.as_ref()?);
let working_dir = root.src_dir.to_file_path().ok()?;
log::debug!("Calling ChkTeX from directory: {}", working_dir.display());
diff --git a/support/texlab/crates/diagnostics/src/citations.rs b/support/texlab/crates/diagnostics/src/citations.rs
index 43d5f495d2..2678d7e456 100644
--- a/support/texlab/crates/diagnostics/src/citations.rs
+++ b/support/texlab/crates/diagnostics/src/citations.rs
@@ -18,13 +18,17 @@ pub fn detect_undefined_citations<'a>(
) -> Option<()> {
let data = document.data.as_tex()?;
+ let bibitems: FxHashSet<&str> = data.semantics.bibitems.iter()
+ .map(|bib| bib.text.as_str())
+ .collect();
+
let entries: FxHashSet<&str> = Entry::find_all(project)
.map(|(_, entry)| entry.name_text())
.collect();
for citation in &data.semantics.citations {
let name = citation.name_text();
- if name != "*" && !entries.contains(name) {
+ if name != "*" && !entries.contains(name) && !bibitems.contains(name) {
let diagnostic = Diagnostic::Tex(citation.name.range, TexError::UndefinedCitation);
results
.entry(document.uri.clone())
@@ -41,24 +45,38 @@ pub fn detect_unused_entries<'a>(
document: &'a Document,
results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) -> Option<()> {
- let data = document.data.as_bib()?;
-
- // If this is a huge bibliography, then don't bother checking for unused entries.
- if data.semantics.entries.len() > MAX_UNUSED_ENTRIES {
- return None;
- }
let citations: FxHashSet<&str> = Citation::find_all(project)
.map(|(_, citation)| citation.name_text())
.collect();
- for entry in &data.semantics.entries {
- if !citations.contains(entry.name.text.as_str()) {
- let diagnostic = Diagnostic::Bib(entry.name.range, BibError::UnusedEntry);
- results
- .entry(document.uri.clone())
- .or_default()
- .push(diagnostic);
+ if let Some(data) = document.data.as_bib()
+ {
+ // If this is a huge bibliography, then don't bother checking for unused entries.
+ if data.semantics.entries.len() > MAX_UNUSED_ENTRIES {
+ return None;
+ }
+
+ for entry in &data.semantics.entries {
+ if !citations.contains(entry.name.text.as_str()) {
+ let diagnostic = Diagnostic::Bib(entry.name.range, BibError::UnusedEntry);
+ results
+ .entry(document.uri.clone())
+ .or_default()
+ .push(diagnostic);
+ }
+ }
+ };
+
+ if let Some(tex_data) = document.data.as_tex(){
+ for bibitem in &tex_data.semantics.bibitems {
+ if !citations.contains(bibitem.text.as_str()) {
+ let diagnostic = Diagnostic::Bib(bibitem.range, BibError::UnusedEntry);
+ results
+ .entry(document.uri.clone())
+ .or_default()
+ .push(diagnostic);
+ }
}
}
diff --git a/support/texlab/crates/distro/src/lib.rs b/support/texlab/crates/distro/src/lib.rs
index 5c0dbe51fb..cf1420baa9 100644
--- a/support/texlab/crates/distro/src/lib.rs
+++ b/support/texlab/crates/distro/src/lib.rs
@@ -4,7 +4,10 @@ mod language;
mod miktex;
mod texlive;
-use std::process::{Command, Stdio};
+use std::{
+ env,
+ process::{Command, Stdio},
+};
use anyhow::Result;
@@ -70,8 +73,14 @@ impl Distro {
DistroKind::Tectonic | DistroKind::Unknown => FileNameDB::default(),
};
- if let Some(bibinputs) = std::env::var_os("BIBINPUTS") {
- for dir in std::env::split_paths(&bibinputs) {
+ Self::read_env_dir(&mut file_name_db, "TEXINPUTS");
+ Self::read_env_dir(&mut file_name_db, "BIBINPUTS");
+ Ok(Self { kind, file_name_db })
+ }
+
+ fn read_env_dir(file_name_db: &mut FileNameDB, env_var: &str) {
+ if let Some(paths) = env::var_os(env_var) {
+ for dir in env::split_paths(&paths) {
if let Ok(entries) = std::fs::read_dir(dir) {
for file in entries
.flatten()
@@ -83,7 +92,5 @@ impl Distro {
}
}
}
-
- Ok(Self { kind, file_name_db })
}
}
diff --git a/support/texlab/crates/parser/Cargo.toml b/support/texlab/crates/parser/Cargo.toml
index 8dd3a771f8..e1edb782c5 100644
--- a/support/texlab/crates/parser/Cargo.toml
+++ b/support/texlab/crates/parser/Cargo.toml
@@ -10,7 +10,7 @@ rust-version.workspace = true
log.workspace = true
logos = "0.14.2"
once_cell.workspace = true
-pathdiff = "0.2.1"
+pathdiff = "0.2.2"
regex.workspace = true
rowan.workspace = true
rustc-hash.workspace = true
diff --git a/support/texlab/crates/parser/src/latex.rs b/support/texlab/crates/parser/src/latex.rs
index 669ba82f99..8379d9c5ca 100644
--- a/support/texlab/crates/parser/src/latex.rs
+++ b/support/texlab/crates/parser/src/latex.rs
@@ -158,6 +158,9 @@ impl<'a> Parser<'a> {
CommandName::EndBlockComment => self.generic_command(),
CommandName::VerbatimBlock => self.verbatim_block(),
CommandName::GraphicsPath => self.graphics_path(),
+ CommandName::BibItem => self.bibitem(),
+ CommandName::TocContentsLine => self.toc_contents_line(),
+ CommandName::TocNumberLine => self.toc_number_line(),
},
}
}
@@ -862,7 +865,20 @@ impl<'a> Parser<'a> {
}
if self.lexer.peek() == Some(Token::LCurly) {
- self.curly_group_word();
+ self.builder.start_node(CURLY_GROUP_WORD.into());
+ self.eat();
+ self.trivia();
+
+ if self.peek() == Some(Token::Word) || self.peek() == Some(Token::Pipe) {
+ self.key();
+ }
+
+ if let Some(Token::CommandName(_)) = self.peek() {
+ self.content(ParserContext::default());
+ }
+
+ self.expect(Token::RCurly);
+ self.builder.finish_node();
}
self.builder.finish_node();
@@ -1235,6 +1251,50 @@ impl<'a> Parser<'a> {
}
}
}
+
+ fn bibitem(&mut self) {
+ self.builder.start_node(BIBITEM.into());
+ self.eat();
+ self.trivia();
+
+ if self.lexer.peek() == Some(Token::LCurly) {
+ self.curly_group_word();
+ }
+
+ self.builder.finish_node();
+ }
+
+ fn toc_contents_line(&mut self) {
+ self.builder.start_node(TOC_CONTENTS_LINE.into());
+ self.eat();
+ self.trivia();
+
+ if self.lexer.peek() == Some(Token::LCurly) {
+ self.curly_group();
+ }
+
+ if self.lexer.peek() == Some(Token::LCurly) {
+ self.curly_group();
+ }
+
+ if self.lexer.peek() == Some(Token::LCurly) {
+ self.curly_group();
+ }
+
+ self.builder.finish_node();
+ }
+
+ fn toc_number_line(&mut self) {
+ self.builder.start_node(TOC_NUMBER_LINE.into());
+ self.eat();
+ self.trivia();
+
+ if self.lexer.peek() == Some(Token::LCurly) {
+ self.curly_group();
+ }
+
+ self.builder.finish_node();
+ }
}
pub fn parse_latex(text: &str, config: &SyntaxConfig) -> GreenNode {
diff --git a/support/texlab/crates/parser/src/latex/lexer/commands.rs b/support/texlab/crates/parser/src/latex/lexer/commands.rs
index 4d1a7ca320..3f8b6e36ed 100644
--- a/support/texlab/crates/parser/src/latex/lexer/commands.rs
+++ b/support/texlab/crates/parser/src/latex/lexer/commands.rs
@@ -96,6 +96,9 @@ pub fn classify(name: &str, config: &SyntaxConfig) -> CommandName {
"iffalse" => CommandName::BeginBlockComment,
"fi" => CommandName::EndBlockComment,
"verb" => CommandName::VerbatimBlock,
+ "bibitem" => CommandName::BibItem,
+ "contentsline" => CommandName::TocContentsLine,
+ "numberline" => CommandName::TocNumberLine,
_ if config.citation_commands.contains(name) => CommandName::Citation,
_ if config.label_definition_commands.contains(name) => CommandName::LabelDefinition,
diff --git a/support/texlab/crates/parser/src/latex/lexer/types.rs b/support/texlab/crates/parser/src/latex/lexer/types.rs
index 85e542792b..796378f671 100644
--- a/support/texlab/crates/parser/src/latex/lexer/types.rs
+++ b/support/texlab/crates/parser/src/latex/lexer/types.rs
@@ -95,6 +95,9 @@ pub enum CommandName {
BeginBlockComment,
EndBlockComment,
VerbatimBlock,
+ BibItem,
+ TocContentsLine,
+ TocNumberLine,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
diff --git a/support/texlab/crates/references/src/command.rs b/support/texlab/crates/references/src/command.rs
index f4504641f2..cf5849a136 100644
--- a/support/texlab/crates/references/src/command.rs
+++ b/support/texlab/crates/references/src/command.rs
@@ -32,7 +32,9 @@ pub(super) fn find_all(context: &mut ReferenceContext) -> Option<()> {
.collect();
for command in &data.semantics.commands {
- if command.text == token.text()[1..] {
+ let command_text = command.text.trim_end_matches('*');
+ let token_text = token.text()[1..].trim_end_matches('*');
+ if command_text == token_text {
let kind = if defs.contains(command) {
ReferenceKind::Definition
} else {
diff --git a/support/texlab/crates/references/src/tests.rs b/support/texlab/crates/references/src/tests.rs
index 845282afb0..7131480699 100644
--- a/support/texlab/crates/references/src/tests.rs
+++ b/support/texlab/crates/references/src/tests.rs
@@ -260,3 +260,43 @@ fn test_new_command_definition_include_decl() {
true,
);
}
+
+#[test]
+fn test_new_command_definition_starred() {
+ check(
+ r#"
+%! main.tex
+\foo
+ ^^^
+\foo*
+ |
+ ^^^^
+
+\NewDocumentCommand{\foo}{s m}{%
+ \IfBooleanTF{#1}{\textbf{#2}}{#2}%
+}
+"#,
+ false,
+ );
+}
+
+#[test]
+fn test_new_command_definition_starred_include_decl() {
+ check(
+ r#"
+%! main.tex
+\foo
+ ^^^
+\foo*
+ |
+ ^^^^
+
+\NewDocumentCommand{\foo}{s m}{%
+ ^^^
+ \IfBooleanTF{#1}{\textbf{#2}}{#2}%
+}
+
+"#,
+ true,
+ );
+}
diff --git a/support/texlab/crates/symbols/src/document/tests.rs b/support/texlab/crates/symbols/src/document/tests.rs
index 25450a6cc5..cf599529fb 100644
--- a/support/texlab/crates/symbols/src/document/tests.rs
+++ b/support/texlab/crates/symbols/src/document/tests.rs
@@ -281,44 +281,44 @@ fn test_section() {
check(
&fixture,
expect![[r#"
- [
- Symbol {
- name: "Foo",
- kind: Section,
- label: None,
- full_range: 43..56,
- selection_range: 43..56,
- children: [],
- },
- Symbol {
- name: "2 Bar",
- kind: Section,
- label: Some(
- Span(
- "sec:bar",
- 71..86,
+ [
+ Symbol {
+ name: "1 Foo",
+ kind: Section,
+ label: None,
+ full_range: 43..56,
+ selection_range: 43..56,
+ children: [],
+ },
+ Symbol {
+ name: "2 Bar",
+ kind: Section,
+ label: Some(
+ Span(
+ "sec:bar",
+ 71..86,
+ ),
),
- ),
- full_range: 58..119,
- selection_range: 71..86,
- children: [
- Symbol {
- name: "Baz",
- kind: Section,
- label: Some(
- Span(
- "sec:baz",
- 104..119,
+ full_range: 58..119,
+ selection_range: 71..86,
+ children: [
+ Symbol {
+ name: "Baz",
+ kind: Section,
+ label: Some(
+ Span(
+ "sec:baz",
+ 104..119,
+ ),
),
- ),
- full_range: 88..119,
- selection_range: 104..119,
- children: [],
- },
- ],
- },
- ]
- "#]],
+ full_range: 88..119,
+ selection_range: 104..119,
+ children: [],
+ },
+ ],
+ },
+ ]
+ "#]],
);
}
diff --git a/support/texlab/crates/symbols/src/document/tex.rs b/support/texlab/crates/symbols/src/document/tex.rs
index e0df9c85c1..734335ef0e 100644
--- a/support/texlab/crates/symbols/src/document/tex.rs
+++ b/support/texlab/crates/symbols/src/document/tex.rs
@@ -67,16 +67,14 @@ impl<'a> SymbolBuilder<'a> {
let group_text = group.content_text()?;
let kind = SymbolKind::Section;
- let symbol = match self.find_label(section.syntax()) {
- Some(label) => {
- let name = match self.find_label_number(&label.text) {
- Some(number) => format!("{number} {group_text}"),
- None => group_text,
- };
+ let name = match self.find_section_number(&group_text) {
+ Some(number) => format!("{number} {group_text}"),
+ None => group_text,
+ };
- Symbol::new_label(name, kind, range, label)
- }
- None => Symbol::new_simple(group_text, kind, range, range),
+ let symbol = match self.find_label(section.syntax()) {
+ Some(label) => Symbol::new_label(name, kind, range, label),
+ None => Symbol::new_simple(name, kind, range, range)
};
Some(symbol)
@@ -247,6 +245,15 @@ impl<'a> SymbolBuilder<'a> {
Some(Span { text, range })
}
+ fn find_section_number(&self, name: &str) -> Option<&str> {
+ self.project
+ .documents
+ .iter()
+ .filter_map(|document| document.data.as_aux())
+ .find_map(|data| data.semantics.section_numbers.get(name))
+ .map(String::as_str)
+ }
+
fn find_label_number(&self, name: &str) -> Option<&str> {
self.project
.documents
diff --git a/support/texlab/crates/syntax/src/latex/cst.rs b/support/texlab/crates/syntax/src/latex/cst.rs
index 806be2aa83..580ef6af12 100644
--- a/support/texlab/crates/syntax/src/latex/cst.rs
+++ b/support/texlab/crates/syntax/src/latex/cst.rs
@@ -750,3 +750,43 @@ impl GraphicsPath {
self.syntax().descendants().filter_map(CurlyGroupWord::cast)
}
}
+
+cst_node!(BibItem, BIBITEM);
+
+impl BibItem {
+ pub fn command(&self) -> Option<SyntaxToken> {
+ self.syntax().first_token()
+ }
+
+ pub fn name(&self) -> Option<CurlyGroupWord> {
+ self.syntax().children().find_map(CurlyGroupWord::cast)
+ }
+}
+
+cst_node!(TocContentsLine, TOC_CONTENTS_LINE);
+
+impl TocContentsLine {
+ pub fn command(&self) -> Option<SyntaxToken> {
+ self.syntax().first_token()
+ }
+
+ pub fn unit(&self) -> Option<CurlyGroup> {
+ self.syntax().children().find_map(CurlyGroup::cast)
+ }
+
+ pub fn line(&self) -> Option<CurlyGroup> {
+ self.syntax().children().filter_map(CurlyGroup::cast).nth(1)
+ }
+}
+
+cst_node!(TocNumberLine, TOC_NUMBER_LINE);
+
+impl TocNumberLine {
+ pub fn command(&self) -> Option<SyntaxToken> {
+ self.syntax().first_token()
+ }
+
+ pub fn number(&self) -> Option<CurlyGroup> {
+ self.syntax().children().find_map(CurlyGroup::cast)
+ }
+}
diff --git a/support/texlab/crates/syntax/src/latex/kind.rs b/support/texlab/crates/syntax/src/latex/kind.rs
index 362f2ea058..f67201e003 100644
--- a/support/texlab/crates/syntax/src/latex/kind.rs
+++ b/support/texlab/crates/syntax/src/latex/kind.rs
@@ -82,6 +82,9 @@ pub enum SyntaxKind {
ENVIRONMENT_DEFINITION,
GRAPHICS_PATH,
BLOCK_COMMENT,
+ BIBITEM,
+ TOC_CONTENTS_LINE,
+ TOC_NUMBER_LINE,
ROOT,
}
diff --git a/support/texlab/crates/texlab/Cargo.toml b/support/texlab/crates/texlab/Cargo.toml
index 149b0c632f..5f73cbf024 100644
--- a/support/texlab/crates/texlab/Cargo.toml
+++ b/support/texlab/crates/texlab/Cargo.toml
@@ -26,7 +26,7 @@ anyhow.workspace = true
base-db = { path = "../base-db" }
bibfmt = { path = "../bibfmt" }
citeproc = { path = "../citeproc" }
-clap = { version = "4.5.19", features = ["derive"] }
+clap = { version = "4.5.20", features = ["derive"] }
commands = { path = "../commands" }
completion = { path = "../completion" }
completion-data = { path = "../completion-data" }
@@ -34,7 +34,7 @@ crossbeam-channel.workspace = true
definition = { path = "../definition" }
diagnostics = { path = "../diagnostics" }
distro = { path = "../distro" }
-fern = "0.6.2"
+fern = "0.7.0"
folding = { path = "../folding" }
highlights = { path = "../highlights" }
hover = { path = "../hover" }
@@ -46,7 +46,7 @@ log.workspace = true
lsp-server = "0.7.7"
lsp-types = "0.95.1"
notify.workspace = true
-notify-debouncer-full = "0.3.1"
+notify-debouncer-full = "0.3.2"
parking_lot = "0.12.3"
parser = { path = "../parser" }
references = { path = "../references" }
diff --git a/support/texlab/crates/texlab/src/features/formatting/latexindent.rs b/support/texlab/crates/texlab/src/features/formatting/latexindent.rs
index d3fffc2050..b956378ed5 100644
--- a/support/texlab/crates/texlab/src/features/formatting/latexindent.rs
+++ b/support/texlab/crates/texlab/src/features/formatting/latexindent.rs
@@ -16,7 +16,7 @@ pub fn format_with_latexindent(
) -> Option<Vec<lsp_types::TextEdit>> {
let config = workspace.config();
let target_dir = tempdir().ok()?;
- let root = ProjectRoot::walk_and_find(workspace, &document.dir);
+ let root = ProjectRoot::walk_and_find(workspace, document.dir.as_ref()?);
let source_dir = root.src_dir.to_file_path().ok()?;
let target_file = target_dir
@@ -72,6 +72,15 @@ fn build_arguments(config: &LatexIndentConfig, target_file: &Path) -> Vec<String
args.push("--modifylinebreaks".to_string());
}
+ match &config.replacement {
+ Some(replacement_flag) => {
+ if ["-r", "-rv", "-rr"].contains(& replacement_flag.as_str()) {
+ args.push(replacement_flag.clone());
+ }
+ },
+ None => {}
+ }
+
args.push(target_file.display().to_string());
args
}
diff --git a/support/texlab/crates/texlab/src/server/options.rs b/support/texlab/crates/texlab/src/server/options.rs
index bc785c56c1..fcb8e1ec60 100644
--- a/support/texlab/crates/texlab/src/server/options.rs
+++ b/support/texlab/crates/texlab/src/server/options.rs
@@ -56,6 +56,7 @@ impl Default for LatexFormatter {
pub struct LatexindentOptions {
pub local: Option<String>,
pub modify_line_breaks: bool,
+ pub replacement: Option<String>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
diff --git a/support/texlab/crates/texlab/src/util/from_proto.rs b/support/texlab/crates/texlab/src/util/from_proto.rs
index 2f4fbe64c5..928b3d6d61 100644
--- a/support/texlab/crates/texlab/src/util/from_proto.rs
+++ b/support/texlab/crates/texlab/src/util/from_proto.rs
@@ -282,6 +282,7 @@ pub fn config(value: Options) -> Config {
config.formatting.latex_indent.local = value.latexindent.local;
config.formatting.latex_indent.modify_line_breaks = value.latexindent.modify_line_breaks;
+ config.formatting.latex_indent.replacement = value.latexindent.replacement;
config.synctex = value
.forward_search
diff --git a/support/texlab/texlab.1 b/support/texlab/texlab.1
index f3d916cf06..27fabe2066 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" "October 2024" "texlab 5.20.0" "User Commands"
+.TH TEXLAB "1" "October 2024" "texlab 5.21.0" "User Commands"
.SH NAME
-texlab \- manual page for texlab 5.20.0
+texlab \- manual page for texlab 5.21.0
.SH SYNOPSIS
.B texlab
[\fI\,OPTIONS\/\fR] [\fI\,COMMAND\/\fR]
diff --git a/support/texlab/texlab.pdf b/support/texlab/texlab.pdf
index d1e81ceebb..152ab2bac4 100644
--- a/support/texlab/texlab.pdf
+++ b/support/texlab/texlab.pdf
Binary files differ