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::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
||||||
SyntaxShape, Type, Value,
|
Signature, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -40,68 +40,67 @@ only unwrap the outer list, and leave the variable's contents untouched."#
|
|||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![
|
vec![
|
||||||
Example {
|
Example {
|
||||||
example: "[0,1,2,3] | append 4",
|
example: "[0 1 2 3] | append 4",
|
||||||
description: "Append one integer to a list",
|
description: "Append one integer to a list",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_int(3),
|
||||||
Value::test_int(3),
|
Value::test_int(4),
|
||||||
Value::test_int(4),
|
])),
|
||||||
],
|
|
||||||
Span::test_data(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: "0 | append [1 2 3]",
|
example: "0 | append [1 2 3]",
|
||||||
description: "Append a list to an item",
|
description: "Append a list to an item",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_int(3),
|
||||||
Value::test_int(3),
|
])),
|
||||||
],
|
|
||||||
Span::test_data(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: r#""a" | append ["b"] "#,
|
example: r#""a" | append ["b"] "#,
|
||||||
description: "Append a list of string to a string",
|
description: "Append a list of string to a string",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![Value::test_string("a"), Value::test_string("b")],
|
Value::test_string("a"),
|
||||||
Span::test_data(),
|
Value::test_string("b"),
|
||||||
)),
|
])),
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: "[0,1] | append [2,3,4]",
|
example: "[0 1] | append [2 3 4]",
|
||||||
description: "Append three integer items",
|
description: "Append three integer items",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_int(3),
|
||||||
Value::test_int(3),
|
Value::test_int(4),
|
||||||
Value::test_int(4),
|
])),
|
||||||
],
|
|
||||||
Span::test_data(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: "[0,1] | append [2,nu,4,shell]",
|
example: "[0 1] | append [2 nu 4 shell]",
|
||||||
description: "Append integers and strings",
|
description: "Append integers and strings",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_string("nu"),
|
||||||
Value::test_string("nu"),
|
Value::test_int(4),
|
||||||
Value::test_int(4),
|
Value::test_string("shell"),
|
||||||
Value::test_string("shell"),
|
])),
|
||||||
],
|
},
|
||||||
Span::test_data(),
|
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,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let val: Value = call.req(engine_state, stack, 0)?;
|
let other: Value = call.req(engine_state, stack, 0)?;
|
||||||
let vec: Vec<Value> = process_value(val);
|
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
|
|
||||||
Ok(input
|
Ok(input
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(vec)
|
.chain(other.into_pipeline_data())
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone())
|
.into_pipeline_data(engine_state.ctrlc.clone())
|
||||||
.set_metadata(metadata))
|
.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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -2,8 +2,8 @@ use nu_engine::CallExt;
|
|||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
|
||||||
SyntaxShape, Type, Value,
|
Signature, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -45,67 +45,66 @@ only unwrap the outer list, and leave the variable's contents untouched."#
|
|||||||
Example {
|
Example {
|
||||||
example: "0 | prepend [1 2 3]",
|
example: "0 | prepend [1 2 3]",
|
||||||
description: "prepend a list to an item",
|
description: "prepend a list to an item",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_int(3),
|
||||||
Value::test_int(3),
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
])),
|
||||||
],
|
|
||||||
Span::test_data(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: r#""a" | prepend ["b"] "#,
|
example: r#""a" | prepend ["b"] "#,
|
||||||
description: "Prepend a list of strings to a string",
|
description: "Prepend a list of strings to a string",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![Value::test_string("b"), Value::test_string("a")],
|
Value::test_string("b"),
|
||||||
Span::test_data(),
|
Value::test_string("a"),
|
||||||
)),
|
])),
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: "[1,2,3,4] | prepend 0",
|
example: "[1 2 3 4] | prepend 0",
|
||||||
description: "Prepend one integer item",
|
description: "Prepend one integer item",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_int(3),
|
||||||
Value::test_int(3),
|
Value::test_int(4),
|
||||||
Value::test_int(4),
|
])),
|
||||||
],
|
|
||||||
Span::test_data(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: "[2,3,4] | prepend [0,1]",
|
example: "[2 3 4] | prepend [0 1]",
|
||||||
description: "Prepend two integer items",
|
description: "Prepend two integer items",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_int(3),
|
||||||
Value::test_int(3),
|
Value::test_int(4),
|
||||||
Value::test_int(4),
|
])),
|
||||||
],
|
|
||||||
Span::test_data(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: "[2,nu,4,shell] | prepend [0,1,rocks]",
|
example: "[2 nu 4 shell] | prepend [0 1 rocks]",
|
||||||
description: "Prepend integers and strings",
|
description: "Prepend integers and strings",
|
||||||
result: Some(Value::list(
|
result: Some(Value::test_list(vec![
|
||||||
vec![
|
Value::test_int(0),
|
||||||
Value::test_int(0),
|
Value::test_int(1),
|
||||||
Value::test_int(1),
|
Value::test_string("rocks"),
|
||||||
Value::test_string("rocks"),
|
Value::test_int(2),
|
||||||
Value::test_int(2),
|
Value::test_string("nu"),
|
||||||
Value::test_string("nu"),
|
Value::test_int(4),
|
||||||
Value::test_int(4),
|
Value::test_string("shell"),
|
||||||
Value::test_string("shell"),
|
])),
|
||||||
],
|
},
|
||||||
Span::test_data(),
|
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,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let val: Value = call.req(engine_state, stack, 0)?;
|
let other: Value = call.req(engine_state, stack, 0)?;
|
||||||
let vec: Vec<Value> = process_value(val);
|
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
|
|
||||||
Ok(vec
|
Ok(other
|
||||||
|
.into_pipeline_data()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(input)
|
.chain(input)
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone())
|
.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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user