diff options
Diffstat (limited to 'support/texlab/crates/completion/src/providers/glossary.rs')
-rw-r--r-- | support/texlab/crates/completion/src/providers/glossary.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/support/texlab/crates/completion/src/providers/glossary.rs b/support/texlab/crates/completion/src/providers/glossary.rs new file mode 100644 index 0000000000..c22f5b5888 --- /dev/null +++ b/support/texlab/crates/completion/src/providers/glossary.rs @@ -0,0 +1,88 @@ +use base_db::semantics::Span; +use rowan::ast::AstNode; +use syntax::latex; + +use crate::{ + util::{find_curly_group_word, CompletionBuilder, ProviderContext}, + CompletionItem, CompletionItemData, CompletionParams, GlossaryEntryData, +}; + +pub fn complete_acronyms<'a>( + params: &'a CompletionParams<'a>, + builder: &mut CompletionBuilder<'a>, +) -> Option<()> { + let cursor = find_acronym(params)?; + let mut proc = Processor(ProviderContext { + builder, + params, + cursor, + }); + + proc.add_acronyms(); + Some(()) +} + +pub fn complete_glossaries<'a>( + params: &'a CompletionParams<'a>, + builder: &mut CompletionBuilder<'a>, +) -> Option<()> { + let cursor = find_glossary(params)?; + let mut proc = Processor(ProviderContext { + builder, + params, + cursor, + }); + + proc.add_acronyms(); + proc.add_glossaries(); + Some(()) +} + +struct Processor<'a, 'b>(ProviderContext<'a, 'b>); + +impl<'a, 'b> Processor<'a, 'b> { + pub fn add_acronyms(&mut self) { + self.add_generic(|node| latex::AcronymDefinition::cast(node)?.name()); + } + + pub fn add_glossaries(&mut self) { + self.add_generic(|node| latex::GlossaryEntryDefinition::cast(node)?.name()); + } + + fn add_generic<F>(&mut self, extract: F) + where + F: Fn(latex::SyntaxNode) -> Option<latex::CurlyGroupWord>, + { + let documents = self.0.params.feature.project.documents.iter(); + for data in documents.filter_map(|document| document.data.as_tex()) { + for name in data + .root_node() + .descendants() + .filter_map(|node| extract(node)) + .filter_map(|name| name.key()) + .map(|name| name.to_string()) + { + if let Some(score) = self.0.builder.matcher.score(&name, &self.0.cursor.text) { + let data = CompletionItemData::GlossaryEntry(GlossaryEntryData { name }); + self.0.builder.items.push(CompletionItem::new_simple( + score, + self.0.cursor.range, + data, + )); + } + } + } + } +} + +fn find_acronym(params: &CompletionParams) -> Option<Span> { + let (cursor, group) = find_curly_group_word(params)?; + latex::AcronymReference::cast(group.syntax().parent()?)?; + Some(cursor) +} + +fn find_glossary(params: &CompletionParams) -> Option<Span> { + let (cursor, group) = find_curly_group_word(params)?; + latex::GlossaryEntryReference::cast(group.syntax().parent()?)?; + Some(cursor) +} |