feat(core): implement rich text matches
This commit is contained in:
parent
038798a2d6
commit
2f53752e97
251
Cargo.lock
generated
251
Cargo.lock
generated
|
@ -299,9 +299,11 @@ dependencies = [
|
|||
"espanso-path",
|
||||
"espanso-render",
|
||||
"espanso-ui",
|
||||
"html2text",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"maplit",
|
||||
"markdown",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simplelog",
|
||||
|
@ -459,6 +461,16 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
|
||||
[[package]]
|
||||
name = "futf"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b"
|
||||
dependencies = [
|
||||
"mac",
|
||||
"new_debug_unreachable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
|
@ -505,6 +517,31 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html2text"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26379dcb715e237b96102a12b505c553e2bffa74bae2e54658748d298660ef1"
|
||||
dependencies = [
|
||||
"html5ever",
|
||||
"markup5ever_rcdom",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html5ever"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b"
|
||||
dependencies = [
|
||||
"log",
|
||||
"mac",
|
||||
"markup5ever",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.0"
|
||||
|
@ -562,6 +599,12 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
|
||||
[[package]]
|
||||
name = "mac-notification-sys"
|
||||
version = "0.3.0"
|
||||
|
@ -589,6 +632,43 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "markdown"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef3aab6a1d529b112695f72beec5ee80e729cb45af58663ec902c8fac764ecdd"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"pipeline",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
"tendril",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever_rcdom"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b"
|
||||
dependencies = [
|
||||
"html5ever",
|
||||
"markup5ever",
|
||||
"tendril",
|
||||
"xml5ever",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
|
@ -613,6 +693,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "notify-rust"
|
||||
version = "4.2.2"
|
||||
|
@ -681,6 +767,50 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pipeline"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d15b6607fa632996eb8a17c9041cb6071cb75ac057abd45dece578723ea8c7c0"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
|
@ -693,6 +823,12 @@ version = "0.2.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
|
@ -730,6 +866,20 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"libc",
|
||||
"rand_chacha 0.2.2",
|
||||
"rand_core 0.5.1",
|
||||
"rand_hc 0.2.0",
|
||||
"rand_pcg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.3"
|
||||
|
@ -737,9 +887,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_chacha 0.3.0",
|
||||
"rand_core 0.6.2",
|
||||
"rand_hc",
|
||||
"rand_hc 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -767,6 +927,15 @@ version = "0.4.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.2"
|
||||
|
@ -776,6 +945,15 @@ dependencies = [
|
|||
"getrandom 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.0"
|
||||
|
@ -785,6 +963,15 @@ dependencies = [
|
|||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
|
@ -933,6 +1120,37 @@ dependencies = [
|
|||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"new_debug_unreachable",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string_cache_codegen"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
|
@ -1010,6 +1228,17 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tendril"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33"
|
||||
dependencies = [
|
||||
"futf",
|
||||
"mac",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
|
@ -1092,6 +1321,12 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
|
@ -1204,6 +1439,18 @@ dependencies = [
|
|||
"bitflags 0.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml5ever"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b1b52e6e8614d4a58b8e70cf51ec0cc21b256ad8206708bcff8139b5bbd6a59"
|
||||
dependencies = [
|
||||
"log",
|
||||
"mac",
|
||||
"markup5ever",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
|
|
|
@ -35,3 +35,5 @@ enum-as-inner = "0.3.3"
|
|||
dirs = "3.0.1"
|
||||
serde = { version = "1.0.123", features = ["derive"] }
|
||||
serde_json = "1.0.62"
|
||||
markdown = "0.3.0"
|
||||
html2text = "0.2.1"
|
|
@ -20,7 +20,7 @@
|
|||
use espanso_inject::{Injector, keys::Key};
|
||||
use espanso_clipboard::Clipboard;
|
||||
|
||||
use crate::engine::{dispatch::TextInjector};
|
||||
use crate::engine::{dispatch::TextInjector, dispatch::HtmlInjector};
|
||||
|
||||
pub struct ClipboardInjectorAdapter<'a> {
|
||||
injector: &'a dyn Injector,
|
||||
|
@ -34,6 +34,16 @@ impl <'a> ClipboardInjectorAdapter<'a> {
|
|||
clipboard,
|
||||
}
|
||||
}
|
||||
|
||||
fn send_paste_combination(&self) -> anyhow::Result<()> {
|
||||
// TODO: handle delay duration
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
||||
// TODO: handle options
|
||||
self.injector.send_key_combination(&[Key::Control, Key::V], Default::default())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> TextInjector for ClipboardInjectorAdapter<'a> {
|
||||
|
@ -45,11 +55,18 @@ impl <'a> TextInjector for ClipboardInjectorAdapter<'a> {
|
|||
// TODO: handle clipboard restoration
|
||||
self.clipboard.set_text(text)?;
|
||||
|
||||
// TODO: handle delay duration
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
||||
// TODO: handle options
|
||||
self.injector.send_key_combination(&[Key::Control, Key::V], Default::default())?;
|
||||
self.send_paste_combination()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> HtmlInjector for ClipboardInjectorAdapter<'a> {
|
||||
fn inject_html(&self, html: &str, fallback_text: &str) -> anyhow::Result<()> {
|
||||
// TODO: handle clipboard restoration
|
||||
self.clipboard.set_html(html, Some(fallback_text))?;
|
||||
|
||||
self.send_paste_combination()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ pub fn initialize_and_spawn(
|
|||
&clipboard_injector,
|
||||
&config_manager,
|
||||
&key_injector,
|
||||
&clipboard_injector,
|
||||
);
|
||||
|
||||
let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
|
||||
|
|
|
@ -19,7 +19,14 @@
|
|||
|
||||
use espanso_config::matches::{Match, MatchEffect};
|
||||
|
||||
use crate::engine::{event::{EventType, internal::DetectedMatch, internal::RenderingRequestedEvent}, process::Multiplexer};
|
||||
use crate::engine::{
|
||||
event::{
|
||||
internal::DetectedMatch,
|
||||
internal::{RenderingRequestedEvent, TextFormat},
|
||||
EventType,
|
||||
},
|
||||
process::Multiplexer,
|
||||
};
|
||||
|
||||
pub trait MatchProvider<'a> {
|
||||
fn get(&self, match_id: i32) -> Option<&'a Match>;
|
||||
|
@ -40,15 +47,24 @@ impl<'a> Multiplexer for MultiplexAdapter<'a> {
|
|||
let m = self.provider.get(detected_match.id)?;
|
||||
|
||||
match &m.effect {
|
||||
MatchEffect::Text(_) => Some(EventType::RenderingRequested(RenderingRequestedEvent {
|
||||
MatchEffect::Text(effect) => Some(EventType::RenderingRequested(RenderingRequestedEvent {
|
||||
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,
|
||||
format: convert_format(&effect.format),
|
||||
})),
|
||||
// TODO: think about rich text and image
|
||||
// TODO: think about image
|
||||
MatchEffect::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_format(format: &espanso_config::matches::TextFormat) -> TextFormat {
|
||||
match format {
|
||||
espanso_config::matches::TextFormat::Plain => TextFormat::Plain,
|
||||
espanso_config::matches::TextFormat::Markdown => TextFormat::Markdown,
|
||||
espanso_config::matches::TextFormat::Html => TextFormat::Html,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
use super::Event;
|
||||
use super::{ModeProvider, Dispatcher, Executor, KeyInjector, TextInjector};
|
||||
use super::{ModeProvider, Dispatcher, Executor, KeyInjector, TextInjector, HtmlInjector};
|
||||
|
||||
pub struct DefaultDispatcher<'a> {
|
||||
executors: Vec<Box<dyn Executor + 'a>>,
|
||||
|
@ -30,6 +30,7 @@ impl<'a> DefaultDispatcher<'a> {
|
|||
clipboard_injector: &'a dyn TextInjector,
|
||||
mode_provider: &'a dyn ModeProvider,
|
||||
key_injector: &'a dyn KeyInjector,
|
||||
html_injector: &'a dyn HtmlInjector,
|
||||
) -> Self {
|
||||
Self {
|
||||
executors: vec![
|
||||
|
@ -41,6 +42,9 @@ impl<'a> DefaultDispatcher<'a> {
|
|||
Box::new(super::executor::key_inject::KeyInjectExecutor::new(
|
||||
key_injector,
|
||||
)),
|
||||
Box::new(super::executor::html_inject::HtmlInjectExecutor::new(
|
||||
html_injector,
|
||||
))
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
61
espanso/src/engine/dispatch/executor/html_inject.rs
Normal file
61
espanso/src/engine/dispatch/executor/html_inject.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 HtmlInjector {
|
||||
fn inject_html(&self, html: &str, fallback: &str) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct HtmlInjectExecutor<'a> {
|
||||
injector: &'a dyn HtmlInjector,
|
||||
}
|
||||
|
||||
impl<'a> HtmlInjectExecutor<'a> {
|
||||
pub fn new(injector: &'a dyn HtmlInjector) -> Self {
|
||||
Self { injector }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Executor for HtmlInjectExecutor<'a> {
|
||||
fn execute(&self, event: &Event) -> bool {
|
||||
if let EventType::HtmlInject(inject_event) = &event.etype {
|
||||
// Render the text fallback for those applications that don't support HTML clipboard
|
||||
let decorator = html2text::render::text_renderer::TrivialDecorator::new();
|
||||
let fallback_text =
|
||||
html2text::from_read_with_decorator(inject_event.html.as_bytes(), 1000000, decorator);
|
||||
|
||||
if let Err(error) = self
|
||||
.injector
|
||||
.inject_html(&inject_event.html, &fallback_text)
|
||||
{
|
||||
error!("html injector reported an error: {:?}", error);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: test
|
|
@ -19,3 +19,4 @@
|
|||
|
||||
pub mod text_inject;
|
||||
pub mod key_inject;
|
||||
pub mod html_inject;
|
|
@ -33,7 +33,8 @@ pub trait Dispatcher {
|
|||
}
|
||||
|
||||
// Re-export dependency injection entities
|
||||
pub use executor::text_inject::{ModeProvider, Mode, TextInjector};
|
||||
pub use executor::html_inject::HtmlInjector;
|
||||
pub use executor::text_inject::{Mode, ModeProvider, TextInjector};
|
||||
|
||||
// TODO: move into module
|
||||
pub trait KeyInjector {
|
||||
|
@ -45,6 +46,13 @@ pub fn default<'a>(
|
|||
clipboard_injector: &'a dyn TextInjector,
|
||||
mode_provider: &'a dyn ModeProvider,
|
||||
key_injector: &'a dyn KeyInjector,
|
||||
html_injector: &'a dyn HtmlInjector,
|
||||
) -> impl Dispatcher + 'a {
|
||||
default::DefaultDispatcher::new(event_injector, clipboard_injector, mode_provider, key_injector)
|
||||
default::DefaultDispatcher::new(
|
||||
event_injector,
|
||||
clipboard_injector,
|
||||
mode_provider,
|
||||
key_injector,
|
||||
html_injector,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,16 @@ pub struct TextInjectRequest {
|
|||
pub force_mode: Option<TextInjectMode>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MarkdownInjectRequest {
|
||||
pub markdown: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HtmlInjectRequest {
|
||||
pub html: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum TextInjectMode {
|
||||
Keys,
|
||||
|
|
|
@ -50,12 +50,21 @@ pub struct RenderingRequestedEvent {
|
|||
pub left_separator: Option<String>,
|
||||
pub right_separator: Option<String>,
|
||||
pub trigger_args: HashMap<String, String>,
|
||||
pub format: TextFormat,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TextFormat {
|
||||
Plain,
|
||||
Markdown,
|
||||
Html,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct RenderedEvent {
|
||||
pub match_id: i32,
|
||||
pub body: String,
|
||||
pub format: TextFormat,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
|
|
@ -69,4 +69,6 @@ pub enum EventType {
|
|||
|
||||
KeySequenceInject(effect::KeySequenceInjectRequest),
|
||||
TextInject(effect::TextInjectRequest),
|
||||
MarkdownInject(effect::MarkdownInjectRequest),
|
||||
HtmlInject(effect::HtmlInjectRequest),
|
||||
}
|
|
@ -22,7 +22,7 @@ use log::trace;
|
|||
use super::{MatchFilter, MatchInfoProvider, MatchSelector, Matcher, Middleware, Multiplexer, Processor, Renderer, middleware::{
|
||||
match_select::MatchSelectMiddleware, matcher::MatcherMiddleware, multiplex::MultiplexMiddleware,
|
||||
render::RenderMiddleware, action::{ActionMiddleware, EventSequenceProvider}, cursor_hint::CursorHintMiddleware, cause::CauseCompensateMiddleware,
|
||||
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider},
|
||||
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider}, markdown::MarkdownMiddleware,
|
||||
past_discard::PastEventsDiscardMiddleware,
|
||||
}};
|
||||
use crate::engine::event::{Event, EventType};
|
||||
|
@ -55,6 +55,7 @@ impl<'a> DefaultProcessor<'a> {
|
|||
Box::new(RenderMiddleware::new(renderer)),
|
||||
Box::new(CursorHintMiddleware::new()),
|
||||
Box::new(ActionMiddleware::new(match_info_provider, event_sequence_provider)),
|
||||
Box::new(MarkdownMiddleware::new()),
|
||||
Box::new(DelayForModifierReleaseMiddleware::new(modifier_status_provider)),
|
||||
],
|
||||
}
|
||||
|
|
|
@ -18,12 +18,7 @@
|
|||
*/
|
||||
|
||||
use super::super::Middleware;
|
||||
use crate::engine::event::{
|
||||
effect::{KeySequenceInjectRequest, TextInjectMode, TextInjectRequest},
|
||||
input::Key,
|
||||
internal::DiscardPreviousEvent,
|
||||
Event, EventType,
|
||||
};
|
||||
use crate::engine::event::{Event, EventType, effect::{HtmlInjectRequest, KeySequenceInjectRequest, MarkdownInjectRequest, TextInjectMode, TextInjectRequest}, input::Key, internal::{DiscardPreviousEvent, TextFormat}};
|
||||
|
||||
pub trait MatchInfoProvider {
|
||||
fn get_force_mode(&self, match_id: i32) -> Option<TextInjectMode>;
|
||||
|
@ -68,10 +63,18 @@ impl<'a> Middleware for ActionMiddleware<'a> {
|
|||
|
||||
Event::caused_by(
|
||||
event.source_id,
|
||||
EventType::TextInject(TextInjectRequest {
|
||||
match m_event.format {
|
||||
TextFormat::Plain => EventType::TextInject(TextInjectRequest {
|
||||
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::CursorHintCompensation(m_event) => {
|
||||
|
|
60
espanso/src/engine/process/middleware/markdown.rs
Normal file
60
espanso/src/engine/process/middleware/markdown.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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::Middleware;
|
||||
use crate::engine::event::{Event, EventType, effect::{HtmlInjectRequest}};
|
||||
|
||||
// Convert markdown injection requests to HTML on the fly
|
||||
pub struct MarkdownMiddleware {}
|
||||
|
||||
impl MarkdownMiddleware {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Middleware for MarkdownMiddleware {
|
||||
fn name(&self) -> &'static str {
|
||||
"markdown"
|
||||
}
|
||||
|
||||
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
|
||||
if let EventType::MarkdownInject(m_event) = &event.etype {
|
||||
// Render the markdown into HTML
|
||||
let html = markdown::to_html(&m_event.markdown);
|
||||
let mut html = html.trim();
|
||||
|
||||
// Remove the surrounding paragraph
|
||||
if html.starts_with("<p>") {
|
||||
html = html.trim_start_matches("<p>");
|
||||
}
|
||||
if html.ends_with("</p>") {
|
||||
html = html.trim_end_matches("</p>");
|
||||
}
|
||||
|
||||
return Event::caused_by(event.source_id, EventType::HtmlInject(HtmlInjectRequest {
|
||||
html: html.to_owned(),
|
||||
}))
|
||||
}
|
||||
|
||||
event
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: test
|
|
@ -23,6 +23,7 @@ pub mod cursor_hint;
|
|||
pub mod delay_modifiers;
|
||||
pub mod match_select;
|
||||
pub mod matcher;
|
||||
pub mod markdown;
|
||||
pub mod multiplex;
|
||||
pub mod past_discard;
|
||||
pub mod render;
|
||||
|
|
|
@ -62,6 +62,7 @@ impl<'a> Middleware for RenderMiddleware<'a> {
|
|||
EventType::Rendered(RenderedEvent {
|
||||
match_id: m_event.match_id,
|
||||
body,
|
||||
format: m_event.format,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -226,6 +226,7 @@ fn main() {
|
|||
let config = ConfigBuilder::new()
|
||||
.set_time_to_local(true)
|
||||
.set_location_level(LevelFilter::Off)
|
||||
.add_filter_ignore_str("html5ever")
|
||||
.build();
|
||||
|
||||
CombinedLogger::init(vec![
|
||||
|
|
Loading…
Reference in New Issue
Block a user