From 45f90c87edeb4f2281b946b70f20ef790267a3a6 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Sun, 9 Aug 2020 11:48:23 +0200 Subject: [PATCH] Add form extension --- src/extension/form.rs | 78 +++++++++++++++++++++++++++++++++++++++++++ src/extension/mod.rs | 6 ++-- src/main.rs | 2 +- src/render/default.rs | 4 --- src/ui/modulo/mod.rs | 13 +++++--- 5 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 src/extension/form.rs diff --git a/src/extension/form.rs b/src/extension/form.rs new file mode 100644 index 0000000..b5b8e83 --- /dev/null +++ b/src/extension/form.rs @@ -0,0 +1,78 @@ +/* + * This file is part of espanso. + * + * Copyright (C) 2020 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 serde_yaml::{Mapping, Value}; +use std::collections::HashMap; +use crate::{ui::modulo::ModuloManager, extension::ExtensionResult, config::Configs}; +use log::error; + +pub struct FormExtension { + manager: ModuloManager, +} + +impl FormExtension { + pub fn new(config: &Configs) -> FormExtension { + let manager = ModuloManager::new(config); + FormExtension { + manager, + } + } +} + +impl super::Extension for FormExtension { + fn name(&self) -> String { + "form".to_owned() + } + + fn calculate(&self, params: &Mapping, _: &Vec, _: &HashMap) -> Option { + let layout = params.get(&Value::from("layout")); + let layout = if let Some(value) = layout { + value.as_str().unwrap_or_default().to_string() + } else { + error!("invoking form extension without specifying a layout"); + return None; + }; + + let mut form_config = Mapping::new(); + form_config.insert(Value::from("layout"), Value::from(layout)); + + if let Some(fields) = params.get(&Value::from("fields")) { + form_config.insert(Value::from("fields"), fields.clone()); + } + + let serialized_config: String = serde_yaml::to_string(&form_config).expect("unable to serialize form config"); + + let output = self.manager.invoke(&["form", "-i", "-"], &serialized_config); + if let Some(output) = output { + let json: Result, _> = serde_json::from_str(&output); + match json { + Ok(json) => { + return Some(ExtensionResult::Multiple(json)); + } + Err(error) => { + error!("modulo json parsing error: {}", error); + return None; + } + } + } else { + error!("modulo form didn't return any output"); + return None; + } + } +} diff --git a/src/extension/mod.rs b/src/extension/mod.rs index a25406b..a6a27a4 100644 --- a/src/extension/mod.rs +++ b/src/extension/mod.rs @@ -17,7 +17,7 @@ * along with espanso. If not, see . */ -use crate::clipboard::ClipboardManager; +use crate::{config::Configs, clipboard::ClipboardManager}; use serde_yaml::Mapping; use std::collections::HashMap; @@ -30,6 +30,7 @@ mod shell; pub mod multiecho; pub mod vardummy; mod utils; +mod form; #[derive(Clone, Debug, PartialEq)] pub enum ExtensionResult { @@ -42,7 +43,7 @@ pub trait Extension { fn calculate(&self, params: &Mapping, args: &Vec, current_vars: &HashMap) -> Option; } -pub fn get_extensions(clipboard_manager: Box) -> Vec> { +pub fn get_extensions(config: &Configs, clipboard_manager: Box) -> Vec> { vec![ Box::new(date::DateExtension::new()), Box::new(shell::ShellExtension::new()), @@ -52,5 +53,6 @@ pub fn get_extensions(clipboard_manager: Box) -> Vec = variables.into_iter().map(|variable| { if variable.var_type == "global" { @@ -131,8 +129,6 @@ impl super::Renderer for DefaultRenderer { variable }).collect(); - println!("{:?}", variables); - let mut output_map: HashMap = HashMap::new(); for variable in variables.into_iter() { diff --git a/src/ui/modulo/mod.rs b/src/ui/modulo/mod.rs index 93c7921..93c523c 100644 --- a/src/ui/modulo/mod.rs +++ b/src/ui/modulo/mod.rs @@ -12,10 +12,13 @@ pub struct ModuloManager { impl ModuloManager { pub fn new(config: &Configs) -> Self { let mut modulo_path: Option = None; - if let Some(ref _modulo_path) = config.modulo_path { + // Check if the `MODULO_PATH` env variable is configured + if let Some(_modulo_path) = std::env::var_os("MODULO_PATH") { + modulo_path = Some(_modulo_path.to_string_lossy().to_string()) + } else if let Some(ref _modulo_path) = config.modulo_path { // Check the configs modulo_path = Some(_modulo_path.to_owned()); }else{ - // First check in the same directory of espanso + // Check in the same directory of espanso if let Ok(exe_path) = std::env::current_exe() { if let Some(parent) = exe_path.parent() { let possible_path = parent.join("modulo"); @@ -59,16 +62,18 @@ impl ModuloManager { None } - fn invoke(&self, args: &[&str], body: &str) -> Option { + pub fn invoke(&self, args: &[&str], body: &str) -> Option { if self.modulo_path.is_none() { error!("Attempt to invoke modulo even though it's not configured"); return None; } if let Some(ref modulo_path) = self.modulo_path { - let mut child = Command::new(modulo_path) + let child = Command::new(modulo_path) .args(args) .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) .spawn(); match child {