forked from extern/nushell
e4fdb36511
* fix empty table and missing spans * wip * WIP * WIP * working version with vars * tidying * WIP * Fix external quoting issue
123 lines
3.5 KiB
Rust
123 lines
3.5 KiB
Rust
use crate::commands::classified::external;
|
|
use crate::commands::WholeStreamCommand;
|
|
use crate::prelude::*;
|
|
|
|
use derive_new::new;
|
|
use parking_lot::Mutex;
|
|
|
|
use nu_errors::ShellError;
|
|
use nu_protocol::hir::{Expression, ExternalArgs, ExternalCommand, Literal, SpannedExpression};
|
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct RunExternalArgs {}
|
|
|
|
#[derive(new)]
|
|
pub struct RunExternalCommand;
|
|
|
|
fn spanned_expression_to_string(expr: SpannedExpression) -> String {
|
|
if let SpannedExpression {
|
|
expr: Expression::Literal(Literal::String(s)),
|
|
..
|
|
} = expr
|
|
{
|
|
s
|
|
} else {
|
|
"notacommand!!!".to_string()
|
|
}
|
|
}
|
|
|
|
impl WholeStreamCommand for RunExternalCommand {
|
|
fn name(&self) -> &str {
|
|
"run_external"
|
|
}
|
|
|
|
fn signature(&self) -> Signature {
|
|
Signature::build(self.name()).rest(SyntaxShape::Any, "external command arguments")
|
|
}
|
|
|
|
fn usage(&self) -> &str {
|
|
""
|
|
}
|
|
|
|
fn run(
|
|
&self,
|
|
args: CommandArgs,
|
|
registry: &CommandRegistry,
|
|
) -> Result<OutputStream, ShellError> {
|
|
let positionals = args.call_info.args.positional.ok_or_else(|| {
|
|
ShellError::untagged_runtime_error("positional arguments unexpectedly empty")
|
|
})?;
|
|
|
|
let mut positionals = positionals.into_iter();
|
|
|
|
let name = positionals
|
|
.next()
|
|
.map(spanned_expression_to_string)
|
|
.ok_or_else(|| {
|
|
ShellError::untagged_runtime_error(
|
|
"run_external unexpectedly missing external name positional arg",
|
|
)
|
|
})?;
|
|
|
|
let command = ExternalCommand {
|
|
name,
|
|
name_tag: args.call_info.name_tag.clone(),
|
|
args: ExternalArgs {
|
|
list: positionals.collect(),
|
|
span: args.call_info.args.span,
|
|
},
|
|
};
|
|
|
|
let mut external_context;
|
|
#[cfg(windows)]
|
|
{
|
|
external_context = Context {
|
|
registry: registry.clone(),
|
|
host: args.host.clone(),
|
|
shell_manager: args.shell_manager.clone(),
|
|
ctrl_c: args.ctrl_c.clone(),
|
|
current_errors: Arc::new(Mutex::new(vec![])),
|
|
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
|
};
|
|
}
|
|
#[cfg(not(windows))]
|
|
{
|
|
external_context = Context {
|
|
registry: registry.clone(),
|
|
host: args.host.clone(),
|
|
shell_manager: args.shell_manager.clone(),
|
|
ctrl_c: args.ctrl_c.clone(),
|
|
current_errors: Arc::new(Mutex::new(vec![])),
|
|
};
|
|
}
|
|
let scope = args.call_info.scope.clone();
|
|
|
|
let is_last = args.call_info.args.is_last;
|
|
let input = args.input;
|
|
let stream = async_stream! {
|
|
let result = external::run_external_command(
|
|
command,
|
|
&mut external_context,
|
|
input,
|
|
&scope,
|
|
is_last,
|
|
).await;
|
|
|
|
match result {
|
|
Ok(mut stream) => {
|
|
while let Some(value) = stream.next().await {
|
|
yield Ok(ReturnSuccess::Value(value));
|
|
}
|
|
},
|
|
Err(e) => {
|
|
yield Err(e);
|
|
},
|
|
_ => {}
|
|
}
|
|
};
|
|
|
|
Ok(stream.to_output_stream())
|
|
}
|
|
}
|