From eca9f461da74f85d0adf2cc8c128405e2f393eb5 Mon Sep 17 00:00:00 2001 From: Nano Date: Tue, 5 Sep 2023 11:47:51 +1200 Subject: [PATCH] Make `append`/`prepend` consistent for ranges (#10231) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR makes `append`/`prepend` more consistent, in particular, it allows you to work with ranges. Previously, you couldn't append a list by range: ```nu > 0..1 | append 2..4 ╭──────╮ │ 0 │ │ 1 │ │ 2..4 │ ╰──────╯ ``` Now it works: ```nu > 0..1 | append 2..4 ╭───╮ │ 0 │ │ 1 │ │ 2 │ │ 3 │ │ 4 │ ╰───╯ ``` # User-Facing Changes If someone needs the old behavior, then it can be obtained like this: ```nu > 0..1 | append [2..4] ╭──────╮ │ 0 │ │ 1 │ │ 2..4 │ ╰──────╯ ``` --- crates/nu-command/src/filters/append.rs | 119 ++++++++++------------ crates/nu-command/src/filters/prepend.rs | 122 ++++++++++------------- 2 files changed, 102 insertions(+), 139 deletions(-) diff --git a/crates/nu-command/src/filters/append.rs b/crates/nu-command/src/filters/append.rs index 859067608..6c95af55f 100644 --- a/crates/nu-command/src/filters/append.rs +++ b/crates/nu-command/src/filters/append.rs @@ -2,8 +2,8 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ - Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span, - SyntaxShape, Type, Value, + Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError, + Signature, SyntaxShape, Type, Value, }; #[derive(Clone)] @@ -40,68 +40,67 @@ only unwrap the outer list, and leave the variable's contents untouched."# fn examples(&self) -> Vec { vec![ Example { - example: "[0,1,2,3] | append 4", + example: "[0 1 2 3] | append 4", description: "Append one integer to a list", - result: Some(Value::list( - vec![ - Value::test_int(0), - Value::test_int(1), - Value::test_int(2), - Value::test_int(3), - Value::test_int(4), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(4), + ])), }, Example { example: "0 | append [1 2 3]", description: "Append a list to an item", - result: Some(Value::list( - vec![ - Value::test_int(0), - Value::test_int(1), - Value::test_int(2), - Value::test_int(3), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + ])), }, Example { example: r#""a" | append ["b"] "#, description: "Append a list of string to a string", - result: Some(Value::list( - vec![Value::test_string("a"), Value::test_string("b")], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_string("a"), + Value::test_string("b"), + ])), }, Example { - example: "[0,1] | append [2,3,4]", + example: "[0 1] | append [2 3 4]", description: "Append three integer items", - result: Some(Value::list( - vec![ - Value::test_int(0), - Value::test_int(1), - Value::test_int(2), - Value::test_int(3), - Value::test_int(4), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(4), + ])), }, Example { - example: "[0,1] | append [2,nu,4,shell]", + example: "[0 1] | append [2 nu 4 shell]", description: "Append integers and strings", - result: Some(Value::list( - vec![ - Value::test_int(0), - Value::test_int(1), - Value::test_int(2), - Value::test_string("nu"), - Value::test_int(4), - Value::test_string("shell"), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_string("nu"), + Value::test_int(4), + Value::test_string("shell"), + ])), + }, + Example { + example: "[0 1] | append 2..4", + description: "Append a range of integers to a list", + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(4), + ])), }, ] } @@ -113,35 +112,17 @@ only unwrap the outer list, and leave the variable's contents untouched."# call: &Call, input: PipelineData, ) -> Result { - let val: Value = call.req(engine_state, stack, 0)?; - let vec: Vec = process_value(val); + let other: Value = call.req(engine_state, stack, 0)?; let metadata = input.metadata(); Ok(input .into_iter() - .chain(vec) + .chain(other.into_pipeline_data()) .into_pipeline_data(engine_state.ctrlc.clone()) .set_metadata(metadata)) } } -fn process_value(val: Value) -> Vec { - match val { - Value::List { - vals: input_vals, .. - } => { - let mut output = vec![]; - for input_val in input_vals { - output.push(input_val); - } - output - } - _ => { - vec![val] - } - } -} - #[cfg(test)] mod test { use super::*; diff --git a/crates/nu-command/src/filters/prepend.rs b/crates/nu-command/src/filters/prepend.rs index 937fe4505..e72bfc505 100644 --- a/crates/nu-command/src/filters/prepend.rs +++ b/crates/nu-command/src/filters/prepend.rs @@ -2,8 +2,8 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ - Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span, - SyntaxShape, Type, Value, + Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError, + Signature, SyntaxShape, Type, Value, }; #[derive(Clone)] @@ -45,67 +45,66 @@ only unwrap the outer list, and leave the variable's contents untouched."# Example { example: "0 | prepend [1 2 3]", description: "prepend a list to an item", - result: Some(Value::list( - vec![ - Value::test_int(1), - Value::test_int(2), - Value::test_int(3), - Value::test_int(0), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(0), + ])), }, Example { example: r#""a" | prepend ["b"] "#, description: "Prepend a list of strings to a string", - result: Some(Value::list( - vec![Value::test_string("b"), Value::test_string("a")], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_string("b"), + Value::test_string("a"), + ])), }, Example { - example: "[1,2,3,4] | prepend 0", + example: "[1 2 3 4] | prepend 0", description: "Prepend one integer item", - result: Some(Value::list( - vec![ - Value::test_int(0), - Value::test_int(1), - Value::test_int(2), - Value::test_int(3), - Value::test_int(4), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(4), + ])), }, Example { - example: "[2,3,4] | prepend [0,1]", + example: "[2 3 4] | prepend [0 1]", description: "Prepend two integer items", - result: Some(Value::list( - vec![ - Value::test_int(0), - Value::test_int(1), - Value::test_int(2), - Value::test_int(3), - Value::test_int(4), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(4), + ])), }, Example { - example: "[2,nu,4,shell] | prepend [0,1,rocks]", + example: "[2 nu 4 shell] | prepend [0 1 rocks]", description: "Prepend integers and strings", - result: Some(Value::list( - vec![ - Value::test_int(0), - Value::test_int(1), - Value::test_string("rocks"), - Value::test_int(2), - Value::test_string("nu"), - Value::test_int(4), - Value::test_string("shell"), - ], - Span::test_data(), - )), + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_string("rocks"), + Value::test_int(2), + Value::test_string("nu"), + Value::test_int(4), + Value::test_string("shell"), + ])), + }, + Example { + example: "[3 4] | prepend 0..2", + description: "Prepend a range", + result: Some(Value::test_list(vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(4), + ])), }, ] } @@ -117,11 +116,11 @@ only unwrap the outer list, and leave the variable's contents untouched."# call: &Call, input: PipelineData, ) -> Result { - let val: Value = call.req(engine_state, stack, 0)?; - let vec: Vec = process_value(val); + let other: Value = call.req(engine_state, stack, 0)?; let metadata = input.metadata(); - Ok(vec + Ok(other + .into_pipeline_data() .into_iter() .chain(input) .into_pipeline_data(engine_state.ctrlc.clone()) @@ -129,23 +128,6 @@ only unwrap the outer list, and leave the variable's contents untouched."# } } -fn process_value(val: Value) -> Vec { - match val { - Value::List { - vals: input_vals, .. - } => { - let mut output = vec![]; - for input_val in input_vals { - output.push(input_val); - } - output - } - _ => { - vec![val] - } - } -} - #[cfg(test)] mod test { use super::*;