summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/completion/citation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/features/completion/citation.rs')
-rw-r--r--support/texlab/src/features/completion/citation.rs74
1 files changed, 61 insertions, 13 deletions
diff --git a/support/texlab/src/features/completion/citation.rs b/support/texlab/src/features/completion/citation.rs
index 6df3364099..0a7cc26b10 100644
--- a/support/texlab/src/features/completion/citation.rs
+++ b/support/texlab/src/features/completion/citation.rs
@@ -26,12 +26,14 @@ pub fn complete_citations<'a>(
let token = context.cursor.as_latex()?;
let range = if token.kind() == latex::WORD {
- token.text_range()
+ latex::Key::cast(token.parent())
+ .map(|key| key.small_range())
+ .or_else(|| latex::Text::cast(token.parent()).map(|text| text.small_range()))?
} else {
TextRange::empty(context.offset)
};
- check_citation(context, token).or_else(|| check_acronym(token))?;
+ check_citation(context).or_else(|| check_acronym(context))?;
for document in &context.request.subset.documents {
if let Some(data) = document.data.as_bibtex() {
for entry in data.root.children().filter_map(bibtex::Entry::cast) {
@@ -46,20 +48,17 @@ pub fn complete_citations<'a>(
Some(())
}
-fn check_citation(
- context: &CursorContext<CompletionParams>,
- token: &latex::SyntaxToken,
-) -> Option<()> {
- let group = latex::CurlyGroupWordList::cast(token.parent())
- .filter(|group| context.is_inside_latex_curly(group))?;
+fn check_citation(context: &CursorContext<CompletionParams>) -> Option<()> {
+ let (_, _, group) = context.find_curly_group_word_list()?;
latex::Citation::cast(group.syntax().parent()?)?;
Some(())
}
-fn check_acronym(token: &latex::SyntaxToken) -> Option<()> {
+fn check_acronym(context: &CursorContext<CompletionParams>) -> Option<()> {
+ let token = context.cursor.as_latex()?;
+
let pair = token.ancestors().find_map(latex::KeyValuePair::cast)?;
- let mut key_words = pair.key()?.words();
- if key_words.next()?.text() != "cite" || key_words.next().is_some() {
+ if pair.key()?.to_string() != "cite" {
return None;
}
@@ -72,7 +71,7 @@ fn make_item<'a>(
entry: bibtex::Entry<'a>,
range: TextRange,
) -> Option<InternalCompletionItem<'a>> {
- let key = entry.key()?.text();
+ let key = entry.key()?.to_string();
let ty = LANGUAGE_DATA
.find_entry_type(&entry.ty()?.text()[1..])
.map(|ty| Structure::Entry(ty.category))
@@ -98,7 +97,7 @@ fn make_item<'a>(
range,
InternalCompletionItemData::Citation {
uri: Arc::clone(&document.uri),
- key: key.into(),
+ key,
text,
ty,
},
@@ -171,6 +170,29 @@ mod tests {
}
#[test]
+ fn test_latex_two_words() {
+ let request = FeatureTester::builder()
+ .files(vec![
+ ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"),
+ ("main.bib", "@article{foo bar,}"),
+ ])
+ .main("main.tex")
+ .line(1)
+ .character(6)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_citations(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(32.into(), 35.into()));
+ }
+ }
+
+ #[test]
fn test_latex_open_brace() {
let request = FeatureTester::builder()
.files(vec![
@@ -241,4 +263,30 @@ mod tests {
assert_eq!(item.range, TextRange::new(54.into(), 54.into()));
}
}
+
+ #[test]
+ fn test_latex_acronym_two_words() {
+ let request = FeatureTester::builder()
+ .files(vec![
+ (
+ "main.tex",
+ "\\addbibresource{main.bib}\n\\DeclareAcronym{foo}{cite={\na b}}",
+ ),
+ ("main.bib", "@article{foo,}"),
+ ])
+ .main("main.tex")
+ .line(2)
+ .character(0)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_citations(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(54.into(), 57.into()));
+ }
+ }
}