aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlaž Hrastnik2021-09-16 06:47:51 +0000
committerBlaž Hrastnik2021-09-16 06:50:14 +0000
commitdd0b15e1f1540d6ca8c58594be302c66005d755c (patch)
tree102ea032e8b35b93d73a43c8f36af6fc203bafea
parentef532e0c0df3e9f8bf4ac5af74b54f32b7ea2728 (diff)
syntax: Properly handle injection-regex for language injections
-rw-r--r--helix-core/src/syntax.rs36
-rw-r--r--helix-term/src/ui/editor.rs3
-rw-r--r--helix-term/src/ui/markdown.rs2
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));