summaryrefslogtreecommitdiff
path: root/support/texlab
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab')
-rw-r--r--support/texlab/CHANGELOG.md17
-rw-r--r--support/texlab/Cargo.lock48
-rw-r--r--support/texlab/crates/base-db/src/config.rs54
-rw-r--r--support/texlab/crates/base-db/src/deps/graph.rs6
-rw-r--r--support/texlab/crates/base-db/src/deps/root.rs4
-rw-r--r--support/texlab/crates/base-db/src/document.rs5
-rw-r--r--support/texlab/crates/base-db/src/semantics/auxiliary.rs2
-rw-r--r--support/texlab/crates/base-db/src/semantics/tex.rs123
-rw-r--r--support/texlab/crates/base-db/src/workspace.rs2
-rw-r--r--support/texlab/crates/bibfmt/src/lib.rs6
-rw-r--r--support/texlab/crates/bibtex-utils/Cargo.toml2
-rw-r--r--support/texlab/crates/commands/Cargo.toml6
-rw-r--r--support/texlab/crates/commands/src/find_envs.rs2
-rw-r--r--support/texlab/crates/commands/src/fwd_search.rs2
-rw-r--r--support/texlab/crates/commands/src/placeholders.rs2
-rw-r--r--support/texlab/crates/completion-data/Cargo.toml6
-rw-r--r--support/texlab/crates/completion/Cargo.toml1
-rw-r--r--support/texlab/crates/completion/src/lib.rs8
-rw-r--r--support/texlab/crates/completion/src/providers/argument.rs2
-rw-r--r--support/texlab/crates/completion/src/providers/color.rs2
-rw-r--r--support/texlab/crates/completion/src/providers/color_model.rs2
-rw-r--r--support/texlab/crates/completion/src/providers/command.rs4
-rw-r--r--support/texlab/crates/completion/src/providers/environment.rs6
-rw-r--r--support/texlab/crates/completion/src/providers/glossary.rs2
-rw-r--r--support/texlab/crates/completion/src/providers/import.rs8
-rw-r--r--support/texlab/crates/completion/src/providers/include.rs6
-rw-r--r--support/texlab/crates/completion/src/providers/label_ref.rs46
-rw-r--r--support/texlab/crates/completion/src/providers/tikz_library.rs2
-rw-r--r--support/texlab/crates/completion/src/tests.rs213
-rw-r--r--support/texlab/crates/definition/src/command.rs12
-rw-r--r--support/texlab/crates/definition/src/tests.rs2
-rw-r--r--support/texlab/crates/diagnostics/src/chktex.rs2
-rw-r--r--support/texlab/crates/diagnostics/src/citations.rs6
-rw-r--r--support/texlab/crates/diagnostics/src/manager.rs10
-rw-r--r--support/texlab/crates/diagnostics/src/tests.rs4
-rw-r--r--support/texlab/crates/distro/Cargo.toml2
-rw-r--r--support/texlab/crates/highlights/src/lib.rs2
-rw-r--r--support/texlab/crates/hover/src/lib.rs12
-rw-r--r--support/texlab/crates/inlay-hints/src/label.rs1
-rw-r--r--support/texlab/crates/ipc/Cargo.toml4
-rw-r--r--support/texlab/crates/parser/src/build_log.rs2
-rw-r--r--support/texlab/crates/parser/src/config.rs24
-rw-r--r--support/texlab/crates/parser/src/latexmkrc.rs8
-rw-r--r--support/texlab/crates/references/src/command.rs2
-rw-r--r--support/texlab/crates/references/src/entry.rs4
-rw-r--r--support/texlab/crates/references/src/label.rs2
-rw-r--r--support/texlab/crates/rename/Cargo.toml1
-rw-r--r--support/texlab/crates/rename/src/command.rs7
-rw-r--r--support/texlab/crates/rename/src/entry.rs4
-rw-r--r--support/texlab/crates/rename/src/label.rs47
-rw-r--r--support/texlab/crates/rename/src/lib.rs30
-rw-r--r--support/texlab/crates/rename/src/tests.rs111
-rw-r--r--support/texlab/crates/texlab/Cargo.toml12
-rw-r--r--support/texlab/crates/texlab/src/features/folding.rs2
-rw-r--r--support/texlab/crates/texlab/src/features/rename.rs2
-rw-r--r--support/texlab/crates/texlab/src/main.rs1
-rw-r--r--support/texlab/crates/texlab/src/server.rs20
-rw-r--r--support/texlab/crates/texlab/src/server/extensions.rs28
-rw-r--r--support/texlab/crates/texlab/src/server/options.rs6
-rw-r--r--support/texlab/crates/texlab/src/util.rs2
-rw-r--r--support/texlab/crates/texlab/src/util/client_flags.rs6
-rw-r--r--support/texlab/crates/texlab/src/util/from_proto.rs80
-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.pdfbin26307 -> 26397 bytes
65 files changed, 754 insertions, 308 deletions
diff --git a/support/texlab/CHANGELOG.md b/support/texlab/CHANGELOG.md
index 0a3b5ed683..007f344876 100644
--- a/support/texlab/CHANGELOG.md
+++ b/support/texlab/CHANGELOG.md
@@ -5,6 +5,23 @@ 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.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
+
+- Don't treat `\label{}` and `\ref{}` with macro parameter as label commands ([#1119](https://github.com/latex-lsp/texlab/issues/1119))
+- Fix parsing `latexmkrc` for `latexmk` versions older than `v4.8.4` ([#1128](https://github.com/latex-lsp/texlab/issues/1128))
+- Remove unused `texlab.rootDirectory` setting from documentation
+
## [5.16.0] - 2024-05-01
### Added
diff --git a/support/texlab/Cargo.lock b/support/texlab/Cargo.lock
index 80599217fd..09847a2a79 100644
--- a/support/texlab/Cargo.lock
+++ b/support/texlab/Cargo.lock
@@ -73,9 +73,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.82"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "autocfg"
@@ -190,9 +190,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.31"
+version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"num-traits",
]
@@ -334,6 +334,7 @@ dependencies = [
"expect-test",
"fuzzy-matcher",
"line-index",
+ "parser",
"rayon",
"rowan",
"rustc-hash",
@@ -594,9 +595,9 @@ dependencies = [
[[package]]
name = "flate2"
-version = "1.0.29"
+version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4556222738635b7a3417ae6130d8f52201e45a0c4d1a907f0826383adb5f85e7"
+checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -860,9 +861,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.153"
+version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "line-index"
@@ -1094,9 +1095,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "parking_lot"
-version = "0.12.1"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -1337,6 +1338,7 @@ name = "rename"
version = "0.0.0"
dependencies = [
"base-db",
+ "parser",
"rowan",
"rustc-hash",
"syntax",
@@ -1404,18 +1406,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
-version = "1.0.199"
+version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a"
+checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.199"
+version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc"
+checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
dependencies = [
"proc-macro2",
"quote",
@@ -1424,9 +1426,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.116"
+version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
+checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [
"itoa",
"ryu",
@@ -1445,9 +1447,9 @@ dependencies = [
[[package]]
name = "serde_repr"
-version = "0.1.18"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
+checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
@@ -1548,7 +1550,7 @@ dependencies = [
[[package]]
name = "texlab"
-version = "5.16.0"
+version = "5.17.0"
dependencies = [
"anyhow",
"base-db",
@@ -1601,18 +1603,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",
diff --git a/support/texlab/crates/base-db/src/config.rs b/support/texlab/crates/base-db/src/config.rs
index 9814e3e674..e4c827e61c 100644
--- a/support/texlab/crates/base-db/src/config.rs
+++ b/support/texlab/crates/base-db/src/config.rs
@@ -3,9 +3,8 @@ use std::time::Duration;
use parser::SyntaxConfig;
use regex::Regex;
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct Config {
- pub root_dir: Option<String>,
pub build: BuildConfig,
pub diagnostics: DiagnosticsConfig,
pub formatting: FormattingConfig,
@@ -36,7 +35,7 @@ pub struct DiagnosticsConfig {
pub delay: Duration,
}
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct ChktexConfig {
pub on_open: bool,
pub on_save: bool,
@@ -65,13 +64,13 @@ pub enum Formatter {
LatexIndent,
}
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct LatexIndentConfig {
pub local: Option<String>,
pub modify_line_breaks: bool,
}
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct SymbolConfig {
pub allowed_patterns: Vec<Regex>,
pub ignored_patterns: Vec<Regex>,
@@ -96,22 +95,6 @@ pub enum MatchingAlgo {
PrefixIgnoreCase,
}
-impl Default for Config {
- fn default() -> Self {
- Self {
- root_dir: None,
- build: BuildConfig::default(),
- diagnostics: DiagnosticsConfig::default(),
- formatting: FormattingConfig::default(),
- synctex: None,
- symbols: SymbolConfig::default(),
- syntax: SyntaxConfig::default(),
- completion: CompletionConfig::default(),
- inlay_hints: InlayHintConfig::default(),
- }
- }
-}
-
impl Default for BuildConfig {
fn default() -> Self {
Self {
@@ -141,17 +124,6 @@ impl Default for DiagnosticsConfig {
}
}
-impl Default for ChktexConfig {
- fn default() -> Self {
- Self {
- on_open: false,
- on_save: false,
- on_edit: false,
- additional_args: Vec::new(),
- }
- }
-}
-
impl Default for FormattingConfig {
fn default() -> Self {
Self {
@@ -163,24 +135,6 @@ impl Default for FormattingConfig {
}
}
-impl Default for LatexIndentConfig {
- fn default() -> Self {
- Self {
- local: None,
- modify_line_breaks: false,
- }
- }
-}
-
-impl Default for SymbolConfig {
- fn default() -> Self {
- Self {
- allowed_patterns: Vec::new(),
- ignored_patterns: Vec::new(),
- }
- }
-}
-
impl Default for InlayHintConfig {
fn default() -> Self {
Self {
diff --git a/support/texlab/crates/base-db/src/deps/graph.rs b/support/texlab/crates/base-db/src/deps/graph.rs
index e07368d078..4b2399b7f8 100644
--- a/support/texlab/crates/base-db/src/deps/graph.rs
+++ b/support/texlab/crates/base-db/src/deps/graph.rs
@@ -22,7 +22,7 @@ pub struct Edge {
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum EdgeData {
- DirectLink(DirectLinkData),
+ DirectLink(Box<DirectLinkData>),
AdditionalFiles,
Artifact,
}
@@ -159,7 +159,7 @@ impl Graph {
for target_uri in file_names
.iter()
.flat_map(|file_name| {
- util::expand_relative_path(&file_name, &start.root.src_dir, workspace.folders())
+ util::expand_relative_path(file_name, &start.root.src_dir, workspace.folders())
})
.chain(distro_files)
{
@@ -179,7 +179,7 @@ impl Graph {
self.edges.push(Edge {
source: start.source.uri.clone(),
target: target.uri.clone(),
- data: EdgeData::DirectLink(link_data),
+ data: EdgeData::DirectLink(Box::new(link_data)),
});
break;
diff --git a/support/texlab/crates/base-db/src/deps/root.rs b/support/texlab/crates/base-db/src/deps/root.rs
index a8cec6604a..03fd41a9a0 100644
--- a/support/texlab/crates/base-db/src/deps/root.rs
+++ b/support/texlab/crates/base-db/src/deps/root.rs
@@ -31,11 +31,11 @@ impl ProjectRoot {
}
let Ok(parent) = current.join("..") else {
- break Self::from_config(workspace, &dir);
+ break Self::from_config(workspace, dir);
};
if current == parent || Some(&parent) == home_dir.as_ref() {
- break Self::from_config(workspace, &dir);
+ break Self::from_config(workspace, dir);
}
current = parent;
diff --git a/support/texlab/crates/base-db/src/document.rs b/support/texlab/crates/base-db/src/document.rs
index 7a388129fd..afb5869d69 100644
--- a/support/texlab/crates/base-db/src/document.rs
+++ b/support/texlab/crates/base-db/src/document.rs
@@ -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 => {
diff --git a/support/texlab/crates/base-db/src/semantics/auxiliary.rs b/support/texlab/crates/base-db/src/semantics/auxiliary.rs
index 489a7d1ac6..8c9fe012e6 100644
--- a/support/texlab/crates/base-db/src/semantics/auxiliary.rs
+++ b/support/texlab/crates/base-db/src/semantics/auxiliary.rs
@@ -36,7 +36,7 @@ impl Semantics {
Some(group)
})?;
- let text = group.content_text()?.replace('{', "").replace('}', "");
+ let text = group.content_text()?.replace(['{', '}'], "");
self.label_numbers.insert(name, text);
Some(())
}
diff --git a/support/texlab/crates/base-db/src/semantics/tex.rs b/support/texlab/crates/base-db/src/semantics/tex.rs
index 1ad8969a80..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,11 +132,16 @@ 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;
};
+ let name = Span::from(&name);
+ if name.text.contains('#') {
+ return;
+ }
+
let full_range = latex::small_range(&label);
let mut objects = Vec::new();
for node in label.syntax().ancestors() {
@@ -185,46 +211,75 @@ impl Semantics {
self.labels.push(Label {
kind: LabelKind::Definition,
- name: Span::from(&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;
};
let full_range = latex::small_range(&label);
for name in name_list.keys() {
- self.labels.push(Label {
- kind: LabelKind::Reference,
- name: Span::from(&name),
- targets: Vec::new(),
- full_range,
- });
+ let name = Span::from(&name);
+ if !name.text.contains('#') {
+ self.labels.push(Label {
+ kind: LabelKind::Reference,
+ 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,
+ });
+ }
}
}
- 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()) {
- self.labels.push(Label {
- kind: LabelKind::ReferenceRange,
- name: Span::from(&from),
- targets: Vec::new(),
- full_range,
- });
+ let name = Span::from(&from);
+ if !name.text.contains('#') {
+ self.labels.push(Label {
+ kind: LabelKind::ReferenceRange,
+ 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,
+ });
+ }
}
if let Some(to) = label.to().and_then(|group| group.key()) {
- self.labels.push(Label {
- kind: LabelKind::ReferenceRange,
- name: Span::from(&to),
- targets: Vec::new(),
- full_range,
- });
+ let name = Span::from(&to);
+ if !name.text.contains('#') {
+ self.labels.push(Label {
+ kind: LabelKind::ReferenceRange,
+ 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,
+ });
+ }
}
}
@@ -232,10 +287,13 @@ impl Semantics {
let full_range = latex::small_range(&citation);
if let Some(list) = citation.key_list() {
for key in list.keys() {
- self.citations.push(Citation {
- name: Span::from(&key),
- full_range,
- });
+ let name = Span::from(&key);
+ if !name.text.contains('#') {
+ self.citations.push(Citation {
+ name: Span::from(&key),
+ full_range,
+ });
+ }
}
}
}
@@ -319,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/base-db/src/workspace.rs b/support/texlab/crates/base-db/src/workspace.rs
index 75674dcf8d..f2564ed415 100644
--- a/support/texlab/crates/base-db/src/workspace.rs
+++ b/support/texlab/crates/base-db/src/workspace.rs
@@ -99,7 +99,7 @@ impl Workspace {
Cow::Owned(text) => text,
};
- let owner = if self.distro.file_name_db.contains(&path) {
+ let owner = if self.distro.file_name_db.contains(path) {
Owner::Distro
} else {
Owner::Server
diff --git a/support/texlab/crates/bibfmt/src/lib.rs b/support/texlab/crates/bibfmt/src/lib.rs
index cfce131f2c..8840daa1c4 100644
--- a/support/texlab/crates/bibfmt/src/lib.rs
+++ b/support/texlab/crates/bibfmt/src/lib.rs
@@ -11,7 +11,7 @@ pub struct Options {
impl Options {
fn indent(&self) -> String {
if self.insert_spaces {
- std::iter::repeat(' ').take(self.tab_size).collect()
+ " ".repeat(self.tab_size)
} else {
String::from("\t")
}
@@ -126,7 +126,7 @@ impl<'a> Formatter<'a> {
}
bibtex::FIELD => {
let field = bibtex::Field::cast(parent).unwrap();
- self.output.push_str(&self.indent);
+ self.output.push_str(self.indent);
let name = field.name_token().unwrap();
self.output.push_str(name.text());
self.output.push_str(" = ");
@@ -160,7 +160,7 @@ impl<'a> Formatter<'a> {
if length + current_length + space_length > self.options.line_length {
self.output.push('\n');
self.output.push_str(self.indent.as_ref());
- for _ in 0..=align - self.options.tab_size as usize {
+ for _ in 0..=align - self.options.tab_size {
self.output.push(' ');
}
length = align;
diff --git a/support/texlab/crates/bibtex-utils/Cargo.toml b/support/texlab/crates/bibtex-utils/Cargo.toml
index 97e13517f5..c20508107c 100644
--- a/support/texlab/crates/bibtex-utils/Cargo.toml
+++ b/support/texlab/crates/bibtex-utils/Cargo.toml
@@ -7,7 +7,7 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-chrono = { version = "0.4.26", default-features = false, features = ["std"] }
+chrono = { version = "0.4.38", default-features = false, features = ["std"] }
human_name = "2.0.3"
itertools = "0.12.1"
rowan = "0.15.15"
diff --git a/support/texlab/crates/commands/Cargo.toml b/support/texlab/crates/commands/Cargo.toml
index c726e5f0d5..6e415f20d6 100644
--- a/support/texlab/crates/commands/Cargo.toml
+++ b/support/texlab/crates/commands/Cargo.toml
@@ -7,17 +7,17 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-anyhow = "1.0.82"
+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.153"
+libc = "0.2.155"
log = "0.4.21"
rowan = "0.15.15"
rustc-hash = "1.1.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/find_envs.rs b/support/texlab/crates/commands/src/find_envs.rs
index 7a17345d80..1ea88657ab 100644
--- a/support/texlab/crates/commands/src/find_envs.rs
+++ b/support/texlab/crates/commands/src/find_envs.rs
@@ -53,7 +53,7 @@ mod tests {
let workspace = fixture.workspace;
let document = workspace.iter().next().unwrap();
let offset = fixture.documents[0].cursor.unwrap();
- let results = find_environments(&document, offset);
+ let results = find_environments(document, offset);
expect.assert_debug_eq(&results);
}
diff --git a/support/texlab/crates/commands/src/fwd_search.rs b/support/texlab/crates/commands/src/fwd_search.rs
index f1991cd48e..f3480ef3e2 100644
--- a/support/texlab/crates/commands/src/fwd_search.rs
+++ b/support/texlab/crates/commands/src/fwd_search.rs
@@ -103,7 +103,7 @@ impl ForwardSearch {
})
.ok_or_else(|| ForwardSearchError::InvalidPath(document.uri.clone()))?;
- let pdf_path = pdf_dir.join(&pdf_name);
+ let pdf_path = pdf_dir.join(pdf_name);
let pdf_exists = pdf_path.exists();
log::debug!("[FwdSearch] pdf_path={pdf_path:?}, pdf_exists={pdf_exists}");
diff --git a/support/texlab/crates/commands/src/placeholders.rs b/support/texlab/crates/commands/src/placeholders.rs
index 9994420f5d..328a95773a 100644
--- a/support/texlab/crates/commands/src/placeholders.rs
+++ b/support/texlab/crates/commands/src/placeholders.rs
@@ -45,6 +45,6 @@ mod tests {
&[('f', "foo")],
);
- assert_eq!(output, vec!["foo".into(), "%f", "%f".into(), "foobar"]);
+ assert_eq!(output, vec!["foo", "%f", "%f", "foobar"]);
}
}
diff --git a/support/texlab/crates/completion-data/Cargo.toml b/support/texlab/crates/completion-data/Cargo.toml
index 59b707e474..970cd6a578 100644
--- a/support/texlab/crates/completion-data/Cargo.toml
+++ b/support/texlab/crates/completion-data/Cargo.toml
@@ -7,12 +7,12 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-flate2 = "1.0.29"
+flate2 = "1.0.30"
itertools = "0.12.1"
once_cell = "1.19.0"
rustc-hash = "1.1.0"
-serde = { version = "1.0.195", features = ["derive"] }
-serde_json = "1.0.115"
+serde = { version = "1.0.202", features = ["derive"] }
+serde_json = "1.0.117"
[lib]
doctest = false
diff --git a/support/texlab/crates/completion/Cargo.toml b/support/texlab/crates/completion/Cargo.toml
index e28e04dfc7..6469b5f004 100644
--- a/support/texlab/crates/completion/Cargo.toml
+++ b/support/texlab/crates/completion/Cargo.toml
@@ -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 7fc5bba174..5bfd94d944 100644
--- a/support/texlab/crates/completion/src/lib.rs
+++ b/support/texlab/crates/completion/src/lib.rs
@@ -72,12 +72,12 @@ 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,
- Self::Directory(name) => &name,
- Self::Argument(data) => &data.0.name,
+ Self::File(name) => name,
+ Self::Directory(name) => name,
+ Self::Argument(data) => data.0.name,
Self::Package(name) => name,
Self::DocumentClass(name) => name,
Self::EntryType(data) => data.0.name,
diff --git a/support/texlab/crates/completion/src/providers/argument.rs b/support/texlab/crates/completion/src/providers/argument.rs
index 6637cecdd6..a9c8f4304b 100644
--- a/support/texlab/crates/completion/src/providers/argument.rs
+++ b/support/texlab/crates/completion/src/providers/argument.rs
@@ -37,7 +37,7 @@ pub fn complete_arguments<'a>(
.filter(|(i, _)| *i == index)
{
for arg in &param.0 {
- if let Some(score) = builder.matcher.score(&arg.name, &cursor.text) {
+ if let Some(score) = builder.matcher.score(arg.name, &cursor.text) {
let data = CompletionItemData::Argument(ArgumentData(arg));
builder
.items
diff --git a/support/texlab/crates/completion/src/providers/color.rs b/support/texlab/crates/completion/src/providers/color.rs
index cbdd38dc32..8be1b50555 100644
--- a/support/texlab/crates/completion/src/providers/color.rs
+++ b/support/texlab/crates/completion/src/providers/color.rs
@@ -14,7 +14,7 @@ pub fn complete_colors<'a>(
latex::ColorReference::cast(group.syntax().parent()?)?;
for name in COLORS {
- if let Some(score) = builder.matcher.score(&name, &cursor.text) {
+ if let Some(score) = builder.matcher.score(name, &cursor.text) {
let data = CompletionItemData::Color(name);
builder
.items
diff --git a/support/texlab/crates/completion/src/providers/color_model.rs b/support/texlab/crates/completion/src/providers/color_model.rs
index 4b991c4807..80970b1913 100644
--- a/support/texlab/crates/completion/src/providers/color_model.rs
+++ b/support/texlab/crates/completion/src/providers/color_model.rs
@@ -14,7 +14,7 @@ pub fn complete_color_models<'a>(
let cursor = check_color_definition(params).or_else(|| check_color_definition_set(params))?;
for name in MODEL_NAMES {
- if let Some(score) = builder.matcher.score(&name, &cursor.text) {
+ if let Some(score) = builder.matcher.score(name, &cursor.text) {
let data = CompletionItemData::ColorModel(name);
builder
.items
diff --git a/support/texlab/crates/completion/src/providers/command.rs b/support/texlab/crates/completion/src/providers/command.rs
index f404d42ab3..34f8876e1f 100644
--- a/support/texlab/crates/completion/src/providers/command.rs
+++ b/support/texlab/crates/completion/src/providers/command.rs
@@ -44,7 +44,7 @@ impl<'a, 'b> Processor<'a, 'b> {
pub fn add_delimiters(&mut self) {
for (left, right) in DELIMITERS {
- let Some(score) = self.0.builder.matcher.score(&left, &self.0.cursor.text) else {
+ let Some(score) = self.0.builder.matcher.score(left, &self.0.cursor.text) else {
continue;
};
@@ -68,7 +68,7 @@ impl<'a, 'b> Processor<'a, 'b> {
let data = CompletionItemData::Command(CommandData {
name: &command.name,
glyph: command.glyph.as_deref(),
- image: command.image.as_deref(),
+ image: command.image,
package: Some(package),
});
diff --git a/support/texlab/crates/completion/src/providers/environment.rs b/support/texlab/crates/completion/src/providers/environment.rs
index 393dd100ba..b56377550e 100644
--- a/support/texlab/crates/completion/src/providers/environment.rs
+++ b/support/texlab/crates/completion/src/providers/environment.rs
@@ -21,7 +21,7 @@ pub fn complete_environments<'a>(
.and_then(|env| env.begin())
.and_then(|begin| begin.name())
.and_then(|name| name.key())
- .map_or_else(|| String::new(), |name| name.to_string());
+ .map_or_else(String::new, |name| name.to_string());
let mut proc = Processor {
inner: ProviderContext {
@@ -48,7 +48,7 @@ impl<'a, 'b> Processor<'a, 'b> {
for package in included_packages(&self.inner.params.feature) {
let envs_with_score = package.environments.iter().filter_map(|env| {
let matcher = &self.inner.builder.matcher;
- let score = matcher.score(&env, &self.inner.cursor.text)?;
+ let score = matcher.score(env, &self.inner.cursor.text)?;
Some((*env, score))
});
@@ -76,7 +76,7 @@ impl<'a, 'b> Processor<'a, 'b> {
{
let matcher = &self.inner.builder.matcher;
let name = theorem.name.text.as_str();
- if let Some(score) = matcher.score(&name, &self.inner.cursor.text) {
+ if let Some(score) = matcher.score(name, &self.inner.cursor.text) {
let data = CompletionItemData::Environment(EnvironmentData {
name,
package: None,
diff --git a/support/texlab/crates/completion/src/providers/glossary.rs b/support/texlab/crates/completion/src/providers/glossary.rs
index c22f5b5888..d01d62a511 100644
--- a/support/texlab/crates/completion/src/providers/glossary.rs
+++ b/support/texlab/crates/completion/src/providers/glossary.rs
@@ -58,7 +58,7 @@ impl<'a, 'b> Processor<'a, 'b> {
for name in data
.root_node()
.descendants()
- .filter_map(|node| extract(node))
+ .filter_map(&extract)
.filter_map(|name| name.key())
.map(|name| name.to_string())
{
diff --git a/support/texlab/crates/completion/src/providers/import.rs b/support/texlab/crates/completion/src/providers/import.rs
index c506026a99..c0f608f9d2 100644
--- a/support/texlab/crates/completion/src/providers/import.rs
+++ b/support/texlab/crates/completion/src/providers/import.rs
@@ -29,13 +29,13 @@ pub fn complete_imports<'a>(
file_names.insert(file_name);
let stem = &file_name[0..file_name.len() - 4];
if kind == latex::PACKAGE_INCLUDE {
- if let Some(score) = builder.matcher.score(&stem, &cursor.text) {
+ if let Some(score) = builder.matcher.score(stem, &cursor.text) {
let data = CompletionItemData::Package(stem);
builder
.items
.push(CompletionItem::new_simple(score, cursor.range, data));
}
- } else if let Some(score) = builder.matcher.score(&stem, &cursor.text) {
+ } else if let Some(score) = builder.matcher.score(stem, &cursor.text) {
let data = CompletionItemData::DocumentClass(stem);
builder
.items
@@ -51,13 +51,13 @@ pub fn complete_imports<'a>(
{
let stem = &file_name[0..file_name.len() - 4];
if kind == latex::PACKAGE_INCLUDE {
- if let Some(score) = builder.matcher.score(&stem, &cursor.text) {
+ if let Some(score) = builder.matcher.score(stem, &cursor.text) {
let data = CompletionItemData::Package(stem);
builder
.items
.push(CompletionItem::new_simple(score, cursor.range, data));
}
- } else if let Some(score) = builder.matcher.score(&stem, &cursor.text) {
+ } else if let Some(score) = builder.matcher.score(stem, &cursor.text) {
let data = CompletionItemData::DocumentClass(stem);
builder
.items
diff --git a/support/texlab/crates/completion/src/providers/include.rs b/support/texlab/crates/completion/src/providers/include.rs
index 60c432d097..d0a042252f 100644
--- a/support/texlab/crates/completion/src/providers/include.rs
+++ b/support/texlab/crates/completion/src/providers/include.rs
@@ -19,9 +19,7 @@ pub fn complete_includes<'a>(
params: &'a CompletionParams<'a>,
builder: &mut CompletionBuilder<'a>,
) -> Option<()> {
- if params.feature.document.path.is_none() {
- return None;
- }
+ params.feature.document.path.as_ref()?;
let (cursor, group) = find_curly_group_word_list(params)?;
@@ -115,7 +113,7 @@ fn current_dir(
graphics_path: Option<&str>,
) -> Option<PathBuf> {
let workspace = &params.workspace;
- let parent = deps::parents(&workspace, params.document)
+ let parent = deps::parents(workspace, params.document)
.iter()
.next()
.map_or(params.document, Clone::clone);
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/providers/tikz_library.rs b/support/texlab/crates/completion/src/providers/tikz_library.rs
index 10a0aa44ba..4c3d7e8955 100644
--- a/support/texlab/crates/completion/src/providers/tikz_library.rs
+++ b/support/texlab/crates/completion/src/providers/tikz_library.rs
@@ -21,7 +21,7 @@ pub fn complete_tikz_libraries<'a>(
};
for name in libraries {
- if let Some(score) = builder.matcher.score(&name, &cursor.text) {
+ if let Some(score) = builder.matcher.score(name, &cursor.text) {
let data = CompletionItemData::TikzLibrary(name);
builder
.items
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/src/command.rs b/support/texlab/crates/definition/src/command.rs
index 3681cdbaa0..ea7ef8c2c2 100644
--- a/support/texlab/crates/definition/src/command.rs
+++ b/support/texlab/crates/definition/src/command.rs
@@ -28,13 +28,11 @@ pub(super) fn goto_definition(context: &mut DefinitionContext) -> Option<()> {
process_old_definition(node.clone()).or_else(|| process_new_definition(node))
})
.filter(|(_, command)| command.text() == name.text())
- .filter_map(|(target_range, command)| {
- Some(DefinitionResult {
- origin_selection_range,
- target: document,
- target_range,
- target_selection_range: command.text_range(),
- })
+ .map(|(target_range, command)| DefinitionResult {
+ origin_selection_range,
+ target: document,
+ target_range,
+ target_selection_range: command.text_range(),
});
context.results.extend(results);
diff --git a/support/texlab/crates/definition/src/tests.rs b/support/texlab/crates/definition/src/tests.rs
index 26f7c0dc3a..0b3f7fa7cc 100644
--- a/support/texlab/crates/definition/src/tests.rs
+++ b/support/texlab/crates/definition/src/tests.rs
@@ -11,7 +11,7 @@ fn check(input: &str) {
.locations()
.filter(|location| location.document == origin_document)
.find(|location| location.range.contains_inclusive(offset))
- .map_or_else(|| TextRange::default(), |location| location.range);
+ .map_or_else(TextRange::default, |location| location.range);
let mut expected = FxHashSet::default();
for document in &fixture.documents {
diff --git a/support/texlab/crates/diagnostics/src/chktex.rs b/support/texlab/crates/diagnostics/src/chktex.rs
index 195ea968e5..a3f539440d 100644
--- a/support/texlab/crates/diagnostics/src/chktex.rs
+++ b/support/texlab/crates/diagnostics/src/chktex.rs
@@ -74,7 +74,7 @@ impl Command {
.build(stdout),
);
- for line in reader.lines().flatten() {
+ for line in reader.lines().map_while(Result::ok) {
let captures = LINE_REGEX.captures(&line).unwrap();
let line = captures[1].parse::<u32>().unwrap() - 1;
let character = captures[2].parse::<u32>().unwrap() - 1;
diff --git a/support/texlab/crates/diagnostics/src/citations.rs b/support/texlab/crates/diagnostics/src/citations.rs
index 0f09f589be..43d5f495d2 100644
--- a/support/texlab/crates/diagnostics/src/citations.rs
+++ b/support/texlab/crates/diagnostics/src/citations.rs
@@ -24,7 +24,7 @@ pub fn detect_undefined_citations<'a>(
for citation in &data.semantics.citations {
let name = citation.name_text();
- if name != "*" && !entries.contains(name) && !name.contains("#") {
+ if name != "*" && !entries.contains(name) {
let diagnostic = Diagnostic::Tex(citation.name.range, TexError::UndefinedCitation);
results
.entry(document.uri.clone())
@@ -65,8 +65,8 @@ pub fn detect_unused_entries<'a>(
Some(())
}
-pub fn detect_duplicate_entries<'a>(
- workspace: &'a Workspace,
+pub fn detect_duplicate_entries(
+ workspace: &Workspace,
results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) {
for conflict in queries::Conflict::find_all::<Entry>(workspace) {
diff --git a/support/texlab/crates/diagnostics/src/manager.rs b/support/texlab/crates/diagnostics/src/manager.rs
index 3573bc40f2..500dc99c13 100644
--- a/support/texlab/crates/diagnostics/src/manager.rs
+++ b/support/texlab/crates/diagnostics/src/manager.rs
@@ -89,16 +89,12 @@ impl Manager {
let config = &workspace.config().diagnostics;
- results.retain(|uri, _| {
- workspace
- .lookup(uri)
- .map_or(false, |document| Self::is_relevant(document))
- });
+ results.retain(|uri, _| workspace.lookup(uri).map_or(false, Self::is_relevant));
- for (_, diagnostics) in &mut results {
+ for diagnostics in results.values_mut() {
diagnostics.retain(|diagnostic| {
filter_regex_patterns(
- &diagnostic.message(),
+ diagnostic.message(),
&config.allowed_patterns,
&config.ignored_patterns,
)
diff --git a/support/texlab/crates/diagnostics/src/tests.rs b/support/texlab/crates/diagnostics/src/tests.rs
index 3688abeaf4..05ad67fc8b 100644
--- a/support/texlab/crates/diagnostics/src/tests.rs
+++ b/support/texlab/crates/diagnostics/src/tests.rs
@@ -6,14 +6,14 @@ fn check(input: &str, expect: Expect) {
let mut manager = crate::Manager::default();
for document in fixture.workspace.iter() {
- manager.update_syntax(&fixture.workspace, &document);
+ manager.update_syntax(&fixture.workspace, document);
}
let results = manager.get(&fixture.workspace);
let results = results
.iter()
.filter(|(_, diags)| !diags.is_empty())
- .sorted_by(|(uri1, _), (uri2, _)| uri1.cmp(&uri2))
+ .sorted_by(|(uri1, _), (uri2, _)| uri1.cmp(uri2))
.map(|(uri, diags)| (uri.as_str(), diags))
.collect_vec();
diff --git a/support/texlab/crates/distro/Cargo.toml b/support/texlab/crates/distro/Cargo.toml
index eefcea2b49..dea6a56979 100644
--- a/support/texlab/crates/distro/Cargo.toml
+++ b/support/texlab/crates/distro/Cargo.toml
@@ -7,7 +7,7 @@ edition.workspace = true
rust-version.workspace = true
[dependencies]
-anyhow = "1.0.82"
+anyhow = "1.0.86"
rustc-hash = "1.1.0"
[lib]
diff --git a/support/texlab/crates/highlights/src/lib.rs b/support/texlab/crates/highlights/src/lib.rs
index 009dd20807..9d7a63b096 100644
--- a/support/texlab/crates/highlights/src/lib.rs
+++ b/support/texlab/crates/highlights/src/lib.rs
@@ -23,7 +23,7 @@ pub struct HighlightParams<'a> {
pub fn find_all(params: &HighlightParams) -> Vec<Highlight> {
let mut results = Vec::new();
- label::find_highlights(&params, &mut results);
+ label::find_highlights(params, &mut results);
results
}
diff --git a/support/texlab/crates/hover/src/lib.rs b/support/texlab/crates/hover/src/lib.rs
index 2d22d50b0b..dcf4d442a9 100644
--- a/support/texlab/crates/hover/src/lib.rs
+++ b/support/texlab/crates/hover/src/lib.rs
@@ -35,12 +35,12 @@ pub enum HoverData<'db> {
}
pub fn find<'a>(params: &HoverParams<'a>) -> Option<Hover<'a>> {
- citation::find_hover(&params)
- .or_else(|| package::find_hover(&params))
- .or_else(|| entry_type::find_hover(&params))
- .or_else(|| field_type::find_hover(&params))
- .or_else(|| label::find_hover(&params))
- .or_else(|| string_ref::find_hover(&params))
+ citation::find_hover(params)
+ .or_else(|| package::find_hover(params))
+ .or_else(|| entry_type::find_hover(params))
+ .or_else(|| field_type::find_hover(params))
+ .or_else(|| label::find_hover(params))
+ .or_else(|| string_ref::find_hover(params))
}
#[cfg(test)]
diff --git a/support/texlab/crates/inlay-hints/src/label.rs b/support/texlab/crates/inlay-hints/src/label.rs
index 8db852752e..6e29c806b6 100644
--- a/support/texlab/crates/inlay-hints/src/label.rs
+++ b/support/texlab/crates/inlay-hints/src/label.rs
@@ -9,7 +9,6 @@ use crate::{InlayHint, InlayHintBuilder, InlayHintData};
pub(super) fn find_hints(builder: &mut InlayHintBuilder) -> Option<()> {
let definitions = base_db::semantics::tex::Label::find_all(&builder.params.feature.project)
- .into_iter()
.filter(|(_, label)| label.kind == LabelKind::Definition)
.map(|(_, label)| (label.name_text(), label))
.collect::<FxHashMap<_, _>>();
diff --git a/support/texlab/crates/ipc/Cargo.toml b/support/texlab/crates/ipc/Cargo.toml
index ae31dcaf55..1e1ff7a822 100644
--- a/support/texlab/crates/ipc/Cargo.toml
+++ b/support/texlab/crates/ipc/Cargo.toml
@@ -8,8 +8,8 @@ rust-version.workspace = true
[dependencies]
crossbeam-channel = "0.5.12"
-serde = "1.0.199"
-serde_json = "1.0.116"
+serde = "1.0.202"
+serde_json = "1.0.117"
log = "0.4.21"
uds_windows = "1.1.0"
diff --git a/support/texlab/crates/parser/src/build_log.rs b/support/texlab/crates/parser/src/build_log.rs
index 420d2dda20..c1f59bd086 100644
--- a/support/texlab/crates/parser/src/build_log.rs
+++ b/support/texlab/crates/parser/src/build_log.rs
@@ -36,7 +36,7 @@ pub fn parse_build_log(log: &str) -> BuildLog {
let warnings = extract_matches(&log, &ranges, &WARNING_REGEX, BuildErrorLevel::Warning);
let bad_boxes = extract_matches(&log, &ranges, &BAD_BOX_REGEX, BuildErrorLevel::Warning);
- let errors = vec![tex_errors, warnings, bad_boxes].concat();
+ let errors = [tex_errors, warnings, bad_boxes].concat();
BuildLog { errors }
}
diff --git a/support/texlab/crates/parser/src/config.rs b/support/texlab/crates/parser/src/config.rs
index f81083f132..95b3e4eb56 100644
--- a/support/texlab/crates/parser/src/config.rs
+++ b/support/texlab/crates/parser/src/config.rs
@@ -8,7 +8,9 @@ pub struct SyntaxConfig {
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,11 +40,21 @@ 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,
math_environments,
@@ -50,7 +62,9 @@ impl Default for SyntaxConfig {
verbatim_environments,
citation_commands,
label_definition_commands,
+ label_definition_prefixes,
label_reference_commands,
+ label_reference_prefixes,
}
}
}
@@ -170,7 +184,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 +198,10 @@ static DEFAULT_LABEL_REFERENCE_COMMANDS: &[&str] = &[
"cref*",
"Cref",
"Cref*",
+ "zcref",
+ "zcref*",
+ "zcpageref",
+ "zcpageref*",
"namecref",
"nameCref",
"lcnamecref",
@@ -192,3 +212,5 @@ static DEFAULT_LABEL_REFERENCE_COMMANDS: &[&str] = &[
"labelcpageref",
"eqref",
];
+
+static DEFAULT_LABEL_REFERENCE_PREFIXES: &[(&str, &str)] = &[];
diff --git a/support/texlab/crates/parser/src/latexmkrc.rs b/support/texlab/crates/parser/src/latexmkrc.rs
index 6013a5f646..58c348d01f 100644
--- a/support/texlab/crates/parser/src/latexmkrc.rs
+++ b/support/texlab/crates/parser/src/latexmkrc.rs
@@ -28,9 +28,9 @@ mod v483 {
.current_dir(temp_dir.path())
.output()?;
- let stderr = String::from_utf8_lossy(&output.stderr);
+ let stdout = String::from_utf8_lossy(&output.stdout);
- let (aux_dir, out_dir) = stderr.lines().find_map(extract_dirs).ok_or_else(|| {
+ let (aux_dir, out_dir) = stdout.lines().find_map(extract_dirs).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Normalized aux and out dir were not found in latexmk output",
@@ -106,7 +106,7 @@ mod v484 {
let mut it = lines
.skip_while(|line| !line.starts_with("Latexmk: Normalized aux dir and out dirs:"))
.nth(1)?
- .split(",");
+ .split(',');
let aux_dir = it.next()?.trim().strip_prefix('\'')?.strip_suffix('\'')?;
@@ -133,7 +133,7 @@ pub fn parse_latexmkrc(input: &str, src_dir: &Path) -> std::io::Result<Latexmkrc
.as_ref()
.and_then(|line| Some((line.find("Version")?, line)))
.and_then(|(i, line)| line[i..].trim_end().strip_prefix("Version "))
- .and_then(|text| versions::Versioning::new(text));
+ .and_then(versions::Versioning::new);
let result = if version.map_or(false, |v| v >= versions::Versioning::new("4.84").unwrap()) {
v484::parse_latexmkrc(input, src_dir)
diff --git a/support/texlab/crates/references/src/command.rs b/support/texlab/crates/references/src/command.rs
index 712da20b73..f4504641f2 100644
--- a/support/texlab/crates/references/src/command.rs
+++ b/support/texlab/crates/references/src/command.rs
@@ -32,7 +32,7 @@ pub(super) fn find_all(context: &mut ReferenceContext) -> Option<()> {
.collect();
for command in &data.semantics.commands {
- if command.text == &token.text()[1..] {
+ if command.text == token.text()[1..] {
let kind = if defs.contains(command) {
ReferenceKind::Definition
} else {
diff --git a/support/texlab/crates/references/src/entry.rs b/support/texlab/crates/references/src/entry.rs
index c3926058e6..722c96fe4a 100644
--- a/support/texlab/crates/references/src/entry.rs
+++ b/support/texlab/crates/references/src/entry.rs
@@ -30,14 +30,14 @@ pub(super) fn find_all(context: &mut ReferenceContext) -> Option<()> {
};
let project = &context.params.feature.project;
- for (document, obj) in queries::objects_with_name::<tex::Citation>(&project, name) {
+ for (document, obj) in queries::objects_with_name::<tex::Citation>(project, name) {
context.results.push(Reference {
location: DocumentLocation::new(document, obj.name.range),
kind: ReferenceKind::Reference,
});
}
- for (document, obj) in queries::objects_with_name::<bib::Entry>(&project, name) {
+ for (document, obj) in queries::objects_with_name::<bib::Entry>(project, name) {
context.results.push(Reference {
location: DocumentLocation::new(document, obj.name.range),
kind: ReferenceKind::Definition,
diff --git a/support/texlab/crates/references/src/label.rs b/support/texlab/crates/references/src/label.rs
index 872ef2dd14..20fc6e0d25 100644
--- a/support/texlab/crates/references/src/label.rs
+++ b/support/texlab/crates/references/src/label.rs
@@ -14,7 +14,7 @@ pub(super) fn find_all(context: &mut ReferenceContext) -> Option<()> {
.name_text();
let project = &context.params.feature.project;
- for (document, label) in queries::objects_with_name::<tex::Label>(&project, name) {
+ for (document, label) in queries::objects_with_name::<tex::Label>(project, name) {
let kind = match label.kind {
tex::LabelKind::Definition => ReferenceKind::Definition,
tex::LabelKind::Reference | tex::LabelKind::ReferenceRange => ReferenceKind::Reference,
diff --git a/support/texlab/crates/rename/Cargo.toml b/support/texlab/crates/rename/Cargo.toml
index 1b2b91ee2a..dc7558515a 100644
--- a/support/texlab/crates/rename/Cargo.toml
+++ b/support/texlab/crates/rename/Cargo.toml
@@ -14,6 +14,7 @@ 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 edcf7db61e..037e09e4ca 100644
--- a/support/texlab/crates/rename/src/command.rs
+++ b/support/texlab/crates/rename/src/command.rs
@@ -19,7 +19,7 @@ pub(super) fn prepare_rename(params: &RenameParams) -> Option<Span> {
))
}
-pub(super) fn rename<'a>(builder: &mut RenameBuilder) -> Option<()> {
+pub(super) fn rename(builder: &mut RenameBuilder) -> Option<()> {
let name = prepare_rename(&builder.params)?;
for document in &builder.params.feature.project.documents {
@@ -35,7 +35,10 @@ pub(super) fn rename<'a>(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 c0b508a506..d35d9e9e84 100644
--- a/support/texlab/crates/rename/src/entry.rs
+++ b/support/texlab/crates/rename/src/entry.rs
@@ -30,7 +30,7 @@ pub(super) fn prepare_rename(params: &RenameParams) -> Option<Span> {
}
}
-pub(super) fn rename<'a>(builder: &mut RenameBuilder) -> Option<()> {
+pub(super) fn rename(builder: &mut RenameBuilder) -> Option<()> {
let name = prepare_rename(&builder.params)?;
let project = &builder.params.feature.project;
@@ -42,7 +42,7 @@ pub(super) fn rename<'a>(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 b7dd197ce0..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,14 +28,28 @@ 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))
- .or_else(|| label::prepare_rename(&params))
+ command::prepare_rename(params)
+ .or_else(|| entry::prepare_rename(params))
+ .or_else(|| label::prepare_rename(params))
.map(|span| span.range)
}
-pub fn rename<'a>(params: RenameParams<'a>) -> RenameResult<'a> {
+pub fn rename(params: RenameParams) -> RenameResult {
let result = RenameResult::default();
let mut builder = RenameBuilder { params, result };
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/texlab/Cargo.toml b/support/texlab/crates/texlab/Cargo.toml
index 4c142a2229..fa419413f5 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.0"
+version = "5.17.0"
license.workspace = true
readme = "README.md"
authors.workspace = true
@@ -22,7 +22,7 @@ test = false
doctest = false
[dependencies]
-anyhow = "1.0.82"
+anyhow = "1.0.86"
base-db = { path = "../base-db" }
bibfmt = { path = "../bibfmt" }
citeproc = { path = "../citeproc" }
@@ -47,17 +47,17 @@ lsp-server = "0.7.6"
lsp-types = "0.95.1"
notify = "6.1.1"
notify-debouncer-full = "0.3.1"
-parking_lot = "0.12.1"
+parking_lot = "0.12.3"
parser = { path = "../parser" }
references = { path = "../references" }
regex = "1.10.4"
rename = { path = "../rename" }
rowan = "0.15.15"
rustc-hash = "1.1.0"
-serde = "1.0.195"
-serde_json = "1.0.115"
+serde = "1.0.202"
+serde_json = "1.0.117"
serde_regex = "1.1.0"
-serde_repr = "0.1.18"
+serde_repr = "0.1.19"
symbols = { path = "../symbols" }
syntax = { path = "../syntax" }
tempfile = "3.10.1"
diff --git a/support/texlab/crates/texlab/src/features/folding.rs b/support/texlab/crates/texlab/src/features/folding.rs
index b19fa8a4da..3669021201 100644
--- a/support/texlab/crates/texlab/src/features/folding.rs
+++ b/support/texlab/crates/texlab/src/features/folding.rs
@@ -9,7 +9,7 @@ pub fn find_all(
) -> Option<Vec<serde_json::Value>> {
let params = from_proto::feature_params(workspace, params.text_document)?;
- let foldings = folding::find_all(&params.document)
+ let foldings = folding::find_all(params.document)
.into_iter()
.filter_map(|folding| {
to_proto::folding_range(folding, &params.document.line_index, client_flags)
diff --git a/support/texlab/crates/texlab/src/features/rename.rs b/support/texlab/crates/texlab/src/features/rename.rs
index b905a7105b..a65f42143b 100644
--- a/support/texlab/crates/texlab/src/features/rename.rs
+++ b/support/texlab/crates/texlab/src/features/rename.rs
@@ -18,5 +18,5 @@ pub fn rename_all(
let new_name = &params.new_name;
let params = from_proto::rename_params(workspace, params.text_document_position)?;
let result = rename::rename(params);
- Some(to_proto::workspace_edit(result, &new_name))
+ Some(to_proto::workspace_edit(result, new_name))
}
diff --git a/support/texlab/crates/texlab/src/main.rs b/support/texlab/crates/texlab/src/main.rs
index ceca02b7f7..d9bf6833d8 100644
--- a/support/texlab/crates/texlab/src/main.rs
+++ b/support/texlab/crates/texlab/src/main.rs
@@ -110,6 +110,7 @@ fn setup_logger(opts: &Opts) {
OpenOptions::new()
.write(true)
.create(true)
+ .truncate(true)
.open(log_file)
.expect("failed to open log file"),
),
diff --git a/support/texlab/crates/texlab/src/server.rs b/support/texlab/crates/texlab/src/server.rs
index ef70c42c71..ff3c7904d3 100644
--- a/support/texlab/crates/texlab/src/server.rs
+++ b/support/texlab/crates/texlab/src/server.rs
@@ -46,7 +46,7 @@ use self::{
#[derive(Debug)]
enum InternalMessage {
SetDistro(Distro),
- SetOptions(Options),
+ SetOptions(Box<Options>),
FileEvent(Vec<DebouncedEvent>),
Diagnostics,
ChktexFinished(Url, Vec<diagnostics::Diagnostic>),
@@ -309,7 +309,9 @@ impl Server {
.parse_options(json.pop().expect("invalid configuration request"))
.unwrap();
- sender.send(InternalMessage::SetOptions(options)).unwrap();
+ sender
+ .send(InternalMessage::SetOptions(Box::new(options)))
+ .unwrap();
}
Err(why) => {
log::error!("Retrieving configuration failed: {}", why);
@@ -700,19 +702,19 @@ impl Server {
let status = if pending_builds.lock().remove(&pid) {
if result?.success() {
- BuildStatus::SUCCESS
+ BuildStatus::Success
} else {
- BuildStatus::ERROR
+ BuildStatus::Error
}
} else {
- BuildStatus::CANCELLED
+ BuildStatus::Cancelled
};
Ok(status)
})
.unwrap_or_else(|why| {
log::error!("Failed to compile document \"{uri}\": {why}");
- BuildStatus::FAILURE
+ BuildStatus::Failure
});
drop(progress_reporter);
@@ -723,7 +725,7 @@ impl Server {
let _ = client.send_response(lsp_server::Response::new_ok(id, result));
}
- if fwd_search_after && status != BuildStatus::CANCELLED {
+ if fwd_search_after && status != BuildStatus::Cancelled {
let _ = internal.send(InternalMessage::ForwardSearch(uri, params.position));
}
});
@@ -760,7 +762,7 @@ impl Server {
self.pool.execute(move || {
let status = match command.and_then(ForwardSearch::run) {
- Ok(()) => ForwardSearchStatus::SUCCESS,
+ Ok(()) => ForwardSearchStatus::Success,
Err(why) => {
log::error!("Failed to execute forward search: {why}");
ForwardSearchStatus::from(why)
@@ -1071,7 +1073,7 @@ impl Server {
self.workspace.write().set_distro(distro);
}
InternalMessage::SetOptions(options) => {
- self.update_options(options);
+ self.update_options(*options);
}
InternalMessage::FileEvent(events) => {
for event in events {
diff --git a/support/texlab/crates/texlab/src/server/extensions.rs b/support/texlab/crates/texlab/src/server/extensions.rs
index ce876c7892..8fa78ef3d2 100644
--- a/support/texlab/crates/texlab/src/server/extensions.rs
+++ b/support/texlab/crates/texlab/src/server/extensions.rs
@@ -33,10 +33,10 @@ pub struct BuildResult {
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize_repr, Deserialize_repr)]
#[repr(i32)]
pub enum BuildStatus {
- SUCCESS = 0,
- ERROR = 1,
- FAILURE = 2,
- CANCELLED = 3,
+ Success = 0,
+ Error = 1,
+ Failure = 2,
+ Cancelled = 3,
}
pub struct ForwardSearchRequest;
@@ -52,21 +52,21 @@ impl lsp_types::request::Request for ForwardSearchRequest {
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize_repr, Deserialize_repr)]
#[repr(i32)]
pub enum ForwardSearchStatus {
- SUCCESS = 0,
- ERROR = 1,
- FAILURE = 2,
- UNCONFIGURED = 3,
+ Success = 0,
+ Error = 1,
+ Failure = 2,
+ Unconfigured = 3,
}
impl From<ForwardSearchError> for ForwardSearchStatus {
fn from(why: ForwardSearchError) -> Self {
match why {
- ForwardSearchError::Unconfigured => ForwardSearchStatus::UNCONFIGURED,
- ForwardSearchError::NotLocal(_) => ForwardSearchStatus::FAILURE,
- ForwardSearchError::InvalidPath(_) => ForwardSearchStatus::ERROR,
- ForwardSearchError::TexNotFound(_) => ForwardSearchStatus::FAILURE,
- ForwardSearchError::PdfNotFound(_) => ForwardSearchStatus::ERROR,
- ForwardSearchError::LaunchViewer(_) => ForwardSearchStatus::ERROR,
+ ForwardSearchError::Unconfigured => ForwardSearchStatus::Unconfigured,
+ ForwardSearchError::NotLocal(_) => ForwardSearchStatus::Failure,
+ ForwardSearchError::InvalidPath(_) => ForwardSearchStatus::Error,
+ ForwardSearchError::TexNotFound(_) => ForwardSearchStatus::Failure,
+ ForwardSearchError::PdfNotFound(_) => ForwardSearchStatus::Error,
+ ForwardSearchError::LaunchViewer(_) => ForwardSearchStatus::Error,
}
}
}
diff --git a/support/texlab/crates/texlab/src/server/options.rs b/support/texlab/crates/texlab/src/server/options.rs
index 02200392f6..1640c9cf7a 100644
--- a/support/texlab/crates/texlab/src/server/options.rs
+++ b/support/texlab/crates/texlab/src/server/options.rs
@@ -1,11 +1,11 @@
-use regex::Regex;
use serde::{Deserialize, Serialize};
+use regex::Regex;
+
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(default)]
pub struct Options {
- pub root_directory: Option<String>,
pub aux_directory: Option<String>,
pub bibtex_formatter: BibtexFormatter,
pub latex_formatter: LatexFormatter,
@@ -126,7 +126,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 d9ec5a2fb1..c301dc7722 100644
--- a/support/texlab/crates/texlab/src/util.rs
+++ b/support/texlab/crates/texlab/src/util.rs
@@ -22,7 +22,7 @@ pub fn normalize_uri(uri: &mut lsp_types::Url) {
}
fn fix_drive_letter(text: &str) -> Option<String> {
- if !text.is_ascii() || text.len() == 0 {
+ if !text.is_ascii() || text.is_empty() {
return None;
}
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 db4f3a5b39..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,30 +95,25 @@ 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,
}
}
-pub fn rename_params<'a>(
- workspace: &'a Workspace,
+pub fn rename_params(
+ workspace: &Workspace,
params: lsp_types::TextDocumentPositionParams,
-) -> Option<RenameParams<'a>> {
+) -> Option<RenameParams> {
let (feature, offset) =
feature_params_offset(workspace, params.text_document, params.position)?;
Some(RenameParams { feature, offset })
}
-pub fn hover_params<'a>(
- workspace: &'a Workspace,
- params: lsp_types::HoverParams,
-) -> Option<HoverParams<'a>> {
+pub fn hover_params(workspace: &Workspace, params: lsp_types::HoverParams) -> Option<HoverParams> {
let (feature, offset) = feature_params_offset(
workspace,
params.text_document_position_params.text_document,
@@ -144,8 +123,8 @@ pub fn hover_params<'a>(
Some(HoverParams { feature, offset })
}
-pub fn inlay_hint_params<'a>(
- workspace: &'a Workspace,
+pub fn inlay_hint_params(
+ workspace: &Workspace,
params: lsp_types::InlayHintParams,
) -> Option<InlayHintParams> {
let feature = feature_params(workspace, params.text_document)?;
@@ -153,10 +132,10 @@ pub fn inlay_hint_params<'a>(
Some(InlayHintParams { feature, range })
}
-pub fn highlight_params<'a>(
- workspace: &'a Workspace,
+pub fn highlight_params(
+ workspace: &Workspace,
params: lsp_types::DocumentHighlightParams,
-) -> Option<HighlightParams<'a>> {
+) -> Option<HighlightParams<'_>> {
let (feature, offset) = feature_params_offset(
workspace,
params.text_document_position_params.text_document,
@@ -166,10 +145,10 @@ pub fn highlight_params<'a>(
Some(HighlightParams { feature, offset })
}
-pub fn definition_params<'a>(
- workspace: &'a Workspace,
+pub fn definition_params(
+ workspace: &Workspace,
params: lsp_types::GotoDefinitionParams,
-) -> Option<DefinitionParams<'a>> {
+) -> Option<DefinitionParams> {
let (feature, offset) = feature_params_offset(
workspace,
params.text_document_position_params.text_document,
@@ -179,10 +158,10 @@ pub fn definition_params<'a>(
Some(DefinitionParams { feature, offset })
}
-pub fn completion_params<'a>(
- workspace: &'a Workspace,
+pub fn completion_params(
+ workspace: &Workspace,
params: lsp_types::CompletionParams,
-) -> Option<CompletionParams<'a>> {
+) -> Option<CompletionParams> {
let (feature, offset) = feature_params_offset(
workspace,
params.text_document_position.text_document,
@@ -192,10 +171,10 @@ pub fn completion_params<'a>(
Some(CompletionParams { feature, offset })
}
-pub fn reference_params<'a>(
- workspace: &'a Workspace,
+pub fn reference_params(
+ workspace: &Workspace,
params: lsp_types::ReferenceParams,
-) -> Option<ReferenceParams<'a>> {
+) -> Option<ReferenceParams> {
let (feature, offset) = feature_params_offset(
workspace,
params.text_document_position.text_document,
@@ -210,19 +189,19 @@ pub fn reference_params<'a>(
})
}
-pub fn feature_params<'a>(
- workspace: &'a Workspace,
+pub fn feature_params(
+ workspace: &Workspace,
text_document: lsp_types::TextDocumentIdentifier,
-) -> Option<FeatureParams<'a>> {
+) -> Option<FeatureParams> {
let document = workspace.lookup(&text_document.uri)?;
Some(FeatureParams::new(workspace, document))
}
-pub fn feature_params_offset<'a>(
- workspace: &'a Workspace,
+pub fn feature_params_offset(
+ workspace: &Workspace,
text_document: lsp_types::TextDocumentIdentifier,
position: lsp_types::Position,
-) -> Option<(FeatureParams<'a>, TextSize)> {
+) -> Option<(FeatureParams, TextSize)> {
let feature = feature_params(workspace, text_document)?;
let offset = feature.document.line_index.offset_lsp(position)?;
Some((feature, offset))
@@ -236,7 +215,6 @@ pub fn completion_resolve_info(item: &mut lsp_types::CompletionItem) -> Option<R
pub fn config(value: Options) -> Config {
let mut config = Config::default();
- config.root_dir = value.root_directory;
config.build.program = value.build.executable.unwrap_or(config.build.program);
config.build.args = value.build.args.unwrap_or(config.build.args);
@@ -362,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 2d4e412dc9..d829a081f9 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.0" "User Commands"
+.TH TEXLAB "1" "June 2024" "texlab 5.17.0" "User Commands"
.SH NAME
-texlab \- manual page for texlab 5.16.0
+texlab \- manual page for texlab 5.17.0
.SH SYNOPSIS
.B texlab
[\fI\,OPTIONS\/\fR] [\fI\,COMMAND\/\fR]
diff --git a/support/texlab/texlab.pdf b/support/texlab/texlab.pdf
index fe59b1f434..828032ce0c 100644
--- a/support/texlab/texlab.pdf
+++ b/support/texlab/texlab.pdf
Binary files differ