Improve config manager and clean code

This commit is contained in:
Federico Terzi 2019-09-07 16:13:13 +02:00
parent 4f712db7cb
commit 2332054bd2
8 changed files with 97 additions and 72 deletions

View File

@ -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
}
}
}
}

View File

@ -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<Match>;
}
pub struct RuntimeConfigManager<S: SystemManager> {
set: ConfigSet,
system_manager: S
}
impl <S: SystemManager> RuntimeConfigManager<S> {
pub fn new(set: ConfigSet, system_manager: S) -> RuntimeConfigManager<S> {
RuntimeConfigManager {
set,
system_manager
}
}
}
impl <S: SystemManager> ConfigManager for RuntimeConfigManager<S> {
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<Match> {
&self.default.matches
fn matches(&self) -> &Vec<Match> {
&self.set.default.matches
}
}

View File

@ -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<S, C> where S: KeyboardSender, C: ClipboardManager {
pub struct Engine<'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> {
sender: S,
clipboard_manager: Arc<C>,
config_set: ConfigSet,
clipboard_manager: &'a C,
config_manager: &'a M,
}
impl <S, C> Engine<S, C> where S: KeyboardSender, C: ClipboardManager{
pub fn new(sender: S, clipboard_manager: Arc<C>, config_set: ConfigSet) -> Engine<S, C> 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 <S, C> MatchReceiver for Engine<S, C> 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.

View File

@ -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::*;

View File

@ -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<KeyEvent>, 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);
}

View File

@ -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<KeyEvent>) {
pub trait Matcher {
fn handle_char(&self, c: char);
fn handle_modifier(&self, m: KeyModifier);
fn watch(&self, receiver: Receiver<KeyEvent>) {
loop {
match receiver.recv() {
Ok(event) => {

View File

@ -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<VecDeque<Vec<MatchEntry<'a>>>>,
toggle_press_time: RefCell<SystemTime>,
@ -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<MatchEntry> = self.config_set.matches().iter()
let new_matches: Vec<MatchEntry> = 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,

View File

@ -53,6 +53,8 @@ impl super::SystemManager for LinuxSystemManager {
}
}
unsafe impl Send for LinuxSystemManager {}
impl LinuxSystemManager {
}