From 3ad4e0348f5f0488f2d47d58f7d2a844c7181cc2 Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 22 Apr 2021 08:54:34 +1200 Subject: [PATCH] Fix external redirect (#3345) * Fix external redirection * Fix external redirection --- crates/nu-cli/src/cli.rs | 22 ++++++---- crates/nu-command/src/commands/benchmark.rs | 19 ++++++-- crates/nu-command/src/commands/do_.rs | 7 +-- .../nu-command/src/commands/each/command.rs | 16 +++++-- crates/nu-command/src/commands/each/group.rs | 12 ++++- crates/nu-command/src/commands/each/window.rs | 8 +++- crates/nu-command/src/commands/empty.rs | 11 +++-- crates/nu-command/src/commands/group_by.rs | 8 +++- crates/nu-command/src/commands/if_.rs | 5 ++- crates/nu-command/src/commands/insert.rs | 8 +++- crates/nu-command/src/commands/merge.rs | 10 ++++- crates/nu-command/src/commands/reduce.rs | 11 ++++- .../nu-command/src/commands/run_external.rs | 3 -- crates/nu-command/src/commands/update.rs | 8 +++- crates/nu-command/src/commands/with_env.rs | 16 ++----- crates/nu-command/src/examples.rs | 4 +- crates/nu-engine/src/evaluate/block.rs | 44 ++++++++++++++----- crates/nu-engine/src/evaluate/evaluator.rs | 2 +- crates/nu-engine/src/evaluate/internal.rs | 4 +- crates/nu-engine/src/script.rs | 6 +-- crates/nu-engine/src/whole_stream_command.rs | 8 ++-- crates/nu-parser/src/parse.rs | 6 +-- crates/nu-protocol/src/hir.rs | 10 ----- tests/shell/pipeline/commands/external.rs | 7 +++ 24 files changed, 164 insertions(+), 91 deletions(-) diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 09a4f65f92..9186d4959c 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -229,13 +229,7 @@ pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box::get_mut(&mut prompt_block) - { - block.set_redirect(ExternalRedirection::Stdout); - } + let (prompt_block, err) = nu_parser::parse(&prompt_line, 0, &context.scope); if err.is_some() { context.scope.exit_scope(); @@ -250,7 +244,12 @@ pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box Result Result { // let start = time(); 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(); let output = result?.into_vec(); @@ -154,7 +162,12 @@ where let time_block = add_implicit_autoview(time_block.block); 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(); result?; context.clear_errors(); diff --git a/crates/nu-command/src/commands/do_.rs b/crates/nu-command/src/commands/do_.rs index fa1d891c0c..1798677d5e 100644 --- a/crates/nu-command/src/commands/do_.rs +++ b/crates/nu-command/src/commands/do_.rs @@ -58,7 +58,7 @@ fn do_(raw_args: CommandArgs) -> Result { let ( DoArgs { ignore_errors, - mut block, + block, }, input, ) = raw_args.process()?; @@ -81,11 +81,8 @@ fn do_(raw_args: CommandArgs) -> Result { x => x, }; - if let Some(block) = std::sync::Arc::::get_mut(&mut block.block) { - block.set_redirect(block_redirection); - } 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(); if ignore_errors { diff --git a/crates/nu-command/src/commands/each/command.rs b/crates/nu-command/src/commands/each/command.rs index aef0b9991e..73221a3832 100644 --- a/crates/nu-command/src/commands/each/command.rs +++ b/crates/nu-command/src/commands/each/command.rs @@ -4,7 +4,8 @@ use nu_engine::WholeStreamCommand; use nu_errors::ShellError; use nu_protocol::{ - hir::CapturedBlock, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, + hir::{CapturedBlock, ExternalRedirection}, + Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, }; pub struct Each; @@ -62,6 +63,7 @@ pub fn process_row( captured_block: Arc>, context: Arc, input: Value, + external_redirection: ExternalRedirection, ) -> Result { 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 @@ -86,7 +88,12 @@ pub fn process_row( 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(); @@ -103,6 +110,7 @@ pub(crate) fn make_indexed_item(index: usize, item: Value) -> Value { fn each(raw_args: CommandArgs) -> Result { 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 block: CapturedBlock = args.req(0)?; @@ -119,7 +127,7 @@ fn each(raw_args: CommandArgs) -> Result { let context = context.clone(); 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, Err(e) => OutputStream::one(Value::error(e)), } @@ -133,7 +141,7 @@ fn each(raw_args: CommandArgs) -> Result { let block = block.clone(); let context = context.clone(); - match process_row(block, context, input) { + match process_row(block, context, input, external_redirection) { Ok(s) => s, Err(e) => OutputStream::one(Value::error(e)), } diff --git a/crates/nu-command/src/commands/each/group.rs b/crates/nu-command/src/commands/each/group.rs index 2dde29ef55..dfbae193fb 100644 --- a/crates/nu-command/src/commands/each/group.rs +++ b/crates/nu-command/src/commands/each/group.rs @@ -2,7 +2,10 @@ use crate::commands::each::process_row; use crate::prelude::*; use nu_engine::WholeStreamCommand; 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 serde::Deserialize; @@ -44,6 +47,7 @@ impl WholeStreamCommand for EachGroup { fn run_with_actions(&self, raw_args: CommandArgs) -> Result { 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 block = Arc::new(Box::new(each_args.block)); @@ -52,6 +56,7 @@ impl WholeStreamCommand for EachGroup { context, group_size: each_args.group_size.item, input, + external_redirection, }; Ok(each_group_iterator.flatten().to_action_stream()) @@ -63,6 +68,7 @@ struct EachGroupIterator { context: Arc, group_size: usize, input: InputStream, + external_redirection: ExternalRedirection, } impl Iterator for EachGroupIterator { @@ -89,6 +95,7 @@ impl Iterator for EachGroupIterator { group, self.block.clone(), self.context.clone(), + self.external_redirection, )) } } @@ -97,13 +104,14 @@ pub(crate) fn run_block_on_vec( input: Vec, block: Arc>, context: Arc, + external_redirection: ExternalRedirection, ) -> OutputStream { let value = Value { value: UntaggedValue::Table(input), tag: Tag::unknown(), }; - match process_row(block, context, value) { + match process_row(block, context, value, external_redirection) { Ok(s) => { // We need to handle this differently depending on whether process_row // returned just 1 value or if it returned multiple as a stream. diff --git a/crates/nu-command/src/commands/each/window.rs b/crates/nu-command/src/commands/each/window.rs index e69b57bbd4..0f8dbd669c 100644 --- a/crates/nu-command/src/commands/each/window.rs +++ b/crates/nu-command/src/commands/each/window.rs @@ -51,6 +51,7 @@ impl WholeStreamCommand for EachWindow { fn run_with_actions(&self, raw_args: CommandArgs) -> Result { 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 block = Arc::new(Box::new(each_args.block)); @@ -76,7 +77,12 @@ impl WholeStreamCommand for EachWindow { let local_window = window.clone(); 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 { None } diff --git a/crates/nu-command/src/commands/empty.rs b/crates/nu-command/src/commands/empty.rs index cf2f569eb4..4c97c0d246 100644 --- a/crates/nu-command/src/commands/empty.rs +++ b/crates/nu-command/src/commands/empty.rs @@ -3,8 +3,8 @@ use nu_engine::run_block; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; use nu_protocol::{ - hir::CapturedBlock, ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, - UntaggedValue, Value, + hir::CapturedBlock, hir::ExternalRedirection, ColumnPath, Primitive, ReturnSuccess, Signature, + SyntaxShape, UntaggedValue, Value, }; use crate::utils::arguments::arguments; @@ -142,7 +142,12 @@ fn process_row( context.scope.add_vars(&default_block.captured.entries); 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(); let mut stream = stream?; diff --git a/crates/nu-command/src/commands/group_by.rs b/crates/nu-command/src/commands/group_by.rs index 32b28b8a43..f495a16c99 100644 --- a/crates/nu-command/src/commands/group_by.rs +++ b/crates/nu-command/src/commands/group_by.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use crate::utils::suggestions::suggestions; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; +use nu_protocol::hir::ExternalRedirection; use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; use nu_value_ext::as_string; @@ -148,7 +149,12 @@ pub fn group_by(args: CommandArgs) -> Result { let run = block.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) => { let collection: Vec = s.drain_vec(); diff --git a/crates/nu-command/src/commands/if_.rs b/crates/nu-command/src/commands/if_.rs index 7226dac411..e32adb0bb2 100644 --- a/crates/nu-command/src/commands/if_.rs +++ b/crates/nu-command/src/commands/if_.rs @@ -59,6 +59,7 @@ impl WholeStreamCommand for If { } fn if_command(raw_args: CommandArgs) -> Result { 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 args = raw_args.evaluate_once()?; @@ -105,9 +106,9 @@ fn if_command(raw_args: CommandArgs) -> Result { Ok(condition) => match condition.as_bool() { Ok(b) => { let result = if b { - run_block(&then_case.block, &*context, input) + run_block(&then_case.block, &*context, input, external_redirection) } else { - run_block(&else_case.block, &*context, input) + run_block(&else_case.block, &*context, input, external_redirection) }; context.scope.exit_scope(); diff --git a/crates/nu-command/src/commands/insert.rs b/crates/nu-command/src/commands/insert.rs index 734c036a17..37a875e52f 100644 --- a/crates/nu-command/src/commands/insert.rs +++ b/crates/nu-command/src/commands/insert.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use nu_engine::run_block; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; +use nu_protocol::hir::ExternalRedirection; use nu_protocol::{ ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, }; @@ -81,7 +82,12 @@ fn process_row( context.scope.add_vars(&block.captured.entries); 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(); diff --git a/crates/nu-command/src/commands/merge.rs b/crates/nu-command/src/commands/merge.rs index 0249c8dd2d..167ad1f7d6 100644 --- a/crates/nu-command/src/commands/merge.rs +++ b/crates/nu-command/src/commands/merge.rs @@ -6,7 +6,8 @@ use nu_engine::WholeStreamCommand; use indexmap::IndexMap; use nu_errors::ShellError; use nu_protocol::{ - hir::CapturedBlock, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, + hir::CapturedBlock, hir::ExternalRedirection, ReturnSuccess, Signature, SyntaxShape, + UntaggedValue, Value, }; pub struct Merge; @@ -53,7 +54,12 @@ fn merge(raw_args: CommandArgs) -> Result { context.scope.enter_scope(); 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(); let table: Option> = match result { diff --git a/crates/nu-command/src/commands/reduce.rs b/crates/nu-command/src/commands/reduce.rs index b0d2eb0aa9..9cf9177a44 100644 --- a/crates/nu-command/src/commands/reduce.rs +++ b/crates/nu-command/src/commands/reduce.rs @@ -5,7 +5,9 @@ use nu_engine::WholeStreamCommand; use nu_engine::{CommandArgs, Example}; use nu_errors::ShellError; 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_stream::ActionStream; @@ -88,7 +90,12 @@ fn process_row( context.scope.enter_scope(); context.scope.add_vars(&block.captured.entries); 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(); result diff --git a/crates/nu-command/src/commands/run_external.rs b/crates/nu-command/src/commands/run_external.rs index 6e9ca6cb65..3814e0e1ad 100644 --- a/crates/nu-command/src/commands/run_external.rs +++ b/crates/nu-command/src/commands/run_external.rs @@ -12,9 +12,6 @@ use nu_protocol::hir::{Expression, ExternalArgs, ExternalCommand, Literal, Spann use nu_protocol::{Signature, SyntaxShape}; use nu_source::Tagged; -#[derive(Deserialize)] -pub struct RunExternalArgs {} - #[derive(new)] pub struct RunExternalCommand { /// Whether or not nushell is being used in an interactive context diff --git a/crates/nu-command/src/commands/update.rs b/crates/nu-command/src/commands/update.rs index b9fa95f5fb..bbf2a8a820 100644 --- a/crates/nu-command/src/commands/update.rs +++ b/crates/nu-command/src/commands/update.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use nu_engine::run_block; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; +use nu_protocol::hir::ExternalRedirection; use nu_protocol::{ ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, }; @@ -86,7 +87,12 @@ fn process_row( context.scope.add_var("$it", input.clone()); 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(); diff --git a/crates/nu-command/src/commands/with_env.rs b/crates/nu-command/src/commands/with_env.rs index a5f883602c..c2a0ebe36f 100644 --- a/crates/nu-command/src/commands/with_env.rs +++ b/crates/nu-command/src/commands/with_env.rs @@ -68,19 +68,9 @@ impl WholeStreamCommand for WithEnv { } fn with_env(raw_args: CommandArgs) -> Result { - 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 ( - WithEnvArgs { - variable, - mut block, - }, - input, - ) = raw_args.process()?; - - if let Some(block) = std::sync::Arc::::get_mut(&mut block.block) { - block.set_redirect(redirection); - } + let (WithEnvArgs { variable, block }, input) = raw_args.process()?; let mut env = IndexMap::new(); @@ -118,7 +108,7 @@ fn with_env(raw_args: CommandArgs) -> Result { context.scope.add_env(env); 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(); result.map(|x| x.to_action_stream()) diff --git a/crates/nu-command/src/examples.rs b/crates/nu-command/src/examples.rs index cd10723014..b8056f71f0 100644 --- a/crates/nu-command/src/examples.rs +++ b/crates/nu-command/src/examples.rs @@ -11,7 +11,7 @@ use stub_generate::{mock_path, Command as StubOpen}; use nu_engine::basic_evaluation_context; use nu_errors::ShellError; use nu_parser::ParserScope; -use nu_protocol::hir::ClassifiedBlock; +use nu_protocol::hir::{ClassifiedBlock, ExternalRedirection}; use nu_protocol::{ShellTypeName, Value}; use nu_source::AnchorLocation; @@ -231,7 +231,7 @@ fn evaluate_block( 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(); diff --git a/crates/nu-engine/src/evaluate/block.rs b/crates/nu-engine/src/evaluate/block.rs index 009a3a601a..8520491329 100644 --- a/crates/nu-engine/src/evaluate/block.rs +++ b/crates/nu-engine/src/evaluate/block.rs @@ -4,7 +4,8 @@ use crate::evaluation_context::EvaluationContext; use nu_errors::ShellError; use nu_parser::ParserScope; 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_source::{Span, Tag}; @@ -15,13 +16,15 @@ pub fn run_block( block: &Block, ctx: &EvaluationContext, mut input: InputStream, + external_redirection: ExternalRedirection, ) -> Result { let mut output: Result = Ok(OutputStream::empty()); for (_, definition) in block.definitions.iter() { 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 { Ok(inp) if inp.is_empty() => {} Ok(inp) => { @@ -75,7 +78,9 @@ pub fn run_block( } } 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 { Ok(inp) if inp.is_empty() => {} Ok(mut output_stream) => { @@ -112,7 +117,13 @@ pub fn run_block( 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(); } @@ -125,13 +136,15 @@ fn run_pipeline( commands: &Pipeline, ctx: &EvaluationContext, mut input: InputStream, + external_redirection: ExternalRedirection, ) -> Result { - for item in commands.list.clone() { - input = match item { + let num_commands = commands.list.len(); + for (command_num, command) in commands.list.iter().enumerate() { + input = match command { ClassifiedCommand::Dynamic(call) => { let mut args = vec![]; - if let Some(positional) = call.positional { - for pos in &positional { + if let Some(positional) = &call.positional { + for pos in positional { let result = run_expression_block(pos, ctx)?.into_vec(); args.push(result); } @@ -160,7 +173,8 @@ fn run_pipeline( { 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(); let result = result?; @@ -174,9 +188,17 @@ fn run_pipeline( 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)? + } + } }; } diff --git a/crates/nu-engine/src/evaluate/evaluator.rs b/crates/nu-engine/src/evaluate/evaluator.rs index 91c0670b3d..15d6d72dfa 100644 --- a/crates/nu-engine/src/evaluate/evaluator.rs +++ b/crates/nu-engine/src/evaluate/evaluator.rs @@ -278,7 +278,7 @@ fn evaluate_invocation(block: &hir::Block, ctx: &EvaluationContext) -> Result InputStream::empty(), }; - let result = run_block(&block, ctx, input)?; + let result = run_block(&block, ctx, input, hir::ExternalRedirection::Stdout)?; let output = result.into_vec(); diff --git a/crates/nu-engine/src/evaluate/internal.rs b/crates/nu-engine/src/evaluate/internal.rs index 4aa2836348..f67773bd1d 100644 --- a/crates/nu-engine/src/evaluate/internal.rs +++ b/crates/nu-engine/src/evaluate/internal.rs @@ -13,7 +13,7 @@ use nu_source::{PrettyDebug, Span, Tag}; use nu_stream::{ActionStream, InputStream}; pub(crate) fn run_internal_command( - command: InternalCommand, + command: &InternalCommand, context: &EvaluationContext, input: InputStream, ) -> Result { @@ -30,7 +30,7 @@ pub(crate) fn run_internal_command( let result = context.run_command( internal_command, Tag::unknown_anchor(command.name_span), - command.args, + command.args.clone(), // FIXME: this is inefficient objects, )?; Ok(InputStream::from_stream(InternalIteratorSimple { diff --git a/crates/nu-engine/src/script.rs b/crates/nu-engine/src/script.rs index 77f1bcc8fd..7abe739f72 100644 --- a/crates/nu-engine/src/script.rs +++ b/crates/nu-engine/src/script.rs @@ -2,8 +2,8 @@ use crate::{maybe_print_errors, path::canonicalize, run_block}; use crate::{BufCodecReader, MaybeTextCodec, StringOrBinary}; use nu_errors::ShellError; use nu_protocol::hir::{ - Call, ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments, - SpannedExpression, + Call, ClassifiedCommand, Expression, ExternalRedirection, InternalCommand, Literal, + NamedArguments, SpannedExpression, }; use nu_protocol::{Primitive, UntaggedValue, Value}; use nu_stream::{InputStream, ToInputStream}; @@ -185,7 +185,7 @@ pub fn process_script( trace!("{:#?}", block); - let result = run_block(&block, ctx, input_stream); + let result = run_block(&block, ctx, input_stream, ExternalRedirection::None); match result { Ok(input) => { diff --git a/crates/nu-engine/src/whole_stream_command.rs b/crates/nu-engine/src/whole_stream_command.rs index c80bff856f..ba5c25db87 100644 --- a/crates/nu-engine/src/whole_stream_command.rs +++ b/crates/nu-engine/src/whole_stream_command.rs @@ -77,11 +77,9 @@ impl WholeStreamCommand for Arc { fn run(&self, args: CommandArgs) -> Result { let call_info = args.call_info.clone(); - let mut block = self.clone(); + let block = self.clone(); - if let Some(block) = std::sync::Arc::::get_mut(&mut block) { - block.set_redirect(call_info.args.external_redirection); - } + let external_redirection = args.call_info.args.external_redirection; let ctx = EvaluationContext::from_args(&args); let evaluated = call_info.evaluate(&ctx)?; @@ -178,7 +176,7 @@ impl WholeStreamCommand for Arc { } } } - let result = run_block(&block, &ctx, input); + let result = run_block(&block, &ctx, input, external_redirection); ctx.scope.exit_scope(); result } diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index 672c3feed9..5a364985fd 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -434,13 +434,9 @@ fn parse_invocation( }; 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(); - if let Some(x) = std::sync::Arc::::get_mut(&mut classified_block) { - x.set_redirect(ExternalRedirection::Stdout); - } - ( SpannedExpression::new(Expression::Invocation(classified_block), lite_arg.span), err, diff --git a/crates/nu-protocol/src/hir.rs b/crates/nu-protocol/src/hir.rs index 8fa0901957..516d28e152 100644 --- a/crates/nu-protocol/src/hir.rs +++ b/crates/nu-protocol/src/hir.rs @@ -206,16 +206,6 @@ impl Block { 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 { self.block.iter().any(|x| x.has_it_usage()) } diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 60173241fc..8d2f46dc12 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -68,6 +68,13 @@ fn correctly_escape_external_arguments() { 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 { use super::nu; use nu_test_support::fs::Stub::{EmptyFile, FileWithContent, FileWithContentToBeTrimmed};