diff options
author | Blaž Hrastnik | 2021-09-16 06:47:51 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2021-09-16 06:50:14 +0000 |
commit | dd0b15e1f1540d6ca8c58594be302c66005d755c (patch) | |
tree | 102ea032e8b35b93d73a43c8f36af6fc203bafea | |
parent | ef532e0c0df3e9f8bf4ac5af74b54f32b7ea2728 (diff) |
syntax: Properly handle injection-regex for language injections
-rw-r--r-- | helix-core/src/syntax.rs | 36 | ||||
-rw-r--r-- | helix-term/src/ui/editor.rs | 3 | ||||
-rw-r--r-- | helix-term/src/ui/markdown.rs | 2 |
3 files changed, 37 insertions, 4 deletions
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index 93da869b..8bbf363f 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -21,6 +21,15 @@ use std::{ use once_cell::sync::{Lazy, OnceCell}; use serde::{Deserialize, Serialize}; +fn deserialize_regex<'de, D>(deserializer: D) -> Result<Option<Regex>, D::Error> +where + D: serde::Deserializer<'de>, +{ + Option::<String>::deserialize(deserializer)? + .map(|buf| Regex::new(&buf).map_err(serde::de::Error::custom)) + .transpose() +} + #[derive(Debug, Serialize, Deserialize)] pub struct Configuration { pub language: Vec<LanguageConfiguration>, @@ -42,7 +51,8 @@ pub struct LanguageConfiguration { pub auto_format: bool, // content_regex - // injection_regex + #[serde(default, skip_serializing, deserialize_with = "deserialize_regex")] + injection_regex: Option<Regex>, // first_line_regex // #[serde(skip)] @@ -243,6 +253,30 @@ impl Loader { .cloned() } + pub fn language_configuration_for_injection_string( + &self, + string: &str, + ) -> Option<Arc<LanguageConfiguration>> { + let mut best_match_length = 0; + let mut best_match_position = None; + for (i, configuration) in self.language_configs.iter().enumerate() { + if let Some(injection_regex) = &configuration.injection_regex { + if let Some(mat) = injection_regex.find(string) { + let length = mat.end() - mat.start(); + if length > best_match_length { + best_match_position = Some(i); + best_match_length = length; + } + } + } + } + + if let Some(i) = best_match_position { + let configuration = &self.language_configs[i]; + return Some(configuration.clone()); + } + None + } pub fn language_configs_iter(&self) -> impl Iterator<Item = &Arc<LanguageConfiguration>> { self.language_configs.iter() } diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 52cf3d2b..0605e2c7 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -147,8 +147,7 @@ impl EditorView { let scopes = theme.scopes(); syntax .highlight_iter(text.slice(..), Some(range), None, |language| { - loader - .language_config_for_scope(&format!("source.{}", language)) + loader.language_configuration_for_injection_string(language) .and_then(|language_config| { let config = language_config.highlight_config(scopes)?; let config_ref = config.as_ref(); diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs index 87b35a2d..4144ed3c 100644 --- a/helix-term/src/ui/markdown.rs +++ b/helix-term/src/ui/markdown.rs @@ -88,7 +88,7 @@ fn parse<'a>( if let Some(theme) = theme { let rope = Rope::from(text.as_ref()); let syntax = loader - .language_config_for_scope(&format!("source.{}", language)) + .language_configuration_for_injection_string(language) .and_then(|config| config.highlight_config(theme.scopes())) .map(|config| Syntax::new(&rope, config)); |