feat(core): improve support for word matches

This commit is contained in:
Federico Terzi 2021-04-18 12:22:08 +02:00
parent 97b789e946
commit 04f1449046
11 changed files with 66 additions and 24 deletions

View File

@ -17,7 +17,10 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use espanso_match::rolling::{matcher::RollingMatcher, RollingMatch};
use espanso_match::rolling::{
matcher::{RollingMatcher, RollingMatcherOptions},
RollingMatch,
};
use crate::engine::{
event::keyboard::Key,
@ -32,13 +35,30 @@ pub struct RollingMatcherAdapter {
impl RollingMatcherAdapter {
pub fn new(matches: &[RollingMatch<i32>]) -> Self {
let matcher = RollingMatcher::new(matches, Default::default());
// TODO: load them from config
let matcher = RollingMatcher::new(
matches,
RollingMatcherOptions {
char_word_separators: vec![
" ".to_string(),
",".to_string(),
".".to_string(),
"?".to_string(),
"!".to_string(),
"\r".to_string(),
"\n".to_string(),
(22u8 as char).to_string(),
],
key_word_separators: vec![],
},
);
Self { matcher }
}
}
impl <'a> Matcher<'a, MatcherState<'a>> for RollingMatcherAdapter {
impl<'a> Matcher<'a, MatcherState<'a>> for RollingMatcherAdapter {
fn process(
&'a self,
prev_state: Option<&MatcherState<'a>>,
@ -80,8 +100,10 @@ impl From<espanso_match::MatchResult<i32>> for MatchResult {
fn from(result: espanso_match::MatchResult<i32>) -> Self {
Self {
id: result.id,
trigger: result.trigger,
args: result.vars,
trigger: result.trigger,
left_separator: result.left_separator,
right_separator: result.right_separator,
args: result.vars,
}
}
}

View File

@ -21,10 +21,7 @@ use std::collections::HashMap;
use espanso_config::matches::{Match, MatchEffect};
use crate::engine::{
event::{render::RenderingRequestedEvent, Event},
process::Multiplexer,
};
use crate::engine::{event::{Event, matches::DetectedMatch, render::RenderingRequestedEvent}, process::Multiplexer};
pub trait MatchProvider<'a> {
fn get(&self, match_id: i32) -> Option<&'a Match>;
@ -41,14 +38,16 @@ impl<'a> MultiplexAdapter<'a> {
}
impl<'a> Multiplexer for MultiplexAdapter<'a> {
fn convert(&self, match_id: i32, trigger: Option<String>, trigger_args: HashMap<String, String>) -> Option<Event> {
let m = self.provider.get(match_id)?;
fn convert(&self, detected_match: DetectedMatch) -> Option<Event> {
let m = self.provider.get(detected_match.id)?;
match &m.effect {
MatchEffect::Text(_) => Some(Event::RenderingRequested(RenderingRequestedEvent {
match_id,
trigger,
trigger_args,
match_id: detected_match.id,
trigger: detected_match.trigger,
left_separator: detected_match.left_separator,
right_separator: detected_match.right_separator,
trigger_args: detected_match.args,
})),
// TODO: think about rich text and image
MatchEffect::None => None,

View File

@ -20,6 +20,7 @@
#[derive(Debug, Clone, PartialEq)]
pub struct TriggerCompensationEvent {
pub trigger: String,
pub left_separator: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]

View File

@ -28,6 +28,8 @@ pub struct MatchesDetectedEvent {
pub struct DetectedMatch {
pub id: i32,
pub trigger: Option<String>,
pub left_separator: Option<String>,
pub right_separator: Option<String>,
pub args: HashMap<String, String>,
}

View File

@ -23,6 +23,8 @@ use std::collections::HashMap;
pub struct RenderingRequestedEvent {
pub match_id: i32,
pub trigger: Option<String>,
pub left_separator: Option<String>,
pub right_separator: Option<String>,
pub trigger_args: HashMap<String, String>,
}

View File

@ -61,11 +61,18 @@ impl<'a> Middleware for ActionMiddleware<'a> {
.collect(),
})
}
Event::TriggerCompensation(m_event) => Event::KeySequenceInject(KeySequenceInjectRequest {
keys: (0..m_event.trigger.chars().count())
.map(|_| Key::Backspace)
.collect(),
}),
Event::TriggerCompensation(m_event) => {
let mut backspace_count = m_event.trigger.chars().count();
// We want to preserve the left separator if present
if let Some(left_separator) = &m_event.left_separator {
backspace_count -= left_separator.chars().count();
}
Event::KeySequenceInject(KeySequenceInjectRequest {
keys: (0..backspace_count).map(|_| Key::Backspace).collect(),
})
}
_ => event,
}

View File

@ -53,6 +53,7 @@ impl Middleware for CauseCompensateMiddleware {
// Before the event, place a trigger compensation
return Event::TriggerCompensation(TriggerCompensationEvent {
trigger: trigger.clone(),
left_separator: m_event.chosen.left_separator.clone(),
});
} else {
return compensated_event;

View File

@ -105,6 +105,8 @@ impl<'a, State> Middleware for MatcherMiddleware<'a, State> {
.map(|result| DetectedMatch {
id: result.id,
trigger: Some(result.trigger),
right_separator: result.right_separator,
left_separator: result.left_separator,
args: result.args,
})
.collect(),

View File

@ -39,7 +39,7 @@ impl<'a> Middleware for MultiplexMiddleware<'a> {
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
if let Event::CauseCompensatedMatch(m_event) = event {
return match self.multiplexer.convert(m_event.m.id, m_event.m.trigger, m_event.m.args) {
return match self.multiplexer.convert(m_event.m) {
Some(event) => event,
None => {
error!("match multiplexing failed");

View File

@ -48,6 +48,12 @@ impl<'a> Middleware for RenderMiddleware<'a> {
if let Event::RenderingRequested(m_event) = event {
match self.renderer.render(m_event.match_id, m_event.trigger_args) {
Ok(body) => {
let body = if let Some(right_separator) = m_event.right_separator {
format!("{}{}", body, right_separator)
} else {
body
};
return Event::Rendered(RenderedEvent {
match_id: m_event.match_id,
body,

View File

@ -17,7 +17,7 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use super::{event::keyboard::Key, Event};
use super::{Event, event::{keyboard::Key, matches::DetectedMatch}};
use anyhow::Result;
use std::collections::HashMap;
use thiserror::Error;
@ -56,6 +56,8 @@ pub enum MatcherEvent {
pub struct MatchResult {
pub id: i32,
pub trigger: String,
pub left_separator: Option<String>,
pub right_separator: Option<String>,
pub args: HashMap<String, String>,
}
@ -70,9 +72,7 @@ pub trait MatchSelector {
pub trait Multiplexer {
fn convert(
&self,
match_id: i32,
trigger: Option<String>,
trigger_args: HashMap<String, String>,
m: DetectedMatch,
) -> Option<Event>;
}