feat(engine): add components to support ipc match exec

This commit is contained in:
Federico Terzi 2021-10-31 15:43:50 +01:00
parent 119d537fb7
commit b38623376e
6 changed files with 120 additions and 4 deletions

View File

@ -0,0 +1,26 @@
/*
* 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::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub struct MatchExecRequestEvent {
pub trigger: Option<String>,
pub args: HashMap<String, String>,
}

View File

@ -18,6 +18,7 @@
*/ */
pub mod effect; pub mod effect;
pub mod external;
pub mod input; pub mod input;
pub mod internal; pub mod internal;
pub mod ui; pub mod ui;
@ -60,6 +61,9 @@ pub enum EventType {
TrayIconClicked, TrayIconClicked,
ContextMenuClicked(input::ContextMenuClickedEvent), ContextMenuClicked(input::ContextMenuClickedEvent),
// External requests
MatchExecRequest(external::MatchExecRequestEvent),
// Internal // Internal
MatchesDetected(internal::MatchesDetectedEvent), MatchesDetected(internal::MatchesDetectedEvent),
MatchSelected(internal::MatchSelectedEvent), MatchSelected(internal::MatchSelectedEvent),

View File

@ -33,16 +33,16 @@ use super::{
render::RenderMiddleware, render::RenderMiddleware,
}, },
DisableOptions, EnabledStatusProvider, MatchFilter, MatchInfoProvider, MatchProvider, DisableOptions, EnabledStatusProvider, MatchFilter, MatchInfoProvider, MatchProvider,
MatchSelector, Matcher, MatcherMiddlewareConfigProvider, Middleware, ModifierStateProvider, MatchResolver, MatchSelector, Matcher, MatcherMiddlewareConfigProvider, Middleware,
Multiplexer, PathProvider, Processor, Renderer, UndoEnabledProvider, ModifierStateProvider, Multiplexer, PathProvider, Processor, Renderer, UndoEnabledProvider,
}; };
use crate::{ use crate::{
event::{Event, EventType}, event::{Event, EventType},
process::middleware::{ process::middleware::{
context_menu::ContextMenuMiddleware, disable::DisableMiddleware, exit::ExitMiddleware, context_menu::ContextMenuMiddleware, disable::DisableMiddleware, exit::ExitMiddleware,
hotkey::HotKeyMiddleware, icon_status::IconStatusMiddleware, hotkey::HotKeyMiddleware, icon_status::IconStatusMiddleware,
image_resolve::ImageResolverMiddleware, search::SearchMiddleware, suppress::SuppressMiddleware, image_resolve::ImageResolverMiddleware, match_exec::MatchExecRequestMiddleware,
undo::UndoMiddleware, search::SearchMiddleware, suppress::SuppressMiddleware, undo::UndoMiddleware,
}, },
}; };
use std::collections::VecDeque; use std::collections::VecDeque;
@ -70,6 +70,7 @@ impl<'a> DefaultProcessor<'a> {
undo_enabled_provider: &'a dyn UndoEnabledProvider, undo_enabled_provider: &'a dyn UndoEnabledProvider,
enabled_status_provider: &'a dyn EnabledStatusProvider, enabled_status_provider: &'a dyn EnabledStatusProvider,
modifier_state_provider: &'a dyn ModifierStateProvider, modifier_state_provider: &'a dyn ModifierStateProvider,
match_resolver: &'a dyn MatchResolver,
) -> DefaultProcessor<'a> { ) -> DefaultProcessor<'a> {
Self { Self {
event_queue: VecDeque::new(), event_queue: VecDeque::new(),
@ -82,6 +83,7 @@ impl<'a> DefaultProcessor<'a> {
matcher_options_provider, matcher_options_provider,
modifier_state_provider, modifier_state_provider,
)), )),
Box::new(MatchExecRequestMiddleware::new(match_resolver)),
Box::new(SuppressMiddleware::new(enabled_status_provider)), Box::new(SuppressMiddleware::new(enabled_status_provider)),
Box::new(ContextMenuMiddleware::new()), Box::new(ContextMenuMiddleware::new()),
Box::new(HotKeyMiddleware::new()), Box::new(HotKeyMiddleware::new()),

View File

@ -0,0 +1,80 @@
/*
* 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 log::warn;
use super::super::Middleware;
use crate::event::{
internal::{DetectedMatch, MatchesDetectedEvent},
Event, EventType,
};
pub trait MatchResolver {
fn find_matches_from_trigger(&self, trigger: &str) -> Vec<DetectedMatch>;
}
pub struct MatchExecRequestMiddleware<'a> {
match_resolver: &'a dyn MatchResolver,
}
impl<'a> MatchExecRequestMiddleware<'a> {
pub fn new(match_resolver: &'a dyn MatchResolver) -> Self {
Self { match_resolver }
}
}
impl<'a> Middleware for MatchExecRequestMiddleware<'a> {
fn name(&self) -> &'static str {
"match_exec_request"
}
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
if let EventType::MatchExecRequest(m_event) = &event.etype {
let mut matches = if let Some(trigger) = &m_event.trigger {
self.match_resolver.find_matches_from_trigger(trigger)
} else {
Vec::new()
};
// Inject the request args into the detected matches
matches.iter_mut().for_each(|m| {
for (key, value) in &m_event.args {
m.args.insert(key.to_string(), value.to_string());
}
});
if matches.is_empty() {
warn!("received match exec request, but no matches have been found for the given query.");
return Event::caused_by(event.source_id, EventType::NOOP);
}
return Event::caused_by(
event.source_id,
EventType::MatchesDetected(MatchesDetectedEvent {
matches,
is_search: false,
}),
);
}
event
}
}
// TODO: test

View File

@ -29,6 +29,7 @@ pub mod hotkey;
pub mod icon_status; pub mod icon_status;
pub mod image_resolve; pub mod image_resolve;
pub mod markdown; pub mod markdown;
pub mod match_exec;
pub mod match_select; pub mod match_select;
pub mod matcher; pub mod matcher;
pub mod multiplex; pub mod multiplex;

View File

@ -37,6 +37,7 @@ pub use middleware::action::{EventSequenceProvider, MatchInfoProvider};
pub use middleware::delay_modifiers::ModifierStatusProvider; pub use middleware::delay_modifiers::ModifierStatusProvider;
pub use middleware::disable::DisableOptions; pub use middleware::disable::DisableOptions;
pub use middleware::image_resolve::PathProvider; pub use middleware::image_resolve::PathProvider;
pub use middleware::match_exec::MatchResolver;
pub use middleware::match_select::{MatchFilter, MatchSelector}; pub use middleware::match_select::{MatchFilter, MatchSelector};
pub use middleware::matcher::{ pub use middleware::matcher::{
MatchResult, Matcher, MatcherEvent, MatcherMiddlewareConfigProvider, ModifierState, MatchResult, Matcher, MatcherEvent, MatcherMiddlewareConfigProvider, ModifierState,
@ -65,6 +66,7 @@ pub fn default<'a, MatcherState>(
undo_enabled_provider: &'a dyn UndoEnabledProvider, undo_enabled_provider: &'a dyn UndoEnabledProvider,
enabled_status_provider: &'a dyn EnabledStatusProvider, enabled_status_provider: &'a dyn EnabledStatusProvider,
modifier_state_provider: &'a dyn ModifierStateProvider, modifier_state_provider: &'a dyn ModifierStateProvider,
match_resolver: &'a dyn MatchResolver,
) -> impl Processor + 'a { ) -> impl Processor + 'a {
default::DefaultProcessor::new( default::DefaultProcessor::new(
matchers, matchers,
@ -82,5 +84,6 @@ pub fn default<'a, MatcherState>(
undo_enabled_provider, undo_enabled_provider,
enabled_status_provider, enabled_status_provider,
modifier_state_provider, modifier_state_provider,
match_resolver,
) )
} }