mdbook_treesitter/
language.rs1use anyhow::{Context, Result, bail};
8use std::collections::HashMap;
9use tree_sitter::{Language, Parser};
10
11use crate::config::QueryConfig;
12
13pub struct LanguageEntry {
16 pub language: Language,
17 pub queries: HashMap<String, QueryConfig>,
19}
20
21pub fn build_registry(
27 user_configs: &HashMap<String, crate::config::LanguageConfig>,
28 book_root: &std::path::Path,
29) -> Result<HashMap<String, LanguageEntry>> {
30 let mut registry: HashMap<String, LanguageEntry> = HashMap::new();
31
32 {
34 registry.insert(
35 "rs".into(),
36 LanguageEntry {
37 language: Language::new(tree_sitter_rust::LANGUAGE),
38 queries: HashMap::new(),
39 },
40 );
41 }
42
43 {
45 registry.insert(
46 "toml".into(),
47 LanguageEntry {
48 language: tree_sitter_toml::language(),
49 queries: HashMap::new(),
50 },
51 );
52 }
53
54 {
56 registry.insert(
57 "md".into(),
58 LanguageEntry {
59 language: Language::new(tree_sitter_md::LANGUAGE),
60 queries: HashMap::new(),
61 },
62 );
63 }
64
65 for (lang_name, lang_cfg) in user_configs {
67 let ext = lang_name_to_ext(lang_name);
68
69 if let Some(parser_path_str) = &lang_cfg.parser {
70 let parser_path = if std::path::Path::new(parser_path_str).is_absolute() {
71 std::path::PathBuf::from(parser_path_str)
72 } else {
73 book_root.join(parser_path_str)
74 };
75 let language = unsafe { load_language_from_so(&parser_path)? };
76 let entry = registry
77 .entry(ext.to_string())
78 .or_insert_with(|| LanguageEntry {
79 language: language.clone(),
80 queries: HashMap::new(),
81 });
82 entry.language = language;
83 }
84
85 if let Some(entry) = registry.get_mut(ext) {
87 for (qname, qcfg) in &lang_cfg.queries {
88 entry.queries.insert(qname.clone(), qcfg.clone());
89 }
90 }
91 }
92
93 Ok(registry)
94}
95
96fn lang_name_to_ext(name: &str) -> &str {
97 match name {
98 "rust" => "rs",
99 "markdown" => "md",
100 "javascript" => "js",
101 "typescript" => "ts",
102 "python" => "py",
103 "c" => "c",
104 "cpp" | "c++" => "cpp",
105 "go" => "go",
106 other => other,
107 }
108}
109
110unsafe fn load_language_from_so(_path: &std::path::Path) -> Result<Language> {
115 bail!(
116 "Dynamic parser loading from `{}` is not yet supported in this build.",
117 _path.display()
118 )
119}
120
121pub fn make_parser(language: &Language) -> Result<Parser> {
123 let mut parser = Parser::new();
124 parser
125 .set_language(language)
126 .context("Failed to configure parser")?;
127 Ok(parser)
128}