diff --git a/src/matcher/mod.rs b/src/matcher/mod.rs index d511bd4..0f2f191 100644 --- a/src/matcher/mod.rs +++ b/src/matcher/mod.rs @@ -33,6 +33,7 @@ pub struct Match { pub content: MatchContentType, pub word: bool, pub passive_only: bool, + pub propagate_case: bool, // Automatically calculated from the triggers, used by the matcher to check for correspondences. #[serde(skip_serializing)] @@ -74,7 +75,7 @@ impl<'a> From<&'a AutoMatch> for Match{ static ref VAR_REGEX: Regex = Regex::new("\\{\\{\\s*(\\w+)\\s*\\}\\}").unwrap(); }; - let triggers = if !other.triggers.is_empty() { + let mut triggers = if !other.triggers.is_empty() { other.triggers.clone() }else if !other.trigger.is_empty() { vec!(other.trigger.clone()) @@ -82,6 +83,26 @@ impl<'a> From<&'a AutoMatch> for Match{ panic!("Match does not have any trigger defined: {:?}", other) }; + // If propagate_case is true, we need to generate all the possible triggers + // For example, specifying "hello" as a trigger, we need to have: + // "hello", "Hello", "HELLO" + if other.propagate_case { + // List with first letter capitalized + let first_capitalized : Vec = triggers.iter().map(|trigger| { + let mut capitalized = trigger.clone(); + let mut v: Vec = capitalized.chars().collect(); + v[0] = v[0].to_uppercase().nth(0).unwrap(); + v.into_iter().collect() + }).collect(); + + let all_capitalized : Vec = triggers.iter().map(|trigger| { + trigger.to_uppercase() + }).collect(); + + triggers.extend(first_capitalized); + triggers.extend(all_capitalized); + } + let trigger_sequences = triggers.iter().map(|trigger| { // Calculate the trigger sequence let mut trigger_sequence = Vec::new(); @@ -148,6 +169,7 @@ impl<'a> From<&'a AutoMatch> for Match{ word: other.word, passive_only: other.passive_only, _trigger_sequences: trigger_sequences, + propagate_case: other.propagate_case, } } } @@ -175,6 +197,9 @@ struct AutoMatch { #[serde(default = "default_passive_only")] pub passive_only: bool, + + #[serde(default = "default_propagate_case")] + pub propagate_case: bool, } fn default_trigger() -> String {"".to_owned()} @@ -184,6 +209,7 @@ fn default_word() -> bool {false} fn default_passive_only() -> bool {false} fn default_replace() -> Option {None} fn default_image_path() -> Option {None} +fn default_propagate_case() -> bool {false} #[derive(Debug, Serialize, Deserialize, Clone)] pub struct MatchVariable { @@ -377,4 +403,60 @@ mod tests { assert_eq!(_match.triggers, vec![":test1", ":test2"]) } + + #[test] + fn test_match_propagate_case() { + let match_str = r###" + trigger: "hello" + replace: "This is a test" + propagate_case: true + "###; + + let _match : Match = serde_yaml::from_str(match_str).unwrap(); + + assert_eq!(_match.triggers, vec!["hello", "Hello", "HELLO"]) + } + + #[test] + fn test_match_propagate_case_multi_trigger() { + let match_str = r###" + triggers: ["hello", "hi"] + replace: "This is a test" + propagate_case: true + "###; + + let _match : Match = serde_yaml::from_str(match_str).unwrap(); + + assert_eq!(_match.triggers, vec!["hello", "hi", "Hello", "Hi", "HELLO", "HI"]) + } + + #[test] + fn test_match_trigger_sequence_with_word_propagate_case() { + let match_str = r###" + trigger: "test" + replace: "This is a test" + word: true + propagate_case: true + "###; + + let _match : Match = serde_yaml::from_str(match_str).unwrap(); + + assert_eq!(_match._trigger_sequences[0][0], TriggerEntry::Char('t')); + assert_eq!(_match._trigger_sequences[0][1], TriggerEntry::Char('e')); + assert_eq!(_match._trigger_sequences[0][2], TriggerEntry::Char('s')); + assert_eq!(_match._trigger_sequences[0][3], TriggerEntry::Char('t')); + assert_eq!(_match._trigger_sequences[0][4], TriggerEntry::WordSeparator); + + assert_eq!(_match._trigger_sequences[1][0], TriggerEntry::Char('T')); + assert_eq!(_match._trigger_sequences[1][1], TriggerEntry::Char('e')); + assert_eq!(_match._trigger_sequences[1][2], TriggerEntry::Char('s')); + assert_eq!(_match._trigger_sequences[1][3], TriggerEntry::Char('t')); + assert_eq!(_match._trigger_sequences[1][4], TriggerEntry::WordSeparator); + + assert_eq!(_match._trigger_sequences[2][0], TriggerEntry::Char('T')); + assert_eq!(_match._trigger_sequences[2][1], TriggerEntry::Char('E')); + assert_eq!(_match._trigger_sequences[2][2], TriggerEntry::Char('S')); + assert_eq!(_match._trigger_sequences[2][3], TriggerEntry::Char('T')); + assert_eq!(_match._trigger_sequences[2][4], TriggerEntry::WordSeparator); + } } \ No newline at end of file