From b56ad92e2528ae86678a32154aec148f2d631c3d Mon Sep 17 00:00:00 2001 From: raccmonteiro <3062698+raccmonteiro@users.noreply.github.com> Date: Fri, 9 Dec 2022 16:20:58 +0000 Subject: [PATCH] `++=` appendAssign operator (#7346) (#7354) # Description Closes https://github.com/nushell/nushell/issues/7346 # Tests + Formatting ``` > mut a = [1 2 3] > $a ++= [4 5 6] > $a [1 2 3 4 5 6] ``` --- .../src/core_commands/help_operators.rs | 7 ++ .../commands/assignment/append_assign.rs | 108 ++++++++++++++++++ .../tests/commands/assignment/mod.rs | 1 + crates/nu-command/tests/commands/mod.rs | 1 + crates/nu-engine/src/eval.rs | 4 + crates/nu-parser/src/parser.rs | 1 + crates/nu-protocol/src/ast/operator.rs | 2 + 7 files changed, 124 insertions(+) create mode 100644 crates/nu-command/tests/commands/assignment/append_assign.rs create mode 100644 crates/nu-command/tests/commands/assignment/mod.rs diff --git a/crates/nu-command/src/core_commands/help_operators.rs b/crates/nu-command/src/core_commands/help_operators.rs index fee5a38587..fcbbeeabd9 100644 --- a/crates/nu-command/src/core_commands/help_operators.rs +++ b/crates/nu-command/src/core_commands/help_operators.rs @@ -81,6 +81,13 @@ fn generate_operator_info() -> Vec { description: "Adds a value to a variable.".into(), precedence: 10, }, + OperatorInfo { + op_type: "Assignment".into(), + operator: "++=".into(), + name: "AppendAssign".into(), + description: "Appends a list or a value to a variable.".into(), + precedence: 10, + }, OperatorInfo { op_type: "Assignment".into(), operator: "-=".into(), diff --git a/crates/nu-command/tests/commands/assignment/append_assign.rs b/crates/nu-command/tests/commands/assignment/append_assign.rs new file mode 100644 index 0000000000..74aa88da1f --- /dev/null +++ b/crates/nu-command/tests/commands/assignment/append_assign.rs @@ -0,0 +1,108 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn append_assign_int() { + let actual = nu!( + cwd: ".", pipeline( + r#" + mut a = [1 2]; + $a ++= [3 4]; + $a + "# + )); + + let expected = nu!( + cwd: ".", pipeline( + r#" + [1 2 3 4] + "# + )); + + print!("{}", actual.out); + print!("{}", expected.out); + assert_eq!(actual.out, expected.out); +} + +#[test] +fn append_assign_string() { + let actual = nu!( + cwd: ".", pipeline( + r#" + mut a = [a b]; + $a ++= [c d]; + $a + "# + )); + + let expected = nu!( + cwd: ".", pipeline( + r#" + [a b c d] + "# + )); + + print!("{}", actual.out); + print!("{}", expected.out); + assert_eq!(actual.out, expected.out); +} + +#[test] +fn append_assign_any() { + let actual = nu!( + cwd: ".", pipeline( + r#" + mut a = [1 2 a]; + $a ++= [b 3]; + $a + "# + )); + + let expected = nu!( + cwd: ".", pipeline( + r#" + [1 2 a b 3] + "# + )); + + print!("{}", actual.out); + print!("{}", expected.out); + assert_eq!(actual.out, expected.out); +} + +#[test] +fn append_assign_both_empty() { + let actual = nu!( + cwd: ".", pipeline( + r#" + mut a = []; + $a ++= []; + $a + "# + )); + + let expected = nu!( + cwd: ".", pipeline( + r#" + [] + "# + )); + + print!("{}", actual.out); + print!("{}", expected.out); + assert_eq!(actual.out, expected.out); +} + +#[test] +fn append_assign_type_mismatch() { + let actual = nu!( + cwd: ".", pipeline( + r#" + mut a = [1 2]; + $a ++= [a]; + "# + )); + + assert!(actual + .err + .contains("expected list, found list")); +} diff --git a/crates/nu-command/tests/commands/assignment/mod.rs b/crates/nu-command/tests/commands/assignment/mod.rs new file mode 100644 index 0000000000..8235f532f5 --- /dev/null +++ b/crates/nu-command/tests/commands/assignment/mod.rs @@ -0,0 +1 @@ +mod append_assign; diff --git a/crates/nu-command/tests/commands/mod.rs b/crates/nu-command/tests/commands/mod.rs index 1237786ac0..3f89a8cffa 100644 --- a/crates/nu-command/tests/commands/mod.rs +++ b/crates/nu-command/tests/commands/mod.rs @@ -2,6 +2,7 @@ mod alias; mod all; mod any; mod append; +mod assignment; mod break_; mod cal; mod cd; diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 20943dddf7..4aae5b0796 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -474,6 +474,10 @@ pub fn eval_expression( let lhs = eval_expression(engine_state, stack, lhs)?; lhs.div(op_span, &rhs, op_span)? } + Assignment::AppendAssign => { + let lhs = eval_expression(engine_state, stack, lhs)?; + lhs.append(op_span, &rhs, op_span)? + } }; match &lhs.expr { diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index ac5591a2b4..2b3c7369f2 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -4429,6 +4429,7 @@ pub fn parse_operator( let operator = match contents { b"=" => Operator::Assignment(Assignment::Assign), b"+=" => Operator::Assignment(Assignment::PlusAssign), + b"++=" => Operator::Assignment(Assignment::AppendAssign), b"-=" => Operator::Assignment(Assignment::MinusAssign), b"*=" => Operator::Assignment(Assignment::MultiplyAssign), b"/=" => Operator::Assignment(Assignment::DivideAssign), diff --git a/crates/nu-protocol/src/ast/operator.rs b/crates/nu-protocol/src/ast/operator.rs index 2b64507440..8572d9126d 100644 --- a/crates/nu-protocol/src/ast/operator.rs +++ b/crates/nu-protocol/src/ast/operator.rs @@ -51,6 +51,7 @@ pub enum Bits { pub enum Assignment { Assign, PlusAssign, + AppendAssign, MinusAssign, MultiplyAssign, DivideAssign, @@ -70,6 +71,7 @@ impl Display for Operator { match self { Operator::Assignment(Assignment::Assign) => write!(f, "="), Operator::Assignment(Assignment::PlusAssign) => write!(f, "+="), + Operator::Assignment(Assignment::AppendAssign) => write!(f, "++="), Operator::Assignment(Assignment::MinusAssign) => write!(f, "-="), Operator::Assignment(Assignment::MultiplyAssign) => write!(f, "*="), Operator::Assignment(Assignment::DivideAssign) => write!(f, "/="),