Skip to content

Commit

Permalink
Provide completion for BibTeX field names
Browse files Browse the repository at this point in the history
  • Loading branch information
pfoerster committed May 13, 2019
1 parent f60b0f5 commit 7adcf9e
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 0 deletions.
132 changes: 132 additions & 0 deletions src/completion/bibtex/field_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use crate::completion::factory;
use crate::feature::FeatureRequest;
use crate::metadata::bibtex_field::BIBTEX_FIELDS;
use crate::syntax::bibtex::{BibtexFinder, BibtexNode, BibtexVisitor};
use crate::syntax::text::SyntaxNode;
use crate::syntax::SyntaxTree;
use lsp_types::{CompletionItem, CompletionParams};

pub struct BibtexFieldNameCompletionProvider;

impl BibtexFieldNameCompletionProvider {
pub async fn execute(request: &FeatureRequest<CompletionParams>) -> Vec<CompletionItem> {
if let SyntaxTree::Bibtex(tree) = &request.document.tree {
let mut finder = BibtexFinder::new(request.params.position);
finder.visit_root(&tree.root);
match finder.results.last() {
Some(BibtexNode::Field(field)) => {
if field.name.range().contains(request.params.position) {
return Self::generate_items();
}
}
Some(BibtexNode::Entry(entry)) => {
if !entry.is_comment() && !entry.ty.range().contains(request.params.position) {
if let Some(key) = &entry.key {
if !key.range().contains(request.params.position) {
return Self::generate_items();
}
} else {
return Self::generate_items();
}
}
}
_ => {}
}
}
Vec::new()
}

fn generate_items() -> Vec<CompletionItem> {
BIBTEX_FIELDS
.iter()
.map(|field| factory::create_field_name(field))
.collect()
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::completion::latex::data::types::LatexComponentDatabase;
use crate::feature::FeatureSpec;
use crate::test_feature;
use lsp_types::Position;

#[test]
fn test_inside_first_field() {
let items = test_feature!(
BibtexFieldNameCompletionProvider,
FeatureSpec {
files: vec![FeatureSpec::file("foo.bib", "@article{foo,\nbar}"),],
main_file: "foo.bib",
position: Position::new(1, 1),
new_name: "",
component_database: LatexComponentDatabase::default(),
}
);
assert_eq!(items.len() > 0, true);
}

#[test]
fn test_inside_second_field() {
let items = test_feature!(
BibtexFieldNameCompletionProvider,
FeatureSpec {
files: vec![FeatureSpec::file(
"foo.bib",
"@article{foo, bar = {baz}, qux}"
),],
main_file: "foo.bib",
position: Position::new(0, 27),
new_name: "",
component_database: LatexComponentDatabase::default(),
}
);
assert_eq!(items.len() > 0, true);
}

#[test]
fn test_inside_entry() {
let items = test_feature!(
BibtexFieldNameCompletionProvider,
FeatureSpec {
files: vec![FeatureSpec::file("foo.bib", "@article{foo, \n}"),],
main_file: "foo.bib",
position: Position::new(1, 0),
new_name: "",
component_database: LatexComponentDatabase::default(),
}
);
assert_eq!(items.len() > 0, true);
}

#[test]
fn test_inside_content() {
let items = test_feature!(
BibtexFieldNameCompletionProvider,
FeatureSpec {
files: vec![FeatureSpec::file("foo.bib", "@article{foo,\nbar = {baz}}"),],
main_file: "foo.bib",
position: Position::new(1, 7),
new_name: "",
component_database: LatexComponentDatabase::default(),
}
);
assert_eq!(items.len() == 0, true);
}

#[test]
fn test_inside_entry_type() {
let items = test_feature!(
BibtexFieldNameCompletionProvider,
FeatureSpec {
files: vec![FeatureSpec::file("foo.bib", "@article{foo,}"),],
main_file: "foo.bib",
position: Position::new(0, 3),
new_name: "",
component_database: LatexComponentDatabase::default(),
}
);
assert_eq!(items.len() == 0, true);
}
}
1 change: 1 addition & 0 deletions src/completion/bibtex/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod field_name;
14 changes: 14 additions & 0 deletions src/completion/factory.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::formatting::{BibtexFormatter, BibtexFormattingOptions};
use crate::metadata::bibtex_field::BibtexField;
use crate::syntax::bibtex::{BibtexEntry, BibtexToken};
use lsp_types::*;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -175,3 +176,16 @@ pub fn create_citation(entry: &BibtexEntry, key: &str) -> CompletionItem {
..CompletionItem::default()
}
}

pub fn create_field_name(field: &BibtexField) -> CompletionItem {
CompletionItem {
label: Cow::from(field.name),
kind: Some(CompletionItemKind::Field),
data: Some(CompletionItemData::FieldName.into()),
documentation: Some(Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: Cow::from(field.documentation),
})),
..CompletionItem::default()
}
}
3 changes: 3 additions & 0 deletions src/completion/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod bibtex;
mod factory;
pub mod latex;
mod quality;

use self::bibtex::field_name::BibtexFieldNameCompletionProvider;
use self::latex::begin_command::LatexBeginCommandCompletionProvider;
use self::latex::citation::LatexCitationCompletionProvider;
use self::latex::color::LatexColorCompletionProvider;
Expand Down Expand Up @@ -31,6 +33,7 @@ impl CompletionProvider {
async move |_| {
concat_feature!(
&request,
BibtexFieldNameCompletionProvider,
LatexKernelEnvironmentCompletionProvider,
LatexPgfLibraryCompletionProvider,
LatexTikzLibraryCompletionProvider,
Expand Down

0 comments on commit 7adcf9e

Please sign in to comment.