Add backspace corrections
This commit is contained in:
parent
189da97f0d
commit
778375c574
|
@ -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>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user