Skip to content

Commit dd0b15e

Browse files
committed
syntax: Properly handle injection-regex for language injections
1 parent ef532e0 commit dd0b15e

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

helix-core/src/syntax.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ use std::{
2121
use once_cell::sync::{Lazy, OnceCell};
2222
use serde::{Deserialize, Serialize};
2323

24+
fn deserialize_regex<'de, D>(deserializer: D) -> Result<Option<Regex>, D::Error>
25+
where
26+
D: serde::Deserializer<'de>,
27+
{
28+
Option::<String>::deserialize(deserializer)?
29+
.map(|buf| Regex::new(&buf).map_err(serde::de::Error::custom))
30+
.transpose()
31+
}
32+
2433
#[derive(Debug, Serialize, Deserialize)]
2534
pub struct Configuration {
2635
pub language: Vec<LanguageConfiguration>,
@@ -42,7 +51,8 @@ pub struct LanguageConfiguration {
4251
pub auto_format: bool,
4352

4453
// content_regex
45-
// injection_regex
54+
#[serde(default, skip_serializing, deserialize_with = "deserialize_regex")]
55+
injection_regex: Option<Regex>,
4656
// first_line_regex
4757
//
4858
#[serde(skip)]
@@ -243,6 +253,30 @@ impl Loader {
243253
.cloned()
244254
}
245255

256+
pub fn language_configuration_for_injection_string(
257+
&self,
258+
string: &str,
259+
) -> Option<Arc<LanguageConfiguration>> {
260+
let mut best_match_length = 0;
261+
let mut best_match_position = None;
262+
for (i, configuration) in self.language_configs.iter().enumerate() {
263+
if let Some(injection_regex) = &configuration.injection_regex {
264+
if let Some(mat) = injection_regex.find(string) {
265+
let length = mat.end() - mat.start();
266+
if length > best_match_length {
267+
best_match_position = Some(i);
268+
best_match_length = length;
269+
}
270+
}
271+
}
272+
}
273+
274+
if let Some(i) = best_match_position {
275+
let configuration = &self.language_configs[i];
276+
return Some(configuration.clone());
277+
}
278+
None
279+
}
246280
pub fn language_configs_iter(&self) -> impl Iterator<Item = &Arc<LanguageConfiguration>> {
247281
self.language_configs.iter()
248282
}

helix-term/src/ui/editor.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ impl EditorView {
147147
let scopes = theme.scopes();
148148
syntax
149149
.highlight_iter(text.slice(..), Some(range), None, |language| {
150-
loader
151-
.language_config_for_scope(&format!("source.{}", language))
150+
loader.language_configuration_for_injection_string(language)
152151
.and_then(|language_config| {
153152
let config = language_config.highlight_config(scopes)?;
154153
let config_ref = config.as_ref();

helix-term/src/ui/markdown.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn parse<'a>(
8888
if let Some(theme) = theme {
8989
let rope = Rope::from(text.as_ref());
9090
let syntax = loader
91-
.language_config_for_scope(&format!("source.{}", language))
91+
.language_configuration_for_injection_string(language)
9292
.and_then(|config| config.highlight_config(theme.scopes()))
9393
.map(|config| Syntax::new(&rope, config));
9494

0 commit comments

Comments
 (0)