diff options
Diffstat (limited to 'support/texlab/crates/completion/src')
-rw-r--r-- | support/texlab/crates/completion/src/lib.rs | 29 | ||||
-rw-r--r-- | support/texlab/crates/completion/src/providers.rs | 6 | ||||
-rw-r--r-- | support/texlab/crates/completion/src/providers/command.rs | 17 | ||||
-rw-r--r-- | support/texlab/crates/completion/src/providers/include.rs | 11 | ||||
-rw-r--r-- | support/texlab/crates/completion/src/providers/label_def.rs | 60 | ||||
-rw-r--r-- | support/texlab/crates/completion/src/providers/label_ref.rs (renamed from support/texlab/crates/completion/src/providers/label.rs) | 2 | ||||
-rw-r--r-- | support/texlab/crates/completion/src/tests.rs | 57 | ||||
-rw-r--r-- | support/texlab/crates/completion/src/util/builder.rs | 1 |
8 files changed, 156 insertions, 27 deletions
diff --git a/support/texlab/crates/completion/src/lib.rs b/support/texlab/crates/completion/src/lib.rs index 6acec28d49..7fc5bba174 100644 --- a/support/texlab/crates/completion/src/lib.rs +++ b/support/texlab/crates/completion/src/lib.rs @@ -45,6 +45,7 @@ impl<'a> CompletionItem<'a> { #[derive(Debug, PartialEq, Eq)] pub enum CompletionItemData<'a> { Command(CommandData<'a>), + CommandLikeDelimiter(&'a str, &'a str), BeginEnvironment, Citation(CitationData<'a>), Environment(EnvironmentData<'a>), @@ -66,6 +67,7 @@ impl<'a> CompletionItemData<'a> { pub fn label<'b: 'a>(&'b self) -> &'a str { match self { Self::Command(data) => data.name, + Self::CommandLikeDelimiter(left, _) => left, Self::BeginEnvironment => "begin", Self::Citation(data) => &data.entry.name.text, Self::Environment(data) => data.name, @@ -83,6 +85,30 @@ impl<'a> CompletionItemData<'a> { Self::TikzLibrary(name) => name, } } + + /// Returns a number that can be used to sort the completion items further before resorting to the label. + /// This is useful for making snippets more visible. + pub fn sort_index(&self) -> u8 { + match self { + Self::Command(_) => 1, + Self::CommandLikeDelimiter(_, _) => 0, + Self::BeginEnvironment => 1, + Self::Citation(_) => 1, + Self::Environment(_) => 1, + Self::GlossaryEntry(_) => 1, + Self::Label(_) => 1, + Self::Color(_) => 1, + Self::ColorModel(_) => 1, + Self::File(_) => 1, + Self::Directory(_) => 1, + Self::Argument(_) => 1, + Self::Package(_) => 1, + Self::DocumentClass(_) => 1, + Self::EntryType(_) => 1, + Self::Field(_) => 1, + Self::TikzLibrary(_) => 1, + } + } } #[derive(PartialEq, Eq)] @@ -171,7 +197,8 @@ pub fn complete<'a>(params: &'a CompletionParams<'a>) -> CompletionResult<'a> { providers::complete_citations(params, &mut builder); providers::complete_acronyms(params, &mut builder); providers::complete_glossaries(params, &mut builder); - providers::complete_labels(params, &mut builder); + providers::complete_label_references(params, &mut builder); + providers::complete_label_definitions(params, &mut builder); providers::complete_colors(params, &mut builder); providers::complete_color_models(params, &mut builder); providers::complete_includes(params, &mut builder); diff --git a/support/texlab/crates/completion/src/providers.rs b/support/texlab/crates/completion/src/providers.rs index 5160c85d85..dc60907f2e 100644 --- a/support/texlab/crates/completion/src/providers.rs +++ b/support/texlab/crates/completion/src/providers.rs @@ -9,7 +9,8 @@ mod field; mod glossary; mod import; mod include; -mod label; +mod label_def; +mod label_ref; mod tikz_library; pub use argument::complete_arguments; @@ -23,5 +24,6 @@ pub use field::complete_fields; pub use glossary::{complete_acronyms, complete_glossaries}; pub use import::complete_imports; pub use include::complete_includes; -pub use label::complete_labels; +pub use label_def::complete_label_definitions; +pub use label_ref::complete_label_references; pub use tikz_library::complete_tikz_libraries; diff --git a/support/texlab/crates/completion/src/providers/command.rs b/support/texlab/crates/completion/src/providers/command.rs index ddbf8bc206..f404d42ab3 100644 --- a/support/texlab/crates/completion/src/providers/command.rs +++ b/support/texlab/crates/completion/src/providers/command.rs @@ -7,6 +7,8 @@ use crate::{ CommandData, CompletionItem, CompletionItemData, CompletionParams, }; +static DELIMITERS: &[(&str, &str)] = &[("(", ")"), ("[", "]"), ("{", "\\}")]; + pub fn complete_commands<'a>( params: &'a CompletionParams<'a>, builder: &mut CompletionBuilder<'a>, @@ -20,6 +22,7 @@ pub fn complete_commands<'a>( }); proc.add_begin_snippet(); + proc.add_delimiters(); proc.add_library(); proc.add_user(); Some(()) @@ -39,6 +42,20 @@ impl<'a, 'b> Processor<'a, 'b> { Some(()) } + 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 { + continue; + }; + + let data = CompletionItemData::CommandLikeDelimiter(left, right); + self.0 + .builder + .items + .push(CompletionItem::new_simple(score, self.0.cursor.range, data)); + } + } + pub fn add_library(&mut self) -> Option<()> { for package in included_packages(&self.0.params.feature) { let commands_with_score = package.commands.iter().filter_map(|command| { diff --git a/support/texlab/crates/completion/src/providers/include.rs b/support/texlab/crates/completion/src/providers/include.rs index f8bb55dfeb..6246624733 100644 --- a/support/texlab/crates/completion/src/providers/include.rs +++ b/support/texlab/crates/completion/src/providers/include.rs @@ -3,7 +3,10 @@ use std::{ path::{Path, PathBuf}, }; -use base_db::{DocumentData, FeatureParams}; +use base_db::{ + deps::{self, ProjectRoot}, + DocumentData, FeatureParams, +}; use rowan::{ast::AstNode, TextLen, TextRange}; use syntax::latex; @@ -112,13 +115,13 @@ fn current_dir( graphics_path: Option<&str>, ) -> Option<PathBuf> { let workspace = ¶ms.workspace; - let parent = workspace - .parents(params.document) + let parent = deps::parents(&workspace, params.document) .iter() .next() .map_or(params.document, Clone::clone); - let path = workspace.current_dir(&parent.dir).to_file_path().ok()?; + let root = ProjectRoot::walk_and_find(workspace, &parent.dir); + let path = root.src_dir.to_file_path().ok()?; let mut path = PathBuf::from(path.to_str()?.replace('\\', "/")); diff --git a/support/texlab/crates/completion/src/providers/label_def.rs b/support/texlab/crates/completion/src/providers/label_def.rs new file mode 100644 index 0000000000..a8966ed62f --- /dev/null +++ b/support/texlab/crates/completion/src/providers/label_def.rs @@ -0,0 +1,60 @@ +use base_db::{ + semantics::{ + tex::{Label, LabelKind}, + Span, + }, + util::queries::Object, +}; +use rowan::ast::AstNode; +use rustc_hash::FxHashSet; +use syntax::latex; + +use crate::{ + util::{find_curly_group_word, CompletionBuilder}, + CompletionParams, +}; + +pub fn complete_label_definitions<'a>( + params: &'a CompletionParams<'a>, + builder: &mut CompletionBuilder<'a>, +) -> Option<()> { + let cursor = find_definition(params)?; + + let label_defs: FxHashSet<&str> = Label::find_all(¶ms.feature.project) + .filter(|(_, label)| label.kind == LabelKind::Definition) + .map(|(_, label)| label.name_text()) + .collect(); + + let label_refs: FxHashSet<&str> = Label::find_all(¶ms.feature.project) + .filter(|(_, label)| label.kind == LabelKind::Reference) + .map(|(_, label)| label.name_text()) + .collect(); + + for label in label_refs.difference(&label_defs) { + let Some(score) = builder.matcher.score(label, &cursor.text) else { + continue; + }; + + let data = crate::LabelData { + name: label, + header: None, + footer: None, + object: None, + keywords: label.to_string(), + }; + + builder.items.push(crate::CompletionItem::new_simple( + score, + cursor.range, + crate::CompletionItemData::Label(data), + )); + } + + Some(()) +} + +fn find_definition(params: &CompletionParams) -> Option<Span> { + let (cursor, group) = find_curly_group_word(params)?; + latex::LabelDefinition::cast(group.syntax().parent()?)?; + Some(cursor) +} diff --git a/support/texlab/crates/completion/src/providers/label.rs b/support/texlab/crates/completion/src/providers/label_ref.rs index 8af2873457..6f71ae3241 100644 --- a/support/texlab/crates/completion/src/providers/label.rs +++ b/support/texlab/crates/completion/src/providers/label_ref.rs @@ -11,7 +11,7 @@ use crate::{ CompletionItem, CompletionItemData, CompletionParams, }; -pub fn complete_labels<'a>( +pub fn complete_label_references<'a>( params: &'a CompletionParams<'a>, builder: &mut CompletionBuilder<'a>, ) -> Option<()> { diff --git a/support/texlab/crates/completion/src/tests.rs b/support/texlab/crates/completion/src/tests.rs index 84cd06447b..f41c9f5e6b 100644 --- a/support/texlab/crates/completion/src/tests.rs +++ b/support/texlab/crates/completion/src/tests.rs @@ -726,40 +726,34 @@ fn component_command_simple() { %! main.tex \ |"#, - expect![[r##" + expect![[r#" [ - Command( - CommandData { - name: "!", - package: [], - }, + CommandLikeDelimiter( + "(", + ")", ), - Command( - CommandData { - name: "\"", - package: [], - }, + CommandLikeDelimiter( + "[", + "]", ), - Command( - CommandData { - name: "#", - package: [], - }, + CommandLikeDelimiter( + "{", + "\\}", ), Command( CommandData { - name: "$", + name: "!", package: [], }, ), Command( CommandData { - name: "%", + name: "\"", package: [], }, ), ] - "##]], + "#]], ); } @@ -1613,6 +1607,31 @@ Lorem ipsum dolor sit amet. } #[test] +fn label_undefined() { + check( + r#" +%! foo.tex +\label{f} + | + ^ +\ref{foo}"#, + expect![[r#" + [ + Label( + LabelData { + name: "foo", + header: None, + footer: None, + object: None, + keywords: "foo", + }, + ), + ] + "#]], + ); +} + +#[test] fn theorem_begin() { check( r#" diff --git a/support/texlab/crates/completion/src/util/builder.rs b/support/texlab/crates/completion/src/util/builder.rs index 4ae0818e58..d219a5f2b1 100644 --- a/support/texlab/crates/completion/src/util/builder.rs +++ b/support/texlab/crates/completion/src/util/builder.rs @@ -32,6 +32,7 @@ impl<'a> CompletionBuilder<'a> { b.preselect .cmp(&a.preselect) .then_with(|| b.score.cmp(&a.score)) + .then_with(|| a.data.sort_index().cmp(&b.data.sort_index())) .then_with(|| a.data.label().cmp(b.data.label())) }); |