Add form extension
This commit is contained in:
parent
a6b78e7142
commit
45f90c87ed
78
src/extension/form.rs
Normal file
78
src/extension/form.rs
Normal file
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<String>, _: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
|
||||
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<HashMap<String, String>, _> = 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<String>, current_vars: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult>;
|
||||
}
|
||||
|
||||
pub fn get_extensions(clipboard_manager: Box<dyn ClipboardManager>) -> Vec<Box<dyn Extension>> {
|
||||
pub fn get_extensions(config: &Configs, clipboard_manager: Box<dyn ClipboardManager>) -> Vec<Box<dyn Extension>> {
|
||||
vec![
|
||||
Box::new(date::DateExtension::new()),
|
||||
Box::new(shell::ShellExtension::new()),
|
||||
|
@ -52,5 +53,6 @@ pub fn get_extensions(clipboard_manager: Box<dyn ClipboardManager>) -> Vec<Box<d
|
|||
Box::new(dummy::DummyExtension::new("dummy")),
|
||||
Box::new(dummy::DummyExtension::new("echo")),
|
||||
Box::new(clipboard::ClipboardExtension::new(clipboard_manager)),
|
||||
Box::new(form::FormExtension::new(config)),
|
||||
]
|
||||
}
|
||||
|
|
|
@ -671,7 +671,7 @@ fn worker_background(
|
|||
|
||||
let keyboard_manager = keyboard::get_manager();
|
||||
|
||||
let extensions = extension::get_extensions(Box::new(clipboard::get_manager()));
|
||||
let extensions = extension::get_extensions(config_manager.default_config(), Box::new(clipboard::get_manager()));
|
||||
|
||||
let renderer =
|
||||
render::default::DefaultRenderer::new(extensions, config_manager.default_config().clone());
|
||||
|
|
|
@ -119,8 +119,6 @@ impl super::Renderer for DefaultRenderer {
|
|||
// Then the ones explicitly specified, in the given order
|
||||
variables.extend(&content.vars);
|
||||
|
||||
println!("{:?}", variables);
|
||||
|
||||
// Replace variable type "global" with the actual reference
|
||||
let variables: Vec<&MatchVariable> = 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<String, ExtensionResult> = HashMap::new();
|
||||
|
||||
for variable in variables.into_iter() {
|
||||
|
|
|
@ -12,10 +12,13 @@ pub struct ModuloManager {
|
|||
impl ModuloManager {
|
||||
pub fn new(config: &Configs) -> Self {
|
||||
let mut modulo_path: Option<String> = 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<String> {
|
||||
pub fn invoke(&self, args: &[&str], body: &str) -> Option<String> {
|
||||
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 {
|
||||
|
|
Loading…
Reference in New Issue
Block a user