Unnamed repository; edit this file 'description' to name the repository.
Add the machinery to load syntax config from TOML.
It's embedded into the binary at build time for now, but it's progress.
Blaž Hrastnik 2021-03-25
parent a900159 · commit e3c4eda
-rw-r--r--Cargo.lock12
-rw-r--r--helix-core/Cargo.toml2
-rw-r--r--helix-core/src/syntax.rs68
-rw-r--r--helix-lsp/src/lib.rs2
-rw-r--r--helix-syntax/Cargo.toml1
-rw-r--r--helix-syntax/languages.toml5
-rw-r--r--helix-syntax/src/lib.rs4
-rw-r--r--helix-term/Cargo.toml3
-rw-r--r--helix-term/src/main.rs8
-rw-r--r--helix-term/src/ui/markdown.rs2
-rw-r--r--helix-view/src/document.rs14
-rw-r--r--languages.toml20
12 files changed, 86 insertions, 55 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4d4d4554..40c2aa13 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -489,6 +489,7 @@ dependencies = [
"once_cell",
"regex",
"ropey",
+ "serde",
"smallvec",
"tendril",
"tree-sitter",
@@ -523,6 +524,7 @@ name = "helix-syntax"
version = "0.1.0"
dependencies = [
"cc",
+ "serde",
"threadpool",
"tree-sitter",
]
@@ -549,6 +551,7 @@ dependencies = [
"pulldown-cmark",
"smol",
"smol-timeout",
+ "toml",
"tui",
]
@@ -1208,6 +1211,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
+name = "toml"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "tree-sitter"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml
index 49641ad6..d95c0f47 100644
--- a/helix-core/Cargo.toml
+++ b/helix-core/Cargo.toml
@@ -19,3 +19,5 @@ unicode-width = "0.1"
tree-sitter = "0.17"
once_cell = "1.4"
regex = "1"
+
+serde = { version = "1.0", features = ["derive"] }
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index 3640e0cf..8a8d649a 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -10,9 +10,19 @@ use std::{
};
use once_cell::sync::{Lazy, OnceCell};
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize)]
+pub struct Configuration {
+ language: Vec<LanguageConfiguration>,
+}
// largely based on tree-sitter/cli/src/loader.rs
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case")]
pub struct LanguageConfiguration {
+ #[serde(rename = "name")]
+ pub(crate) language_id: Lang,
pub scope: String, // source.rust
pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
@@ -24,22 +34,29 @@ pub struct LanguageConfiguration {
// injection_regex
// first_line_regex
//
- //
- pub(crate) language_id: Lang,
+ #[serde(skip)]
pub(crate) highlight_config: OnceCell<Option<Arc<HighlightConfiguration>>>,
// tags_config OnceCell<> https://github.com/tree-sitter/tree-sitter/pull/583
- pub language_server_config: Option<LanguageServerConfiguration>,
- pub indent_config: Option<IndentationConfiguration>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub language_server: Option<LanguageServerConfiguration>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub indent: Option<IndentationConfiguration>,
}
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case")]
pub struct LanguageServerConfiguration {
pub command: String,
+ #[serde(default)]
+ #[serde(skip_serializing_if = "Vec::is_empty")]
pub args: Vec<String>,
}
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case")]
pub struct IndentationConfiguration {
pub tab_width: usize,
- pub indent_unit: String,
+ pub unit: String,
}
impl LanguageConfiguration {
@@ -81,7 +98,7 @@ impl LanguageConfiguration {
}
}
-pub static LOADER: Lazy<Loader> = Lazy::new(Loader::init);
+pub static LOADER: OnceCell<Loader> = OnceCell::new();
pub struct Loader {
// highlight_names ?
@@ -90,48 +107,13 @@ pub struct Loader {
}
impl Loader {
- fn init() -> Self {
+ pub fn new(config: Configuration) -> Self {
let mut loader = Self {
language_configs: Vec::new(),
language_config_ids_by_file_type: HashMap::new(),
};
- // hardcoded from now, might load from toml
- let configs = vec![
- LanguageConfiguration {
- scope: "source.rust".to_string(),
- file_types: vec!["rs".to_string()],
- language_id: Lang::Rust,
- highlight_config: OnceCell::new(),
- //
- path: "../helix-syntax/languages/tree-sitter-rust".into(),
- roots: vec![],
- language_server_config: Some(LanguageServerConfiguration {
- command: "rust-analyzer".to_string(),
- args: vec![],
- }),
- indent_config: Some(IndentationConfiguration {
- tab_width: 4,
- indent_unit: String::from(" "),
- }),
- },
- LanguageConfiguration {
- scope: "source.toml".to_string(),
- file_types: vec!["toml".to_string()],
- language_id: Lang::Toml,
- highlight_config: OnceCell::new(),
- //
- path: "../helix-syntax/languages/tree-sitter-toml".into(),
- roots: vec![],
- language_server_config: None,
- indent_config: Some(IndentationConfiguration {
- tab_width: 2,
- indent_unit: String::from(" "),
- }),
- },
- ];
-
- for config in configs {
+ for config in config.language {
// get the next id
let language_id = loader.language_configs.len();
diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs
index 64aa38f1..e7fe816a 100644
--- a/helix-lsp/src/lib.rs
+++ b/helix-lsp/src/lib.rs
@@ -127,7 +127,7 @@ impl Registry {
ex: &smol::Executor,
) -> Option<Arc<Client>> {
// TODO: propagate the error
- if let Some(config) = &language_config.language_server_config {
+ if let Some(config) = &language_config.language_server {
// avoid borrow issues
let inner = &mut self.inner;
let s_incoming = &self.incoming;
diff --git a/helix-syntax/Cargo.toml b/helix-syntax/Cargo.toml
index c50e3091..f145b6c0 100644
--- a/helix-syntax/Cargo.toml
+++ b/helix-syntax/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2018"
[dependencies]
tree-sitter = "0.17"
+serde = { version = "1.0", features = ["derive"] }
[build-dependencies]
cc = { version = "1", features = ["parallel"] }
diff --git a/helix-syntax/languages.toml b/helix-syntax/languages.toml
deleted file mode 100644
index dc4fcf6f..00000000
--- a/helix-syntax/languages.toml
+++ /dev/null
@@ -1,5 +0,0 @@
-[[language]]
-name = "rust"
-scope = "source.rust"
-injection-regex = "rust"
-file-types = ["rs"]
diff --git a/helix-syntax/src/lib.rs b/helix-syntax/src/lib.rs
index 64fe1023..5d3e0d99 100644
--- a/helix-syntax/src/lib.rs
+++ b/helix-syntax/src/lib.rs
@@ -1,3 +1,4 @@
+use serde::{Deserialize, Serialize};
use tree_sitter::Language;
#[macro_export]
@@ -12,7 +13,8 @@ macro_rules! mk_extern {
#[macro_export]
macro_rules! mk_enum {
( $( $camel:ident ),* ) => {
- #[derive(Clone, Copy, Debug, PartialEq)]
+ #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
+ #[serde(rename_all = "lowercase")]
pub enum Lang {
$(
$camel,
diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml
index eaf8ebd7..2f3aa384 100644
--- a/helix-term/Cargo.toml
+++ b/helix-term/Cargo.toml
@@ -41,3 +41,6 @@ ignore = "0.4"
dirs-next = "2.0"
# markdown doc rendering
pulldown-cmark = { version = "0.8", default-features = false }
+
+# config
+toml = "0.5"
diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs
index 84b52ea2..dc6f31f4 100644
--- a/helix-term/src/main.rs
+++ b/helix-term/src/main.rs
@@ -73,6 +73,14 @@ fn main() {
setup_logging(verbosity).expect("failed to initialize logging.");
+ // initialize language registry
+ use helix_core::syntax::{Loader, LOADER};
+ let toml = include_str!("../../languages.toml");
+ LOADER.get_or_init(|| {
+ let config = toml::from_str(&toml).expect("Could not parse languages.toml");
+ Loader::new(config)
+ });
+
for _ in 0..num_cpus::get() {
std::thread::spawn(move || smol::block_on(EX.run(smol::future::pending::<()>())));
}
diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs
index c4f6039b..55b90ad4 100644
--- a/helix-term/src/ui/markdown.rs
+++ b/helix-term/src/ui/markdown.rs
@@ -80,6 +80,8 @@ fn parse<'a>(contents: &'a str, theme: Option<&Theme>) -> tui::text::Text<'a> {
let rope = Rope::from(text.as_ref());
let syntax = syntax::LOADER
+ .get()
+ .unwrap()
.language_config_for_scope(&format!("source.{}", language))
.and_then(|config| config.highlight_config(theme.scopes()))
.map(|config| Syntax::new(&rope, config));
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index 0286b2b9..0ab8abbb 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -97,7 +97,10 @@ impl Document {
let mut doc = Self::new(doc);
- let language_config = LOADER.language_config_for_file_name(path.as_path());
+ let language_config = LOADER
+ .get()
+ .unwrap()
+ .language_config_for_file_name(path.as_path());
doc.set_language(language_config, scopes);
// canonicalize path to absolute value
@@ -161,7 +164,8 @@ impl Document {
}
pub fn set_language2(&mut self, scope: &str, scopes: &[String]) {
- let language_config = LOADER.language_config_for_scope(scope);
+ let language_config = LOADER.get().unwrap().language_config_for_scope(scope);
+
self.set_language(language_config, scopes);
}
@@ -304,7 +308,7 @@ impl Document {
pub fn tab_width(&self) -> usize {
self.language
.as_ref()
- .and_then(|config| config.indent_config.as_ref())
+ .and_then(|config| config.indent.as_ref())
.map(|config| config.tab_width)
.unwrap_or(4) // fallback to 4 columns
}
@@ -313,8 +317,8 @@ impl Document {
pub fn indent_unit(&self) -> &str {
self.language
.as_ref()
- .and_then(|config| config.indent_config.as_ref())
- .map(|config| config.indent_unit.as_str())
+ .and_then(|config| config.indent.as_ref())
+ .map(|config| config.unit.as_str())
.unwrap_or(" ") // fallback to 2 spaces
// " ".repeat(TAB_WIDTH)
diff --git a/languages.toml b/languages.toml
new file mode 100644
index 00000000..eca55a13
--- /dev/null
+++ b/languages.toml
@@ -0,0 +1,20 @@
+[[language]]
+name = "rust"
+scope = "source.rust"
+injection-regex = "rust"
+file-types = ["rs"]
+roots = []
+path = "../helix-syntax/languages/tree-sitter-rust"
+
+language-server = { command = "rust-analyzer" }
+indent = { tab-width = 4, unit = " " }
+
+[[language]]
+name = "toml"
+scope = "source.toml"
+injection-regex = "toml"
+file-types = ["toml"]
+roots = []
+path = "../helix-syntax/languages/tree-sitter-toml"
+
+indent = { tab-width = 2, unit = " " }