diff options
author | Norbert Preining <norbert@preining.info> | 2024-10-27 03:03:33 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2024-10-27 03:03:33 +0000 |
commit | ade38177952984be4fbae56a1f8d212db1d2b689 (patch) | |
tree | 1ed7e11480908e7bfab6d3edee14fe2a0e040817 /support/texlab | |
parent | bcdaee1dcafa3d6898089a20f60acf2aee48c3e5 (diff) |
CTAN sync 202410270303
Diffstat (limited to 'support/texlab')
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 Binary files differindex d1e81ceebb..152ab2bac4 100644 --- a/support/texlab/texlab.pdf +++ b/support/texlab/texlab.pdf |