mirror of
https://github.com/nushell/nushell
synced 2024-12-27 21:43:09 +00:00
Fix external redirect (#3345)
* Fix external redirection * Fix external redirection
This commit is contained in:
parent
02d5729941
commit
3ad4e0348f
24 changed files with 164 additions and 91 deletions
|
@ -229,13 +229,7 @@ pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box<dyn E
|
||||||
let prompt_line = prompt.as_string()?;
|
let prompt_line = prompt.as_string()?;
|
||||||
|
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
let (mut prompt_block, err) = nu_parser::parse(&prompt_line, 0, &context.scope);
|
let (prompt_block, err) = nu_parser::parse(&prompt_line, 0, &context.scope);
|
||||||
|
|
||||||
if let Some(block) =
|
|
||||||
std::sync::Arc::<nu_protocol::hir::Block>::get_mut(&mut prompt_block)
|
|
||||||
{
|
|
||||||
block.set_redirect(ExternalRedirection::Stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if err.is_some() {
|
if err.is_some() {
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
@ -250,7 +244,12 @@ pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box<dyn E
|
||||||
nu_ansi_term::ansi::RESET
|
nu_ansi_term::ansi::RESET
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let run_result = run_block(&prompt_block, &context, InputStream::empty());
|
let run_result = run_block(
|
||||||
|
&prompt_block,
|
||||||
|
&context,
|
||||||
|
InputStream::empty(),
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
match run_result {
|
match run_result {
|
||||||
|
@ -485,7 +484,12 @@ pub fn parse_and_eval(line: &str, ctx: &EvaluationContext) -> Result<String, She
|
||||||
|
|
||||||
let input_stream = InputStream::empty();
|
let input_stream = InputStream::empty();
|
||||||
|
|
||||||
let result = run_block(&classified_block, ctx, input_stream);
|
let result = run_block(
|
||||||
|
&classified_block,
|
||||||
|
ctx,
|
||||||
|
input_stream,
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
);
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
|
|
||||||
result?.collect_string(Tag::unknown()).map(|x| x.item)
|
result?.collect_string(Tag::unknown()).map(|x| x.item)
|
||||||
|
|
|
@ -5,7 +5,10 @@ use nu_engine::run_block;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
hir::{Block, CapturedBlock, ClassifiedCommand, Group, InternalCommand, Pipeline},
|
hir::{
|
||||||
|
Block, CapturedBlock, ClassifiedCommand, ExternalRedirection, Group, InternalCommand,
|
||||||
|
Pipeline,
|
||||||
|
},
|
||||||
Dictionary, Signature, SyntaxShape, UntaggedValue, Value,
|
Dictionary, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
use rand::{
|
use rand::{
|
||||||
|
@ -84,7 +87,12 @@ fn benchmark(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
// let start = time();
|
// let start = time();
|
||||||
|
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
let result = run_block(&block.block, &context, input);
|
let result = run_block(
|
||||||
|
&block.block,
|
||||||
|
&context,
|
||||||
|
input,
|
||||||
|
ExternalRedirection::StdoutAndStderr,
|
||||||
|
);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
let output = result?.into_vec();
|
let output = result?.into_vec();
|
||||||
|
|
||||||
|
@ -154,7 +162,12 @@ where
|
||||||
let time_block = add_implicit_autoview(time_block.block);
|
let time_block = add_implicit_autoview(time_block.block);
|
||||||
|
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
let result = run_block(&time_block, context, benchmark_output);
|
let result = run_block(
|
||||||
|
&time_block,
|
||||||
|
context,
|
||||||
|
benchmark_output,
|
||||||
|
ExternalRedirection::StdoutAndStderr,
|
||||||
|
);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
result?;
|
result?;
|
||||||
context.clear_errors();
|
context.clear_errors();
|
||||||
|
|
|
@ -58,7 +58,7 @@ fn do_(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
let (
|
let (
|
||||||
DoArgs {
|
DoArgs {
|
||||||
ignore_errors,
|
ignore_errors,
|
||||||
mut block,
|
block,
|
||||||
},
|
},
|
||||||
input,
|
input,
|
||||||
) = raw_args.process()?;
|
) = raw_args.process()?;
|
||||||
|
@ -81,11 +81,8 @@ fn do_(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
x => x,
|
x => x,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(block) = std::sync::Arc::<nu_protocol::hir::Block>::get_mut(&mut block.block) {
|
|
||||||
block.set_redirect(block_redirection);
|
|
||||||
}
|
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
let result = run_block(&block.block, &context, input);
|
let result = run_block(&block.block, &context, input, block_redirection);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
if ignore_errors {
|
if ignore_errors {
|
||||||
|
|
|
@ -4,7 +4,8 @@ use nu_engine::WholeStreamCommand;
|
||||||
|
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
hir::CapturedBlock, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
hir::{CapturedBlock, ExternalRedirection},
|
||||||
|
Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Each;
|
pub struct Each;
|
||||||
|
@ -62,6 +63,7 @@ pub fn process_row(
|
||||||
captured_block: Arc<Box<CapturedBlock>>,
|
captured_block: Arc<Box<CapturedBlock>>,
|
||||||
context: Arc<EvaluationContext>,
|
context: Arc<EvaluationContext>,
|
||||||
input: Value,
|
input: Value,
|
||||||
|
external_redirection: ExternalRedirection,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let input_clone = input.clone();
|
let input_clone = input.clone();
|
||||||
// When we process a row, we need to know whether the block wants to have the contents of the row as
|
// When we process a row, we need to know whether the block wants to have the contents of the row as
|
||||||
|
@ -86,7 +88,12 @@ pub fn process_row(
|
||||||
context.scope.add_var("$it", input);
|
context.scope.add_var("$it", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = run_block(&captured_block.block, &*context, input_stream);
|
let result = run_block(
|
||||||
|
&captured_block.block,
|
||||||
|
&*context,
|
||||||
|
input_stream,
|
||||||
|
external_redirection,
|
||||||
|
);
|
||||||
|
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
|
@ -103,6 +110,7 @@ pub(crate) fn make_indexed_item(index: usize, item: Value) -> Value {
|
||||||
|
|
||||||
fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||||
|
let external_redirection = raw_args.call_info.args.external_redirection;
|
||||||
let args = raw_args.evaluate_once()?;
|
let args = raw_args.evaluate_once()?;
|
||||||
|
|
||||||
let block: CapturedBlock = args.req(0)?;
|
let block: CapturedBlock = args.req(0)?;
|
||||||
|
@ -119,7 +127,7 @@ fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let row = make_indexed_item(input.0, input.1);
|
let row = make_indexed_item(input.0, input.1);
|
||||||
|
|
||||||
match process_row(block, context, row) {
|
match process_row(block, context, row, external_redirection) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => OutputStream::one(Value::error(e)),
|
Err(e) => OutputStream::one(Value::error(e)),
|
||||||
}
|
}
|
||||||
|
@ -133,7 +141,7 @@ fn each(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let block = block.clone();
|
let block = block.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
|
|
||||||
match process_row(block, context, input) {
|
match process_row(block, context, input, external_redirection) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => OutputStream::one(Value::error(e)),
|
Err(e) => OutputStream::one(Value::error(e)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,10 @@ use crate::commands::each::process_row;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::CapturedBlock, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{
|
||||||
|
hir::{CapturedBlock, ExternalRedirection},
|
||||||
|
Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
|
};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
@ -44,6 +47,7 @@ impl WholeStreamCommand for EachGroup {
|
||||||
|
|
||||||
fn run_with_actions(&self, raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
fn run_with_actions(&self, raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||||
|
let external_redirection = raw_args.call_info.args.external_redirection;
|
||||||
let (each_args, input): (EachGroupArgs, _) = raw_args.process()?;
|
let (each_args, input): (EachGroupArgs, _) = raw_args.process()?;
|
||||||
let block = Arc::new(Box::new(each_args.block));
|
let block = Arc::new(Box::new(each_args.block));
|
||||||
|
|
||||||
|
@ -52,6 +56,7 @@ impl WholeStreamCommand for EachGroup {
|
||||||
context,
|
context,
|
||||||
group_size: each_args.group_size.item,
|
group_size: each_args.group_size.item,
|
||||||
input,
|
input,
|
||||||
|
external_redirection,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(each_group_iterator.flatten().to_action_stream())
|
Ok(each_group_iterator.flatten().to_action_stream())
|
||||||
|
@ -63,6 +68,7 @@ struct EachGroupIterator {
|
||||||
context: Arc<EvaluationContext>,
|
context: Arc<EvaluationContext>,
|
||||||
group_size: usize,
|
group_size: usize,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
|
external_redirection: ExternalRedirection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for EachGroupIterator {
|
impl Iterator for EachGroupIterator {
|
||||||
|
@ -89,6 +95,7 @@ impl Iterator for EachGroupIterator {
|
||||||
group,
|
group,
|
||||||
self.block.clone(),
|
self.block.clone(),
|
||||||
self.context.clone(),
|
self.context.clone(),
|
||||||
|
self.external_redirection,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,13 +104,14 @@ pub(crate) fn run_block_on_vec(
|
||||||
input: Vec<Value>,
|
input: Vec<Value>,
|
||||||
block: Arc<Box<CapturedBlock>>,
|
block: Arc<Box<CapturedBlock>>,
|
||||||
context: Arc<EvaluationContext>,
|
context: Arc<EvaluationContext>,
|
||||||
|
external_redirection: ExternalRedirection,
|
||||||
) -> OutputStream {
|
) -> OutputStream {
|
||||||
let value = Value {
|
let value = Value {
|
||||||
value: UntaggedValue::Table(input),
|
value: UntaggedValue::Table(input),
|
||||||
tag: Tag::unknown(),
|
tag: Tag::unknown(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match process_row(block, context, value) {
|
match process_row(block, context, value, external_redirection) {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
// We need to handle this differently depending on whether process_row
|
// We need to handle this differently depending on whether process_row
|
||||||
// returned just 1 value or if it returned multiple as a stream.
|
// returned just 1 value or if it returned multiple as a stream.
|
||||||
|
|
|
@ -51,6 +51,7 @@ impl WholeStreamCommand for EachWindow {
|
||||||
|
|
||||||
fn run_with_actions(&self, raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
fn run_with_actions(&self, raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||||
|
let external_redirection = raw_args.call_info.args.external_redirection;
|
||||||
let (each_args, mut input): (EachWindowArgs, _) = raw_args.process()?;
|
let (each_args, mut input): (EachWindowArgs, _) = raw_args.process()?;
|
||||||
let block = Arc::new(Box::new(each_args.block));
|
let block = Arc::new(Box::new(each_args.block));
|
||||||
|
|
||||||
|
@ -76,7 +77,12 @@ impl WholeStreamCommand for EachWindow {
|
||||||
let local_window = window.clone();
|
let local_window = window.clone();
|
||||||
|
|
||||||
if i % stride == 0 {
|
if i % stride == 0 {
|
||||||
Some(run_block_on_vec(local_window, block, context))
|
Some(run_block_on_vec(
|
||||||
|
local_window,
|
||||||
|
block,
|
||||||
|
context,
|
||||||
|
external_redirection,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ use nu_engine::run_block;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
hir::CapturedBlock, ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape,
|
hir::CapturedBlock, hir::ExternalRedirection, ColumnPath, Primitive, ReturnSuccess, Signature,
|
||||||
UntaggedValue, Value,
|
SyntaxShape, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::utils::arguments::arguments;
|
use crate::utils::arguments::arguments;
|
||||||
|
@ -142,7 +142,12 @@ fn process_row(
|
||||||
context.scope.add_vars(&default_block.captured.entries);
|
context.scope.add_vars(&default_block.captured.entries);
|
||||||
context.scope.add_var("$it", input.clone());
|
context.scope.add_var("$it", input.clone());
|
||||||
|
|
||||||
let stream = run_block(&default_block.block, &*context, input_stream);
|
let stream = run_block(
|
||||||
|
&default_block.block,
|
||||||
|
&*context,
|
||||||
|
input_stream,
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
let mut stream = stream?;
|
let mut stream = stream?;
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::prelude::*;
|
||||||
use crate::utils::suggestions::suggestions;
|
use crate::utils::suggestions::suggestions;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::hir::ExternalRedirection;
|
||||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
use nu_value_ext::as_string;
|
use nu_value_ext::as_string;
|
||||||
|
@ -148,7 +149,12 @@ pub fn group_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let run = block.clone();
|
let run = block.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
|
|
||||||
match crate::commands::each::process_row(run, context, value.clone()) {
|
match crate::commands::each::process_row(
|
||||||
|
run,
|
||||||
|
context,
|
||||||
|
value.clone(),
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
) {
|
||||||
Ok(mut s) => {
|
Ok(mut s) => {
|
||||||
let collection: Vec<Value> = s.drain_vec();
|
let collection: Vec<Value> = s.drain_vec();
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ impl WholeStreamCommand for If {
|
||||||
}
|
}
|
||||||
fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let tag = raw_args.call_info.name_tag.clone();
|
let tag = raw_args.call_info.name_tag.clone();
|
||||||
|
let external_redirection = raw_args.call_info.args.external_redirection;
|
||||||
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
let context = Arc::new(EvaluationContext::from_args(&raw_args));
|
||||||
|
|
||||||
let args = raw_args.evaluate_once()?;
|
let args = raw_args.evaluate_once()?;
|
||||||
|
@ -105,9 +106,9 @@ fn if_command(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(condition) => match condition.as_bool() {
|
Ok(condition) => match condition.as_bool() {
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
let result = if b {
|
let result = if b {
|
||||||
run_block(&then_case.block, &*context, input)
|
run_block(&then_case.block, &*context, input, external_redirection)
|
||||||
} else {
|
} else {
|
||||||
run_block(&else_case.block, &*context, input)
|
run_block(&else_case.block, &*context, input, external_redirection)
|
||||||
};
|
};
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::prelude::*;
|
||||||
use nu_engine::run_block;
|
use nu_engine::run_block;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::hir::ExternalRedirection;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
|
@ -81,7 +82,12 @@ fn process_row(
|
||||||
context.scope.add_vars(&block.captured.entries);
|
context.scope.add_vars(&block.captured.entries);
|
||||||
context.scope.add_var("$it", input.clone());
|
context.scope.add_var("$it", input.clone());
|
||||||
|
|
||||||
let result = run_block(&block.block, &*context, input_stream);
|
let result = run_block(
|
||||||
|
&block.block,
|
||||||
|
&*context,
|
||||||
|
input_stream,
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
);
|
||||||
|
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ use nu_engine::WholeStreamCommand;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
hir::CapturedBlock, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
hir::CapturedBlock, hir::ExternalRedirection, ReturnSuccess, Signature, SyntaxShape,
|
||||||
|
UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
pub struct Merge;
|
pub struct Merge;
|
||||||
|
|
||||||
|
@ -53,7 +54,12 @@ fn merge(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
|
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
context.scope.add_vars(&block.captured.entries);
|
context.scope.add_vars(&block.captured.entries);
|
||||||
let result = run_block(&block.block, &context, InputStream::empty());
|
let result = run_block(
|
||||||
|
&block.block,
|
||||||
|
&context,
|
||||||
|
InputStream::empty(),
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
let table: Option<Vec<Value>> = match result {
|
let table: Option<Vec<Value>> = match result {
|
||||||
|
|
|
@ -5,7 +5,9 @@ use nu_engine::WholeStreamCommand;
|
||||||
use nu_engine::{CommandArgs, Example};
|
use nu_engine::{CommandArgs, Example};
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_parser::ParserScope;
|
use nu_parser::ParserScope;
|
||||||
use nu_protocol::{hir::CapturedBlock, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{
|
||||||
|
hir::CapturedBlock, hir::ExternalRedirection, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
|
};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
use nu_stream::ActionStream;
|
use nu_stream::ActionStream;
|
||||||
|
|
||||||
|
@ -88,7 +90,12 @@ fn process_row(
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
context.scope.add_vars(&block.captured.entries);
|
context.scope.add_vars(&block.captured.entries);
|
||||||
context.scope.add_var("$it", row);
|
context.scope.add_var("$it", row);
|
||||||
let result = run_block(&block.block, context, input_stream);
|
let result = run_block(
|
||||||
|
&block.block,
|
||||||
|
context,
|
||||||
|
input_stream,
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
|
@ -12,9 +12,6 @@ use nu_protocol::hir::{Expression, ExternalArgs, ExternalCommand, Literal, Spann
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct RunExternalArgs {}
|
|
||||||
|
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
pub struct RunExternalCommand {
|
pub struct RunExternalCommand {
|
||||||
/// Whether or not nushell is being used in an interactive context
|
/// Whether or not nushell is being used in an interactive context
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::prelude::*;
|
||||||
use nu_engine::run_block;
|
use nu_engine::run_block;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::hir::ExternalRedirection;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
|
@ -86,7 +87,12 @@ fn process_row(
|
||||||
context.scope.add_var("$it", input.clone());
|
context.scope.add_var("$it", input.clone());
|
||||||
context.scope.add_vars(&captured_block.captured.entries);
|
context.scope.add_vars(&captured_block.captured.entries);
|
||||||
|
|
||||||
let result = run_block(&captured_block.block, &*context, input_stream);
|
let result = run_block(
|
||||||
|
&captured_block.block,
|
||||||
|
&*context,
|
||||||
|
input_stream,
|
||||||
|
ExternalRedirection::Stdout,
|
||||||
|
);
|
||||||
|
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
|
|
|
@ -68,19 +68,9 @@ impl WholeStreamCommand for WithEnv {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_env(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
fn with_env(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
let redirection = raw_args.call_info.args.external_redirection;
|
let external_redirection = raw_args.call_info.args.external_redirection;
|
||||||
let context = EvaluationContext::from_args(&raw_args);
|
let context = EvaluationContext::from_args(&raw_args);
|
||||||
let (
|
let (WithEnvArgs { variable, block }, input) = raw_args.process()?;
|
||||||
WithEnvArgs {
|
|
||||||
variable,
|
|
||||||
mut block,
|
|
||||||
},
|
|
||||||
input,
|
|
||||||
) = raw_args.process()?;
|
|
||||||
|
|
||||||
if let Some(block) = std::sync::Arc::<nu_protocol::hir::Block>::get_mut(&mut block.block) {
|
|
||||||
block.set_redirect(redirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut env = IndexMap::new();
|
let mut env = IndexMap::new();
|
||||||
|
|
||||||
|
@ -118,7 +108,7 @@ fn with_env(raw_args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||||
context.scope.add_env(env);
|
context.scope.add_env(env);
|
||||||
context.scope.add_vars(&block.captured.entries);
|
context.scope.add_vars(&block.captured.entries);
|
||||||
|
|
||||||
let result = run_block(&block.block, &context, input);
|
let result = run_block(&block.block, &context, input, external_redirection);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
result.map(|x| x.to_action_stream())
|
result.map(|x| x.to_action_stream())
|
||||||
|
|
|
@ -11,7 +11,7 @@ use stub_generate::{mock_path, Command as StubOpen};
|
||||||
use nu_engine::basic_evaluation_context;
|
use nu_engine::basic_evaluation_context;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_parser::ParserScope;
|
use nu_parser::ParserScope;
|
||||||
use nu_protocol::hir::ClassifiedBlock;
|
use nu_protocol::hir::{ClassifiedBlock, ExternalRedirection};
|
||||||
use nu_protocol::{ShellTypeName, Value};
|
use nu_protocol::{ShellTypeName, Value};
|
||||||
use nu_source::AnchorLocation;
|
use nu_source::AnchorLocation;
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ fn evaluate_block(
|
||||||
|
|
||||||
ctx.scope.enter_scope();
|
ctx.scope.enter_scope();
|
||||||
|
|
||||||
let result = run_block(&block.block, ctx, input_stream);
|
let result = run_block(&block.block, ctx, input_stream, ExternalRedirection::Stdout);
|
||||||
|
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ use crate::evaluation_context::EvaluationContext;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_parser::ParserScope;
|
use nu_parser::ParserScope;
|
||||||
use nu_protocol::hir::{
|
use nu_protocol::hir::{
|
||||||
Block, Call, ClassifiedCommand, Expression, Pipeline, SpannedExpression, Synthetic,
|
Block, Call, ClassifiedCommand, Expression, ExternalRedirection, Pipeline, SpannedExpression,
|
||||||
|
Synthetic,
|
||||||
};
|
};
|
||||||
use nu_protocol::{UntaggedValue, Value};
|
use nu_protocol::{UntaggedValue, Value};
|
||||||
use nu_source::{Span, Tag};
|
use nu_source::{Span, Tag};
|
||||||
|
@ -15,13 +16,15 @@ pub fn run_block(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
ctx: &EvaluationContext,
|
ctx: &EvaluationContext,
|
||||||
mut input: InputStream,
|
mut input: InputStream,
|
||||||
|
external_redirection: ExternalRedirection,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let mut output: Result<InputStream, ShellError> = Ok(OutputStream::empty());
|
let mut output: Result<InputStream, ShellError> = Ok(OutputStream::empty());
|
||||||
for (_, definition) in block.definitions.iter() {
|
for (_, definition) in block.definitions.iter() {
|
||||||
ctx.scope.add_definition(definition.clone());
|
ctx.scope.add_definition(definition.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
for group in &block.block {
|
let num_groups = block.block.len();
|
||||||
|
for (group_num, group) in block.block.iter().enumerate() {
|
||||||
match output {
|
match output {
|
||||||
Ok(inp) if inp.is_empty() => {}
|
Ok(inp) if inp.is_empty() => {}
|
||||||
Ok(inp) => {
|
Ok(inp) => {
|
||||||
|
@ -75,7 +78,9 @@ pub fn run_block(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = Ok(OutputStream::empty());
|
output = Ok(OutputStream::empty());
|
||||||
for pipeline in &group.pipelines {
|
|
||||||
|
let num_pipelines = group.pipelines.len();
|
||||||
|
for (pipeline_num, pipeline) in group.pipelines.iter().enumerate() {
|
||||||
match output {
|
match output {
|
||||||
Ok(inp) if inp.is_empty() => {}
|
Ok(inp) if inp.is_empty() => {}
|
||||||
Ok(mut output_stream) => {
|
Ok(mut output_stream) => {
|
||||||
|
@ -112,7 +117,13 @@ pub fn run_block(
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = run_pipeline(pipeline, ctx, input);
|
output = if group_num == (num_groups - 1) && pipeline_num == (num_pipelines - 1) {
|
||||||
|
// we're at the end of the block, so use the given external redirection
|
||||||
|
run_pipeline(pipeline, ctx, input, external_redirection)
|
||||||
|
} else {
|
||||||
|
// otherwise, we're in the middle of the block, so use a default redirection
|
||||||
|
run_pipeline(pipeline, ctx, input, ExternalRedirection::Stdout)
|
||||||
|
};
|
||||||
|
|
||||||
input = OutputStream::empty();
|
input = OutputStream::empty();
|
||||||
}
|
}
|
||||||
|
@ -125,13 +136,15 @@ fn run_pipeline(
|
||||||
commands: &Pipeline,
|
commands: &Pipeline,
|
||||||
ctx: &EvaluationContext,
|
ctx: &EvaluationContext,
|
||||||
mut input: InputStream,
|
mut input: InputStream,
|
||||||
|
external_redirection: ExternalRedirection,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
for item in commands.list.clone() {
|
let num_commands = commands.list.len();
|
||||||
input = match item {
|
for (command_num, command) in commands.list.iter().enumerate() {
|
||||||
|
input = match command {
|
||||||
ClassifiedCommand::Dynamic(call) => {
|
ClassifiedCommand::Dynamic(call) => {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
if let Some(positional) = call.positional {
|
if let Some(positional) = &call.positional {
|
||||||
for pos in &positional {
|
for pos in positional {
|
||||||
let result = run_expression_block(pos, ctx)?.into_vec();
|
let result = run_expression_block(pos, ctx)?.into_vec();
|
||||||
args.push(result);
|
args.push(result);
|
||||||
}
|
}
|
||||||
|
@ -160,7 +173,8 @@ fn run_pipeline(
|
||||||
{
|
{
|
||||||
ctx.scope.add_var(param.0.name(), value[0].clone());
|
ctx.scope.add_var(param.0.name(), value[0].clone());
|
||||||
}
|
}
|
||||||
let result = run_block(&captured_block.block, ctx, input);
|
let result =
|
||||||
|
run_block(&captured_block.block, ctx, input, external_redirection);
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
|
|
||||||
let result = result?;
|
let result = result?;
|
||||||
|
@ -174,9 +188,17 @@ fn run_pipeline(
|
||||||
|
|
||||||
ClassifiedCommand::Expr(expr) => run_expression_block(&*expr, ctx)?,
|
ClassifiedCommand::Expr(expr) => run_expression_block(&*expr, ctx)?,
|
||||||
|
|
||||||
ClassifiedCommand::Error(err) => return Err(err.into()),
|
ClassifiedCommand::Error(err) => return Err(err.clone().into()),
|
||||||
|
|
||||||
ClassifiedCommand::Internal(left) => run_internal_command(left, ctx, input)?,
|
ClassifiedCommand::Internal(left) => {
|
||||||
|
if command_num == (num_commands - 1) {
|
||||||
|
let mut left = left.clone();
|
||||||
|
left.args.external_redirection = external_redirection;
|
||||||
|
run_internal_command(&left, ctx, input)?
|
||||||
|
} else {
|
||||||
|
run_internal_command(left, ctx, input)?
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -278,7 +278,7 @@ fn evaluate_invocation(block: &hir::Block, ctx: &EvaluationContext) -> Result<Va
|
||||||
None => InputStream::empty(),
|
None => InputStream::empty(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = run_block(&block, ctx, input)?;
|
let result = run_block(&block, ctx, input, hir::ExternalRedirection::Stdout)?;
|
||||||
|
|
||||||
let output = result.into_vec();
|
let output = result.into_vec();
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ use nu_source::{PrettyDebug, Span, Tag};
|
||||||
use nu_stream::{ActionStream, InputStream};
|
use nu_stream::{ActionStream, InputStream};
|
||||||
|
|
||||||
pub(crate) fn run_internal_command(
|
pub(crate) fn run_internal_command(
|
||||||
command: InternalCommand,
|
command: &InternalCommand,
|
||||||
context: &EvaluationContext,
|
context: &EvaluationContext,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
|
@ -30,7 +30,7 @@ pub(crate) fn run_internal_command(
|
||||||
let result = context.run_command(
|
let result = context.run_command(
|
||||||
internal_command,
|
internal_command,
|
||||||
Tag::unknown_anchor(command.name_span),
|
Tag::unknown_anchor(command.name_span),
|
||||||
command.args,
|
command.args.clone(), // FIXME: this is inefficient
|
||||||
objects,
|
objects,
|
||||||
)?;
|
)?;
|
||||||
Ok(InputStream::from_stream(InternalIteratorSimple {
|
Ok(InputStream::from_stream(InternalIteratorSimple {
|
||||||
|
|
|
@ -2,8 +2,8 @@ use crate::{maybe_print_errors, path::canonicalize, run_block};
|
||||||
use crate::{BufCodecReader, MaybeTextCodec, StringOrBinary};
|
use crate::{BufCodecReader, MaybeTextCodec, StringOrBinary};
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::hir::{
|
use nu_protocol::hir::{
|
||||||
Call, ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments,
|
Call, ClassifiedCommand, Expression, ExternalRedirection, InternalCommand, Literal,
|
||||||
SpannedExpression,
|
NamedArguments, SpannedExpression,
|
||||||
};
|
};
|
||||||
use nu_protocol::{Primitive, UntaggedValue, Value};
|
use nu_protocol::{Primitive, UntaggedValue, Value};
|
||||||
use nu_stream::{InputStream, ToInputStream};
|
use nu_stream::{InputStream, ToInputStream};
|
||||||
|
@ -185,7 +185,7 @@ pub fn process_script(
|
||||||
|
|
||||||
trace!("{:#?}", block);
|
trace!("{:#?}", block);
|
||||||
|
|
||||||
let result = run_block(&block, ctx, input_stream);
|
let result = run_block(&block, ctx, input_stream, ExternalRedirection::None);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(input) => {
|
Ok(input) => {
|
||||||
|
|
|
@ -77,11 +77,9 @@ impl WholeStreamCommand for Arc<Block> {
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let call_info = args.call_info.clone();
|
let call_info = args.call_info.clone();
|
||||||
|
|
||||||
let mut block = self.clone();
|
let block = self.clone();
|
||||||
|
|
||||||
if let Some(block) = std::sync::Arc::<nu_protocol::hir::Block>::get_mut(&mut block) {
|
let external_redirection = args.call_info.args.external_redirection;
|
||||||
block.set_redirect(call_info.args.external_redirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ctx = EvaluationContext::from_args(&args);
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
let evaluated = call_info.evaluate(&ctx)?;
|
let evaluated = call_info.evaluate(&ctx)?;
|
||||||
|
@ -178,7 +176,7 @@ impl WholeStreamCommand for Arc<Block> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let result = run_block(&block, &ctx, input);
|
let result = run_block(&block, &ctx, input, external_redirection);
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -434,13 +434,9 @@ fn parse_invocation(
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.enter_scope();
|
scope.enter_scope();
|
||||||
let (mut classified_block, err) = classify_block(&lite_block, scope);
|
let (classified_block, err) = classify_block(&lite_block, scope);
|
||||||
scope.exit_scope();
|
scope.exit_scope();
|
||||||
|
|
||||||
if let Some(x) = std::sync::Arc::<nu_protocol::hir::Block>::get_mut(&mut classified_block) {
|
|
||||||
x.set_redirect(ExternalRedirection::Stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
(
|
||||||
SpannedExpression::new(Expression::Invocation(classified_block), lite_arg.span),
|
SpannedExpression::new(Expression::Invocation(classified_block), lite_arg.span),
|
||||||
err,
|
err,
|
||||||
|
|
|
@ -206,16 +206,6 @@ impl Block {
|
||||||
self.infer_params();
|
self.infer_params();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_redirect(&mut self, external_redirection: ExternalRedirection) {
|
|
||||||
if let Some(group) = self.block.last_mut() {
|
|
||||||
if let Some(pipeline) = group.pipelines.last_mut() {
|
|
||||||
if let Some(ClassifiedCommand::Internal(internal)) = pipeline.list.last_mut() {
|
|
||||||
internal.args.external_redirection = external_redirection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_it_usage(&self) -> bool {
|
pub fn has_it_usage(&self) -> bool {
|
||||||
self.block.iter().any(|x| x.has_it_usage())
|
self.block.iter().any(|x| x.has_it_usage())
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,13 @@ fn correctly_escape_external_arguments() {
|
||||||
assert_eq!(actual.out, "$0");
|
assert_eq!(actual.out, "$0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn redirects_custom_command_external() {
|
||||||
|
let actual = nu!(cwd: ".", r#"def foo [] { nu --testbin cococo foo bar }; foo | str length "#);
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "8");
|
||||||
|
}
|
||||||
|
|
||||||
mod it_evaluation {
|
mod it_evaluation {
|
||||||
use super::nu;
|
use super::nu;
|
||||||
use nu_test_support::fs::Stub::{EmptyFile, FileWithContent, FileWithContentToBeTrimmed};
|
use nu_test_support::fs::Stub::{EmptyFile, FileWithContent, FileWithContentToBeTrimmed};
|
||||||
|
|
Loading…
Reference in a new issue