From b8d4bb76703bcb15578e2b23c5d256532180b894 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Tue, 3 Dec 2019 03:01:24 +0000 Subject: CTAN sync 201912030301 --- support/texlab/src/completion/quality.rs | 125 +++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 support/texlab/src/completion/quality.rs (limited to 'support/texlab/src/completion/quality.rs') diff --git a/support/texlab/src/completion/quality.rs b/support/texlab/src/completion/quality.rs new file mode 100644 index 0000000000..d643219809 --- /dev/null +++ b/support/texlab/src/completion/quality.rs @@ -0,0 +1,125 @@ +use crate::range::RangeExt; +use crate::syntax::*; +use crate::workspace::*; +use futures_boxed::boxed; +use lsp_types::{CompletionItem, CompletionParams, Position}; +use std::borrow::Cow; + +pub struct OrderByQualityCompletionProvider { + pub provider: F, +} + +impl OrderByQualityCompletionProvider { + pub fn new(provider: F) -> Self { + Self { provider } + } +} + +impl FeatureProvider for OrderByQualityCompletionProvider +where + F: FeatureProvider> + Send + Sync, +{ + type Params = CompletionParams; + type Output = Vec; + + #[boxed] + async fn execute<'a>(&'a self, request: &'a FeatureRequest) -> Self::Output { + let query = Self::get_query( + request.document(), + request.params.text_document_position.position, + ); + let mut items = self.provider.execute(&request).await; + items.sort_by_key(|item| -Self::get_quality(&query, &item)); + items + } +} + +impl OrderByQualityCompletionProvider { + fn get_query(document: &Document, position: Position) -> Option> { + match &document.tree { + SyntaxTree::Latex(tree) => { + let node = tree + .find_command_by_name(position) + .map(LatexNode::Command) + .or_else(|| tree.find(position).into_iter().last())?; + + match node { + LatexNode::Root(_) | LatexNode::Group(_) => Some("".into()), + LatexNode::Command(command) => Some(command.name.text()[1..].to_owned().into()), + LatexNode::Text(text) => text + .words + .iter() + .find(|word| word.range().contains(position)) + .map(|word| word.text().to_owned().into()), + LatexNode::Comma(_) => Some(",".into()), + LatexNode::Math(math) => Some(math.token.text().to_owned().into()), + } + } + SyntaxTree::Bibtex(tree) => { + fn get_type_query(ty: &BibtexToken, position: Position) -> Option> { + if ty.range().contains(position) { + Some((&ty.text()[1..]).into()) + } else { + Some("".into()) + } + } + match tree.find(position).pop()? { + BibtexNode::Root(_) => Some("".into()), + BibtexNode::Preamble(preamble) => get_type_query(&preamble.ty, position), + BibtexNode::String(string) => get_type_query(&string.ty, position), + BibtexNode::Entry(entry) => get_type_query(&entry.ty, position), + BibtexNode::Comment(comment) => Some(comment.token.text().into()), + BibtexNode::Field(field) => { + if field.name.range().contains(position) { + Some(field.name.text().into()) + } else { + Some("".into()) + } + } + BibtexNode::Word(word) => Some(word.token.text().into()), + BibtexNode::Command(command) => Some((&command.token.text()[1..]).into()), + BibtexNode::QuotedContent(_) + | BibtexNode::BracedContent(_) + | BibtexNode::Concat(_) => Some("".into()), + } + } + } + } + + fn get_quality(query: &Option>, item: &CompletionItem) -> i32 { + if item.preselect == Some(true) { + return 8; + } + + let label = &item.label; + if let Some(query) = query { + if label == query { + return 7; + } + + if label.to_lowercase() == query.to_lowercase() { + return 6; + } + + if label.starts_with(query.as_ref()) { + return 5; + } + + if label.to_lowercase().starts_with(&query.to_lowercase()) { + return 4; + } + + if label.contains(query.as_ref()) { + return 3; + } + + if label.to_lowercase().contains(&query.to_lowercase()) { + return 2; + } + + 1 + } else { + 0 + } + } +} -- cgit v1.2.3