forked from extern/nushell
Make append
/prepend
consistent for ranges (#10231)
# 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 │ ╰──────╯ ```
This commit is contained in:
parent
08aaa9494c
commit
eca9f461da
@ -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<Example> {
|
||||
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<PipelineData, ShellError> {
|
||||
let val: Value = call.req(engine_state, stack, 0)?;
|
||||
let vec: Vec<Value> = 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<Value> {
|
||||
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::*;
|
||||
|
@ -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<PipelineData, ShellError> {
|
||||
let val: Value = call.req(engine_state, stack, 0)?;
|
||||
let vec: Vec<Value> = 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<Value> {
|
||||
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::*;
|
||||
|
Loading…
Reference in New Issue
Block a user