espanso/src/matcher/scrolling.rs

114 lines
3.7 KiB
Rust
Raw Normal View History

use crate::matcher::{Match, MatchReceiver};
2019-09-05 15:20:52 +00:00
use std::cell::RefCell;
2019-09-05 17:18:55 +00:00
use crate::keyboard::KeyModifier;
2019-09-05 18:54:19 +00:00
use crate::config::Configs;
use crate::keyboard::KeyModifier::BACKSPACE;
use std::time::SystemTime;
2019-09-05 20:34:35 +00:00
use std::collections::VecDeque;
2019-09-05 15:20:52 +00:00
pub struct ScrollingMatcher<'a, R> where R: MatchReceiver{
2019-09-05 18:54:19 +00:00
configs: Configs,
2019-09-05 15:20:52 +00:00
receiver: R,
2019-09-05 20:34:35 +00:00
current_set_queue: RefCell<VecDeque<Vec<MatchEntry<'a>>>>,
2019-09-05 17:51:16 +00:00
toggle_press_time: RefCell<SystemTime>,
is_enabled: RefCell<bool>,
2019-08-31 15:00:23 +00:00
}
struct MatchEntry<'a> {
2019-09-05 18:54:19 +00:00
start: usize,
2019-08-31 15:00:23 +00:00
_match: &'a Match
}
2019-09-05 15:20:52 +00:00
impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiver+Send{
fn handle_char(&'a self, c: char) {
2019-09-05 17:51:16 +00:00
// if not enabled, avoid any processing
if !*(self.is_enabled.borrow()) {
return;
}
2019-09-05 20:34:35 +00:00
let mut current_set_queue = self.current_set_queue.borrow_mut();
2019-09-05 15:20:52 +00:00
2019-09-05 18:54:19 +00:00
let new_matches: Vec<MatchEntry> = self.configs.matches.iter()
2019-08-31 15:00:23 +00:00
.filter(|&x| x.trigger.chars().nth(0).unwrap() == c)
2019-09-05 18:54:19 +00:00
.map(|x | MatchEntry{start: 1, _match: &x})
2019-08-31 15:00:23 +00:00
.collect();
// TODO: use an associative structure to improve the efficiency of this first "new_matches" lookup.
2019-09-05 20:34:35 +00:00
let combined_matches: Vec<MatchEntry> = match current_set_queue.back() {
Some(last_matches) => {
let mut updated: Vec<MatchEntry> = last_matches.iter()
.filter(|&x| {
x._match.trigger[x.start..].chars().nth(0).unwrap() == c
})
.map(|x | MatchEntry{start: x.start+1, _match: &x._match})
.collect();
updated.extend(new_matches);
updated
},
None => {new_matches},
};
2019-08-31 15:00:23 +00:00
2019-09-01 18:46:46 +00:00
let mut found_match = None;
2019-08-31 15:00:23 +00:00
2019-09-05 20:34:35 +00:00
for entry in combined_matches.iter() {
2019-09-05 18:54:19 +00:00
if entry.start == entry._match.trigger.len() {
2019-09-01 18:46:46 +00:00
found_match = Some(entry._match);
2019-08-31 15:00:23 +00:00
break;
}
}
2019-09-05 20:34:35 +00:00
current_set_queue.push_back(combined_matches);
if current_set_queue.len() as i32 > (self.configs.backspace_limit + 1) {
current_set_queue.pop_front();
}
2019-09-01 18:46:46 +00:00
if let Some(_match) = found_match {
2019-09-05 20:34:35 +00:00
if let Some(last) = current_set_queue.back_mut() {
last.clear();
}
2019-08-31 15:00:23 +00:00
self.receiver.on_match(_match);
}
}
2019-09-05 17:18:55 +00:00
fn handle_modifier(&'a self, m: KeyModifier) {
2019-09-05 18:54:19 +00:00
if m == self.configs.toggle_key {
let mut toggle_press_time = self.toggle_press_time.borrow_mut();
if let Ok(elapsed) = toggle_press_time.elapsed() {
if elapsed.as_millis() < self.configs.toggle_interval as u128 {
2019-09-05 17:51:16 +00:00
let mut is_enabled = self.is_enabled.borrow_mut();
*is_enabled = !(*is_enabled);
if !*is_enabled {
2019-09-05 20:34:35 +00:00
self.current_set_queue.borrow_mut().clear();
2019-09-05 17:51:16 +00:00
}
println!("Enabled {}", *is_enabled);
2019-09-05 18:54:19 +00:00
}
}
2019-09-05 17:18:55 +00:00
2019-09-05 18:54:19 +00:00
(*toggle_press_time) = SystemTime::now();
}
2019-09-05 20:34:35 +00:00
// Backspace handling, basically "rewinding history"
if m == BACKSPACE {
let mut current_set_queue = self.current_set_queue.borrow_mut();
current_set_queue.pop_back();
}
2019-09-05 17:18:55 +00:00
}
}
2019-09-05 15:20:52 +00:00
impl <'a, R> ScrollingMatcher<'a, R> where R: MatchReceiver {
2019-09-05 18:54:19 +00:00
pub fn new(configs: Configs, receiver: R) -> ScrollingMatcher<'a, R> {
2019-09-05 20:34:35 +00:00
let current_set_queue = RefCell::new(VecDeque::new());
2019-09-05 18:54:19 +00:00
let toggle_press_time = RefCell::new(SystemTime::now());
2019-09-05 17:51:16 +00:00
ScrollingMatcher{
configs,
receiver,
2019-09-05 20:34:35 +00:00
current_set_queue,
2019-09-05 17:51:16 +00:00
toggle_press_time,
is_enabled: RefCell::new(true)
}
}
}