aboutsummaryrefslogtreecommitdiff
path: root/helix-core/src/syntax.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-core/src/syntax.rs')
-rw-r--r--helix-core/src/syntax.rs23
1 files changed, 22 insertions, 1 deletions
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index 18504c21..f136ecd0 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -40,18 +40,21 @@ where
}
#[derive(Debug, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
pub struct Configuration {
pub language: Vec<LanguageConfiguration>,
}
// largely based on tree-sitter/cli/src/loader.rs
#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
+#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct LanguageConfiguration {
#[serde(rename = "name")]
pub language_id: String,
pub scope: String, // source.rust
pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
+ #[serde(default)]
+ pub shebangs: Vec<String>, // interpreter(s) associated with language
pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
pub comment_token: Option<String>,
@@ -309,6 +312,7 @@ pub struct Loader {
// highlight_names ?
language_configs: Vec<Arc<LanguageConfiguration>>,
language_config_ids_by_file_type: HashMap<String, usize>, // Vec<usize>
+ language_config_ids_by_shebang: HashMap<String, usize>,
}
impl Loader {
@@ -316,6 +320,7 @@ impl Loader {
let mut loader = Self {
language_configs: Vec::new(),
language_config_ids_by_file_type: HashMap::new(),
+ language_config_ids_by_shebang: HashMap::new(),
};
for config in config.language {
@@ -328,6 +333,11 @@ impl Loader {
.language_config_ids_by_file_type
.insert(file_type.clone(), language_id);
}
+ for shebang in &config.shebangs {
+ loader
+ .language_config_ids_by_shebang
+ .insert(shebang.clone(), language_id);
+ }
loader.language_configs.push(Arc::new(config));
}
@@ -353,6 +363,17 @@ impl Loader {
// TODO: content_regex handling conflict resolution
}
+ pub fn language_config_for_shebang(&self, source: &Rope) -> Option<Arc<LanguageConfiguration>> {
+ let line = Cow::from(source.line(0));
+ static SHEBANG_REGEX: Lazy<Regex> =
+ Lazy::new(|| Regex::new(r"^#!\s*(?:\S*[/\\](?:env\s+)?)?([^\s\.\d]+)").unwrap());
+ let configuration_id = SHEBANG_REGEX
+ .captures(&line)
+ .and_then(|cap| self.language_config_ids_by_shebang.get(&cap[1]));
+
+ configuration_id.and_then(|&id| self.language_configs.get(id).cloned())
+ }
+
pub fn language_config_for_scope(&self, scope: &str) -> Option<Arc<LanguageConfiguration>> {
self.language_configs
.iter()