use crate::errors::{IOError, PluginError};
use crate::settings;
use getter_derive_rs::Getter;
use serde::{Deserialize, Serialize};
use std::{
error::Error,
process::{Command, Output, Stdio},
};
#[derive(Debug, Deserialize, Serialize, Getter, Clone)]
#[serde(rename_all = "snake_case")]
pub struct Plugin {
name: String,
exec: String,
}
impl Default for Plugin {
fn default() -> Self {
Plugin {
name: Default::default(),
exec: Default::default(),
}
}
}
pub fn invoke(plugin_str: &str, args_options: Option<Vec<&str>>) -> Result<Output, Box<dyn Error>> {
let command_str = get_plugin(plugin_str)?.get_exec();
let mut args = args_options.unwrap_or_default();
let command = str_to_command!(command_str, &mut args);
let output = Command::new(command).args(args).output()?;
Ok(output)
}
pub fn bind(plugin_str: &str, args_options: Option<Vec<&str>>) -> Result<Vec<u8>, Box<dyn Error>> {
let command_str = get_plugin(plugin_str)?.get_exec();
let mut args = args_options.unwrap_or_default();
let command = str_to_command!(command_str, &mut args);
let child = Command::new(command)
.args(args)
.stdin(Stdio::piped())
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
let output = child.wait_with_output()?;
if output.status.success() {
Ok(output.stdout)
} else {
Err(IOError::StdErr {
err: String::from_utf8(output.stderr)?,
}
.into())
}
}
pub fn get_plugin(q_plugin: &str) -> Result<Plugin, Box<dyn Error>> {
let plugins = settings::get_settings()?.get_plugins();
plugins
.into_iter()
.find(|plugin| plugin.name == q_plugin)
.map_or(
Err(PluginError::PluginNotFound {
plugin: q_plugin.into(),
}
.into()),
|plugin| Ok(plugin),
)
}
pub fn new(name: &str, exec: &str) -> Plugin {
Plugin {
name: name.to_string(),
exec: exec.to_string(),
}
}