Add trigger for toggle

This commit is contained in:
Federico Terzi 2019-09-05 20:54:19 +02:00
parent 2d9af53e74
commit 5d51b856b3
5 changed files with 56 additions and 28 deletions

View File

@ -6,25 +6,27 @@ use crate::matcher::Match;
use std::fs::File; 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::*;
// 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");
#[derive(Debug, Serialize, Deserialize)] // Default values for primitives
pub struct Configs {
#[serde(default)]
pub backspace_enabled: bool,
pub matches: Vec<Match> fn default_toggle_interval() -> u32 {
230
} }
impl Default for Configs { #[derive(Clone, Debug, Serialize, Deserialize)]
fn default() -> Self { pub struct Configs {
Configs { #[serde(default)]
backspace_enabled: false, pub toggle_key: KeyModifier,
matches: Vec::new()
} #[serde(default = "default_toggle_interval")]
} pub toggle_interval: u32,
pub matches: Vec<Match>
} }
impl Configs { impl Configs {

View File

@ -1,13 +1,15 @@
use crate::matcher::{Match, MatchReceiver}; use crate::matcher::{Match, MatchReceiver};
use crate::keyboard::KeyboardSender; use crate::keyboard::KeyboardSender;
use crate::config::Configs;
pub struct Engine<S> where S: KeyboardSender { pub struct Engine<S> where S: KeyboardSender {
sender: S sender: S,
configs: Configs,
} }
impl <S> Engine<S> where S: KeyboardSender{ impl <S> Engine<S> where S: KeyboardSender{
pub fn new(sender: S) -> Engine<S> where S: KeyboardSender { pub fn new(sender: S, configs: Configs) -> Engine<S> where S: KeyboardSender {
Engine{sender} Engine{sender, configs }
} }
} }

View File

@ -8,13 +8,14 @@ mod linux;
mod macos; mod macos;
use std::sync::mpsc; use std::sync::mpsc;
use serde::{Serialize, Deserialize};
pub trait KeyboardInterceptor { pub trait KeyboardInterceptor {
fn initialize(&self); fn initialize(&self);
fn start(&self); fn start(&self);
} }
#[derive(Debug)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum KeyModifier { pub enum KeyModifier {
CTRL, CTRL,
SHIFT, SHIFT,
@ -23,6 +24,12 @@ pub enum KeyModifier {
BACKSPACE, BACKSPACE,
} }
impl Default for KeyModifier {
fn default() -> Self {
KeyModifier::ALT
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum KeyEvent { pub enum KeyEvent {
Char(char), Char(char),

View File

@ -13,15 +13,16 @@ mod config;
fn main() { fn main() {
let configs = Configs::load_default(); let configs = Configs::load_default();
println!("{:#?}", configs);
let (txc, rxc) = mpsc::channel(); let (txc, rxc) = mpsc::channel();
let sender = keyboard::get_sender(); let sender = keyboard::get_sender();
let engine = Engine::new(sender); let engine = Engine::new(sender, configs.clone());
thread::spawn(move || { thread::spawn(move || {
let matcher = ScrollingMatcher::new(configs.matches.to_vec(), engine); let matcher = ScrollingMatcher::new(configs.clone(), engine);
matcher.watch(rxc); matcher.watch(rxc);
}); });

View File

@ -1,15 +1,19 @@
use crate::matcher::{Match, MatchReceiver}; use crate::matcher::{Match, MatchReceiver};
use std::cell::RefCell; use std::cell::RefCell;
use crate::keyboard::KeyModifier; use crate::keyboard::KeyModifier;
use crate::config::Configs;
use crate::keyboard::KeyModifier::BACKSPACE;
use std::time::SystemTime;
pub struct ScrollingMatcher<'a, R> where R: MatchReceiver{ pub struct ScrollingMatcher<'a, R> where R: MatchReceiver{
matches: Vec<Match>, configs: Configs,
receiver: R, receiver: R,
current_set: RefCell<Vec<MatchEntry<'a>>> current_set: RefCell<Vec<MatchEntry<'a>>>,
toggle_press_time: RefCell<SystemTime>
} }
struct MatchEntry<'a> { struct MatchEntry<'a> {
remaining: &'a str, start: usize,
_match: &'a Match _match: &'a Match
} }
@ -17,15 +21,17 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv
fn handle_char(&'a self, c: char) { fn handle_char(&'a self, c: char) {
let mut current_set = self.current_set.borrow_mut(); let mut current_set = self.current_set.borrow_mut();
let new_matches: Vec<MatchEntry> = self.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)
.map(|x | MatchEntry{remaining: &x.trigger[1..], _match: &x}) .map(|x | MatchEntry{start: 1, _match: &x})
.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 old_matches: Vec<MatchEntry> = (*current_set).iter()
.filter(|&x| x.remaining.chars().nth(0).unwrap() == c) .filter(|&x| {
.map(|x | MatchEntry{remaining: &x.remaining[1..], _match: &x._match}) x._match.trigger[x.start..].chars().nth(0).unwrap() == c
})
.map(|x | MatchEntry{start: x.start+1, _match: &x._match})
.collect(); .collect();
(*current_set) = old_matches; (*current_set) = old_matches;
@ -34,7 +40,7 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv
let mut found_match = None; let mut found_match = None;
for entry in (*current_set).iter() { for entry in (*current_set).iter() {
if entry.remaining.len() == 0 { if entry.start == entry._match.trigger.len() {
found_match = Some(entry._match); found_match = Some(entry._match);
break; break;
} }
@ -47,13 +53,23 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv
} }
fn handle_modifier(&'a self, m: KeyModifier) { fn handle_modifier(&'a self, m: KeyModifier) {
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 {
println!("Disable! {}", elapsed.as_millis());
}
}
(*toggle_press_time) = SystemTime::now();
}
} }
} }
impl <'a, R> ScrollingMatcher<'a, R> where R: MatchReceiver { impl <'a, R> ScrollingMatcher<'a, R> where R: MatchReceiver {
pub fn new(matches:Vec<Match>, 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 = RefCell::new(Vec::new());
ScrollingMatcher{ matches, receiver, current_set } let toggle_press_time = RefCell::new(SystemTime::now());
ScrollingMatcher{ configs, receiver, current_set, toggle_press_time }
} }
} }