From 6b4cbe7a982e86ed65276c49210dd0fd0702eb67 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Sat, 6 Apr 2024 23:55:22 +0000 Subject: [PATCH] `explain` refactor (#12432) # Description Refactors the `explain` command. Part of this is fixing the `type` column which used to always be `string` for each row. --- crates/nu-command/src/debug/explain.rs | 66 +++++++++++++------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/crates/nu-command/src/debug/explain.rs b/crates/nu-command/src/debug/explain.rs index 60e917783b..24f6f2f22a 100644 --- a/crates/nu-command/src/debug/explain.rs +++ b/crates/nu-command/src/debug/explain.rs @@ -41,7 +41,7 @@ impl Command for Explain { let ctrlc = engine_state.ctrlc.clone(); let mut stack = stack.captures_to_stack(capture_block.captures); - let elements = get_pipeline_elements(engine_state, &mut stack, block, call.head)?; + let elements = get_pipeline_elements(engine_state, &mut stack, block, call.head); Ok(elements.into_pipeline_data(ctrlc)) } @@ -61,56 +61,54 @@ pub fn get_pipeline_elements( stack: &mut Stack, block: &Block, span: Span, -) -> Result, ShellError> { - let mut element_values = vec![]; - +) -> Vec { let eval_expression = get_eval_expression(engine_state); - for (pipeline_idx, pipeline) in block.pipelines.iter().enumerate() { - let mut i = 0; - while i < pipeline.elements.len() { - let pipeline_element = &pipeline.elements[i]; - let pipeline_expression = &pipeline_element.expr; - let pipeline_span = pipeline_element.expr.span; + block + .pipelines + .iter() + .enumerate() + .flat_map(|(p_idx, pipeline)| { + pipeline + .elements + .iter() + .enumerate() + .map(move |(e_idx, element)| (format!("{p_idx}_{e_idx}"), element)) + }) + .map(move |(cmd_index, element)| { + let expression = &element.expr; + let expr_span = element.expr.span; - let element_str = - String::from_utf8_lossy(engine_state.get_span_contents(pipeline_span)); - let value = Value::string(element_str.to_string(), pipeline_span); - let expr = pipeline_expression.expr.clone(); - let (command_name, command_args_value) = if let Expr::Call(call) = expr { + let (command_name, command_args_value, ty) = if let Expr::Call(call) = &expression.expr + { let command = engine_state.get_decl(call.decl_id); ( command.name().to_string(), - get_arguments(engine_state, stack, *call, eval_expression), + get_arguments(engine_state, stack, call.as_ref(), eval_expression), + command.signature().get_output_type().to_string(), ) } else { - ("no-op".to_string(), vec![]) + ("no-op".to_string(), vec![], expression.ty.to_string()) }; - let index = format!("{pipeline_idx}_{i}"); - let value_type = value.get_type(); - let value_span = value.span(); - let value_span_start = value_span.start as i64; - let value_span_end = value_span.end as i64; let record = record! { - "cmd_index" => Value::string(index, span), - "cmd_name" => Value::string(command_name, value_span), - "type" => Value::string(value_type.to_string(), span), - "cmd_args" => Value::list(command_args_value, value_span), - "span_start" => Value::int(value_span_start, span), - "span_end" => Value::int(value_span_end, span), + "cmd_index" => Value::string(cmd_index, span), + "cmd_name" => Value::string(command_name, expr_span), + "type" => Value::string(ty, span), + "cmd_args" => Value::list(command_args_value, expr_span), + "span_start" => Value::int(expr_span.start as i64, span), + "span_end" => Value::int(expr_span.end as i64, span), }; - element_values.push(Value::record(record, value_span)); - i += 1; - } - } - Ok(element_values) + + Value::record(record, expr_span) + }) + .collect() } fn get_arguments( engine_state: &EngineState, stack: &mut Stack, - call: Call, + call: &Call, eval_expression_fn: fn(&EngineState, &mut Stack, &Expression) -> Result, ) -> Vec { let mut arg_value = vec![];