espanso/src/engine.rs

133 lines
4.1 KiB
Rust
Raw Normal View History

use crate::matcher::{Match, MatchReceiver};
2019-09-13 13:03:03 +00:00
use crate::keyboard::KeyboardManager;
2019-09-07 14:13:13 +00:00
use crate::config::ConfigManager;
use crate::config::BackendType;
use crate::clipboard::ClipboardManager;
2019-09-08 11:37:58 +00:00
use log::{info};
2019-09-12 21:24:55 +00:00
use crate::ui::{UIManager, MenuItem, MenuItemType};
2019-09-13 09:55:42 +00:00
use crate::event::{ActionEventReceiver, ActionEvent, ActionType};
2019-09-12 21:24:55 +00:00
use std::cell::RefCell;
2019-09-13 13:03:03 +00:00
use std::process::exit;
2019-09-13 13:03:03 +00:00
pub struct Engine<'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>,
2019-09-08 11:37:58 +00:00
U: UIManager> {
2019-09-13 13:03:03 +00:00
keyboard_manager: &'a S,
2019-09-07 14:13:13 +00:00
clipboard_manager: &'a C,
config_manager: &'a M,
2019-09-08 11:37:58 +00:00
ui_manager: &'a U,
2019-09-12 21:24:55 +00:00
enabled: RefCell<bool>,
}
2019-09-13 13:03:03 +00:00
impl <'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>, U: UIManager>
2019-09-08 11:37:58 +00:00
Engine<'a, S, C, M, U> {
2019-09-13 13:03:03 +00:00
pub fn new(keyboard_manager: &'a S, clipboard_manager: &'a C, config_manager: &'a M, ui_manager: &'a U) -> Engine<'a, S, C, M, U> {
2019-09-12 21:24:55 +00:00
let enabled = RefCell::new(true);
2019-09-13 13:03:03 +00:00
Engine{keyboard_manager, clipboard_manager, config_manager, ui_manager, enabled }
2019-09-12 21:24:55 +00:00
}
fn build_menu(&self) -> Vec<MenuItem> {
let mut menu = Vec::new();
let enabled = self.enabled.borrow();
let toggle_text = if *enabled {
"Disable"
}else{
"Enable"
}.to_owned();
menu.push(MenuItem{
item_type: MenuItemType::Button,
item_name: toggle_text,
2019-09-12 21:53:17 +00:00
item_id: ActionType::Toggle as i32,
2019-09-12 21:24:55 +00:00
});
menu.push(MenuItem{
item_type: MenuItemType::Separator,
item_name: "".to_owned(),
item_id: 999,
});
menu.push(MenuItem{
item_type: MenuItemType::Button,
item_name: "Exit".to_owned(),
2019-09-12 21:53:17 +00:00
item_id: ActionType::Exit as i32,
2019-09-12 21:24:55 +00:00
});
menu
}
}
2019-09-13 13:03:03 +00:00
impl <'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>, U: UIManager>
2019-09-08 11:37:58 +00:00
MatchReceiver for Engine<'a, S, C, M, U>{
2019-08-31 15:00:23 +00:00
fn on_match(&self, m: &Match) {
2019-09-09 15:13:58 +00:00
let config = self.config_manager.active_config();
if config.disabled {
return;
}
2019-09-07 15:59:34 +00:00
2019-09-13 13:03:03 +00:00
self.keyboard_manager.delete_string(m.trigger.len() as i32);
2019-09-07 15:59:34 +00:00
match config.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.
if cfg!(target_os = "linux") {
2019-09-13 13:03:03 +00:00
self.keyboard_manager.send_string(m.replace.as_str());
}else{
// To handle newlines, substitute each "\n" char with an Enter key press.
let splits = m.replace.lines();
2019-09-06 20:19:28 +00:00
for (i, split) in splits.enumerate() {
if i > 0 {
2019-09-13 13:03:03 +00:00
self.keyboard_manager.send_enter();
}
2019-09-13 13:03:03 +00:00
self.keyboard_manager.send_string(split);
}
}
},
BackendType::Clipboard => {
self.clipboard_manager.set_clipboard(m.replace.as_str());
2019-09-13 13:03:03 +00:00
self.keyboard_manager.trigger_paste();
},
}
}
2019-09-08 11:37:58 +00:00
fn on_toggle(&self, status: bool) {
let message = if status {
"espanso enabled"
}else{
"espanso disabled"
};
info!("Toggled: {}", message);
2019-09-12 21:24:55 +00:00
let mut enabled_ref = self.enabled.borrow_mut();
*enabled_ref = status;
2019-09-08 11:37:58 +00:00
self.ui_manager.notify(message);
}
2019-09-12 20:14:41 +00:00
}
2019-09-13 13:03:03 +00:00
impl <'a, S: KeyboardManager, C: ClipboardManager,
2019-09-12 20:14:41 +00:00
M: ConfigManager<'a>, U: UIManager> ActionEventReceiver for Engine<'a, S, C, M, U>{
2019-09-12 21:24:55 +00:00
fn on_action_event(&self, e: ActionEvent) {
match e {
ActionEvent::IconClick => {
self.ui_manager.show_menu(self.build_menu());
},
ActionEvent::ContextMenuClick(id) => {
2019-09-13 13:03:03 +00:00
match id {
ActionType::Exit => {
info!("Terminating expanso from the context menu");
exit(0);
},
_ => {}
}
2019-09-12 21:24:55 +00:00
}
}
2019-09-12 20:14:41 +00:00
}
}