@@ -10,9 +10,19 @@ use std::{
1010};
1111
1212use once_cell::sync::{Lazy, OnceCell};
13+use serde::{Deserialize, Serialize};
14+
15+#[derive(Serialize, Deserialize)]
16+pub struct Configuration {
17+ language: Vec<LanguageConfiguration>,
18+}
1319
1420// largely based on tree-sitter/cli/src/loader.rs
21+#[derive(Serialize, Deserialize)]
22+#[serde(rename_all = "kebab-case")]
1523pub struct LanguageConfiguration {
24+ #[serde(rename = "name")]
25+ pub(crate) language_id: Lang,
1626 pub scope: String, // source.rust
1727 pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
1828 pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
@@ -24,22 +34,29 @@ pub struct LanguageConfiguration {
2434 // injection_regex
2535 // first_line_regex
2636 //
27− //
28− pub(crate) language_id: Lang,
37+ #[serde(skip)]
2938 pub(crate) highlight_config: OnceCell<Option<Arc<HighlightConfiguration>>>,
3039 // tags_config OnceCell<> https://github.com/tree-sitter/tree-sitter/pull/583
31− pub language_server_config: Option<LanguageServerConfiguration>,
32− pub indent_config: Option<IndentationConfiguration>,
40+ #[serde(skip_serializing_if = "Option::is_none")]
41+ pub language_server: Option<LanguageServerConfiguration>,
42+ #[serde(skip_serializing_if = "Option::is_none")]
43+ pub indent: Option<IndentationConfiguration>,
3344}
3445
46+#[derive(Serialize, Deserialize)]
47+#[serde(rename_all = "kebab-case")]
3548pub struct LanguageServerConfiguration {
3649 pub command: String,
50+ #[serde(default)]
51+ #[serde(skip_serializing_if = "Vec::is_empty")]
3752 pub args: Vec<String>,
3853}
3954
55+#[derive(Serialize, Deserialize)]
56+#[serde(rename_all = "kebab-case")]
4057pub struct IndentationConfiguration {
4158 pub tab_width: usize,
42− pub indent_unit: String,
59+ pub unit: String,
4360}
4461
4562impl LanguageConfiguration {
@@ -81,7 +98,7 @@ impl LanguageConfiguration {
8198 }
8299}
83100
84−pub static LOADER: Lazy<Loader> = Lazy::new(Loader::init);
101+pub static LOADER: OnceCell<Loader> = OnceCell::new();
85102
86103pub struct Loader {
87104 // highlight_names ?
@@ -90,48 +107,13 @@ pub struct Loader {
90107}
91108
92109impl Loader {
93− fn init() -> Self {
110+ pub fn new(config: Configuration) -> Self {
94111 let mut loader = Self {
95112 language_configs: Vec::new(),
96113 language_config_ids_by_file_type: HashMap::new(),
97114 };
98115
99− // hardcoded from now, might load from toml
100− let configs = vec![
101− LanguageConfiguration {
102− scope: "source.rust".to_string(),
103− file_types: vec!["rs".to_string()],
104− language_id: Lang::Rust,
105− highlight_config: OnceCell::new(),
106− //
107− path: "../helix-syntax/languages/tree-sitter-rust".into(),
108− roots: vec![],
109− language_server_config: Some(LanguageServerConfiguration {
110− command: "rust-analyzer".to_string(),
111− args: vec![],
112− }),
113− indent_config: Some(IndentationConfiguration {
114− tab_width: 4,
115− indent_unit: String::from(" "),
116− }),
117− },
118− LanguageConfiguration {
119− scope: "source.toml".to_string(),
120− file_types: vec!["toml".to_string()],
121− language_id: Lang::Toml,
122− highlight_config: OnceCell::new(),
123− //
124− path: "../helix-syntax/languages/tree-sitter-toml".into(),
125− roots: vec![],
126− language_server_config: None,
127− indent_config: Some(IndentationConfiguration {
128− tab_width: 2,
129− indent_unit: String::from(" "),
130− }),
131− },
132− ];
133−
134− for config in configs {
116+ for config in config.language {
135117 // get the next id
136118 let language_id = loader.language_configs.len();
137119