syntax: Properly handle injection-regex for language injections

pull/733/head
Blaž Hrastnik 3 years ago
parent ef532e0c0d
commit dd0b15e1f1

@ -21,6 +21,15 @@ use std::{
use once_cell::sync::{Lazy, OnceCell}; use once_cell::sync::{Lazy, OnceCell};
use serde::{Deserialize, Serialize}; 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)] #[derive(Debug, Serialize, Deserialize)]
pub struct Configuration { pub struct Configuration {
pub language: Vec<LanguageConfiguration>, pub language: Vec<LanguageConfiguration>,
@ -42,7 +51,8 @@ pub struct LanguageConfiguration {
pub auto_format: bool, pub auto_format: bool,
// content_regex // content_regex
// injection_regex #[serde(default, skip_serializing, deserialize_with = "deserialize_regex")]
injection_regex: Option<Regex>,
// first_line_regex // first_line_regex
// //
#[serde(skip)] #[serde(skip)]
@ -243,6 +253,30 @@ impl Loader {
.cloned() .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>> { pub fn language_configs_iter(&self) -> impl Iterator<Item = &Arc<LanguageConfiguration>> {
self.language_configs.iter() self.language_configs.iter()
} }

@ -147,8 +147,7 @@ impl EditorView {
let scopes = theme.scopes(); let scopes = theme.scopes();
syntax syntax
.highlight_iter(text.slice(..), Some(range), None, |language| { .highlight_iter(text.slice(..), Some(range), None, |language| {
loader loader.language_configuration_for_injection_string(language)
.language_config_for_scope(&format!("source.{}", language))
.and_then(|language_config| { .and_then(|language_config| {
let config = language_config.highlight_config(scopes)?; let config = language_config.highlight_config(scopes)?;
let config_ref = config.as_ref(); let config_ref = config.as_ref();

@ -88,7 +88,7 @@ fn parse<'a>(
if let Some(theme) = theme { if let Some(theme) = theme {
let rope = Rope::from(text.as_ref()); let rope = Rope::from(text.as_ref());
let syntax = loader let syntax = loader
.language_config_for_scope(&format!("source.{}", language)) .language_configuration_for_injection_string(language)
.and_then(|config| config.highlight_config(theme.scopes())) .and_then(|config| config.highlight_config(theme.scopes()))
.map(|config| Syntax::new(&rope, config)); .map(|config| Syntax::new(&rope, config));

Loading…
Cancel
Save