feat(core): first draft of builtin matches
This commit is contained in:
parent
90db84b92f
commit
48d05a3f32
38
espanso/src/cli/worker/builtin/debug.rs
Normal file
38
espanso/src/cli/worker/builtin/debug.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::{cli::worker::builtin::generate_next_builtin_id, engine::event::{EventType, effect::TextInjectRequest}};
|
||||||
|
|
||||||
|
use super::BuiltInMatch;
|
||||||
|
|
||||||
|
pub fn create_match_show_active_config_info() -> BuiltInMatch {
|
||||||
|
BuiltInMatch {
|
||||||
|
id: generate_next_builtin_id(),
|
||||||
|
label: "Display active config information",
|
||||||
|
triggers: vec!["#acfg#".to_string()],
|
||||||
|
action: |context| {
|
||||||
|
println!("active config: {:?}", context.get_active_config().label());
|
||||||
|
|
||||||
|
EventType::TextInject(TextInjectRequest {
|
||||||
|
text: "test".to_string(),
|
||||||
|
force_mode: None,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
57
espanso/src/cli/worker/builtin/mod.rs
Normal file
57
espanso/src/cli/worker/builtin/mod.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use crate::engine::event::EventType;
|
||||||
|
|
||||||
|
use super::context::Context;
|
||||||
|
|
||||||
|
mod debug;
|
||||||
|
|
||||||
|
const MIN_BUILTIN_MATCH_ID: i32 = 1_000_000_000;
|
||||||
|
|
||||||
|
pub struct BuiltInMatch {
|
||||||
|
pub id: i32,
|
||||||
|
pub label: &'static str,
|
||||||
|
pub triggers: Vec<String>,
|
||||||
|
pub action: fn(context: &dyn Context) -> EventType,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_builtin_matches() -> Vec<BuiltInMatch> {
|
||||||
|
vec![
|
||||||
|
debug::create_match_show_active_config_info(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_builtin_match(id: i32) -> bool {
|
||||||
|
id >= MIN_BUILTIN_MATCH_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static CURRENT_BUILTIN_MATCH_ID: Cell<i32> = Cell::new(MIN_BUILTIN_MATCH_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_next_builtin_id() -> i32 {
|
||||||
|
CURRENT_BUILTIN_MATCH_ID.with(|value| {
|
||||||
|
let current = value.get();
|
||||||
|
value.set(current + 1);
|
||||||
|
current
|
||||||
|
})
|
||||||
|
}
|
|
@ -26,6 +26,8 @@ use espanso_config::{
|
||||||
use espanso_info::{AppInfo, AppInfoProvider};
|
use espanso_info::{AppInfo, AppInfoProvider};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
use super::builtin::is_builtin_match;
|
||||||
|
|
||||||
pub struct ConfigManager<'a> {
|
pub struct ConfigManager<'a> {
|
||||||
config_store: &'a dyn ConfigStore,
|
config_store: &'a dyn ConfigStore,
|
||||||
match_store: &'a dyn MatchStore,
|
match_store: &'a dyn MatchStore,
|
||||||
|
@ -57,7 +59,7 @@ impl<'a> ConfigManager<'a> {
|
||||||
(config.clone(), self.match_store.query(&match_paths))
|
(config.clone(), self.match_store.query(&match_paths))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default(&self) -> Arc<dyn Config>{
|
pub fn default(&self) -> Arc<dyn Config> {
|
||||||
self.config_store.default()
|
self.config_store.default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,12 +78,22 @@ impl<'a> crate::engine::process::MatchFilter for ConfigManager<'a> {
|
||||||
let ids_set: HashSet<i32> = HashSet::from_iter(matches_ids.iter().copied());
|
let ids_set: HashSet<i32> = HashSet::from_iter(matches_ids.iter().copied());
|
||||||
let (_, match_set) = self.active_context();
|
let (_, match_set) = self.active_context();
|
||||||
|
|
||||||
match_set
|
let active_user_defined_matches: Vec<i32> = match_set
|
||||||
.matches
|
.matches
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| ids_set.contains(&m.id))
|
.filter(|m| ids_set.contains(&m.id))
|
||||||
.map(|m| m.id)
|
.map(|m| m.id)
|
||||||
.collect()
|
.collect();
|
||||||
|
|
||||||
|
let builtin_matches: Vec<i32> = matches_ids
|
||||||
|
.into_iter()
|
||||||
|
.filter(|id| is_builtin_match(**id))
|
||||||
|
.map(|id| *id)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut output = active_user_defined_matches;
|
||||||
|
output.extend(builtin_matches);
|
||||||
|
output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
43
espanso/src/cli/worker/context/default.rs
Normal file
43
espanso/src/cli/worker/context/default.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::cli::worker::config::ConfigManager;
|
||||||
|
|
||||||
|
pub struct DefaultContext<'a> {
|
||||||
|
config_manager: &'a ConfigManager<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DefaultContext<'a> {
|
||||||
|
pub fn new(config_manager: &'a ConfigManager<'a>) -> Self {
|
||||||
|
Self { config_manager }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Context for DefaultContext<'a> {}
|
||||||
|
|
||||||
|
impl<'a> ConfigContext for DefaultContext<'a> {
|
||||||
|
fn get_default_config(&self) -> Arc<dyn Config> {
|
||||||
|
self.config_manager.default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_active_config(&self) -> Arc<dyn Config> {
|
||||||
|
self.config_manager.active()
|
||||||
|
}
|
||||||
|
}
|
32
espanso/src/cli/worker/context/mod.rs
Normal file
32
espanso/src/cli/worker/context/mod.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use espanso_config::config::Config;
|
||||||
|
|
||||||
|
mod default;
|
||||||
|
pub use default::DefaultContext;
|
||||||
|
|
||||||
|
pub trait Context: ConfigContext {}
|
||||||
|
|
||||||
|
pub trait ConfigContext {
|
||||||
|
fn get_default_config(&self) -> Arc<dyn Config>;
|
||||||
|
fn get_active_config(&self) -> Arc<dyn Config>;
|
||||||
|
}
|
|
@ -28,8 +28,7 @@ use espanso_path::Paths;
|
||||||
use espanso_ui::{event::UIEvent, UIRemote};
|
use espanso_ui::{event::UIEvent, UIRemote};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
|
|
||||||
use crate::{cli::worker::{
|
use crate::{cli::worker::{context::Context, engine::{
|
||||||
engine::{
|
|
||||||
dispatch::executor::{
|
dispatch::executor::{
|
||||||
clipboard_injector::ClipboardInjectorAdapter, context_menu::ContextMenuHandlerAdapter,
|
clipboard_injector::ClipboardInjectorAdapter, context_menu::ContextMenuHandlerAdapter,
|
||||||
event_injector::EventInjectorAdapter, icon::IconHandlerAdapter,
|
event_injector::EventInjectorAdapter, icon::IconHandlerAdapter,
|
||||||
|
@ -49,9 +48,7 @@ use crate::{cli::worker::{
|
||||||
RendererAdapter,
|
RendererAdapter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}, match_cache::{CombinedMatchCache, MatchCache}}, engine::event::ExitMode, preferences::Preferences};
|
||||||
match_cache::MatchCache,
|
|
||||||
}, engine::event::ExitMode, preferences::Preferences};
|
|
||||||
|
|
||||||
use super::secure_input::SecureInputEvent;
|
use super::secure_input::SecureInputEvent;
|
||||||
|
|
||||||
|
@ -82,13 +79,18 @@ pub fn initialize_and_spawn(
|
||||||
espanso_info::get_provider().expect("unable to initialize app info provider");
|
espanso_info::get_provider().expect("unable to initialize app info provider");
|
||||||
let config_manager =
|
let config_manager =
|
||||||
super::config::ConfigManager::new(&*config_store, &*match_store, &*app_info_provider);
|
super::config::ConfigManager::new(&*config_store, &*match_store, &*app_info_provider);
|
||||||
let match_converter = MatchConverter::new(&*config_store, &*match_store);
|
|
||||||
let match_cache = MatchCache::load(&*config_store, &*match_store);
|
let match_cache = MatchCache::load(&*config_store, &*match_store);
|
||||||
|
|
||||||
let modulo_manager = crate::gui::modulo::manager::ModuloManager::new();
|
let modulo_manager = crate::gui::modulo::manager::ModuloManager::new();
|
||||||
let modulo_form_ui = crate::gui::modulo::form::ModuloFormUI::new(&modulo_manager);
|
let modulo_form_ui = crate::gui::modulo::form::ModuloFormUI::new(&modulo_manager);
|
||||||
let modulo_search_ui = crate::gui::modulo::search::ModuloSearchUI::new(&modulo_manager);
|
let modulo_search_ui = crate::gui::modulo::search::ModuloSearchUI::new(&modulo_manager);
|
||||||
|
|
||||||
|
let context: Box<dyn Context> = Box::new(super::context::DefaultContext::new(&config_manager));
|
||||||
|
let builtin_matches = super::builtin::get_builtin_matches();
|
||||||
|
let combined_match_cache = CombinedMatchCache::load(&match_cache, &builtin_matches);
|
||||||
|
|
||||||
|
let match_converter = MatchConverter::new(&*config_store, &*match_store, &builtin_matches);
|
||||||
|
|
||||||
let has_granted_capabilities = grant_linux_capabilities(use_evdev_backend);
|
let has_granted_capabilities = grant_linux_capabilities(use_evdev_backend);
|
||||||
|
|
||||||
// TODO: pass all the options
|
// TODO: pass all the options
|
||||||
|
@ -129,8 +131,8 @@ pub fn initialize_and_spawn(
|
||||||
super::engine::process::middleware::matcher::MatcherState,
|
super::engine::process::middleware::matcher::MatcherState,
|
||||||
>,
|
>,
|
||||||
> = vec![&rolling_matcher, ®ex_matcher];
|
> = vec![&rolling_matcher, ®ex_matcher];
|
||||||
let selector = MatchSelectorAdapter::new(&modulo_search_ui, &match_cache);
|
let selector = MatchSelectorAdapter::new(&modulo_search_ui, &combined_match_cache);
|
||||||
let multiplexer = MultiplexAdapter::new(&match_cache);
|
let multiplexer = MultiplexAdapter::new(&combined_match_cache, &*context);
|
||||||
|
|
||||||
let injector = espanso_inject::get_injector(InjectorCreationOptions {
|
let injector = espanso_inject::get_injector(InjectorCreationOptions {
|
||||||
use_evdev: use_evdev_backend,
|
use_evdev: use_evdev_backend,
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use espanso_config::matches::{Match};
|
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -28,7 +27,13 @@ use crate::{
|
||||||
const MAX_LABEL_LEN: usize = 100;
|
const MAX_LABEL_LEN: usize = 100;
|
||||||
|
|
||||||
pub trait MatchProvider<'a> {
|
pub trait MatchProvider<'a> {
|
||||||
fn get_matches(&self, ids: &[i32]) -> Vec<&'a Match>;
|
fn get_matches(&self, ids: &[i32]) -> Vec<MatchSummary<'a>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MatchSummary<'a> {
|
||||||
|
pub id: i32,
|
||||||
|
pub label: &'a str,
|
||||||
|
pub tag: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MatchSelectorAdapter<'a> {
|
pub struct MatchSelectorAdapter<'a> {
|
||||||
|
@ -49,15 +54,14 @@ impl<'a> MatchSelector for MatchSelectorAdapter<'a> {
|
||||||
fn select(&self, matches_ids: &[i32]) -> Option<i32> {
|
fn select(&self, matches_ids: &[i32]) -> Option<i32> {
|
||||||
let matches = self.match_provider.get_matches(&matches_ids);
|
let matches = self.match_provider.get_matches(&matches_ids);
|
||||||
let search_items: Vec<SearchItem> = matches
|
let search_items: Vec<SearchItem> = matches
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|m| {
|
.map(|m| {
|
||||||
let label = m.description();
|
let clipped_label = &m.label[..std::cmp::min(m.label.len(), MAX_LABEL_LEN)];
|
||||||
let clipped_label = &label[..std::cmp::min(label.len(), MAX_LABEL_LEN)];
|
|
||||||
|
|
||||||
SearchItem {
|
SearchItem {
|
||||||
id: m.id.to_string(),
|
id: m.id.to_string(),
|
||||||
label: clipped_label.to_string(),
|
label: clipped_label.to_string(),
|
||||||
tag: m.cause_description().map(String::from),
|
tag: m.tag.map(String::from),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -30,16 +30,24 @@ use espanso_match::{
|
||||||
};
|
};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
use crate::cli::worker::builtin::BuiltInMatch;
|
||||||
|
|
||||||
pub struct MatchConverter<'a> {
|
pub struct MatchConverter<'a> {
|
||||||
config_store: &'a dyn ConfigStore,
|
config_store: &'a dyn ConfigStore,
|
||||||
match_store: &'a dyn MatchStore,
|
match_store: &'a dyn MatchStore,
|
||||||
|
builtin_matches: &'a [BuiltInMatch],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MatchConverter<'a> {
|
impl<'a> MatchConverter<'a> {
|
||||||
pub fn new(config_store: &'a dyn ConfigStore, match_store: &'a dyn MatchStore) -> Self {
|
pub fn new(
|
||||||
|
config_store: &'a dyn ConfigStore,
|
||||||
|
match_store: &'a dyn MatchStore,
|
||||||
|
builtin_matches: &'a [BuiltInMatch],
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
config_store,
|
config_store,
|
||||||
match_store,
|
match_store,
|
||||||
|
builtin_matches,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +56,7 @@ impl<'a> MatchConverter<'a> {
|
||||||
let match_set = self.global_match_set();
|
let match_set = self.global_match_set();
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
|
|
||||||
|
// First convert configuration (user-defined) matches
|
||||||
for m in match_set.matches {
|
for m in match_set.matches {
|
||||||
if let MatchCause::Trigger(cause) = &m.cause {
|
if let MatchCause::Trigger(cause) = &m.cause {
|
||||||
for trigger in cause.triggers.iter() {
|
for trigger in cause.triggers.iter() {
|
||||||
|
@ -64,6 +73,17 @@ impl<'a> MatchConverter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Then convert built-in ones
|
||||||
|
for m in self.builtin_matches {
|
||||||
|
for trigger in m.triggers.iter() {
|
||||||
|
matches.push(RollingMatch::from_string(
|
||||||
|
m.id,
|
||||||
|
&trigger,
|
||||||
|
&StringMatchOptions::default()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
matches
|
matches
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,10 +94,7 @@ impl<'a> MatchConverter<'a> {
|
||||||
|
|
||||||
for m in match_set.matches {
|
for m in match_set.matches {
|
||||||
if let MatchCause::Regex(cause) = &m.cause {
|
if let MatchCause::Regex(cause) = &m.cause {
|
||||||
matches.push(RegexMatch::new(
|
matches.push(RegexMatch::new(m.id, &cause.regex))
|
||||||
m.id,
|
|
||||||
&cause.regex,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,27 +19,42 @@
|
||||||
|
|
||||||
use espanso_config::matches::{Match, MatchEffect};
|
use espanso_config::matches::{Match, MatchEffect};
|
||||||
|
|
||||||
use crate::engine::{event::{EventType, internal::DetectedMatch, internal::{ImageRequestedEvent, RenderingRequestedEvent, TextFormat}}, process::Multiplexer};
|
use crate::{
|
||||||
|
cli::worker::{builtin::BuiltInMatch, context::Context},
|
||||||
|
engine::{
|
||||||
|
event::{
|
||||||
|
internal::DetectedMatch,
|
||||||
|
internal::{ImageRequestedEvent, RenderingRequestedEvent, TextFormat},
|
||||||
|
EventType,
|
||||||
|
},
|
||||||
|
process::Multiplexer,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub trait MatchProvider<'a> {
|
pub trait MatchProvider<'a> {
|
||||||
fn get(&self, match_id: i32) -> Option<&'a Match>;
|
fn get(&self, match_id: i32) -> Option<MatchResult<'a>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum MatchResult<'a> {
|
||||||
|
User(&'a Match),
|
||||||
|
Builtin(&'a BuiltInMatch),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MultiplexAdapter<'a> {
|
pub struct MultiplexAdapter<'a> {
|
||||||
provider: &'a dyn MatchProvider<'a>,
|
provider: &'a dyn MatchProvider<'a>,
|
||||||
|
context: &'a dyn Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MultiplexAdapter<'a> {
|
impl<'a> MultiplexAdapter<'a> {
|
||||||
pub fn new(provider: &'a dyn MatchProvider<'a>) -> Self {
|
pub fn new(provider: &'a dyn MatchProvider<'a>, context: &'a dyn Context) -> Self {
|
||||||
Self { provider }
|
Self { provider, context }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Multiplexer for MultiplexAdapter<'a> {
|
impl<'a> Multiplexer for MultiplexAdapter<'a> {
|
||||||
fn convert(&self, detected_match: DetectedMatch) -> Option<EventType> {
|
fn convert(&self, detected_match: DetectedMatch) -> Option<EventType> {
|
||||||
let m = self.provider.get(detected_match.id)?;
|
match self.provider.get(detected_match.id)? {
|
||||||
|
MatchResult::User(m) => match &m.effect {
|
||||||
match &m.effect {
|
|
||||||
MatchEffect::Text(effect) => Some(EventType::RenderingRequested(RenderingRequestedEvent {
|
MatchEffect::Text(effect) => Some(EventType::RenderingRequested(RenderingRequestedEvent {
|
||||||
match_id: detected_match.id,
|
match_id: detected_match.id,
|
||||||
trigger: detected_match.trigger,
|
trigger: detected_match.trigger,
|
||||||
|
@ -53,6 +68,10 @@ impl<'a> Multiplexer for MultiplexAdapter<'a> {
|
||||||
image_path: effect.path.clone(),
|
image_path: effect.path.clone(),
|
||||||
})),
|
})),
|
||||||
MatchEffect::None => None,
|
MatchEffect::None => None,
|
||||||
|
},
|
||||||
|
MatchResult::Builtin(m) => {
|
||||||
|
Some((m.action)(self.context))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ use espanso_config::{
|
||||||
matches::{store::MatchStore, Match, MatchEffect},
|
matches::{store::MatchStore, Match, MatchEffect},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::{builtin::BuiltInMatch, engine::process::middleware::match_select::MatchSummary};
|
||||||
|
|
||||||
pub struct MatchCache<'a> {
|
pub struct MatchCache<'a> {
|
||||||
cache: HashMap<i32, &'a Match>,
|
cache: HashMap<i32, &'a Match>,
|
||||||
}
|
}
|
||||||
|
@ -43,12 +45,6 @@ impl<'a> MatchCache<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> super::engine::process::middleware::multiplex::MatchProvider<'a> for MatchCache<'a> {
|
|
||||||
fn get(&self, match_id: i32) -> Option<&'a Match> {
|
|
||||||
self.cache.get(&match_id).map(|m| *m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> super::engine::process::middleware::render::MatchProvider<'a> for MatchCache<'a> {
|
impl<'a> super::engine::process::middleware::render::MatchProvider<'a> for MatchCache<'a> {
|
||||||
fn matches(&self) -> Vec<&'a Match> {
|
fn matches(&self) -> Vec<&'a Match> {
|
||||||
self.cache.iter().map(|(_, m)| *m).collect()
|
self.cache.iter().map(|(_, m)| *m).collect()
|
||||||
|
@ -59,15 +55,6 @@ impl<'a> super::engine::process::middleware::render::MatchProvider<'a> for Match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> super::engine::process::middleware::match_select::MatchProvider<'a> for MatchCache<'a> {
|
|
||||||
fn get_matches(&self, ids: &[i32]) -> Vec<&'a Match> {
|
|
||||||
ids
|
|
||||||
.iter()
|
|
||||||
.flat_map(|id| self.cache.get(&id).map(|m| *m))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> crate::engine::process::MatchInfoProvider for MatchCache<'a> {
|
impl<'a> crate::engine::process::MatchInfoProvider for MatchCache<'a> {
|
||||||
fn get_force_mode(&self, match_id: i32) -> Option<crate::engine::event::effect::TextInjectMode> {
|
fn get_force_mode(&self, match_id: i32) -> Option<crate::engine::event::effect::TextInjectMode> {
|
||||||
let m = self.cache.get(&match_id)?;
|
let m = self.cache.get(&match_id)?;
|
||||||
|
@ -87,3 +74,79 @@ impl<'a> crate::engine::process::MatchInfoProvider for MatchCache<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CombinedMatchCache<'a> {
|
||||||
|
user_match_cache: &'a MatchCache<'a>,
|
||||||
|
builtin_match_cache: HashMap<i32, &'a BuiltInMatch>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum MatchVariant<'a> {
|
||||||
|
User(&'a Match),
|
||||||
|
Builtin(&'a BuiltInMatch),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CombinedMatchCache<'a> {
|
||||||
|
pub fn load(user_match_cache: &'a MatchCache<'a>, builtin_matches: &'a [BuiltInMatch]) -> Self {
|
||||||
|
let mut builtin_match_cache = HashMap::new();
|
||||||
|
|
||||||
|
for m in builtin_matches {
|
||||||
|
builtin_match_cache.insert(m.id, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
builtin_match_cache,
|
||||||
|
user_match_cache,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, match_id: i32) -> Option<MatchVariant<'a>> {
|
||||||
|
if let Some(user_match) = self.user_match_cache.cache.get(&match_id).map(|m| *m) {
|
||||||
|
return Some(MatchVariant::User(user_match));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(builtin_match) = self.builtin_match_cache.get(&match_id).map(|m| *m) {
|
||||||
|
return Some(MatchVariant::Builtin(builtin_match));
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> super::engine::process::middleware::match_select::MatchProvider<'a>
|
||||||
|
for CombinedMatchCache<'a>
|
||||||
|
{
|
||||||
|
fn get_matches(&self, ids: &[i32]) -> Vec<MatchSummary<'a>> {
|
||||||
|
ids
|
||||||
|
.iter()
|
||||||
|
.filter_map(|id| self.get(*id))
|
||||||
|
.map(|m| match m {
|
||||||
|
MatchVariant::User(m) => MatchSummary {
|
||||||
|
id: m.id,
|
||||||
|
label: m.description(),
|
||||||
|
tag: m.cause_description(),
|
||||||
|
},
|
||||||
|
MatchVariant::Builtin(m) => MatchSummary {
|
||||||
|
id: m.id,
|
||||||
|
label: m.label,
|
||||||
|
tag: m.triggers.first().map(String::as_ref),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> super::engine::process::middleware::multiplex::MatchProvider<'a>
|
||||||
|
for CombinedMatchCache<'a>
|
||||||
|
{
|
||||||
|
fn get(
|
||||||
|
&self,
|
||||||
|
match_id: i32,
|
||||||
|
) -> Option<super::engine::process::middleware::multiplex::MatchResult<'a>> {
|
||||||
|
Some(match self.get(match_id)? {
|
||||||
|
MatchVariant::User(m) => super::engine::process::middleware::multiplex::MatchResult::User(m),
|
||||||
|
MatchVariant::Builtin(m) => {
|
||||||
|
super::engine::process::middleware::multiplex::MatchResult::Builtin(m)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,9 @@ use self::ui::util::convert_icon_paths_to_tray_vec;
|
||||||
|
|
||||||
use super::{CliModule, CliModuleArgs};
|
use super::{CliModule, CliModuleArgs};
|
||||||
|
|
||||||
|
mod builtin;
|
||||||
mod config;
|
mod config;
|
||||||
|
mod context;
|
||||||
mod daemon_monitor;
|
mod daemon_monitor;
|
||||||
mod engine;
|
mod engine;
|
||||||
mod ipc;
|
mod ipc;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user