summaryrefslogtreecommitdiff
path: root/helix-syntax/src/lib.rs
blob: b6c0ecf353e444207c5e8d638b04b664cde734c3 (plain) (blame)
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
use anyhow::{Context, Result};
use libloading::{Library, Symbol};
use tree_sitter::Language;

fn replace_dashes_with_underscores(name: &str) -> String {
    let mut result = String::with_capacity(name.len());
    for c in name.chars() {
        if c == '-' {
            result.push('_');
        } else {
            result.push(c);
        }
    }
    result
}
#[cfg(unix)]
const DYLIB_EXTENSION: &str = "so";

#[cfg(windows)]
const DYLIB_EXTENSION: &str = "dll";

pub fn get_language(runtime_path: &std::path::Path, name: &str) -> Result<Language> {
    let name = name.to_ascii_lowercase();
    let mut library_path = runtime_path.join("grammars").join(&name);
    // TODO: duplicated under build
    library_path.set_extension(DYLIB_EXTENSION);

    let library = unsafe { Library::new(&library_path) }
        .with_context(|| format!("Error opening dynamic library {:?}", &library_path))?;
    let language_fn_name = format!("tree_sitter_{}", replace_dashes_with_underscores(&name));
    let language = unsafe {
        let language_fn: Symbol<unsafe extern "C" fn() -> Language> = library
            .get(language_fn_name.as_bytes())
            .with_context(|| format!("Failed to load symbol {}", language_fn_name))?;
        language_fn()
    };
    std::mem::forget(library);
    Ok(language)
}