From 191d35065000f39a39ef6aeaf6b28c4feb716154 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Sat, 31 Aug 2019 17:00:23 +0200 Subject: [PATCH] Add matching mechanism --- src/engine.rs | 2 +- src/main.rs | 5 ++++- src/matcher/mod.rs | 6 +++--- src/matcher/scrolling.rs | 45 +++++++++++++++++++++++++++++++++------- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 59a04d6..41dc997 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -12,7 +12,7 @@ impl <'a> Engine<'a> { } impl <'a> MatchReceiver for Engine<'a>{ - fn on_match(&self, m: Match) { + fn on_match(&self, m: &Match) { self.sender.delete_string(m.trigger.len() as i32); self.sender.send_string(m.result.as_str()); } diff --git a/src/main.rs b/src/main.rs index 3b68f05..232bf5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::sync::mpsc; use crate::keyboard::KeyboardInterceptor; use crate::matcher::Matcher; +use crate::matcher::Match; use crate::matcher::scrolling::ScrollingMatcher; use crate::engine::Engine; @@ -21,6 +22,8 @@ fn main() { let engine = Engine::new(&sender); - let matcher = ScrollingMatcher::new(&engine); + let matches = vec![Match{trigger:"e'".to_owned(), result: "รจ".to_owned()}, Match{trigger:":lol".to_owned(), result: "๐Ÿ˜‚".to_owned()}]; + + let mut matcher = ScrollingMatcher::new(&matches, &engine); matcher.watch(&rxc); } \ No newline at end of file diff --git a/src/matcher/mod.rs b/src/matcher/mod.rs index 07f9f47..7a4c160 100644 --- a/src/matcher/mod.rs +++ b/src/matcher/mod.rs @@ -8,12 +8,12 @@ pub struct Match { } pub trait MatchReceiver { - fn on_match(&self, m: Match); + fn on_match(&self, m: &Match); } pub trait Matcher { - fn handle_char(&self, c: char); - fn watch(&self, receiver: &Receiver) { + fn handle_char(&mut self, c: char); + fn watch(&mut self, receiver: &Receiver) { loop { match receiver.recv() { Ok(c) => { diff --git a/src/matcher/scrolling.rs b/src/matcher/scrolling.rs index 14023dd..9c3eed8 100644 --- a/src/matcher/scrolling.rs +++ b/src/matcher/scrolling.rs @@ -1,21 +1,52 @@ use crate::matcher::{Match, MatchReceiver}; pub struct ScrollingMatcher<'a>{ - receiver: &'a MatchReceiver + matches: &'a Vec, + receiver: &'a MatchReceiver, + current_set: Vec> +} + +struct MatchEntry<'a> { + remaining: &'a str, + _match: &'a Match } impl <'a> super::Matcher for ScrollingMatcher<'a> { - fn handle_char(&self, c: char) { - println!("Scroll {}",c); + fn handle_char(&mut self, c: char) { + let mut new_matches: Vec = self.matches.iter() + .filter(|&x| x.trigger.chars().nth(0).unwrap() == c) + .map(|x | MatchEntry{remaining: &x.trigger[1..], _match: &x}) + .collect(); + // TODO: use an associative structure to improve the efficiency of this first "new_matches" lookup. - if c == 'a' { - self.receiver.on_match(Match{trigger: "a".to_owned(), result: "ciao".to_owned()}); + let old_matches = self.current_set.iter() + .filter(|&x| x.remaining.chars().nth(0).unwrap() == c) + .map(|x | MatchEntry{remaining: &x.remaining[1..], _match: &x._match}) + .collect(); + + self.current_set = old_matches; + self.current_set.append(&mut new_matches); + + let mut found = false; + let mut foundMatch = None; + + for entry in self.current_set.iter_mut() { + if entry.remaining.len() == 0 { + foundMatch = Some(entry._match); + break; + } + } + + if let Some(_match) = foundMatch { + self.current_set.clear(); + self.receiver.on_match(_match); } } } impl <'a> ScrollingMatcher<'a> { - pub fn new(receiver: &'a MatchReceiver) -> ScrollingMatcher<'a> { - ScrollingMatcher{ receiver } + pub fn new(matches:&'a Vec, receiver: &'a MatchReceiver) -> ScrollingMatcher<'a> { + let current_set = Vec::new(); + ScrollingMatcher{ matches, receiver, current_set } } } \ No newline at end of file