feat(core): implement image matches
This commit is contained in:
parent
7a8e39fdad
commit
ddd62b225f
|
@ -17,10 +17,12 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use espanso_inject::{Injector, keys::Key};
|
use espanso_inject::{Injector, keys::Key};
|
||||||
use espanso_clipboard::Clipboard;
|
use espanso_clipboard::Clipboard;
|
||||||
|
|
||||||
use crate::engine::{dispatch::TextInjector, dispatch::HtmlInjector};
|
use crate::engine::{dispatch::HtmlInjector, dispatch::{ImageInjector, TextInjector}};
|
||||||
|
|
||||||
pub struct ClipboardInjectorAdapter<'a> {
|
pub struct ClipboardInjectorAdapter<'a> {
|
||||||
injector: &'a dyn Injector,
|
injector: &'a dyn Injector,
|
||||||
|
@ -71,3 +73,19 @@ impl <'a> HtmlInjector for ClipboardInjectorAdapter<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <'a> ImageInjector for ClipboardInjectorAdapter<'a> {
|
||||||
|
fn inject_image(&self, image_path: &str) -> anyhow::Result<()> {
|
||||||
|
let path = PathBuf::from(image_path);
|
||||||
|
if !path.is_file() {
|
||||||
|
return Err(std::io::Error::new(std::io::ErrorKind::NotFound, "image can't be found in the given path").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle clipboard restoration
|
||||||
|
self.clipboard.set_image(&path)?;
|
||||||
|
|
||||||
|
self.send_paste_combination()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,12 +22,15 @@ use espanso_config::{config::ConfigStore, matches::store::MatchStore};
|
||||||
use espanso_path::Paths;
|
use espanso_path::Paths;
|
||||||
use ui::selector::MatchSelectorAdapter;
|
use ui::selector::MatchSelectorAdapter;
|
||||||
|
|
||||||
|
use crate::cli::worker::engine::path::PathProviderAdapter;
|
||||||
|
|
||||||
use super::ui::icon::IconPaths;
|
use super::ui::icon::IconPaths;
|
||||||
|
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
pub mod match_cache;
|
pub mod match_cache;
|
||||||
pub mod matcher;
|
pub mod matcher;
|
||||||
pub mod multiplex;
|
pub mod multiplex;
|
||||||
|
pub mod path;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
@ -99,6 +102,7 @@ pub fn initialize_and_spawn(
|
||||||
]);
|
]);
|
||||||
let renderer_adapter =
|
let renderer_adapter =
|
||||||
super::engine::render::RendererAdapter::new(&match_cache, &config_manager, &renderer);
|
super::engine::render::RendererAdapter::new(&match_cache, &config_manager, &renderer);
|
||||||
|
let path_provider = PathProviderAdapter::new(&paths);
|
||||||
|
|
||||||
let mut processor = crate::engine::process::default(
|
let mut processor = crate::engine::process::default(
|
||||||
&matchers,
|
&matchers,
|
||||||
|
@ -109,6 +113,7 @@ pub fn initialize_and_spawn(
|
||||||
&match_cache,
|
&match_cache,
|
||||||
&modifier_state_store,
|
&modifier_state_store,
|
||||||
&sequencer,
|
&sequencer,
|
||||||
|
&path_provider,
|
||||||
);
|
);
|
||||||
|
|
||||||
let event_injector =
|
let event_injector =
|
||||||
|
@ -125,6 +130,7 @@ pub fn initialize_and_spawn(
|
||||||
&config_manager,
|
&config_manager,
|
||||||
&key_injector,
|
&key_injector,
|
||||||
&clipboard_injector,
|
&clipboard_injector,
|
||||||
|
&clipboard_injector,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
|
let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
|
||||||
|
|
|
@ -19,14 +19,7 @@
|
||||||
|
|
||||||
use espanso_config::matches::{Match, MatchEffect};
|
use espanso_config::matches::{Match, MatchEffect};
|
||||||
|
|
||||||
use crate::engine::{
|
use crate::engine::{event::{EventType, internal::DetectedMatch, internal::{ImageRequestedEvent, RenderingRequestedEvent, TextFormat}}, process::Multiplexer};
|
||||||
event::{
|
|
||||||
internal::DetectedMatch,
|
|
||||||
internal::{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<&'a Match>;
|
||||||
|
@ -55,7 +48,10 @@ impl<'a> Multiplexer for MultiplexAdapter<'a> {
|
||||||
trigger_args: detected_match.args,
|
trigger_args: detected_match.args,
|
||||||
format: convert_format(&effect.format),
|
format: convert_format(&effect.format),
|
||||||
})),
|
})),
|
||||||
// TODO: think about image
|
MatchEffect::Image(effect) => Some(EventType::ImageRequested(ImageRequestedEvent {
|
||||||
|
match_id: detected_match.id,
|
||||||
|
image_path: effect.path.clone(),
|
||||||
|
})),
|
||||||
MatchEffect::None => None,
|
MatchEffect::None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
40
espanso/src/cli/worker/engine/path.rs
Normal file
40
espanso/src/cli/worker/engine/path.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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 espanso_path::Paths;
|
||||||
|
|
||||||
|
use crate::engine::process::PathProvider;
|
||||||
|
|
||||||
|
pub struct PathProviderAdapter<'a> {
|
||||||
|
paths: &'a Paths,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a> PathProviderAdapter<'a> {
|
||||||
|
pub fn new(paths: &'a Paths) -> Self {
|
||||||
|
Self {
|
||||||
|
paths,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a> PathProvider for PathProviderAdapter<'a> {
|
||||||
|
fn get_config_path(&self) -> &std::path::Path {
|
||||||
|
&self.paths.config
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use super::Event;
|
use super::{Event, ImageInjector};
|
||||||
use super::{ModeProvider, Dispatcher, Executor, KeyInjector, TextInjector, HtmlInjector};
|
use super::{ModeProvider, Dispatcher, Executor, KeyInjector, TextInjector, HtmlInjector};
|
||||||
|
|
||||||
pub struct DefaultDispatcher<'a> {
|
pub struct DefaultDispatcher<'a> {
|
||||||
|
@ -31,6 +31,7 @@ impl<'a> DefaultDispatcher<'a> {
|
||||||
mode_provider: &'a dyn ModeProvider,
|
mode_provider: &'a dyn ModeProvider,
|
||||||
key_injector: &'a dyn KeyInjector,
|
key_injector: &'a dyn KeyInjector,
|
||||||
html_injector: &'a dyn HtmlInjector,
|
html_injector: &'a dyn HtmlInjector,
|
||||||
|
image_injector: &'a dyn ImageInjector,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
executors: vec![
|
executors: vec![
|
||||||
|
@ -44,6 +45,9 @@ impl<'a> DefaultDispatcher<'a> {
|
||||||
)),
|
)),
|
||||||
Box::new(super::executor::html_inject::HtmlInjectExecutor::new(
|
Box::new(super::executor::html_inject::HtmlInjectExecutor::new(
|
||||||
html_injector,
|
html_injector,
|
||||||
|
)),
|
||||||
|
Box::new(super::executor::image_inject::ImageInjectExecutor::new(
|
||||||
|
image_injector,
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
56
espanso/src/engine/dispatch/executor/image_inject.rs
Normal file
56
espanso/src/engine/dispatch/executor/image_inject.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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::super::{Event, Executor};
|
||||||
|
use crate::engine::event::EventType;
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
pub trait ImageInjector {
|
||||||
|
fn inject_image(&self, path: &str) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImageInjectExecutor<'a> {
|
||||||
|
injector: &'a dyn ImageInjector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ImageInjectExecutor<'a> {
|
||||||
|
pub fn new(injector: &'a dyn ImageInjector) -> Self {
|
||||||
|
Self { injector }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Executor for ImageInjectExecutor<'a> {
|
||||||
|
fn execute(&self, event: &Event) -> bool {
|
||||||
|
if let EventType::ImageInject(inject_event) = &event.etype {
|
||||||
|
if let Err(error) = self
|
||||||
|
.injector
|
||||||
|
.inject_image(&inject_event.image_path)
|
||||||
|
{
|
||||||
|
error!("image injector reported an error: {:?}", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
|
@ -19,4 +19,5 @@
|
||||||
|
|
||||||
pub mod text_inject;
|
pub mod text_inject;
|
||||||
pub mod key_inject;
|
pub mod key_inject;
|
||||||
pub mod html_inject;
|
pub mod html_inject;
|
||||||
|
pub mod image_inject;
|
|
@ -35,6 +35,7 @@ pub trait Dispatcher {
|
||||||
// Re-export dependency injection entities
|
// Re-export dependency injection entities
|
||||||
pub use executor::html_inject::HtmlInjector;
|
pub use executor::html_inject::HtmlInjector;
|
||||||
pub use executor::text_inject::{Mode, ModeProvider, TextInjector};
|
pub use executor::text_inject::{Mode, ModeProvider, TextInjector};
|
||||||
|
pub use executor::image_inject::{ImageInjector};
|
||||||
|
|
||||||
// TODO: move into module
|
// TODO: move into module
|
||||||
pub trait KeyInjector {
|
pub trait KeyInjector {
|
||||||
|
@ -47,6 +48,7 @@ pub fn default<'a>(
|
||||||
mode_provider: &'a dyn ModeProvider,
|
mode_provider: &'a dyn ModeProvider,
|
||||||
key_injector: &'a dyn KeyInjector,
|
key_injector: &'a dyn KeyInjector,
|
||||||
html_injector: &'a dyn HtmlInjector,
|
html_injector: &'a dyn HtmlInjector,
|
||||||
|
image_injector: &'a dyn ImageInjector,
|
||||||
) -> impl Dispatcher + 'a {
|
) -> impl Dispatcher + 'a {
|
||||||
default::DefaultDispatcher::new(
|
default::DefaultDispatcher::new(
|
||||||
event_injector,
|
event_injector,
|
||||||
|
@ -54,5 +56,6 @@ pub fn default<'a>(
|
||||||
mode_provider,
|
mode_provider,
|
||||||
key_injector,
|
key_injector,
|
||||||
html_injector,
|
html_injector,
|
||||||
|
image_injector,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,4 +55,9 @@ pub enum TextInjectMode {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct KeySequenceInjectRequest {
|
pub struct KeySequenceInjectRequest {
|
||||||
pub keys: Vec<Key>,
|
pub keys: Vec<Key>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ImageInjectRequest {
|
||||||
|
pub image_path: String,
|
||||||
}
|
}
|
|
@ -60,6 +60,17 @@ pub enum TextFormat {
|
||||||
Html,
|
Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct ImageRequestedEvent {
|
||||||
|
pub match_id: i32,
|
||||||
|
pub image_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct ImageResolvedEvent {
|
||||||
|
pub image_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct RenderedEvent {
|
pub struct RenderedEvent {
|
||||||
pub match_id: i32,
|
pub match_id: i32,
|
||||||
|
|
|
@ -59,7 +59,9 @@ pub enum EventType {
|
||||||
CauseCompensatedMatch(internal::CauseCompensatedMatchEvent),
|
CauseCompensatedMatch(internal::CauseCompensatedMatchEvent),
|
||||||
|
|
||||||
RenderingRequested(internal::RenderingRequestedEvent),
|
RenderingRequested(internal::RenderingRequestedEvent),
|
||||||
|
ImageRequested(internal::ImageRequestedEvent),
|
||||||
Rendered(internal::RenderedEvent),
|
Rendered(internal::RenderedEvent),
|
||||||
|
ImageResolved(internal::ImageResolvedEvent),
|
||||||
MatchInjected,
|
MatchInjected,
|
||||||
DiscardPrevious(internal::DiscardPreviousEvent),
|
DiscardPrevious(internal::DiscardPreviousEvent),
|
||||||
|
|
||||||
|
@ -71,4 +73,5 @@ pub enum EventType {
|
||||||
TextInject(effect::TextInjectRequest),
|
TextInject(effect::TextInjectRequest),
|
||||||
MarkdownInject(effect::MarkdownInjectRequest),
|
MarkdownInject(effect::MarkdownInjectRequest),
|
||||||
HtmlInject(effect::HtmlInjectRequest),
|
HtmlInject(effect::HtmlInjectRequest),
|
||||||
|
ImageInject(effect::ImageInjectRequest),
|
||||||
}
|
}
|
|
@ -19,13 +19,13 @@
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use super::{MatchFilter, MatchInfoProvider, MatchSelector, Matcher, Middleware, Multiplexer, Processor, Renderer, middleware::{
|
use super::{MatchFilter, MatchInfoProvider, MatchSelector, Matcher, Middleware, Multiplexer, PathProvider, Processor, Renderer, middleware::{
|
||||||
match_select::MatchSelectMiddleware, matcher::MatcherMiddleware, multiplex::MultiplexMiddleware,
|
match_select::MatchSelectMiddleware, matcher::MatcherMiddleware, multiplex::MultiplexMiddleware,
|
||||||
render::RenderMiddleware, action::{ActionMiddleware, EventSequenceProvider}, cursor_hint::CursorHintMiddleware, cause::CauseCompensateMiddleware,
|
render::RenderMiddleware, action::{ActionMiddleware, EventSequenceProvider}, cursor_hint::CursorHintMiddleware, cause::CauseCompensateMiddleware,
|
||||||
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider}, markdown::MarkdownMiddleware,
|
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider}, markdown::MarkdownMiddleware,
|
||||||
past_discard::PastEventsDiscardMiddleware,
|
past_discard::PastEventsDiscardMiddleware,
|
||||||
}};
|
}};
|
||||||
use crate::engine::event::{Event, EventType};
|
use crate::engine::{event::{Event, EventType}, process::middleware::image_resolve::ImageResolverMiddleware};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub struct DefaultProcessor<'a> {
|
pub struct DefaultProcessor<'a> {
|
||||||
|
@ -43,6 +43,7 @@ impl<'a> DefaultProcessor<'a> {
|
||||||
match_info_provider: &'a dyn MatchInfoProvider,
|
match_info_provider: &'a dyn MatchInfoProvider,
|
||||||
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
||||||
event_sequence_provider: &'a dyn EventSequenceProvider,
|
event_sequence_provider: &'a dyn EventSequenceProvider,
|
||||||
|
path_provider: &'a dyn PathProvider,
|
||||||
) -> DefaultProcessor<'a> {
|
) -> DefaultProcessor<'a> {
|
||||||
Self {
|
Self {
|
||||||
event_queue: VecDeque::new(),
|
event_queue: VecDeque::new(),
|
||||||
|
@ -53,6 +54,7 @@ impl<'a> DefaultProcessor<'a> {
|
||||||
Box::new(CauseCompensateMiddleware::new()),
|
Box::new(CauseCompensateMiddleware::new()),
|
||||||
Box::new(MultiplexMiddleware::new(multiplexer)),
|
Box::new(MultiplexMiddleware::new(multiplexer)),
|
||||||
Box::new(RenderMiddleware::new(renderer)),
|
Box::new(RenderMiddleware::new(renderer)),
|
||||||
|
Box::new(ImageResolverMiddleware::new(path_provider)),
|
||||||
Box::new(CursorHintMiddleware::new()),
|
Box::new(CursorHintMiddleware::new()),
|
||||||
Box::new(ActionMiddleware::new(match_info_provider, event_sequence_provider)),
|
Box::new(ActionMiddleware::new(match_info_provider, event_sequence_provider)),
|
||||||
Box::new(MarkdownMiddleware::new()),
|
Box::new(MarkdownMiddleware::new()),
|
||||||
|
|
|
@ -18,7 +18,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use super::super::Middleware;
|
use super::super::Middleware;
|
||||||
use crate::engine::event::{Event, EventType, effect::{HtmlInjectRequest, KeySequenceInjectRequest, MarkdownInjectRequest, TextInjectMode, TextInjectRequest}, input::Key, internal::{DiscardPreviousEvent, TextFormat}};
|
use crate::engine::event::{
|
||||||
|
effect::{
|
||||||
|
HtmlInjectRequest, ImageInjectRequest, KeySequenceInjectRequest, MarkdownInjectRequest,
|
||||||
|
TextInjectMode, TextInjectRequest,
|
||||||
|
},
|
||||||
|
input::Key,
|
||||||
|
internal::{DiscardPreviousEvent, TextFormat},
|
||||||
|
Event, EventType,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait MatchInfoProvider {
|
pub trait MatchInfoProvider {
|
||||||
fn get_force_mode(&self, match_id: i32) -> Option<TextInjectMode>;
|
fn get_force_mode(&self, match_id: i32) -> Option<TextInjectMode>;
|
||||||
|
@ -52,7 +60,7 @@ impl<'a> Middleware for ActionMiddleware<'a> {
|
||||||
|
|
||||||
fn next(&self, event: Event, dispatch: &mut dyn FnMut(Event)) -> Event {
|
fn next(&self, event: Event, dispatch: &mut dyn FnMut(Event)) -> Event {
|
||||||
match &event.etype {
|
match &event.etype {
|
||||||
EventType::Rendered(m_event) => {
|
EventType::Rendered(_) | EventType::ImageResolved(_) => {
|
||||||
dispatch(Event::caused_by(event.source_id, EventType::MatchInjected));
|
dispatch(Event::caused_by(event.source_id, EventType::MatchInjected));
|
||||||
dispatch(Event::caused_by(
|
dispatch(Event::caused_by(
|
||||||
event.source_id,
|
event.source_id,
|
||||||
|
@ -61,21 +69,30 @@ impl<'a> Middleware for ActionMiddleware<'a> {
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
Event::caused_by(
|
match &event.etype {
|
||||||
event.source_id,
|
EventType::Rendered(m_event) => Event::caused_by(
|
||||||
match m_event.format {
|
event.source_id,
|
||||||
TextFormat::Plain => EventType::TextInject(TextInjectRequest {
|
match m_event.format {
|
||||||
text: m_event.body.clone(),
|
TextFormat::Plain => EventType::TextInject(TextInjectRequest {
|
||||||
force_mode: self.match_info_provider.get_force_mode(m_event.match_id),
|
text: m_event.body.clone(),
|
||||||
|
force_mode: self.match_info_provider.get_force_mode(m_event.match_id),
|
||||||
|
}),
|
||||||
|
TextFormat::Html => EventType::HtmlInject(HtmlInjectRequest {
|
||||||
|
html: m_event.body.clone(),
|
||||||
|
}),
|
||||||
|
TextFormat::Markdown => EventType::MarkdownInject(MarkdownInjectRequest {
|
||||||
|
markdown: m_event.body.clone(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
EventType::ImageResolved(m_event) => Event::caused_by(
|
||||||
|
event.source_id,
|
||||||
|
EventType::ImageInject(ImageInjectRequest {
|
||||||
|
image_path: m_event.image_path.clone(),
|
||||||
}),
|
}),
|
||||||
TextFormat::Html => EventType::HtmlInject(HtmlInjectRequest {
|
),
|
||||||
html: m_event.body.clone(),
|
_ => unreachable!()
|
||||||
}),
|
}
|
||||||
TextFormat::Markdown => EventType::MarkdownInject(MarkdownInjectRequest {
|
|
||||||
markdown: m_event.body.clone(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
EventType::CursorHintCompensation(m_event) => {
|
EventType::CursorHintCompensation(m_event) => {
|
||||||
dispatch(Event::caused_by(
|
dispatch(Event::caused_by(
|
||||||
|
|
81
espanso/src/engine/process/middleware/image_resolve.rs
Normal file
81
espanso/src/engine/process/middleware/image_resolve.rs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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::{
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::{error};
|
||||||
|
|
||||||
|
use super::super::Middleware;
|
||||||
|
use crate::engine::event::{Event, EventType, internal::ImageResolvedEvent};
|
||||||
|
|
||||||
|
pub trait PathProvider {
|
||||||
|
fn get_config_path(&self) -> &Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImageResolverMiddleware<'a> {
|
||||||
|
provider: &'a dyn PathProvider,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ImageResolverMiddleware<'a> {
|
||||||
|
pub fn new(provider: &'a dyn PathProvider) -> Self {
|
||||||
|
Self { provider }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Middleware for ImageResolverMiddleware<'a> {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"image_resolve"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
|
||||||
|
if let EventType::ImageRequested(m_event) = &event.etype {
|
||||||
|
// On Windows, we have to replace the forward / with the backslash \ in the path
|
||||||
|
let path = if cfg!(target_os = "windows") {
|
||||||
|
m_event.image_path.replace("/", "\\")
|
||||||
|
} else {
|
||||||
|
m_event.image_path.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = if path.contains("$CONFIG") {
|
||||||
|
let config_path = match self.provider.get_config_path().canonicalize() {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(err) => {
|
||||||
|
error!("unable to canonicalize the config path into the image resolver: {}", err);
|
||||||
|
self.provider.get_config_path().to_owned()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
path.replace("$CONFIG", &config_path.to_string_lossy())
|
||||||
|
} else {
|
||||||
|
path
|
||||||
|
};
|
||||||
|
|
||||||
|
return Event::caused_by(event.source_id, EventType::ImageResolved(ImageResolvedEvent {
|
||||||
|
image_path: path,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
|
@ -21,6 +21,7 @@ pub mod action;
|
||||||
pub mod cause;
|
pub mod cause;
|
||||||
pub mod cursor_hint;
|
pub mod cursor_hint;
|
||||||
pub mod delay_modifiers;
|
pub mod delay_modifiers;
|
||||||
|
pub mod image_resolve;
|
||||||
pub mod match_select;
|
pub mod match_select;
|
||||||
pub mod matcher;
|
pub mod matcher;
|
||||||
pub mod markdown;
|
pub mod markdown;
|
||||||
|
|
|
@ -94,6 +94,7 @@ pub enum RendererError {
|
||||||
|
|
||||||
pub use middleware::action::{MatchInfoProvider, EventSequenceProvider};
|
pub use middleware::action::{MatchInfoProvider, EventSequenceProvider};
|
||||||
pub use middleware::delay_modifiers::ModifierStatusProvider;
|
pub use middleware::delay_modifiers::ModifierStatusProvider;
|
||||||
|
pub use middleware::image_resolve::PathProvider;
|
||||||
|
|
||||||
pub fn default<'a, MatcherState>(
|
pub fn default<'a, MatcherState>(
|
||||||
matchers: &'a [&'a dyn Matcher<'a, MatcherState>],
|
matchers: &'a [&'a dyn Matcher<'a, MatcherState>],
|
||||||
|
@ -104,6 +105,7 @@ pub fn default<'a, MatcherState>(
|
||||||
match_info_provider: &'a dyn MatchInfoProvider,
|
match_info_provider: &'a dyn MatchInfoProvider,
|
||||||
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
||||||
event_sequence_provider: &'a dyn EventSequenceProvider,
|
event_sequence_provider: &'a dyn EventSequenceProvider,
|
||||||
|
path_provider: &'a dyn PathProvider,
|
||||||
) -> impl Processor + 'a {
|
) -> impl Processor + 'a {
|
||||||
default::DefaultProcessor::new(
|
default::DefaultProcessor::new(
|
||||||
matchers,
|
matchers,
|
||||||
|
@ -114,5 +116,6 @@ pub fn default<'a, MatcherState>(
|
||||||
match_info_provider,
|
match_info_provider,
|
||||||
modifier_status_provider,
|
modifier_status_provider,
|
||||||
event_sequence_provider,
|
event_sequence_provider,
|
||||||
|
path_provider,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user