diff --git a/crates/nu-command/src/core_commands/try_.rs b/crates/nu-command/src/core_commands/try_.rs index 49aade1c31..8503c6ea96 100644 --- a/crates/nu-command/src/core_commands/try_.rs +++ b/crates/nu-command/src/core_commands/try_.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Block, Command, EngineState, Stack}; +use nu_protocol::engine::{Block, Closure, Command, EngineState, Stack}; use nu_protocol::{Category, Example, PipelineData, Signature, SyntaxShape, Type, Value}; #[derive(Clone)] @@ -21,7 +21,10 @@ impl Command for Try { .required("try_block", SyntaxShape::Block, "block to run") .optional( "else_expression", - SyntaxShape::Keyword(b"catch".to_vec(), Box::new(SyntaxShape::Block)), + SyntaxShape::Keyword( + b"catch".to_vec(), + Box::new(SyntaxShape::Closure(Some(vec![SyntaxShape::Any]))), + ), "block to run if try block fails", ) .category(Category::Core) @@ -44,16 +47,24 @@ impl Command for Try { input: PipelineData, ) -> Result { let try_block: Block = call.req(engine_state, stack, 0)?; - let catch_block: Option = call.opt(engine_state, stack, 1)?; + let catch_block: Option = call.opt(engine_state, stack, 1)?; let try_block = engine_state.get_block(try_block.block_id); let result = eval_block(engine_state, stack, try_block, input, false, false); match result { - Err(_) | Ok(PipelineData::Value(Value::Error { .. }, ..)) => { + Err(error) | Ok(PipelineData::Value(Value::Error { error }, ..)) => { if let Some(catch_block) = catch_block { let catch_block = engine_state.get_block(catch_block.block_id); + + if let Some(var) = catch_block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + let err_value = Value::Error { error }; + stack.add_var(*var_id, err_value); + } + } + eval_block( engine_state, stack, diff --git a/crates/nu-command/tests/commands/try_.rs b/crates/nu-command/tests/commands/try_.rs index 03da540082..514e2e7a9c 100644 --- a/crates/nu-command/tests/commands/try_.rs +++ b/crates/nu-command/tests/commands/try_.rs @@ -24,3 +24,15 @@ fn try_catch() { assert!(output.out.contains("hello")); }) } + +#[test] +fn catch_can_access_error() { + Playground::setup("try_catch_test", |dirs, _sandbox| { + let output = nu!( + cwd: dirs.test(), + "try { foobarbaz } catch { |err| $err }" + ); + + assert!(output.err.contains("External command failed")); + }) +}