From 2332054bd209866d28b69d641243dac38a93e208 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Sat, 7 Sep 2019 16:13:13 +0200 Subject: [PATCH] Improve config manager and clean code --- src/clipboard/linux.rs | 22 ++++++++------------ src/config.rs | 44 +++++++++++++++++++++++++++++++-------- src/engine.rs | 19 ++++++++--------- src/keyboard/linux.rs | 3 +-- src/main.rs | 45 +++++++++++++++++++++------------------- src/matcher/mod.rs | 8 +++---- src/matcher/scrolling.rs | 26 +++++++++++------------ src/system/linux.rs | 2 ++ 8 files changed, 97 insertions(+), 72 deletions(-) diff --git a/src/clipboard/linux.rs b/src/clipboard/linux.rs index 6cec754..424eb90 100644 --- a/src/clipboard/linux.rs +++ b/src/clipboard/linux.rs @@ -1,5 +1,5 @@ -use std::process::{Command, ExitStatus, Stdio}; -use std::io::{Write, Read}; +use std::process::{Command, Stdio}; +use std::io::{Write}; pub struct LinuxClipboardManager { @@ -26,24 +26,20 @@ impl super::ClipboardManager for LinuxClipboardManager { } fn set_clipboard(&self, payload: &str) { - let mut res = Command::new("xclip") + let res = Command::new("xclip") .args(&["-sel", "clip"]) .stdin(Stdio::piped()) .spawn(); if let Ok(mut child) = res { - let mut stdin = child.stdin.as_mut(); + let stdin = child.stdin.as_mut(); - if let Some(mut output) = stdin { - output.write_all(payload.as_bytes()); + if let Some(output) = stdin { + let res = output.write_all(payload.as_bytes()); -// let status = child.wait(); -// -// if let Ok(status) = status { -// if !status.success() { -// //TODO: log error -// } -// } + if let Err(_) = res { + // TODO: log error + } } } } diff --git a/src/config.rs b/src/config.rs index 0aaf161..46e971f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,6 +7,7 @@ use std::fs::{File, create_dir_all}; use std::io::Read; use serde::{Serialize, Deserialize}; use crate::keyboard::KeyModifier; +use crate::system::SystemManager; use std::collections::HashSet; // TODO: add documentation link @@ -148,24 +149,49 @@ impl ConfigSet { // TODO: tests panic!("Could not generate default position for config file"); } +} - pub fn toggle_key(&self) -> &KeyModifier { - &self.default.toggle_key +pub trait ConfigManager { + fn toggle_key(&self) -> &KeyModifier; + fn toggle_interval(&self) -> u32; + fn backspace_limit(&self) -> i32; + fn backend(&self) -> &BackendType; + fn matches(&self) -> &Vec; +} + +pub struct RuntimeConfigManager { + set: ConfigSet, + + system_manager: S +} + +impl RuntimeConfigManager { + pub fn new(set: ConfigSet, system_manager: S) -> RuntimeConfigManager { + RuntimeConfigManager { + set, + system_manager + } + } +} + +impl ConfigManager for RuntimeConfigManager { + fn toggle_key(&self) -> &KeyModifier { + &self.set.default.toggle_key } - pub fn toggle_interval(&self) -> u32 { - self.default.toggle_interval + fn toggle_interval(&self) -> u32 { + self.set.default.toggle_interval } - pub fn backspace_limit(&self) -> i32 { - self.default.backspace_limit + fn backspace_limit(&self) -> i32 { + self.set.default.backspace_limit } - pub fn backend(&self) -> &BackendType { + fn backend(&self) -> &BackendType { &BackendType::Inject // TODO make dynamic based on system current active app } - pub fn matches(&self) -> &Vec { - &self.default.matches + fn matches(&self) -> &Vec { + &self.set.default.matches } } \ No newline at end of file diff --git a/src/engine.rs b/src/engine.rs index 0f86cd8..9846f51 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,27 +1,26 @@ use crate::matcher::{Match, MatchReceiver}; use crate::keyboard::KeyboardSender; -use crate::config::ConfigSet; +use crate::config::ConfigManager; use crate::config::BackendType; use crate::clipboard::ClipboardManager; -use std::sync::Arc; -pub struct Engine where S: KeyboardSender, C: ClipboardManager { +pub struct Engine<'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> { sender: S, - clipboard_manager: Arc, - config_set: ConfigSet, + clipboard_manager: &'a C, + config_manager: &'a M, } -impl Engine where S: KeyboardSender, C: ClipboardManager{ - pub fn new(sender: S, clipboard_manager: Arc, config_set: ConfigSet) -> Engine where S: KeyboardSender, C: ClipboardManager { - Engine{sender, clipboard_manager, config_set } +impl <'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> Engine<'a, S, C, M> { + pub fn new<'b>(sender: S, clipboard_manager: &'b C, config_manager: &'b M) -> Engine<'b, S, C, M> { + Engine{sender, clipboard_manager, config_manager } } } -impl MatchReceiver for Engine where S: KeyboardSender, C: ClipboardManager{ +impl <'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> MatchReceiver for Engine<'a, S, C, M>{ fn on_match(&self, m: &Match) { self.sender.delete_string(m.trigger.len() as i32); - match self.config_set.backend() { + match self.config_manager.backend() { BackendType::Inject => { // Send the expected string. On linux, newlines are managed automatically // while on windows and macos, we need to emulate a Enter key press. diff --git a/src/keyboard/linux.rs b/src/keyboard/linux.rs index f5ccd67..75b9616 100644 --- a/src/keyboard/linux.rs +++ b/src/keyboard/linux.rs @@ -1,6 +1,5 @@ -use std::{thread}; use std::sync::mpsc; -use std::os::raw::{c_char, c_void}; +use std::os::raw::{c_void}; use std::ffi::CString; use crate::keyboard::{KeyEvent, KeyModifier}; use crate::keyboard::KeyModifier::*; diff --git a/src/main.rs b/src/main.rs index 4c0128e..2b95557 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,14 @@ -use std::sync::{mpsc, Arc}; -use crate::keyboard::KeyboardInterceptor; +use std::sync::{mpsc}; +use crate::keyboard::{KeyboardInterceptor, KeyEvent}; use crate::matcher::Matcher; use crate::matcher::scrolling::ScrollingMatcher; use crate::engine::Engine; -use crate::config::{Configs, ConfigSet}; +use crate::config::{ConfigSet, RuntimeConfigManager}; use crate::ui::UIManager; -use crate::clipboard::ClipboardManager; -use crate::system::SystemManager; use std::thread; use clap::{App, Arg}; use std::path::Path; +use std::sync::mpsc::Receiver; mod ui; mod bridge; @@ -56,28 +55,32 @@ fn main() { } fn espanso_main(config_set: ConfigSet) { - let ui_manager = ui::get_uimanager(); - ui_manager.notify("Hello guys"); - - let system_manager = system::get_manager(); - - let clipboard_manager = clipboard::get_manager(); - let clipboard_manager_arc = Arc::new(clipboard_manager); - let (txc, rxc) = mpsc::channel(); - let sender = keyboard::get_sender(); - - let engine = Engine::new(sender, - Arc::clone(&clipboard_manager_arc), - config_set.clone()); - thread::spawn(move || { - let matcher = ScrollingMatcher::new(config_set.clone(), engine); - matcher.watch(rxc); + espanso_background(rxc, config_set); }); let interceptor = keyboard::get_interceptor(txc); interceptor.initialize(); interceptor.start(); +} + +fn espanso_background(rxc: Receiver, config_set: ConfigSet) { + let system_manager = system::get_manager(); + let config_manager = RuntimeConfigManager::new(config_set, system_manager); + + let ui_manager = ui::get_uimanager(); + ui_manager.notify("Hello guys"); + + let clipboard_manager = clipboard::get_manager(); + + let sender = keyboard::get_sender(); + + let engine = Engine::new(sender, + &clipboard_manager, + &config_manager); + + let matcher = ScrollingMatcher::new(&config_manager, engine); + matcher.watch(rxc); } \ No newline at end of file diff --git a/src/matcher/mod.rs b/src/matcher/mod.rs index a8c66ca..46b9236 100644 --- a/src/matcher/mod.rs +++ b/src/matcher/mod.rs @@ -14,10 +14,10 @@ pub trait MatchReceiver { fn on_match(&self, m: &Match); } -pub trait Matcher<'a>: Send { - fn handle_char(&'a self, c: char); - fn handle_modifier(&'a self, m: KeyModifier); - fn watch(&'a self, receiver: Receiver) { +pub trait Matcher { + fn handle_char(&self, c: char); + fn handle_modifier(&self, m: KeyModifier); + fn watch(&self, receiver: Receiver) { loop { match receiver.recv() { Ok(event) => { diff --git a/src/matcher/scrolling.rs b/src/matcher/scrolling.rs index 17660ca..ee6f676 100644 --- a/src/matcher/scrolling.rs +++ b/src/matcher/scrolling.rs @@ -1,13 +1,13 @@ use crate::matcher::{Match, MatchReceiver}; use std::cell::RefCell; use crate::keyboard::KeyModifier; -use crate::config::ConfigSet; +use crate::config::ConfigManager; use crate::keyboard::KeyModifier::BACKSPACE; use std::time::SystemTime; use std::collections::VecDeque; -pub struct ScrollingMatcher<'a, R> where R: MatchReceiver{ - config_set: ConfigSet, +pub struct ScrollingMatcher<'a, R: MatchReceiver, M: ConfigManager> { + config_manager: &'a M, receiver: R, current_set_queue: RefCell>>>, toggle_press_time: RefCell, @@ -19,8 +19,8 @@ struct MatchEntry<'a> { _match: &'a Match } -impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiver+Send{ - fn handle_char(&'a self, c: char) { +impl <'a, R: MatchReceiver, M: ConfigManager> super::Matcher for ScrollingMatcher<'a, R, M> where{ + fn handle_char(&self, c: char) { // if not enabled, avoid any processing if !*(self.is_enabled.borrow()) { return; @@ -28,7 +28,7 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv let mut current_set_queue = self.current_set_queue.borrow_mut(); - let new_matches: Vec = self.config_set.matches().iter() + let new_matches: Vec = self.config_manager.matches().iter() .filter(|&x| x.trigger.chars().nth(0).unwrap() == c) .map(|x | MatchEntry{start: 1, _match: &x}) .collect(); @@ -60,7 +60,7 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv current_set_queue.push_back(combined_matches); - if current_set_queue.len() as i32 > (self.config_set.backspace_limit() + 1) { + if current_set_queue.len() as i32 > (self.config_manager.backspace_limit() + 1) { current_set_queue.pop_front(); } @@ -72,11 +72,11 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv } } - fn handle_modifier(&'a self, m: KeyModifier) { - if m == *self.config_set.toggle_key() { + fn handle_modifier(&self, m: KeyModifier) { + if m == *self.config_manager.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.config_set.toggle_interval() as u128 { + if elapsed.as_millis() < self.config_manager.toggle_interval() as u128 { let mut is_enabled = self.is_enabled.borrow_mut(); *is_enabled = !(*is_enabled); @@ -98,13 +98,13 @@ impl <'a, R> super::Matcher<'a> for ScrollingMatcher<'a, R> where R: MatchReceiv } } } -impl <'a, R> ScrollingMatcher<'a, R> where R: MatchReceiver { - pub fn new(config_set: ConfigSet, receiver: R) -> ScrollingMatcher<'a, R> { +impl <'a, R: MatchReceiver, M: ConfigManager> ScrollingMatcher<'a, R, M> { + pub fn new(config_manager: &'a M, receiver: R) -> ScrollingMatcher<'a, R, M> { let current_set_queue = RefCell::new(VecDeque::new()); let toggle_press_time = RefCell::new(SystemTime::now()); ScrollingMatcher{ - config_set, + config_manager, receiver, current_set_queue, toggle_press_time, diff --git a/src/system/linux.rs b/src/system/linux.rs index 588df52..52e188f 100644 --- a/src/system/linux.rs +++ b/src/system/linux.rs @@ -53,6 +53,8 @@ impl super::SystemManager for LinuxSystemManager { } } +unsafe impl Send for LinuxSystemManager {} + impl LinuxSystemManager { } \ No newline at end of file