diff --git a/crates/nu-cli/src/completions/completer.rs b/crates/nu-cli/src/completions/completer.rs index f4e3b1e817..079425e2a7 100644 --- a/crates/nu-cli/src/completions/completer.rs +++ b/crates/nu-cli/src/completions/completer.rs @@ -25,7 +25,7 @@ impl NuCompleter { pub fn new(engine_state: Arc, stack: Arc) -> Self { Self { engine_state, - stack: Stack::with_parent(stack).reset_out_dest().capture(), + stack: Stack::with_parent(stack).reset_out_dest().collect_value(), } } diff --git a/crates/nu-cli/src/menus/menu_completions.rs b/crates/nu-cli/src/menus/menu_completions.rs index af653843f0..4c4c9f59e8 100644 --- a/crates/nu-cli/src/menus/menu_completions.rs +++ b/crates/nu-cli/src/menus/menu_completions.rs @@ -28,7 +28,7 @@ impl NuMenuCompleter { Self { block_id, span, - stack: stack.reset_out_dest().capture(), + stack: stack.reset_out_dest().collect_value(), engine_state, only_buffer_difference, } diff --git a/crates/nu-cli/src/reedline_config.rs b/crates/nu-cli/src/reedline_config.rs index 71fd9f32e1..6c3d457612 100644 --- a/crates/nu-cli/src/reedline_config.rs +++ b/crates/nu-cli/src/reedline_config.rs @@ -122,7 +122,7 @@ pub(crate) fn add_menus( engine_state.merge_delta(delta)?; - let mut temp_stack = Stack::new().capture(); + let mut temp_stack = Stack::new().collect_value(); let input = PipelineData::Empty; menu_eval_results.push(eval_block::( &engine_state, diff --git a/crates/nu-cmd-lang/src/core_commands/do_.rs b/crates/nu-cmd-lang/src/core_commands/do_.rs index 742bc3d218..3a48c66745 100644 --- a/crates/nu-cmd-lang/src/core_commands/do_.rs +++ b/crates/nu-cmd-lang/src/core_commands/do_.rs @@ -166,7 +166,10 @@ impl Command for Do { } Ok(PipelineData::ByteStream(mut stream, metadata)) if ignore_program_errors - && !matches!(caller_stack.stdout(), OutDest::Pipe | OutDest::Capture) => + && !matches!( + caller_stack.stdout(), + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value + ) => { if let ByteStreamSource::Child(child) = stream.source_mut() { child.ignore_error(); diff --git a/crates/nu-cmd-lang/src/core_commands/let_.rs b/crates/nu-cmd-lang/src/core_commands/let_.rs index 3e0b2f97eb..b7deca5b81 100644 --- a/crates/nu-cmd-lang/src/core_commands/let_.rs +++ b/crates/nu-cmd-lang/src/core_commands/let_.rs @@ -63,7 +63,7 @@ impl Command for Let { let block = engine_state.get_block(block_id); let eval_block = get_eval_block(engine_state); - let stack = &mut stack.start_capture(); + let stack = &mut stack.start_collect_value(); let pipeline_data = eval_block(engine_state, stack, block, input)?; let value = pipeline_data.into_value(call.head)?; diff --git a/crates/nu-cmd-lang/src/core_commands/mut_.rs b/crates/nu-cmd-lang/src/core_commands/mut_.rs index a72d8f484f..785a47f943 100644 --- a/crates/nu-cmd-lang/src/core_commands/mut_.rs +++ b/crates/nu-cmd-lang/src/core_commands/mut_.rs @@ -63,7 +63,7 @@ impl Command for Mut { let block = engine_state.get_block(block_id); let eval_block = get_eval_block(engine_state); - let stack = &mut stack.start_capture(); + let stack = &mut stack.start_collect_value(); let pipeline_data = eval_block(engine_state, stack, block, input)?; let value = pipeline_data.into_value(call.head)?; diff --git a/crates/nu-cmd-lang/src/example_support.rs b/crates/nu-cmd-lang/src/example_support.rs index 8df5a6c1e8..e430c35c43 100644 --- a/crates/nu-cmd-lang/src/example_support.rs +++ b/crates/nu-cmd-lang/src/example_support.rs @@ -126,7 +126,7 @@ pub fn eval_block( cwd: &std::path::Path, engine_state: &EngineState, ) -> Value { - let mut stack = Stack::new().capture(); + let mut stack = Stack::new().collect_value(); stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy())); @@ -143,7 +143,7 @@ pub fn check_example_evaluates_to_expected_output( cwd: &std::path::Path, engine_state: &mut Box, ) { - let mut stack = Stack::new().capture(); + let mut stack = Stack::new().collect_value(); // Set up PWD stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy())); diff --git a/crates/nu-command/src/filesystem/save.rs b/crates/nu-command/src/filesystem/save.rs index 1b6ddd5982..f14ed25471 100644 --- a/crates/nu-command/src/filesystem/save.rs +++ b/crates/nu-command/src/filesystem/save.rs @@ -270,7 +270,7 @@ impl Command for Save { } fn pipe_redirection(&self) -> (Option, Option) { - (Some(OutDest::Capture), Some(OutDest::Capture)) + (Some(OutDest::PipeSeparate), Some(OutDest::PipeSeparate)) } } diff --git a/crates/nu-command/src/filters/tee.rs b/crates/nu-command/src/filters/tee.rs index 65c0aba546..02afdc5271 100644 --- a/crates/nu-command/src/filters/tee.rs +++ b/crates/nu-command/src/filters/tee.rs @@ -158,7 +158,7 @@ use it in your pipeline."# let tee_thread = spawn_tee(info.clone(), eval_block)?; let tee = IoTee::new(stderr, tee_thread); match stack.stderr() { - OutDest::Pipe | OutDest::Capture => { + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value => { child.stderr = Some(ChildPipe::Tee(Box::new(tee))); Ok(None) } @@ -176,7 +176,7 @@ use it in your pipeline."# if let Some(stdout) = child.stdout.take() { match stack.stdout() { - OutDest::Pipe | OutDest::Capture => { + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value => { child.stdout = Some(stdout); Ok(()) } @@ -191,7 +191,7 @@ use it in your pipeline."# let stderr_thread = if let Some(stderr) = child.stderr.take() { let info = info.clone(); match stack.stderr() { - OutDest::Pipe | OutDest::Capture => { + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value => { child.stderr = Some(stderr); Ok(None) } @@ -213,7 +213,7 @@ use it in your pipeline."# let tee_thread = spawn_tee(info.clone(), eval_block)?; let tee = IoTee::new(stdout, tee_thread); match stack.stdout() { - OutDest::Pipe | OutDest::Capture => { + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value => { child.stdout = Some(ChildPipe::Tee(Box::new(tee))); Ok(()) } @@ -280,7 +280,7 @@ use it in your pipeline."# } fn pipe_redirection(&self) -> (Option, Option) { - (Some(OutDest::Capture), Some(OutDest::Capture)) + (Some(OutDest::PipeSeparate), Some(OutDest::PipeSeparate)) } } diff --git a/crates/nu-command/src/system/complete.rs b/crates/nu-command/src/system/complete.rs index 948f8acec6..21b33ac656 100644 --- a/crates/nu-command/src/system/complete.rs +++ b/crates/nu-command/src/system/complete.rs @@ -93,6 +93,6 @@ impl Command for Complete { } fn pipe_redirection(&self) -> (Option, Option) { - (Some(OutDest::Capture), Some(OutDest::Capture)) + (Some(OutDest::PipeSeparate), Some(OutDest::PipeSeparate)) } } diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 70a00bc815..80c1c94e23 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -340,7 +340,7 @@ fn write_pipeline_data( } else if let PipelineData::Value(Value::Binary { val, .. }, ..) = data { writer.write_all(&val)?; } else { - stack.start_capture(); + stack.start_collect_value(); // Turn off color as we pass data through Arc::make_mut(&mut engine_state.config).use_ansi_coloring = false; @@ -367,7 +367,7 @@ pub fn command_not_found( ) -> ShellError { // Run the `command_not_found` hook if there is one. if let Some(hook) = &stack.get_config(engine_state).hooks.command_not_found { - let mut stack = stack.start_capture(); + let mut stack = stack.start_collect_value(); // Set a special environment variable to avoid infinite loops when the // `command_not_found` hook triggers itself. let canary = "ENTERED_COMMAND_NOT_FOUND"; diff --git a/crates/nu-command/tests/commands/try_.rs b/crates/nu-command/tests/commands/try_.rs index 58d1c8f80a..dc8c7ba5f8 100644 --- a/crates/nu-command/tests/commands/try_.rs +++ b/crates/nu-command/tests/commands/try_.rs @@ -105,3 +105,15 @@ fn exit_code_available_in_catch() { let actual = nu!("try { nu -c 'exit 42' } catch { |e| $e.exit_code }"); assert_eq!(actual.out, "42"); } + +#[test] +fn try_catches_exit_code_in_assignment() { + let actual = nu!("let x = try { nu -c 'exit 42' } catch { |e| $e.exit_code }; $x"); + assert_eq!(actual.out, "42"); +} + +#[test] +fn try_catches_exit_code_in_expr() { + let actual = nu!("print (try { nu -c 'exit 42' } catch { |e| $e.exit_code })"); + assert_eq!(actual.out, "42"); +} diff --git a/crates/nu-engine/src/compile/call.rs b/crates/nu-engine/src/compile/call.rs index d9f1b8e581..e928b63826 100644 --- a/crates/nu-engine/src/compile/call.rs +++ b/crates/nu-engine/src/compile/call.rs @@ -108,7 +108,7 @@ pub(crate) fn compile_call( working_set, builder, expr, - RedirectModes::capture_out(arg.span()), + RedirectModes::value(arg.span()), None, arg_reg, )?; diff --git a/crates/nu-engine/src/compile/expression.rs b/crates/nu-engine/src/compile/expression.rs index 80fc4fb3fb..0badb76b45 100644 --- a/crates/nu-engine/src/compile/expression.rs +++ b/crates/nu-engine/src/compile/expression.rs @@ -90,7 +90,7 @@ pub(crate) fn compile_expression( working_set, builder, part_expr, - RedirectModes::capture_out(part_expr.span), + RedirectModes::value(part_expr.span), None, reg, )?; @@ -148,7 +148,7 @@ pub(crate) fn compile_expression( working_set, builder, subexpr, - RedirectModes::capture_out(subexpr.span), + RedirectModes::value(subexpr.span), None, out_reg, )?; @@ -217,7 +217,7 @@ pub(crate) fn compile_expression( working_set, builder, expr, - RedirectModes::capture_out(expr.span), + RedirectModes::value(expr.span), None, reg, )?; @@ -265,7 +265,7 @@ pub(crate) fn compile_expression( working_set, builder, column, - RedirectModes::capture_out(column.span), + RedirectModes::value(column.span), None, reg, )?; @@ -290,7 +290,7 @@ pub(crate) fn compile_expression( working_set, builder, item, - RedirectModes::capture_out(item.span), + RedirectModes::value(item.span), None, item_reg, )?; @@ -337,7 +337,7 @@ pub(crate) fn compile_expression( working_set, builder, key, - RedirectModes::capture_out(key.span), + RedirectModes::value(key.span), None, key_reg, )?; @@ -345,7 +345,7 @@ pub(crate) fn compile_expression( working_set, builder, val, - RedirectModes::capture_out(val.span), + RedirectModes::value(val.span), None, val_reg, )?; @@ -365,7 +365,7 @@ pub(crate) fn compile_expression( working_set, builder, expr, - RedirectModes::capture_out(expr.span), + RedirectModes::value(expr.span), None, reg, )?; @@ -449,7 +449,7 @@ pub(crate) fn compile_expression( // general, which shouldn't be captured any differently than they otherwise // would be. if !full_cell_path.tail.is_empty() { - RedirectModes::capture_out(expr.span) + RedirectModes::value(expr.span) } else { redirect_modes }, @@ -491,7 +491,7 @@ pub(crate) fn compile_expression( working_set, builder, exprs_iter.next().expect("peek() was Some"), - RedirectModes::capture_out(expr.span), + RedirectModes::value(expr.span), None, out_reg, )?; @@ -507,7 +507,7 @@ pub(crate) fn compile_expression( working_set, builder, expr, - RedirectModes::capture_out(expr.span), + RedirectModes::value(expr.span), None, scratch_reg, )?; diff --git a/crates/nu-engine/src/compile/keyword.rs b/crates/nu-engine/src/compile/keyword.rs index f9a81ab6d1..62c5b7108a 100644 --- a/crates/nu-engine/src/compile/keyword.rs +++ b/crates/nu-engine/src/compile/keyword.rs @@ -47,7 +47,7 @@ pub(crate) fn compile_if( working_set, builder, condition, - RedirectModes::capture_out(condition.span), + RedirectModes::value(condition.span), None, condition_reg, )?; @@ -181,7 +181,7 @@ pub(crate) fn compile_match( working_set, builder, match_expr, - RedirectModes::capture_out(match_expr.span), + RedirectModes::value(match_expr.span), None, match_reg, )?; @@ -233,7 +233,7 @@ pub(crate) fn compile_match( working_set, builder, guard, - RedirectModes::capture_out(guard.span), + RedirectModes::value(guard.span), None, guard_reg, )?; @@ -319,7 +319,7 @@ pub(crate) fn compile_let( working_set, builder, block, - RedirectModes::capture_out(call.head), + RedirectModes::value(call.head), Some(io_reg), io_reg, )?; @@ -427,7 +427,7 @@ pub(crate) fn compile_try( working_set, builder, catch_expr, - RedirectModes::capture_out(catch_expr.span), + RedirectModes::value(catch_expr.span), None, closure_reg, )?; @@ -655,7 +655,7 @@ pub(crate) fn compile_while( working_set, builder, cond_arg, - RedirectModes::capture_out(call.head), + RedirectModes::value(call.head), None, io_reg, )?; @@ -739,7 +739,7 @@ pub(crate) fn compile_for( working_set, builder, in_expr, - RedirectModes::capture_out(in_expr.span), + RedirectModes::value(in_expr.span), None, stream_reg, )?; @@ -867,7 +867,7 @@ pub(crate) fn compile_return( working_set, builder, arg_expr, - RedirectModes::capture_out(arg_expr.span), + RedirectModes::value(arg_expr.span), None, io_reg, )?; diff --git a/crates/nu-engine/src/compile/operator.rs b/crates/nu-engine/src/compile/operator.rs index a1ed3f66df..bad206358d 100644 --- a/crates/nu-engine/src/compile/operator.rs +++ b/crates/nu-engine/src/compile/operator.rs @@ -35,7 +35,7 @@ pub(crate) fn compile_binary_op( working_set, builder, rhs, - RedirectModes::capture_out(rhs.span), + RedirectModes::value(rhs.span), None, out_reg, )?; @@ -53,7 +53,7 @@ pub(crate) fn compile_binary_op( working_set, builder, lhs, - RedirectModes::capture_out(lhs.span), + RedirectModes::value(lhs.span), None, lhs_reg, )?; @@ -73,7 +73,7 @@ pub(crate) fn compile_binary_op( working_set, builder, rhs, - RedirectModes::capture_out(rhs.span), + RedirectModes::value(rhs.span), None, lhs_reg, )?; @@ -96,7 +96,7 @@ pub(crate) fn compile_binary_op( working_set, builder, rhs, - RedirectModes::capture_out(rhs.span), + RedirectModes::value(rhs.span), None, lhs_reg, )?; @@ -118,7 +118,7 @@ pub(crate) fn compile_binary_op( working_set, builder, rhs, - RedirectModes::capture_out(rhs.span), + RedirectModes::value(rhs.span), None, rhs_reg, )?; @@ -277,7 +277,7 @@ pub(crate) fn compile_assignment( working_set, builder, &path.head, - RedirectModes::capture_out(path.head.span), + RedirectModes::value(path.head.span), None, head_reg, )?; diff --git a/crates/nu-engine/src/compile/redirect.rs b/crates/nu-engine/src/compile/redirect.rs index 15af1a9f8c..eaedd65213 100644 --- a/crates/nu-engine/src/compile/redirect.rs +++ b/crates/nu-engine/src/compile/redirect.rs @@ -14,9 +14,9 @@ pub(crate) struct RedirectModes { } impl RedirectModes { - pub(crate) fn capture_out(span: Span) -> Self { + pub(crate) fn value(span: Span) -> Self { RedirectModes { - out: Some(RedirectMode::Capture.into_spanned(span)), + out: Some(RedirectMode::Value.into_spanned(span)), err: None, } } @@ -46,7 +46,7 @@ pub(crate) fn redirection_target_to_mode( working_set, builder, expr, - RedirectModes::capture_out(*redir_span), + RedirectModes::value(*redir_span), None, path_reg, )?; @@ -148,7 +148,8 @@ pub(crate) fn out_dest_to_redirect_mode( out_dest .map(|out_dest| match out_dest { OutDest::Pipe => Ok(RedirectMode::Pipe), - OutDest::Capture => Ok(RedirectMode::Capture), + OutDest::PipeSeparate => Ok(RedirectMode::PipeSeparate), + OutDest::Value => Ok(RedirectMode::Value), OutDest::Null => Ok(RedirectMode::Null), OutDest::Inherit => Ok(RedirectMode::Inherit), OutDest::File(_) => Err(CompileError::InvalidRedirectMode { span }), diff --git a/crates/nu-engine/src/documentation.rs b/crates/nu-engine/src/documentation.rs index 9d7ea7f8f2..92f2c3b925 100644 --- a/crates/nu-engine/src/documentation.rs +++ b/crates/nu-engine/src/documentation.rs @@ -23,7 +23,7 @@ pub fn get_full_help( // internally call several commands (`table`, `ansi`, `nu-highlight`) and get their // `PipelineData` using this `Stack`, any other output should not be redirected like the main // execution. - let stack = &mut stack.start_capture(); + let stack = &mut stack.start_collect_value(); let signature = engine_state .get_signature(command) @@ -202,7 +202,7 @@ fn get_documentation( )); } - let caller_stack = &mut Stack::new().capture(); + let caller_stack = &mut Stack::new().collect_value(); if let Ok(result) = eval_call::( engine_state, caller_stack, @@ -329,7 +329,7 @@ fn update_ansi_from_config( theme_component: &str, ) { if let Some(color) = &nu_config.color_config.get(theme_component) { - let caller_stack = &mut Stack::new().capture(); + let caller_stack = &mut Stack::new().collect_value(); let span = Span::unknown(); let span_id = UNKNOWN_SPAN_ID; diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index ccb494e68e..f0effb9a37 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -235,7 +235,7 @@ pub fn eval_expression( stack: &mut Stack, expr: &Expression, ) -> Result { - let stack = &mut stack.start_capture(); + let stack = &mut stack.start_collect_value(); ::eval::(engine_state, stack, expr) } @@ -278,7 +278,7 @@ pub fn eval_expression_with_input( let block = engine_state.get_block(*block_id); if !full_cell_path.tail.is_empty() { - let stack = &mut stack.start_capture(); + let stack = &mut stack.start_collect_value(); // FIXME: protect this collect with ctrl-c input = eval_subexpression::(engine_state, stack, block, input)? .into_value(*span)? @@ -325,7 +325,7 @@ fn eval_redirection( } RedirectionTarget::Pipe { .. } => { let dest = match next_out { - None | Some(OutDest::Capture) => OutDest::Pipe, + None | Some(OutDest::PipeSeparate) => OutDest::Pipe, Some(next) => next, }; Ok(Redirection::Pipe(dest)) @@ -357,7 +357,7 @@ fn eval_element_redirection( let stderr = eval_redirection::(engine_state, stack, target, None)?; if matches!(stderr, Redirection::Pipe(OutDest::Pipe)) { let dest = match next_out { - None | Some(OutDest::Capture) => OutDest::Pipe, + None | Some(OutDest::PipeSeparate) => OutDest::Pipe, Some(next) => next, }; // e>| redirection, don't override current stack `stdout` diff --git a/crates/nu-engine/src/eval_ir.rs b/crates/nu-engine/src/eval_ir.rs index 7cc4e0267d..790016cb1b 100644 --- a/crates/nu-engine/src/eval_ir.rs +++ b/crates/nu-engine/src/eval_ir.rs @@ -1414,7 +1414,8 @@ fn eval_redirection( ) -> Result, ShellError> { match mode { RedirectMode::Pipe => Ok(Some(Redirection::Pipe(OutDest::Pipe))), - RedirectMode::Capture => Ok(Some(Redirection::Pipe(OutDest::Capture))), + RedirectMode::PipeSeparate => Ok(Some(Redirection::Pipe(OutDest::PipeSeparate))), + RedirectMode::Value => Ok(Some(Redirection::Pipe(OutDest::Value))), RedirectMode::Null => Ok(Some(Redirection::Pipe(OutDest::Null))), RedirectMode::Inherit => Ok(Some(Redirection::Pipe(OutDest::Inherit))), RedirectMode::File { file_num } => { diff --git a/crates/nu-explore/src/nu_common/command.rs b/crates/nu-explore/src/nu_common/command.rs index 269382d1f0..ef0157ac67 100644 --- a/crates/nu-explore/src/nu_common/command.rs +++ b/crates/nu-explore/src/nu_common/command.rs @@ -96,8 +96,8 @@ fn eval_source2( } let stack = &mut stack.push_redirection( - Some(Redirection::Pipe(OutDest::Capture)), - Some(Redirection::Pipe(OutDest::Capture)), + Some(Redirection::Pipe(OutDest::PipeSeparate)), + Some(Redirection::Pipe(OutDest::PipeSeparate)), ); eval_block::(engine_state, stack, &block, input) } diff --git a/crates/nu-plugin-engine/src/context.rs b/crates/nu-plugin-engine/src/context.rs index 160ce802b2..6b6b1a15f3 100644 --- a/crates/nu-plugin-engine/src/context.rs +++ b/crates/nu-plugin-engine/src/context.rs @@ -190,8 +190,8 @@ impl<'a> PluginExecutionContext for PluginExecutionCommandContext<'a> { .reset_pipes(); let stack = &mut stack.push_redirection( - redirect_stdout.then_some(Redirection::Pipe(OutDest::Capture)), - redirect_stderr.then_some(Redirection::Pipe(OutDest::Capture)), + redirect_stdout.then_some(Redirection::Pipe(OutDest::PipeSeparate)), + redirect_stderr.then_some(Redirection::Pipe(OutDest::PipeSeparate)), ); // Set up the positional arguments @@ -239,8 +239,8 @@ impl<'a> PluginExecutionContext for PluginExecutionCommandContext<'a> { let decl = self.engine_state.get_decl(decl_id); let stack = &mut self.stack.push_redirection( - redirect_stdout.then_some(Redirection::Pipe(OutDest::Capture)), - redirect_stderr.then_some(Redirection::Pipe(OutDest::Capture)), + redirect_stdout.then_some(Redirection::Pipe(OutDest::PipeSeparate)), + redirect_stderr.then_some(Redirection::Pipe(OutDest::PipeSeparate)), ); let mut call_builder = ir::Call::build(decl_id, call.head); diff --git a/crates/nu-plugin-engine/src/persistent.rs b/crates/nu-plugin-engine/src/persistent.rs index f9dcc5143b..e664b37f87 100644 --- a/crates/nu-plugin-engine/src/persistent.rs +++ b/crates/nu-plugin-engine/src/persistent.rs @@ -353,7 +353,7 @@ impl GetPlugin for PersistentPlugin { // We need the current environment variables for `python` based plugins. Or // we'll likely have a problem when a plugin is implemented in a virtual Python // environment. - let stack = &mut stack.start_capture(); + let stack = &mut stack.start_collect_value(); nu_engine::env::env_to_strings(engine_state, stack) }) .transpose()?; diff --git a/crates/nu-plugin-test-support/src/plugin_test.rs b/crates/nu-plugin-test-support/src/plugin_test.rs index d414887e84..1d66674824 100644 --- a/crates/nu-plugin-test-support/src/plugin_test.rs +++ b/crates/nu-plugin-test-support/src/plugin_test.rs @@ -156,7 +156,7 @@ impl PluginTest { }; // Eval the block with the input - let mut stack = Stack::new().capture(); + let mut stack = Stack::new().collect_value(); let data = eval_block::(&self.engine_state, &mut stack, &block, input)?; if matches!(data, PipelineData::ByteStream(..)) { Ok(data) diff --git a/crates/nu-protocol/src/engine/stack.rs b/crates/nu-protocol/src/engine/stack.rs index 854b338c1d..843315871a 100644 --- a/crates/nu-protocol/src/engine/stack.rs +++ b/crates/nu-protocol/src/engine/stack.rs @@ -1,7 +1,7 @@ use crate::{ engine::{ ArgumentStack, EngineState, ErrorHandlerStack, Redirection, StackCallArgGuard, - StackCaptureGuard, StackIoGuard, StackOutDest, DEFAULT_OVERLAY_NAME, + StackCollectValueGuard, StackIoGuard, StackOutDest, DEFAULT_OVERLAY_NAME, }, Config, OutDest, ShellError, Span, Value, VarId, ENV_VARIABLE_ID, NU_VARIABLE_ID, }; @@ -68,7 +68,7 @@ impl Stack { /// stdout and stderr will be set to [`OutDest::Inherit`]. So, if the last command is an external command, /// then its output will be forwarded to the terminal/stdio streams. /// - /// Use [`Stack::capture`] afterwards if you need to evaluate an expression to a [`Value`] + /// Use [`Stack::collect_value`] afterwards if you need to evaluate an expression to a [`Value`] /// (as opposed to a [`PipelineData`](crate::PipelineData)). pub fn new() -> Self { Self { @@ -299,7 +299,8 @@ impl Stack { } pub fn captures_to_stack(&self, captures: Vec<(VarId, Value)>) -> Stack { - self.captures_to_stack_preserve_out_dest(captures).capture() + self.captures_to_stack_preserve_out_dest(captures) + .collect_value() } pub fn captures_to_stack_preserve_out_dest(&self, captures: Vec<(VarId, Value)>) -> Stack { @@ -589,11 +590,11 @@ impl Stack { self.out_dest.pipe_stderr.as_ref() } - /// Temporarily set the pipe stdout redirection to [`OutDest::Capture`]. + /// Temporarily set the pipe stdout redirection to [`OutDest::Value`]. /// /// This is used before evaluating an expression into a `Value`. - pub fn start_capture(&mut self) -> StackCaptureGuard { - StackCaptureGuard::new(self) + pub fn start_collect_value(&mut self) -> StackCollectValueGuard { + StackCollectValueGuard::new(self) } /// Temporarily use the output redirections in the parent scope. @@ -612,14 +613,14 @@ impl Stack { StackIoGuard::new(self, stdout, stderr) } - /// Mark stdout for the last command as [`OutDest::Capture`]. + /// Mark stdout for the last command as [`OutDest::Value`]. /// /// This will irreversibly alter the output redirections, and so it only makes sense to use this on an owned `Stack` /// (which is why this function does not take `&mut self`). /// - /// See [`Stack::start_capture`] which can temporarily set stdout as [`OutDest::Capture`] for a mutable `Stack` reference. - pub fn capture(mut self) -> Self { - self.out_dest.pipe_stdout = Some(OutDest::Capture); + /// See [`Stack::start_collect_value`] which can temporarily set stdout as [`OutDest::Value`] for a mutable `Stack` reference. + pub fn collect_value(mut self) -> Self { + self.out_dest.pipe_stdout = Some(OutDest::Value); self.out_dest.pipe_stderr = None; self } diff --git a/crates/nu-protocol/src/engine/stack_out_dest.rs b/crates/nu-protocol/src/engine/stack_out_dest.rs index 7699d29edd..b11177ec3a 100644 --- a/crates/nu-protocol/src/engine/stack_out_dest.rs +++ b/crates/nu-protocol/src/engine/stack_out_dest.rs @@ -184,15 +184,15 @@ impl Drop for StackIoGuard<'_> { } } -pub struct StackCaptureGuard<'a> { +pub struct StackCollectValueGuard<'a> { stack: &'a mut Stack, old_pipe_stdout: Option, old_pipe_stderr: Option, } -impl<'a> StackCaptureGuard<'a> { +impl<'a> StackCollectValueGuard<'a> { pub(crate) fn new(stack: &'a mut Stack) -> Self { - let old_pipe_stdout = mem::replace(&mut stack.out_dest.pipe_stdout, Some(OutDest::Capture)); + let old_pipe_stdout = mem::replace(&mut stack.out_dest.pipe_stdout, Some(OutDest::Value)); let old_pipe_stderr = stack.out_dest.pipe_stderr.take(); Self { stack, @@ -202,7 +202,7 @@ impl<'a> StackCaptureGuard<'a> { } } -impl<'a> Deref for StackCaptureGuard<'a> { +impl<'a> Deref for StackCollectValueGuard<'a> { type Target = Stack; fn deref(&self) -> &Self::Target { @@ -210,13 +210,13 @@ impl<'a> Deref for StackCaptureGuard<'a> { } } -impl<'a> DerefMut for StackCaptureGuard<'a> { +impl<'a> DerefMut for StackCollectValueGuard<'a> { fn deref_mut(&mut self) -> &mut Self::Target { self.stack } } -impl Drop for StackCaptureGuard<'_> { +impl Drop for StackCollectValueGuard<'_> { fn drop(&mut self) { self.out_dest.pipe_stdout = self.old_pipe_stdout.take(); self.out_dest.pipe_stderr = self.old_pipe_stderr.take(); @@ -233,7 +233,7 @@ pub struct StackCallArgGuard<'a> { impl<'a> StackCallArgGuard<'a> { pub(crate) fn new(stack: &'a mut Stack) -> Self { - let old_pipe_stdout = mem::replace(&mut stack.out_dest.pipe_stdout, Some(OutDest::Capture)); + let old_pipe_stdout = mem::replace(&mut stack.out_dest.pipe_stdout, Some(OutDest::Value)); let old_pipe_stderr = stack.out_dest.pipe_stderr.take(); let old_stdout = stack diff --git a/crates/nu-protocol/src/ir/display.rs b/crates/nu-protocol/src/ir/display.rs index feac8f961d..0168306f8a 100644 --- a/crates/nu-protocol/src/ir/display.rs +++ b/crates/nu-protocol/src/ir/display.rs @@ -1,8 +1,6 @@ -use std::fmt; - -use crate::{ast::Pattern, engine::EngineState, DeclId, VarId}; - use super::{DataSlice, Instruction, IrBlock, Literal, RedirectMode}; +use crate::{ast::Pattern, engine::EngineState, DeclId, VarId}; +use std::fmt::{self}; pub struct FmtIrBlock<'a> { pub(super) engine_state: &'a EngineState, @@ -310,7 +308,8 @@ impl fmt::Display for RedirectMode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { RedirectMode::Pipe => write!(f, "pipe"), - RedirectMode::Capture => write!(f, "capture"), + RedirectMode::PipeSeparate => write!(f, "pipe separate"), + RedirectMode::Value => write!(f, "value"), RedirectMode::Null => write!(f, "null"), RedirectMode::Inherit => write!(f, "inherit"), RedirectMode::File { file_num } => write!(f, "file({file_num})"), diff --git a/crates/nu-protocol/src/ir/mod.rs b/crates/nu-protocol/src/ir/mod.rs index c2f51f514a..8c1bb52240 100644 --- a/crates/nu-protocol/src/ir/mod.rs +++ b/crates/nu-protocol/src/ir/mod.rs @@ -446,7 +446,8 @@ pub enum Literal { #[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub enum RedirectMode { Pipe, - Capture, + PipeSeparate, + Value, Null, Inherit, /// Use the given numbered file. diff --git a/crates/nu-protocol/src/pipeline/byte_stream.rs b/crates/nu-protocol/src/pipeline/byte_stream.rs index 6811b7b89b..0dc03b3091 100644 --- a/crates/nu-protocol/src/pipeline/byte_stream.rs +++ b/crates/nu-protocol/src/pipeline/byte_stream.rs @@ -580,8 +580,8 @@ impl ByteStream { copy_with_signals(file, dest, span, signals)?; } ByteStreamSource::Child(mut child) => { - // All `OutDest`s except `OutDest::Capture` will cause `stderr` to be `None`. - // Only `save`, `tee`, and `complete` set the stderr `OutDest` to `OutDest::Capture`, + // All `OutDest`s except `OutDest::PipeSeparate` will cause `stderr` to be `None`. + // Only `save`, `tee`, and `complete` set the stderr `OutDest` to `OutDest::PipeSeparate`, // and those commands have proper simultaneous handling of stdout and stderr. debug_assert!(child.stderr.is_none(), "stderr should not exist"); @@ -614,7 +614,7 @@ impl ByteStream { write_to_out_dest(read, stdout, true, span, signals)?; } ByteStreamSource::File(file) => match stdout { - OutDest::Pipe | OutDest::Capture | OutDest::Null => {} + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value | OutDest::Null => {} OutDest::Inherit => { copy_with_signals(file, io::stdout(), span, signals)?; } @@ -970,7 +970,7 @@ fn write_to_out_dest( signals: &Signals, ) -> Result<(), ShellError> { match stream { - OutDest::Pipe | OutDest::Capture => return Ok(()), + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value => return Ok(()), OutDest::Null => copy_with_signals(read, io::sink(), span, signals), OutDest::Inherit if stdout => copy_with_signals(read, io::stdout(), span, signals), OutDest::Inherit => copy_with_signals(read, io::stderr(), span, signals), diff --git a/crates/nu-protocol/src/pipeline/out_dest.rs b/crates/nu-protocol/src/pipeline/out_dest.rs index 69955e6b0b..8ea8395378 100644 --- a/crates/nu-protocol/src/pipeline/out_dest.rs +++ b/crates/nu-protocol/src/pipeline/out_dest.rs @@ -10,13 +10,17 @@ pub enum OutDest { /// If stdout and stderr are both set to `Pipe`, /// then they will combined into the `stdout` of [`ChildProcess`](crate::process::ChildProcess). Pipe, - /// Capture output to later be collected into a [`Value`](crate::Value), `Vec`, or used in some other way. + /// Redirect the stdout and/or stderr of one command as the input for the next command in the pipeline. /// /// The output stream(s) will be available in the `stdout` or `stderr` of [`ChildProcess`](crate::process::ChildProcess). /// /// This is similar to `Pipe` but will never combine stdout and stderr /// or place an external command's stderr into `stdout` of [`ChildProcess`](crate::process::ChildProcess). - Capture, + PipeSeparate, + /// Signifies the result of the pipeline will be immediately collected into a value after this command. + /// + /// So, it is fine to collect the stream ahead of time in the current command. + Value, /// Ignore output. /// /// This will forward output to the null device for the platform. @@ -46,7 +50,7 @@ impl TryFrom<&OutDest> for Stdio { fn try_from(out_dest: &OutDest) -> Result { match out_dest { - OutDest::Pipe | OutDest::Capture => Ok(Self::piped()), + OutDest::Pipe | OutDest::PipeSeparate | OutDest::Value => Ok(Self::piped()), OutDest::Null => Ok(Self::null()), OutDest::Inherit => Ok(Self::inherit()), OutDest::File(file) => Ok(file.try_clone()?.into()), diff --git a/crates/nu-protocol/src/pipeline/pipeline_data.rs b/crates/nu-protocol/src/pipeline/pipeline_data.rs index da0fea3213..45704e2cf4 100644 --- a/crates/nu-protocol/src/pipeline/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline/pipeline_data.rs @@ -167,8 +167,8 @@ impl PipelineData { /// Writes all values or redirects all output to the current [`OutDest`]s in `stack`. /// - /// For [`OutDest::Pipe`] and [`OutDest::Capture`], this will return the `PipelineData` as is - /// without consuming input and without writing anything. + /// For [`OutDest::Pipe`] and [`OutDest::PipeSeparate`], this will return the `PipelineData` as + /// is without consuming input and without writing anything. /// /// For the other [`OutDest`]s, the given `PipelineData` will be completely consumed /// and `PipelineData::Empty` will be returned (assuming no errors). @@ -178,11 +178,18 @@ impl PipelineData { stack: &mut Stack, ) -> Result { match (self, stack.stdout()) { - (data, OutDest::Pipe | OutDest::Capture) => return Ok(data), + (PipelineData::Empty, ..) => {} + (data, OutDest::Pipe | OutDest::PipeSeparate) => return Ok(data), + (data, OutDest::Value) => { + let metadata = data.metadata(); + let span = data.span().unwrap_or(Span::unknown()); + return data + .into_value(span) + .map(|val| PipelineData::Value(val, metadata)); + } (PipelineData::ByteStream(stream, ..), stdout) => { stream.write_to_out_dests(stdout, stack.stderr())?; } - (PipelineData::Empty, ..) => {} (PipelineData::Value(..), OutDest::Null) => {} (PipelineData::ListStream(stream, ..), OutDest::Null) => { // we need to drain the stream in case there are external commands in the pipeline diff --git a/src/test_bins.rs b/src/test_bins.rs index d5ae92ec60..efa7e9dd7d 100644 --- a/src/test_bins.rs +++ b/src/test_bins.rs @@ -337,7 +337,7 @@ pub fn nu_repl() { let config = engine_state.get_config(); { - let stack = &mut stack.start_capture(); + let stack = &mut stack.start_collect_value(); match eval_block::(&engine_state, stack, &block, input) { Ok(pipeline_data) => match pipeline_data.collect_string("", config) { Ok(s) => last_output = s,