diff --git a/crates/nu-cmd-lang/src/example_support.rs b/crates/nu-cmd-lang/src/example_support.rs index bb03bbaf8c..72ea36972f 100644 --- a/crates/nu-cmd-lang/src/example_support.rs +++ b/crates/nu-cmd-lang/src/example_support.rs @@ -4,7 +4,7 @@ use nu_protocol::{ ast::Block, debugger::WithoutDebug, engine::{StateDelta, StateWorkingSet}, - Range, + report_error_new, Range, }; use std::{ sync::Arc, @@ -124,7 +124,10 @@ pub fn eval_block( nu_engine::eval_block::(engine_state, &mut stack, &block, input) .and_then(|data| data.into_value(Span::test_data())) - .unwrap_or_else(|err| panic!("test eval error in `{}`: {:?}", "TODO", err)) + .unwrap_or_else(|err| { + report_error_new(engine_state, &err); + panic!("test eval error in `{}`: {:?}", "TODO", err) + }) } pub fn check_example_evaluates_to_expected_output( diff --git a/crates/nu-command/src/example_test.rs b/crates/nu-command/src/example_test.rs index 476113aa2d..4879cab0a9 100644 --- a/crates/nu-command/src/example_test.rs +++ b/crates/nu-command/src/example_test.rs @@ -31,7 +31,7 @@ mod test_examples { check_example_evaluates_to_expected_output, check_example_input_and_output_types_match_command_signature, }; - use nu_cmd_lang::{Break, Echo, If, Let, Mut}; + use nu_cmd_lang::{Break, Describe, Echo, If, Let, Mut}; use nu_protocol::{ engine::{Command, EngineState, StateWorkingSet}, Type, @@ -81,6 +81,7 @@ mod test_examples { working_set.add_decl(Box::new(Break)); working_set.add_decl(Box::new(Date)); working_set.add_decl(Box::new(Default)); + working_set.add_decl(Box::new(Describe)); working_set.add_decl(Box::new(Each)); working_set.add_decl(Box::new(Echo)); working_set.add_decl(Box::new(Enumerate)); diff --git a/crates/nu-engine/src/compile/expression.rs b/crates/nu-engine/src/compile/expression.rs index 52f4ea4643..948eb5c238 100644 --- a/crates/nu-engine/src/compile/expression.rs +++ b/crates/nu-engine/src/compile/expression.rs @@ -172,23 +172,22 @@ pub(crate) fn compile_expression( } } Expr::Collect(var_id, expr) => { - let in_reg = match in_reg { - Some(in_reg) => in_reg, - None => { - let reg_id = builder.next_register()?; - builder.load_empty(reg_id)?; - reg_id - } + let store_reg = if let Some(in_reg) = in_reg { + // Collect, clone, store + builder.push(Instruction::Collect { src_dst: in_reg }.into_spanned(expr.span))?; + builder.clone_reg(in_reg, expr.span)? + } else { + // Just store nothing in the variable + builder.literal(Literal::Nothing.into_spanned(Span::unknown()))? }; - // Implicit collect builder.push( Instruction::StoreVariable { var_id: *var_id, - src: in_reg, + src: store_reg, } .into_spanned(expr.span), )?; - compile_expression(working_set, builder, expr, redirect_modes, None, out_reg)?; + compile_expression(working_set, builder, expr, redirect_modes, in_reg, out_reg)?; // Clean it up afterward builder.push(Instruction::DropVariable { var_id: *var_id }.into_spanned(expr.span))?; Ok(()) diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index a1f7222a1d..84fa700934 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -10,8 +10,8 @@ use nu_protocol::{ debugger::DebugContext, engine::{Closure, EngineState, Redirection, Stack, StateWorkingSet}, eval_base::Eval, - ByteStreamSource, Config, FromValue, IntoPipelineData, OutDest, PipelineData, ShellError, Span, - Spanned, Type, Value, VarId, ENV_VARIABLE_ID, + ByteStreamSource, Config, DataSource, FromValue, IntoPipelineData, OutDest, PipelineData, + PipelineMetadata, ShellError, Span, Spanned, Type, Value, VarId, ENV_VARIABLE_ID, }; use nu_utils::IgnoreCaseExt; use std::{fs::OpenOptions, path::PathBuf, sync::Arc}; @@ -619,10 +619,28 @@ pub fn eval_collect( // Evaluate the expression with the variable set to the collected input let span = input.span().unwrap_or(Span::unknown()); - stack.add_var(var_id, input.into_value(span)?); + let metadata = match input.metadata() { + // Remove the `FilePath` metadata, because after `collect` it's no longer necessary to + // check where some input came from. + Some(PipelineMetadata { + data_source: DataSource::FilePath(_), + content_type: None, + }) => None, + other => other, + }; - let result = eval_expression_with_input::(engine_state, stack, expr, PipelineData::empty()) - .map(|(result, _failed)| result); + let input = input.into_value(span)?; + + stack.add_var(var_id, input.clone()); + + let result = eval_expression_with_input::( + engine_state, + stack, + expr, + // We still have to pass it as input + input.into_pipeline_data_with_metadata(metadata), + ) + .map(|(result, _failed)| result); stack.remove_var(var_id);