Add backspace corrections

This commit is contained in:
Federico Terzi 2019-09-05 22:34:35 +02:00
parent 189da97f0d
commit 778375c574
3 changed files with 42 additions and 18 deletions

View File

@ -7,7 +7,6 @@ use std::fs::File;
use std::io::Read; use std::io::Read;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use crate::keyboard::KeyModifier; use crate::keyboard::KeyModifier;
use crate::keyboard::KeyModifier::*;
// TODO: add documentation link // TODO: add documentation link
const DEFAULT_CONFIG_FILE_CONTENT : &str = include_str!("res/config.yaml"); const DEFAULT_CONFIG_FILE_CONTENT : &str = include_str!("res/config.yaml");
@ -18,6 +17,10 @@ fn default_toggle_interval() -> u32 {
230 230
} }
fn default_backspace_limit() -> i32 {
3
}
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Configs { pub struct Configs {
#[serde(default)] #[serde(default)]
@ -26,6 +29,9 @@ pub struct Configs {
#[serde(default = "default_toggle_interval")] #[serde(default = "default_toggle_interval")]
pub toggle_interval: u32, pub toggle_interval: u32,
#[serde(default = "default_backspace_limit")]
pub backspace_limit: i32,
pub matches: Vec<Match> pub matches: Vec<Match>
} }

View File

@ -1,4 +1,3 @@
use std::thread;
use std::sync::mpsc; use std::sync::mpsc;
use widestring::{U16CString}; use widestring::{U16CString};
use crate::keyboard::{KeyEvent, KeyModifier}; use crate::keyboard::{KeyEvent, KeyModifier};

View File

@ -4,11 +4,12 @@ use crate::keyboard::KeyModifier;
use crate::config::Configs; use crate::config::Configs;
use crate::keyboard::KeyModifier::BACKSPACE; use crate::keyboard::KeyModifier::BACKSPACE;
use std::time::SystemTime; use std::time::SystemTime;
use std::collections::VecDeque;
pub struct ScrollingMatcher<'a, R> where R: MatchReceiver{ pub struct ScrollingMatcher<'a, R> where R: MatchReceiver{
configs: Configs, configs: Configs,
receiver: R, receiver: R,
current_set: RefCell<Vec<MatchEntry<'a>>>, current_set_queue: RefCell<VecDeque<Vec<MatchEntry<'a>>>>,
toggle_press_time: RefCell<SystemTime>, toggle_press_time: RefCell<SystemTime>,
is_enabled: RefCell<bool>, is_enabled: RefCell<bool>,
} }
@ -25,7 +26,7 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv
return; return;
} }
let mut current_set = self.current_set.borrow_mut(); let mut current_set_queue = self.current_set_queue.borrow_mut();
let new_matches: Vec<MatchEntry> = self.configs.matches.iter() let new_matches: Vec<MatchEntry> = self.configs.matches.iter()
.filter(|&x| x.trigger.chars().nth(0).unwrap() == c) .filter(|&x| x.trigger.chars().nth(0).unwrap() == c)
@ -33,27 +34,40 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv
.collect(); .collect();
// TODO: use an associative structure to improve the efficiency of this first "new_matches" lookup. // TODO: use an associative structure to improve the efficiency of this first "new_matches" lookup.
let old_matches: Vec<MatchEntry> = (*current_set).iter() let combined_matches: Vec<MatchEntry> = match current_set_queue.back() {
Some(last_matches) => {
let mut updated: Vec<MatchEntry> = last_matches.iter()
.filter(|&x| { .filter(|&x| {
x._match.trigger[x.start..].chars().nth(0).unwrap() == c x._match.trigger[x.start..].chars().nth(0).unwrap() == c
}) })
.map(|x | MatchEntry{start: x.start+1, _match: &x._match}) .map(|x | MatchEntry{start: x.start+1, _match: &x._match})
.collect(); .collect();
(*current_set) = old_matches; updated.extend(new_matches);
(*current_set).extend(new_matches); updated
},
None => {new_matches},
};
let mut found_match = None; let mut found_match = None;
for entry in (*current_set).iter() { for entry in combined_matches.iter() {
if entry.start == entry._match.trigger.len() { if entry.start == entry._match.trigger.len() {
found_match = Some(entry._match); found_match = Some(entry._match);
break; break;
} }
} }
current_set_queue.push_back(combined_matches);
if current_set_queue.len() as i32 > (self.configs.backspace_limit + 1) {
current_set_queue.pop_front();
}
if let Some(_match) = found_match { if let Some(_match) = found_match {
(*current_set).clear(); if let Some(last) = current_set_queue.back_mut() {
last.clear();
}
self.receiver.on_match(_match); self.receiver.on_match(_match);
} }
} }
@ -67,7 +81,7 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv
*is_enabled = !(*is_enabled); *is_enabled = !(*is_enabled);
if !*is_enabled { if !*is_enabled {
self.current_set.borrow_mut().clear(); self.current_set_queue.borrow_mut().clear();
} }
println!("Enabled {}", *is_enabled); println!("Enabled {}", *is_enabled);
@ -76,18 +90,23 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv
(*toggle_press_time) = SystemTime::now(); (*toggle_press_time) = SystemTime::now();
} }
// Backspace handling, basically "rewinding history"
if m == BACKSPACE {
let mut current_set_queue = self.current_set_queue.borrow_mut();
current_set_queue.pop_back();
}
} }
} }
impl <'a, R> ScrollingMatcher<'a, R> where R: MatchReceiver { impl <'a, R> ScrollingMatcher<'a, R> where R: MatchReceiver {
pub fn new(configs: Configs, receiver: R) -> ScrollingMatcher<'a, R> { pub fn new(configs: Configs, receiver: R) -> ScrollingMatcher<'a, R> {
let current_set = RefCell::new(Vec::new()); let current_set_queue = RefCell::new(VecDeque::new());
let toggle_press_time = RefCell::new(SystemTime::now()); let toggle_press_time = RefCell::new(SystemTime::now());
ScrollingMatcher{ ScrollingMatcher{
configs, configs,
receiver, receiver,
current_set, current_set_queue,
toggle_press_time, toggle_press_time,
is_enabled: RefCell::new(true) is_enabled: RefCell::new(true)
} }