From 9081ca76e709cbde1fe594ee5db3f8b7bfd03b97 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Mon, 15 Nov 2021 22:25:30 +0100 Subject: [PATCH] feat(core): wire up textview UI events --- .../worker/engine/dispatch/executor/mod.rs | 1 + .../engine/dispatch/executor/text_ui.rs | 39 ++++++++++++++ espanso/src/cli/worker/engine/mod.rs | 4 ++ espanso/src/gui/mod.rs | 7 ++- espanso/src/gui/modulo/manager.rs | 49 ++++++++++++++++++ espanso/src/gui/modulo/mod.rs | 1 + espanso/src/gui/modulo/textview.rs | 51 +++++++++++++++++++ 7 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 espanso/src/cli/worker/engine/dispatch/executor/text_ui.rs create mode 100644 espanso/src/gui/modulo/textview.rs diff --git a/espanso/src/cli/worker/engine/dispatch/executor/mod.rs b/espanso/src/cli/worker/engine/dispatch/executor/mod.rs index 7fee77a..ff3dc19 100644 --- a/espanso/src/cli/worker/engine/dispatch/executor/mod.rs +++ b/espanso/src/cli/worker/engine/dispatch/executor/mod.rs @@ -23,6 +23,7 @@ pub mod event_injector; pub mod icon; pub mod key_injector; pub mod secure_input; +pub mod text_ui; pub trait InjectParamsProvider { fn get(&self) -> InjectParams; diff --git a/espanso/src/cli/worker/engine/dispatch/executor/text_ui.rs b/espanso/src/cli/worker/engine/dispatch/executor/text_ui.rs new file mode 100644 index 0000000..5d73932 --- /dev/null +++ b/espanso/src/cli/worker/engine/dispatch/executor/text_ui.rs @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +use espanso_engine::dispatch::TextUIHandler; + +use crate::gui::TextUI; + +pub struct TextUIHandlerAdapter<'a> { + text_ui: &'a dyn TextUI, +} + +impl<'a> TextUIHandlerAdapter<'a> { + pub fn new(text_ui: &'a dyn TextUI) -> Self { + Self { text_ui } + } +} + +impl<'a> TextUIHandler for TextUIHandlerAdapter<'a> { + fn show_text(&self, title: &str, text: &str) -> anyhow::Result<()> { + self.text_ui.show_text(title, text)?; + Ok(()) + } +} diff --git a/espanso/src/cli/worker/engine/mod.rs b/espanso/src/cli/worker/engine/mod.rs index 07c653a..0cd74b2 100644 --- a/espanso/src/cli/worker/engine/mod.rs +++ b/espanso/src/cli/worker/engine/mod.rs @@ -37,6 +37,7 @@ use crate::{ clipboard_injector::ClipboardInjectorAdapter, context_menu::ContextMenuHandlerAdapter, event_injector::EventInjectorAdapter, icon::IconHandlerAdapter, key_injector::KeyInjectorAdapter, secure_input::SecureInputManagerAdapter, + text_ui::TextUIHandlerAdapter, }, process::middleware::{ image_resolve::PathProviderAdapter, @@ -106,6 +107,7 @@ pub fn initialize_and_spawn( let modulo_manager = crate::gui::modulo::manager::ModuloManager::new(); 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_text_ui = crate::gui::modulo::textview::ModuloTextUI::new(&modulo_manager); let context: Box = Box::new(super::context::DefaultContext::new( &config_manager, @@ -241,6 +243,7 @@ pub fn initialize_and_spawn( let context_menu_adapter = ContextMenuHandlerAdapter::new(&*ui_remote); let icon_adapter = IconHandlerAdapter::new(&*ui_remote); let secure_input_adapter = SecureInputManagerAdapter::new(); + let text_ui_adapter = TextUIHandlerAdapter::new(&modulo_text_ui); let dispatcher = espanso_engine::dispatch::default( &event_injector, &clipboard_injector, @@ -251,6 +254,7 @@ pub fn initialize_and_spawn( &context_menu_adapter, &icon_adapter, &secure_input_adapter, + &text_ui_adapter, ); // Disable previously granted linux capabilities if not needed anymore diff --git a/espanso/src/gui/mod.rs b/espanso/src/gui/mod.rs index bcd26e7..86ae5db 100644 --- a/espanso/src/gui/mod.rs +++ b/espanso/src/gui/mod.rs @@ -17,7 +17,7 @@ * along with espanso. If not, see . */ -use std::collections::HashMap; +use std::{collections::HashMap, path::Path}; use anyhow::Result; @@ -58,3 +58,8 @@ pub enum FormField { values: Vec, }, } + +pub trait TextUI { + fn show_text(&self, title: &str, text: &str) -> Result<()>; + fn show_file(&self, title: &str, path: &Path) -> Result<()>; +} diff --git a/espanso/src/gui/modulo/manager.rs b/espanso/src/gui/modulo/manager.rs index 0cc3184..e371db9 100644 --- a/espanso/src/gui/modulo/manager.rs +++ b/espanso/src/gui/modulo/manager.rs @@ -39,6 +39,52 @@ impl ModuloManager { Self { is_support_enabled } } + pub fn invoke_no_output(&self, args: &[&str], body: &str) -> Result<()> { + if self.is_support_enabled { + let exec_path = std::env::current_exe().expect("unable to obtain current exec path"); + let mut command = Command::new(exec_path); + let mut full_args = vec!["modulo"]; + full_args.extend(args); + command + .args(full_args) + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()); + + crate::util::set_command_flags(&mut command); + + let child = command.spawn(); + + match child { + Ok(mut child) => { + if let Some(stdin) = child.stdin.as_mut() { + match stdin.write_all(body.as_bytes()) { + Ok(_) => { + // Get the output + match child.wait_with_output() { + Ok(child_output) => { + if child_output.status.success() { + Ok(()) + } else { + Err(ModuloError::NonZeroExit.into()) + } + } + Err(error) => Err(ModuloError::Error(error).into()), + } + } + Err(error) => Err(ModuloError::Error(error).into()), + } + } else { + Err(ModuloError::StdinError.into()) + } + } + Err(error) => Err(ModuloError::Error(error).into()), + } + } else { + Err(ModuloError::MissingModulo.into()) + } + } + pub fn invoke(&self, args: &[&str], body: &str) -> Result { if self.is_support_enabled { let exec_path = std::env::current_exe().expect("unable to obtain current exec path"); @@ -101,6 +147,9 @@ pub enum ModuloError { )] MissingModulo, + #[error("modulo returned a non-zero exit code")] + NonZeroExit, + #[error("modulo returned an empty output")] EmptyOutput, diff --git a/espanso/src/gui/modulo/mod.rs b/espanso/src/gui/modulo/mod.rs index 9e27396..e065ab4 100644 --- a/espanso/src/gui/modulo/mod.rs +++ b/espanso/src/gui/modulo/mod.rs @@ -20,3 +20,4 @@ pub mod form; pub mod manager; pub mod search; +pub mod textview; diff --git a/espanso/src/gui/modulo/textview.rs b/espanso/src/gui/modulo/textview.rs new file mode 100644 index 0000000..66d0834 --- /dev/null +++ b/espanso/src/gui/modulo/textview.rs @@ -0,0 +1,51 @@ +/* + * 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 . + */ + +use crate::gui::TextUI; + +use super::manager::ModuloManager; + +pub struct ModuloTextUI<'a> { + manager: &'a ModuloManager, +} + +impl<'a> ModuloTextUI<'a> { + pub fn new(manager: &'a ModuloManager) -> Self { + Self { manager } + } +} + +impl<'a> TextUI for ModuloTextUI<'a> { + fn show_text(&self, title: &str, text: &str) -> anyhow::Result<()> { + self + .manager + .invoke_no_output(&["textview", "--title", title, "-i", "-"], text)?; + + Ok(()) + } + + fn show_file(&self, title: &str, path: &std::path::Path) -> anyhow::Result<()> { + let path_str = path.to_string_lossy().to_string(); + self + .manager + .invoke_no_output(&["textview", "--title", title, "-i", &path_str], "")?; + + Ok(()) + } +}