Plugin option for shell (#517)

* calling plugin without shell

* spelling error

* option on register to select a shell
This commit is contained in:
Fernando Herrera
2021-12-18 18:13:56 +00:00
committed by GitHub
parent b3b328d19d
commit 8933dde324
8 changed files with 108 additions and 22 deletions

View File

@ -14,16 +14,23 @@ pub struct PluginDeclaration {
name: String,
signature: Signature,
filename: PathBuf,
shell: Option<PathBuf>,
encoding: EncodingType,
}
impl PluginDeclaration {
pub fn new(filename: PathBuf, signature: Signature, encoding: EncodingType) -> Self {
pub fn new(
filename: PathBuf,
signature: Signature,
encoding: EncodingType,
shell: Option<PathBuf>,
) -> Self {
Self {
name: signature.name.clone(),
signature,
filename,
encoding,
shell,
}
}
}
@ -52,7 +59,7 @@ impl Command for PluginDeclaration {
// Decode information from plugin
// Create PipelineData
let source_file = Path::new(&self.filename);
let mut plugin_cmd = create_command(source_file);
let mut plugin_cmd = create_command(source_file, &self.shell);
let mut child = plugin_cmd.spawn().map_err(|err| {
let decl = engine_state.get_decl(call.decl_id);
@ -131,7 +138,7 @@ impl Command for PluginDeclaration {
Ok(pipeline_data)
}
fn is_plugin(&self) -> Option<(&PathBuf, &str)> {
Some((&self.filename, self.encoding.to_str()))
fn is_plugin(&self) -> Option<(&PathBuf, &str, &Option<PathBuf>)> {
Some((&self.filename, self.encoding.to_str(), &self.shell))
}
}

View File

View File

@ -4,7 +4,7 @@ pub use declaration::PluginDeclaration;
use crate::protocol::{LabeledError, PluginCall, PluginResponse};
use crate::EncodingType;
use std::io::BufReader;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::{Command as CommandSys, Stdio};
use nu_protocol::ShellError;
@ -35,10 +35,15 @@ pub trait PluginEncoder: Clone {
) -> Result<PluginResponse, ShellError>;
}
fn create_command(path: &Path) -> CommandSys {
let mut process = match path.extension() {
None => std::process::Command::new(path),
Some(extension) => {
fn create_command(path: &Path, shell: &Option<PathBuf>) -> CommandSys {
let mut process = match (path.extension(), shell) {
(_, Some(shell)) => {
let mut process = std::process::Command::new(shell);
process.arg(path);
process
}
(Some(extension), None) => {
let (shell, separator) = match extension.to_str() {
Some("cmd") | Some("bat") => (Some("cmd"), Some("/c")),
Some("sh") => (Some("sh"), Some("-c")),
@ -63,6 +68,7 @@ fn create_command(path: &Path) -> CommandSys {
_ => std::process::Command::new(path),
}
}
(None, None) => std::process::Command::new(path),
};
// Both stdout and stdin are piped so we can receive information from the plugin
@ -71,8 +77,12 @@ fn create_command(path: &Path) -> CommandSys {
process
}
pub fn get_signature(path: &Path, encoding: &EncodingType) -> Result<Vec<Signature>, ShellError> {
let mut plugin_cmd = create_command(path);
pub fn get_signature(
path: &Path,
encoding: &EncodingType,
shell: &Option<PathBuf>,
) -> Result<Vec<Signature>, ShellError> {
let mut plugin_cmd = create_command(path, shell);
let mut child = plugin_cmd.spawn().map_err(|err| {
ShellError::PluginFailedToLoad(format!("Error spawning child process: {}", err))