feat(config): refactor YAML match parsing to account for new form syntax #856
This commit is contained in:
parent
7244d34c7c
commit
34ba1e39e4
|
@ -102,7 +102,7 @@ fn split_config(config: LegacyConfig) -> (LegacyInteropConfig, LegacyMatchGroup)
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|var| {
|
.filter_map(|var| {
|
||||||
let m: YAMLMatch = serde_yaml::from_value(var.clone()).ok()?;
|
let m: YAMLMatch = serde_yaml::from_value(var.clone()).ok()?;
|
||||||
let (m, warnings) = try_convert_into_match(m).ok()?;
|
let (m, warnings) = try_convert_into_match(m, true).ok()?;
|
||||||
warnings.into_iter().for_each(|warning| {
|
warnings.into_iter().for_each(|warning| {
|
||||||
warn!("{}", warning);
|
warn!("{}", warning);
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,6 +43,8 @@ mod util;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref VAR_REGEX: Regex = Regex::new("\\{\\{\\s*(\\w+)(\\.\\w+)?\\s*\\}\\}").unwrap();
|
static ref VAR_REGEX: Regex = Regex::new("\\{\\{\\s*(\\w+)(\\.\\w+)?\\s*\\}\\}").unwrap();
|
||||||
|
static ref FORM_CONTROL_REGEX: Regex =
|
||||||
|
Regex::new("\\[\\[\\s*(\\w+)(\\.\\w+)?\\s*\\]\\]").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an alias to make the meaning more explicit
|
// Create an alias to make the meaning more explicit
|
||||||
|
@ -85,7 +87,7 @@ impl Importer for YAMLImporter {
|
||||||
|
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
for yaml_match in yaml_group.matches.as_ref().cloned().unwrap_or_default() {
|
for yaml_match in yaml_group.matches.as_ref().cloned().unwrap_or_default() {
|
||||||
match try_convert_into_match(yaml_match) {
|
match try_convert_into_match(yaml_match, false) {
|
||||||
Ok((m, warnings)) => {
|
Ok((m, warnings)) => {
|
||||||
matches.push(m);
|
matches.push(m);
|
||||||
non_fatal_errors.extend(warnings.into_iter().map(ErrorRecord::warn));
|
non_fatal_errors.extend(warnings.into_iter().map(ErrorRecord::warn));
|
||||||
|
@ -119,7 +121,10 @@ impl Importer for YAMLImporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_convert_into_match(yaml_match: YAMLMatch) -> Result<(Match, Vec<Warning>)> {
|
pub fn try_convert_into_match(
|
||||||
|
yaml_match: YAMLMatch,
|
||||||
|
use_compatibility_mode: bool,
|
||||||
|
) -> Result<(Match, Vec<Warning>)> {
|
||||||
let mut warnings = Vec::new();
|
let mut warnings = Vec::new();
|
||||||
|
|
||||||
if yaml_match.uppercase_style.is_some() && yaml_match.propagate_case.is_none() {
|
if yaml_match.uppercase_style.is_some() && yaml_match.propagate_case.is_none() {
|
||||||
|
@ -216,21 +221,45 @@ pub fn try_convert_into_match(yaml_match: YAMLMatch) -> Result<(Match, Vec<Warni
|
||||||
force_mode,
|
force_mode,
|
||||||
})
|
})
|
||||||
} else if let Some(form_layout) = yaml_match.form {
|
} else if let Some(form_layout) = yaml_match.form {
|
||||||
// TODO: test form case
|
|
||||||
// Replace all the form fields with actual variables
|
// Replace all the form fields with actual variables
|
||||||
let resolved_layout = VAR_REGEX
|
|
||||||
.replace_all(&form_layout, |caps: &Captures| {
|
// In v2.1.0-alpha the form control syntax was replaced with [[control]]
|
||||||
let var_name = caps.get(1).unwrap().as_str();
|
// instead of {{control}}, so we check if compatibility mode is being used.
|
||||||
format!("{{{{form1.{}}}}}", var_name)
|
// TODO: remove once compatibility mode is removed
|
||||||
})
|
|
||||||
.to_string();
|
let (resolved_replace, resolved_layout) = if use_compatibility_mode {
|
||||||
|
(
|
||||||
|
VAR_REGEX
|
||||||
|
.replace_all(&form_layout, |caps: &Captures| {
|
||||||
|
let var_name = caps.get(1).unwrap().as_str();
|
||||||
|
format!("{{{{form1.{}}}}}", var_name)
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
VAR_REGEX
|
||||||
|
.replace_all(&form_layout, |caps: &Captures| {
|
||||||
|
let var_name = caps.get(1).unwrap().as_str();
|
||||||
|
format!("[[{}]]", var_name)
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
FORM_CONTROL_REGEX
|
||||||
|
.replace_all(&form_layout, |caps: &Captures| {
|
||||||
|
let var_name = caps.get(1).unwrap().as_str();
|
||||||
|
format!("{{{{form1.{}}}}}", var_name)
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
form_layout,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
// Convert escaped brakets in forms
|
// Convert escaped brakets in forms
|
||||||
let resolved_layout = resolved_layout.replace("\\{", "{ ").replace("\\}", " }");
|
let resolved_replace = resolved_replace.replace("\\{", "{ ").replace("\\}", " }");
|
||||||
|
|
||||||
// Convert the form data to valid variables
|
// Convert the form data to valid variables
|
||||||
let mut params = Params::new();
|
let mut params = Params::new();
|
||||||
params.insert("layout".to_string(), Value::String(form_layout));
|
params.insert("layout".to_string(), Value::String(resolved_layout));
|
||||||
|
|
||||||
if let Some(fields) = yaml_match.form_fields {
|
if let Some(fields) = yaml_match.form_fields {
|
||||||
params.insert("fields".to_string(), Value::Object(convert_params(fields)?));
|
params.insert("fields".to_string(), Value::Object(convert_params(fields)?));
|
||||||
|
@ -244,7 +273,7 @@ pub fn try_convert_into_match(yaml_match: YAMLMatch) -> Result<(Match, Vec<Warni
|
||||||
}];
|
}];
|
||||||
|
|
||||||
MatchEffect::Text(TextEffect {
|
MatchEffect::Text(TextEffect {
|
||||||
replace: resolved_layout,
|
replace: resolved_replace,
|
||||||
vars,
|
vars,
|
||||||
format: TextFormat::Plain,
|
format: TextFormat::Plain,
|
||||||
force_mode,
|
force_mode,
|
||||||
|
@ -295,9 +324,12 @@ mod tests {
|
||||||
};
|
};
|
||||||
use std::fs::create_dir_all;
|
use std::fs::create_dir_all;
|
||||||
|
|
||||||
fn create_match_with_warnings(yaml: &str) -> Result<(Match, Vec<Warning>)> {
|
fn create_match_with_warnings(
|
||||||
|
yaml: &str,
|
||||||
|
use_compatibility_mode: bool,
|
||||||
|
) -> Result<(Match, Vec<Warning>)> {
|
||||||
let yaml_match: YAMLMatch = serde_yaml::from_str(yaml)?;
|
let yaml_match: YAMLMatch = serde_yaml::from_str(yaml)?;
|
||||||
let (mut m, warnings) = try_convert_into_match(yaml_match)?;
|
let (mut m, warnings) = try_convert_into_match(yaml_match, use_compatibility_mode)?;
|
||||||
|
|
||||||
// Reset the IDs to correctly compare them
|
// Reset the IDs to correctly compare them
|
||||||
m.id = 0;
|
m.id = 0;
|
||||||
|
@ -309,7 +341,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_match(yaml: &str) -> Result<Match> {
|
fn create_match(yaml: &str) -> Result<Match> {
|
||||||
let (m, warnings) = create_match_with_warnings(yaml)?;
|
let (m, warnings) = create_match_with_warnings(yaml, false)?;
|
||||||
if !warnings.is_empty() {
|
if !warnings.is_empty() {
|
||||||
panic!("warnings were detected but not handled: {:?}", warnings);
|
panic!("warnings were detected but not handled: {:?}", warnings);
|
||||||
}
|
}
|
||||||
|
@ -529,6 +561,7 @@ mod tests {
|
||||||
replace: "world"
|
replace: "world"
|
||||||
uppercase_style: "capitalize"
|
uppercase_style: "capitalize"
|
||||||
"#,
|
"#,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -545,6 +578,7 @@ mod tests {
|
||||||
uppercase_style: "invalid"
|
uppercase_style: "invalid"
|
||||||
propagate_case: true
|
propagate_case: true
|
||||||
"#,
|
"#,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -554,6 +588,116 @@ mod tests {
|
||||||
assert_eq!(warnings.len(), 1);
|
assert_eq!(warnings.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn form_maps_correctly() {
|
||||||
|
let mut params = Params::new();
|
||||||
|
params.insert(
|
||||||
|
"layout".to_string(),
|
||||||
|
Value::String("Hi [[name]]!".to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
form: "Hi [[name]]!"
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "Hi {{form1.name}}!".to_string(),
|
||||||
|
vars: vec![Variable {
|
||||||
|
id: 0,
|
||||||
|
name: "form1".to_string(),
|
||||||
|
var_type: "form".to_string(),
|
||||||
|
params
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn form_maps_correctly_with_variable_injection() {
|
||||||
|
let mut params = Params::new();
|
||||||
|
params.insert(
|
||||||
|
"layout".to_string(),
|
||||||
|
Value::String("Hi [[name]]! {{signature}}".to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
form: "Hi [[name]]! {{signature}}"
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "Hi {{form1.name}}! {{signature}}".to_string(),
|
||||||
|
vars: vec![Variable {
|
||||||
|
id: 0,
|
||||||
|
name: "form1".to_string(),
|
||||||
|
var_type: "form".to_string(),
|
||||||
|
params
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn form_maps_correctly_legacy_format() {
|
||||||
|
let mut params = Params::new();
|
||||||
|
params.insert(
|
||||||
|
"layout".to_string(),
|
||||||
|
Value::String("Hi [[name]]!".to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
create_match_with_warnings(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
form: "Hi {{name}}!"
|
||||||
|
"#,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.0,
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "Hi {{form1.name}}!".to_string(),
|
||||||
|
vars: vec![Variable {
|
||||||
|
id: 0,
|
||||||
|
name: "form1".to_string(),
|
||||||
|
var_type: "form".to_string(),
|
||||||
|
params
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vars_maps_correctly() {
|
fn vars_maps_correctly() {
|
||||||
let mut params = Params::new();
|
let mut params = Params::new();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user