summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/completion/component_command.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/features/completion/component_command.rs')
-rw-r--r--support/texlab/src/features/completion/component_command.rs177
1 files changed, 177 insertions, 0 deletions
diff --git a/support/texlab/src/features/completion/component_command.rs b/support/texlab/src/features/completion/component_command.rs
new file mode 100644
index 0000000000..aba5a78597
--- /dev/null
+++ b/support/texlab/src/features/completion/component_command.rs
@@ -0,0 +1,177 @@
+use cancellation::CancellationToken;
+use lsp_types::CompletionParams;
+
+use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext};
+
+use super::types::{InternalCompletionItem, InternalCompletionItemData};
+
+pub fn complete_component_commands<'a>(
+ context: &'a CursorContext<CompletionParams>,
+ items: &mut Vec<InternalCompletionItem<'a>>,
+ cancellation_token: &CancellationToken,
+) -> Option<()> {
+ cancellation_token.result().ok()?;
+
+ let range = context.cursor.command_range(context.offset)?;
+
+ for component in COMPONENT_DATABASE.linked_components(&context.request.subset) {
+ cancellation_token.result().ok()?;
+ for command in &component.commands {
+ items.push(InternalCompletionItem::new(
+ range,
+ InternalCompletionItemData::ComponentCommand {
+ name: &command.name,
+ image: command.image.as_deref(),
+ glyph: command.glyph.as_deref(),
+ file_names: &component.file_names,
+ },
+ ));
+ }
+ }
+
+ Some(())
+}
+
+#[cfg(test)]
+mod tests {
+ use cstree::TextRange;
+
+ use crate::features::testing::FeatureTester;
+
+ use super::*;
+
+ #[test]
+ fn test_empty_latex_document() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", "")])
+ .main("main.tex")
+ .line(0)
+ .character(0)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_component_commands(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[test]
+ fn test_empty_bibtex_document() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.bib", "")])
+ .main("main.bib")
+ .line(0)
+ .character(0)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_component_commands(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[test]
+ fn test_latex_simple() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", "\\")])
+ .main("main.tex")
+ .line(0)
+ .character(1)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_component_commands(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(1.into(), 1.into()));
+ }
+ }
+
+ #[test]
+ fn test_latex_simple_before() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", "\\")])
+ .main("main.tex")
+ .line(0)
+ .character(0)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_component_commands(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(actual_items.is_empty());
+ }
+
+ #[test]
+ fn test_latex_simple_package() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", "\\\n\\usepackage{lipsum}")])
+ .main("main.tex")
+ .line(0)
+ .character(1)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_component_commands(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in &actual_items {
+ assert_eq!(item.range, TextRange::new(1.into(), 1.into()));
+ }
+
+ assert!(actual_items
+ .iter()
+ .any(|item| item.data.label() == "lipsum"));
+ }
+
+ #[test]
+ fn test_latex_simple_existing() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", "\\foo")])
+ .main("main.tex")
+ .line(0)
+ .character(2)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_component_commands(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(1.into(), 4.into()));
+ }
+ }
+
+ #[test]
+ fn test_bibtex_simple() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.bib", "@a{b,c={\\ }}")])
+ .main("main.bib")
+ .line(0)
+ .character(9)
+ .build()
+ .completion();
+
+ let context = CursorContext::new(request);
+ let mut actual_items = Vec::new();
+ complete_component_commands(&context, &mut actual_items, CancellationToken::none());
+
+ assert!(!actual_items.is_empty());
+ for item in actual_items {
+ assert_eq!(item.range, TextRange::new(9.into(), 10.into()));
+ }
+ }
+}