summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/completion/import.rs
blob: 9cb35b68a7af3e287e0e7fc637676e3c9de9c0fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use lsp_types::CompletionParams;
use rowan::ast::AstNode;
use rustc_hash::FxHashSet;
use smol_str::SmolStr;

use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex};

use super::types::{InternalCompletionItem, InternalCompletionItemData};

pub fn complete_imports<'a>(
    context: &'a CursorContext<CompletionParams>,
    items: &mut Vec<InternalCompletionItem<'a>>,
) -> Option<()> {
    let (_, range, group) = context.find_curly_group_word_list()?;

    let (extension, mut factory): (
        &str,
        Box<dyn FnMut(SmolStr) -> InternalCompletionItemData<'a>>,
    ) = match group.syntax().parent()?.kind() {
        latex::PACKAGE_INCLUDE => (
            "sty",
            Box::new(|name| InternalCompletionItemData::Package { name }),
        ),
        latex::CLASS_INCLUDE => (
            "cls",
            Box::new(|name| InternalCompletionItemData::Class { name }),
        ),
        _ => return None,
    };

    let mut file_names = FxHashSet::default();
    for file_name in COMPONENT_DATABASE
        .components
        .iter()
        .flat_map(|comp| comp.file_names.iter())
        .filter(|file_name| file_name.ends_with(extension))
    {
        file_names.insert(file_name);
        let stem = &file_name[0..file_name.len() - 4];
        let data = factory(stem.into());
        items.push(InternalCompletionItem::new(range, data));
    }

    let resolver = &context.request.workspace.environment.resolver;
    for file_name in resolver
        .files_by_name
        .keys()
        .filter(|file_name| file_name.ends_with(extension) && !file_names.contains(file_name))
    {
        let stem = &file_name[0..file_name.len() - 4];
        let data = factory(stem.into());
        items.push(InternalCompletionItem::new(range, data));
    }

    Some(())
}