Improve config manager and clean code
This commit is contained in:
parent
4f712db7cb
commit
2332054bd2
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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::*;
|
||||
|
|
45
src/main.rs
45
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<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);
|
||||
}
|
|
@ -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) => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -53,6 +53,8 @@ impl super::SystemManager for LinuxSystemManager {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for LinuxSystemManager {}
|
||||
|
||||
impl LinuxSystemManager {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user