aboutsummaryrefslogtreecommitdiff
path: root/helix-loader
diff options
context:
space:
mode:
authorKirawi2022-04-18 03:10:51 +0000
committerGitHub2022-04-18 03:10:51 +0000
commitc2a40d9d5229c701fa1a6d0fb80ce4ba86e8dc0c (patch)
treeb27da29863432ca7ee48c582f5aeb538d7a39ea1 /helix-loader
parentbe656c14e32243fc32ed68f9a3240301f2902df7 (diff)
Add support for local language configuration (#1249)
* add local configuration * move config loading to Application::new * simplify find_root_impl
Diffstat (limited to 'helix-loader')
-rw-r--r--helix-loader/Cargo.toml2
-rw-r--r--helix-loader/src/config.rs26
-rw-r--r--helix-loader/src/grammar.rs2
-rw-r--r--helix-loader/src/lib.rs53
4 files changed, 66 insertions, 17 deletions
diff --git a/helix-loader/Cargo.toml b/helix-loader/Cargo.toml
index 21b37333..607d1a0a 100644
--- a/helix-loader/Cargo.toml
+++ b/helix-loader/Cargo.toml
@@ -18,6 +18,8 @@ tree-sitter = "0.20"
libloading = "0.7"
once_cell = "1.9"
+log = "0.4"
+
# cloning/compiling tree-sitter grammars
cc = { version = "1" }
threadpool = { version = "1.0" }
diff --git a/helix-loader/src/config.rs b/helix-loader/src/config.rs
new file mode 100644
index 00000000..3d71baed
--- /dev/null
+++ b/helix-loader/src/config.rs
@@ -0,0 +1,26 @@
+/// Default bultin-in languages.toml.
+pub fn default_lang_config() -> toml::Value {
+ toml::from_slice(include_bytes!("../../languages.toml"))
+ .expect("Could not parse bultin-in languages.toml to valid toml")
+}
+
+/// User configured languages.toml file, merged with the default config.
+pub fn user_lang_config() -> Result<toml::Value, toml::de::Error> {
+ let config = crate::local_config_dirs()
+ .into_iter()
+ .chain([crate::config_dir()].into_iter())
+ .map(|path| path.join("languages.toml"))
+ .filter_map(|file| {
+ std::fs::read(&file)
+ .map(|config| toml::from_slice(&config))
+ .ok()
+ })
+ .collect::<Result<Vec<_>, _>>()?
+ .into_iter()
+ .chain([default_lang_config()].into_iter())
+ .fold(toml::Value::Table(toml::value::Table::default()), |a, b| {
+ crate::merge_toml_values(b, a)
+ });
+
+ Ok(config)
+}
diff --git a/helix-loader/src/grammar.rs b/helix-loader/src/grammar.rs
index 7474713a..9d63a2be 100644
--- a/helix-loader/src/grammar.rs
+++ b/helix-loader/src/grammar.rs
@@ -92,7 +92,7 @@ pub fn build_grammars() -> Result<()> {
// merged. The `grammar_selection` key of the config is then used to filter
// down all grammars into a subset of the user's choosing.
fn get_grammar_configs() -> Result<Vec<GrammarConfiguration>> {
- let config: Configuration = crate::user_lang_config()
+ let config: Configuration = crate::config::user_lang_config()
.context("Could not parse languages.toml")?
.try_into()?;
diff --git a/helix-loader/src/lib.rs b/helix-loader/src/lib.rs
index a2c4d96f..de2951f8 100644
--- a/helix-loader/src/lib.rs
+++ b/helix-loader/src/lib.rs
@@ -1,3 +1,4 @@
+pub mod config;
pub mod grammar;
use etcetera::base_strategy::{choose_base_strategy, BaseStrategy};
@@ -36,6 +37,15 @@ pub fn config_dir() -> std::path::PathBuf {
path
}
+pub fn local_config_dirs() -> Vec<std::path::PathBuf> {
+ let directories = find_root_impl(None, &[".helix".to_string()])
+ .into_iter()
+ .map(|path| path.join(".helix"))
+ .collect();
+ log::debug!("Located configuration folders: {:?}", directories);
+ directories
+}
+
pub fn cache_dir() -> std::path::PathBuf {
// TODO: allow env var override
let strategy = choose_base_strategy().expect("Unable to find the config directory!");
@@ -56,25 +66,36 @@ pub fn log_file() -> std::path::PathBuf {
cache_dir().join("helix.log")
}
-/// Default bultin-in languages.toml.
-pub fn default_lang_config() -> toml::Value {
- toml::from_slice(include_bytes!("../../languages.toml"))
- .expect("Could not parse bultin-in languages.toml to valid toml")
-}
-
-/// User configured languages.toml file, merged with the default config.
-pub fn user_lang_config() -> Result<toml::Value, toml::de::Error> {
- let def_lang_conf = default_lang_config();
- let data = std::fs::read(crate::config_dir().join("languages.toml"));
- let user_lang_conf = match data {
- Ok(raw) => {
- let value = toml::from_slice(&raw)?;
- merge_toml_values(def_lang_conf, value)
+pub fn find_root_impl(root: Option<&str>, root_markers: &[String]) -> Vec<std::path::PathBuf> {
+ let current_dir = std::env::current_dir().expect("unable to determine current directory");
+ let mut directories = Vec::new();
+
+ let root = match root {
+ Some(root) => {
+ let root = std::path::Path::new(root);
+ if root.is_absolute() {
+ root.to_path_buf()
+ } else {
+ current_dir.join(root)
+ }
}
- Err(_) => def_lang_conf,
+ None => current_dir,
};
- Ok(user_lang_conf)
+ for ancestor in root.ancestors() {
+ // don't go higher than repo
+ if ancestor.join(".git").is_dir() {
+ // Use workspace if detected from marker
+ directories.push(ancestor.to_path_buf());
+ break;
+ } else if root_markers
+ .iter()
+ .any(|marker| ancestor.join(marker).exists())
+ {
+ directories.push(ancestor.to_path_buf());
+ }
+ }
+ directories
}
// right overrides left