mirror of
https://github.com/nushell/nushell.git
synced 2024-12-23 23:49:44 +01:00
Remove deprecated --numbered
flag from four commands (#7777)
# Description Remove `--numbered` from ~~`for`~~, `each`, `par-each`, `reduce` and `each while`. These all provide indexes (numbering) via the optional second param to their closures. EDIT: Closes #6986. # User-Facing Changes Every command that had `--numbered` listed as "deprecated" in their help docs is affected. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
parent
215ed141e7
commit
9945241b77
@ -34,7 +34,7 @@ impl Command for For {
|
||||
.required("block", SyntaxShape::Block, "the block to run")
|
||||
.switch(
|
||||
"numbered",
|
||||
"returned a numbered item ($it.index and $it.item)",
|
||||
"return a numbered item ($it.index and $it.item)",
|
||||
Some('n'),
|
||||
)
|
||||
.creates_scope()
|
||||
|
@ -9,9 +9,9 @@ pub fn test_examples(cmd: impl Command + 'static) {
|
||||
#[cfg(test)]
|
||||
mod test_examples {
|
||||
use super::super::{
|
||||
Ansi, Date, Echo, From, If, Into, IntoString, Let, LetEnv, Math, MathEuler, MathPi,
|
||||
MathRound, Path, Random, Split, SplitColumn, SplitRow, Str, StrJoin, StrLength, StrReplace,
|
||||
Url, Values, Wrap,
|
||||
Ansi, Date, Echo, Enumerate, Flatten, From, Get, If, Into, IntoString, Let, LetEnv, Math,
|
||||
MathEuler, MathPi, MathRound, ParEach, Path, Random, Sort, SortBy, Split, SplitColumn,
|
||||
SplitRow, Str, StrJoin, StrLength, StrReplace, Update, Url, Values, Wrap,
|
||||
};
|
||||
use crate::{Break, Each, Mut, To};
|
||||
use itertools::Itertools;
|
||||
@ -61,35 +61,42 @@ mod test_examples {
|
||||
// Base functions that are needed for testing
|
||||
// Try to keep this working set small to keep tests running as fast as possible
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
working_set.add_decl(Box::new(Ansi));
|
||||
working_set.add_decl(Box::new(Break));
|
||||
working_set.add_decl(Box::new(Date));
|
||||
working_set.add_decl(Box::new(Each));
|
||||
working_set.add_decl(Box::new(Echo));
|
||||
working_set.add_decl(Box::new(Enumerate));
|
||||
working_set.add_decl(Box::new(Flatten));
|
||||
working_set.add_decl(Box::new(From));
|
||||
working_set.add_decl(Box::new(Get));
|
||||
working_set.add_decl(Box::new(If));
|
||||
working_set.add_decl(Box::new(Into));
|
||||
working_set.add_decl(Box::new(IntoString));
|
||||
working_set.add_decl(Box::new(Let));
|
||||
working_set.add_decl(Box::new(LetEnv));
|
||||
working_set.add_decl(Box::new(Math));
|
||||
working_set.add_decl(Box::new(MathEuler));
|
||||
working_set.add_decl(Box::new(MathPi));
|
||||
working_set.add_decl(Box::new(MathRound));
|
||||
working_set.add_decl(Box::new(Mut));
|
||||
working_set.add_decl(Box::new(Path));
|
||||
working_set.add_decl(Box::new(ParEach));
|
||||
working_set.add_decl(Box::new(Random));
|
||||
working_set.add_decl(Box::new(Sort));
|
||||
working_set.add_decl(Box::new(SortBy));
|
||||
working_set.add_decl(Box::new(Split));
|
||||
working_set.add_decl(Box::new(SplitColumn));
|
||||
working_set.add_decl(Box::new(SplitRow));
|
||||
working_set.add_decl(Box::new(Str));
|
||||
working_set.add_decl(Box::new(StrJoin));
|
||||
working_set.add_decl(Box::new(StrLength));
|
||||
working_set.add_decl(Box::new(StrReplace));
|
||||
working_set.add_decl(Box::new(From));
|
||||
working_set.add_decl(Box::new(If));
|
||||
working_set.add_decl(Box::new(To));
|
||||
working_set.add_decl(Box::new(Into));
|
||||
working_set.add_decl(Box::new(IntoString));
|
||||
working_set.add_decl(Box::new(Random));
|
||||
working_set.add_decl(Box::new(Split));
|
||||
working_set.add_decl(Box::new(SplitColumn));
|
||||
working_set.add_decl(Box::new(SplitRow));
|
||||
working_set.add_decl(Box::new(Math));
|
||||
working_set.add_decl(Box::new(Path));
|
||||
working_set.add_decl(Box::new(Date));
|
||||
working_set.add_decl(Box::new(Url));
|
||||
working_set.add_decl(Box::new(Update));
|
||||
working_set.add_decl(Box::new(Values));
|
||||
working_set.add_decl(Box::new(Ansi));
|
||||
working_set.add_decl(Box::new(Wrap));
|
||||
working_set.add_decl(Box::new(LetEnv));
|
||||
working_set.add_decl(Box::new(Echo));
|
||||
working_set.add_decl(Box::new(Break));
|
||||
working_set.add_decl(Box::new(Mut));
|
||||
working_set.add_decl(Box::new(MathEuler));
|
||||
working_set.add_decl(Box::new(MathPi));
|
||||
working_set.add_decl(Box::new(MathRound));
|
||||
// Adding the command that is being tested to the working set
|
||||
working_set.add_decl(cmd);
|
||||
|
||||
|
@ -43,9 +43,14 @@ impl Command for All {
|
||||
example: "[[status]; [UP] [UP]] | all {|el| $el.status == UP }",
|
||||
result: Some(Value::test_bool(true)),
|
||||
},
|
||||
Example {
|
||||
description: "Check that each item is a string",
|
||||
example: "[foo bar 2 baz] | all { ($in | describe) == 'string' }",
|
||||
result: Some(Value::test_bool(false)),
|
||||
},
|
||||
Example {
|
||||
description: "Check that all values are equal to twice their index",
|
||||
example: "[0 2 4 6] | all {|el ind| $el == $ind * 2 }",
|
||||
example: "[0 2 4 6] | enumerate | all {|i| $i.item == $i.index * 2 }",
|
||||
result: Some(Value::test_bool(true)),
|
||||
},
|
||||
Example {
|
||||
@ -80,7 +85,7 @@ impl Command for All {
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
let engine_state = engine_state.clone();
|
||||
|
||||
for (idx, value) in input.into_interruptible_iter(ctrlc).enumerate() {
|
||||
for value in input.into_interruptible_iter(ctrlc) {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -89,18 +94,6 @@ impl Command for All {
|
||||
if let Some(var_id) = var_id {
|
||||
stack.add_var(var_id, value.clone());
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let eval = eval_block(
|
||||
&engine_state,
|
||||
|
@ -43,9 +43,14 @@ impl Command for Any {
|
||||
example: "[[status]; [UP] [DOWN] [UP]] | any {|el| $el.status == DOWN }",
|
||||
result: Some(Value::test_bool(true)),
|
||||
},
|
||||
Example {
|
||||
description: "Check that any item is a string",
|
||||
example: "[1 2 3 4] | any { ($in | describe) == 'string' }",
|
||||
result: Some(Value::test_bool(false)),
|
||||
},
|
||||
Example {
|
||||
description: "Check if any value is equal to twice its own index",
|
||||
example: "[9 8 7 6] | any {|el ind| $el == $ind * 2 }",
|
||||
example: "[9 8 7 6] | enumerate | any {|i| $i.item == $i.index * 2 }",
|
||||
result: Some(Value::test_bool(true)),
|
||||
},
|
||||
Example {
|
||||
@ -80,7 +85,7 @@ impl Command for Any {
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
let engine_state = engine_state.clone();
|
||||
|
||||
for (idx, value) in input.into_interruptible_iter(ctrlc).enumerate() {
|
||||
for value in input.into_interruptible_iter(ctrlc) {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -89,18 +94,6 @@ impl Command for Any {
|
||||
if let Some(var_id) = var_id {
|
||||
stack.add_var(var_id, value.clone());
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let eval = eval_block(
|
||||
&engine_state,
|
||||
|
@ -35,21 +35,19 @@ with 'transpose' first."#
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("each")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.input_output_types(vec![
|
||||
(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(Type::Table(vec![]), Type::List(Box::new(Type::Any))),
|
||||
])
|
||||
.required(
|
||||
"closure",
|
||||
SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])),
|
||||
"the closure to run",
|
||||
)
|
||||
.switch("keep-empty", "keep empty result cells", Some('k'))
|
||||
.switch(
|
||||
"numbered",
|
||||
"iterate with an index (deprecated; use a two-parameter closure instead)",
|
||||
Some('n'),
|
||||
)
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
@ -96,7 +94,7 @@ with 'transpose' first."#
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
example: r#"[1 2 3] | each {|el ind| if $el == 2 { $"found 2 at ($ind)!"} }"#,
|
||||
example: r#"[1 2 3] | enumerate | each {|e| if $e.item == 2 { $"found 2 at ($e.index)!"} }"#,
|
||||
description:
|
||||
"Iterate over each element, producing a list showing indexes of any 2s",
|
||||
result: Some(Value::List {
|
||||
@ -106,7 +104,7 @@ with 'transpose' first."#
|
||||
},
|
||||
Example {
|
||||
example: r#"[1 2 3] | each --keep-empty {|e| if $e == 2 { "found 2!"} }"#,
|
||||
description: "Iterate over each element, keeping all results",
|
||||
description: "Iterate over each element, keeping null results",
|
||||
result: Some(Value::List {
|
||||
vals: stream_test_2,
|
||||
span: Span::test_data(),
|
||||
@ -124,7 +122,6 @@ with 'transpose' first."#
|
||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||
|
||||
let numbered = call.has_flag("numbered");
|
||||
let keep_empty = call.has_flag("keep-empty");
|
||||
|
||||
let metadata = input.metadata();
|
||||
@ -144,11 +141,8 @@ with 'transpose' first."#
|
||||
PipelineData::Value(Value::Range { .. }, ..)
|
||||
| PipelineData::Value(Value::List { .. }, ..)
|
||||
| PipelineData::ListStream { .. } => Ok(input
|
||||
// To enumerate over the input (for the index argument),
|
||||
// it must be converted into an iterator using into_iter().
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map_while(move |(idx, x)| {
|
||||
.map_while(move |x| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -156,37 +150,7 @@ with 'transpose' first."#
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
// -n changes the first argument into an {index, item} record.
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Optional second index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,8 +178,7 @@ with 'transpose' first."#
|
||||
..
|
||||
} => Ok(stream
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map_while(move |(idx, x)| {
|
||||
.map_while(move |x| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -229,24 +192,7 @@ with 'transpose' first."#
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,20 +24,18 @@ impl Command for EachWhile {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build(self.name())
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.input_output_types(vec![
|
||||
(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(Type::Table(vec![]), Type::List(Box::new(Type::Any))),
|
||||
])
|
||||
.required(
|
||||
"closure",
|
||||
SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])),
|
||||
"the closure to run",
|
||||
)
|
||||
.switch(
|
||||
"numbered",
|
||||
"iterate with an index (deprecated; use a two-parameter closure instead)",
|
||||
Some('n'),
|
||||
)
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
@ -66,7 +64,7 @@ impl Command for EachWhile {
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
example: r#"[1 2 3] | each while {|el ind| if $el < 2 { $"value ($el) at ($ind)!"} }"#,
|
||||
example: r#"[1 2 3] | enumerate | each while {|e| if $e.item < 2 { $"value ($e.item) at ($e.index)!"} }"#,
|
||||
description: "Iterate over each element, printing the matching value and its index",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_string("value 1 at 0!")],
|
||||
@ -84,7 +82,6 @@ impl Command for EachWhile {
|
||||
input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||
let numbered = call.has_flag("numbered");
|
||||
|
||||
let metadata = input.metadata();
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
@ -102,12 +99,9 @@ impl Command for EachWhile {
|
||||
PipelineData::Value(Value::Range { .. }, ..)
|
||||
| PipelineData::Value(Value::List { .. }, ..)
|
||||
| PipelineData::ListStream { .. } => Ok(input
|
||||
// To enumerate over the input (for the index argument),
|
||||
// it must be converted into an iterator using into_iter().
|
||||
// TODO: Could this be changed to .into_interruptible_iter(ctrlc) ?
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map_while(move |(idx, x)| {
|
||||
.map_while(move |x| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -115,36 +109,7 @@ impl Command for EachWhile {
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Optional second index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,8 +140,7 @@ impl Command for EachWhile {
|
||||
..
|
||||
} => Ok(stream
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map_while(move |(idx, x)| {
|
||||
.map_while(move |x| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -189,24 +153,7 @@ impl Command for EachWhile {
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,17 +204,7 @@ impl Command for EachWhile {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[7 8 9 10] | each while {|el ind| $el + $ind } | to nuon"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[7, 9, 11, 13]");
|
||||
}
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
@ -72,8 +72,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
// To enumerate over the input (for the index argument),
|
||||
// it must be converted into an iterator using into_iter().
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.filter_map(move |(idx, x)| {
|
||||
.filter_map(move |x| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -84,18 +83,6 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
match eval_block(
|
||||
&engine_state,
|
||||
@ -125,8 +112,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
..
|
||||
} => Ok(stream
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.filter_map(move |(idx, x)| {
|
||||
.filter_map(move |x| {
|
||||
// see note above about with_env()
|
||||
stack.with_env(&orig_env_vars, &orig_env_hidden);
|
||||
|
||||
@ -140,18 +126,6 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
match eval_block(
|
||||
&engine_state,
|
||||
|
@ -64,27 +64,37 @@ impl Command for Insert {
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
}, Example {
|
||||
},
|
||||
Example {
|
||||
description: "Insert a new column into a table, populating all rows",
|
||||
example: "[[project, lang]; ['Nushell', 'Rust']] | insert type 'shell'",
|
||||
result: Some(Value::List { vals: vec![Value::Record { cols: vec!["project".into(), "lang".into(), "type".into()],
|
||||
vals: vec![Value::test_string("Nushell"), Value::test_string("Rust"), Value::test_string("shell")], span: Span::test_data()}], span: Span::test_data()}),
|
||||
},
|
||||
Example {
|
||||
description: "Insert a column with values equal to their row index, plus the value of 'foo' in each row",
|
||||
example: "[[foo]; [7] [8] [9]] | insert bar {|el ind| $el.foo + $ind }",
|
||||
example: "[[foo]; [7] [8] [9]] | enumerate | insert bar {|e| $e.item.foo + $e.index } | flatten",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::Record {
|
||||
cols: vec!["foo".into(), "bar".into()],
|
||||
cols: vec!["index".into(), "foo".into(), "bar".into()],
|
||||
vals: vec![
|
||||
Value::test_int(0),
|
||||
Value::test_int(7),
|
||||
Value::test_int(7),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}, Value::Record {
|
||||
cols: vec!["foo".into(), "bar".into()],
|
||||
cols: vec!["index".into(),"foo".into(), "bar".into()],
|
||||
vals: vec![
|
||||
Value::test_int(1),
|
||||
Value::test_int(8),
|
||||
Value::test_int(9),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}, Value::Record {
|
||||
cols: vec!["foo".into(), "bar".into()],
|
||||
cols: vec!["index".into(), "foo".into(), "bar".into()],
|
||||
vals: vec![
|
||||
Value::test_int(2),
|
||||
Value::test_int(9),
|
||||
Value::test_int(11),
|
||||
],
|
||||
@ -122,9 +132,6 @@ fn insert(
|
||||
let orig_env_vars = stack.env_vars.clone();
|
||||
let orig_env_hidden = stack.env_hidden.clone();
|
||||
|
||||
// enumerate() can't be used here because it converts records into tables
|
||||
// when combined with into_pipeline_data(). Hence, the index is tracked manually like so.
|
||||
let mut idx: i64 = 0;
|
||||
input.map(
|
||||
move |mut input| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
@ -138,13 +145,6 @@ fn insert(
|
||||
stack.add_var(*var_id, input.clone())
|
||||
}
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(*var_id, Value::Int { val: idx, span });
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
let output = eval_block(
|
||||
&engine_state,
|
||||
|
@ -23,20 +23,18 @@ impl Command for ParEach {
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("par-each")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.input_output_types(vec![
|
||||
(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
),
|
||||
(Type::Table(vec![]), Type::List(Box::new(Type::Any))),
|
||||
])
|
||||
.required(
|
||||
"closure",
|
||||
SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])),
|
||||
"the closure to run",
|
||||
)
|
||||
.switch(
|
||||
"numbered",
|
||||
"iterate with an index (deprecated; use a two-parameter closure instead)",
|
||||
Some('n'),
|
||||
)
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
@ -49,8 +47,29 @@ impl Command for ParEach {
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
example: r#"[1 2 3] | par-each -n { |it| if $it.item == 2 { $"found 2 at ($it.index)!"} }"#,
|
||||
description: "Iterate over each element, print the matching value and its index",
|
||||
example: r#"[foo bar baz] | par-each {|e| $e + '!' } | sort"#,
|
||||
description: "Output can still be sorted afterward",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::test_string("bar!"),
|
||||
Value::test_string("baz!"),
|
||||
Value::test_string("foo!"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
example: r#"1..3 | enumerate | par-each {|p| update item ($p.item * 2)} | sort-by item | get item"#,
|
||||
description: "Enumerate and sort-by can be used to reconstruct the original order",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_int(2), Value::test_int(4), Value::test_int(6)],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
},
|
||||
Example {
|
||||
example: r#"[1 2 3] | enumerate | par-each { |e| if $e.item == 2 { $"found 2 at ($e.index)!"} }"#,
|
||||
description:
|
||||
"Iterate over each element, producing a list showing indexes of any 2s",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_string("found 2 at 1!")],
|
||||
span: Span::test_data(),
|
||||
@ -68,12 +87,10 @@ impl Command for ParEach {
|
||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||
|
||||
let numbered = call.has_flag("numbered");
|
||||
let metadata = input.metadata();
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
let block_id = capture_block.block_id;
|
||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||
let span = call.head;
|
||||
let redirect_stdout = call.redirect_stdout;
|
||||
let redirect_stderr = call.redirect_stderr;
|
||||
|
||||
@ -81,45 +98,15 @@ impl Command for ParEach {
|
||||
PipelineData::Empty => Ok(PipelineData::Empty),
|
||||
PipelineData::Value(Value::Range { val, .. }, ..) => Ok(val
|
||||
.into_range_iter(ctrlc.clone())?
|
||||
.enumerate()
|
||||
.par_bridge()
|
||||
.map(move |(idx, x)| {
|
||||
.map(move |x| {
|
||||
let block = engine_state.get_block(block_id);
|
||||
|
||||
let mut stack = stack.clone();
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Optional second index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,45 +132,15 @@ impl Command for ParEach {
|
||||
.into_pipeline_data(ctrlc)),
|
||||
PipelineData::Value(Value::List { vals: val, .. }, ..) => Ok(val
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.par_bridge()
|
||||
.map(move |(idx, x)| {
|
||||
.map(move |x| {
|
||||
let block = engine_state.get_block(block_id);
|
||||
|
||||
let mut stack = stack.clone();
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Optional second index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,45 +165,15 @@ impl Command for ParEach {
|
||||
.flatten()
|
||||
.into_pipeline_data(ctrlc)),
|
||||
PipelineData::ListStream(stream, ..) => Ok(stream
|
||||
.enumerate()
|
||||
.par_bridge()
|
||||
.map(move |(idx, x)| {
|
||||
.map(move |x| {
|
||||
let block = engine_state.get_block(block_id);
|
||||
|
||||
let mut stack = stack.clone();
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Optional second index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,9 +202,8 @@ impl Command for ParEach {
|
||||
stdout: Some(stream),
|
||||
..
|
||||
} => Ok(stream
|
||||
.enumerate()
|
||||
.par_bridge()
|
||||
.map(move |(idx, x)| {
|
||||
.map(move |x| {
|
||||
let x = match x {
|
||||
Ok(x) => x,
|
||||
Err(err) => return Value::Error { error: err }.into_pipeline_data(),
|
||||
@ -289,36 +215,7 @@ impl Command for ParEach {
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
if numbered {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Record {
|
||||
cols: vec!["index".into(), "item".into()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
x.clone(),
|
||||
],
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Optional second index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
stack.add_var(*var_id, x.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,17 +263,6 @@ impl Command for ParEach {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[7,8,9,10] | par-each {|el ind| $ind } | describe"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "list<int> (stream)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
|
@ -16,7 +16,10 @@ impl Command for Reduce {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("reduce")
|
||||
.input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Any)])
|
||||
.input_output_types(vec![
|
||||
(Type::List(Box::new(Type::Any)), Type::Any),
|
||||
(Type::Table(vec![]), Type::Any),
|
||||
])
|
||||
.named(
|
||||
"fold",
|
||||
SyntaxShape::Any,
|
||||
@ -32,11 +35,6 @@ impl Command for Reduce {
|
||||
])),
|
||||
"reducing function",
|
||||
)
|
||||
.switch(
|
||||
"numbered",
|
||||
"iterate with an index (deprecated; use a 3-parameter closure instead)",
|
||||
Some('n'),
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
@ -55,9 +53,10 @@ impl Command for Reduce {
|
||||
result: Some(Value::test_int(10)),
|
||||
},
|
||||
Example {
|
||||
example: "[ 8 7 6 ] | reduce {|it, acc, ind| $acc + $it + $ind }",
|
||||
example:
|
||||
"[ 8 7 6 ] | enumerate | reduce -f 0 {|it, acc| $acc + $it.item + $it.index }",
|
||||
description: "Sum values of a list, plus their indexes",
|
||||
result: Some(Value::test_int(22)),
|
||||
result: Some(Value::test_int(24)),
|
||||
},
|
||||
Example {
|
||||
example: "[ 1 2 3 4 ] | reduce -f 10 {|it, acc| $acc + $it }",
|
||||
@ -70,7 +69,7 @@ impl Command for Reduce {
|
||||
result: Some(Value::test_string("ArXhur, KXng Xf Xhe BrXXXns")),
|
||||
},
|
||||
Example {
|
||||
example: r#"['foo.gz', 'bar.gz', 'baz.gz'] | reduce -f '' {|str all ind| $"($all)(if $ind != 0 {'; '})($ind + 1)-($str)" }"#,
|
||||
example: r#"['foo.gz', 'bar.gz', 'baz.gz'] | enumerate | reduce -f '' {|str all| $"($all)(if $str.index != 0 {'; '})($str.index + 1)-($str.item)" }"#,
|
||||
description:
|
||||
"Add ascending numbers to each of the filenames, and join with semicolons.",
|
||||
result: Some(Value::test_string("1-foo.gz; 2-bar.gz; 3-baz.gz")),
|
||||
@ -88,7 +87,6 @@ impl Command for Reduce {
|
||||
let span = call.head;
|
||||
|
||||
let fold: Option<Value> = call.get_flag(engine_state, stack, "fold")?;
|
||||
let numbered = call.has_flag("numbered");
|
||||
let capture_block: Closure = call.req(engine_state, stack, 0)?;
|
||||
let mut stack = stack.captures_to_stack(&capture_block.captures);
|
||||
let block = engine_state.get_block(capture_block.block_id);
|
||||
@ -104,10 +102,10 @@ impl Command for Reduce {
|
||||
// it must be converted into an iterator using into_iter().
|
||||
let mut input_iter = input.into_iter();
|
||||
|
||||
let (off, start_val) = if let Some(val) = fold {
|
||||
(0, val)
|
||||
let start_val = if let Some(val) = fold {
|
||||
val
|
||||
} else if let Some(val) = input_iter.next() {
|
||||
(1, val)
|
||||
val
|
||||
} else {
|
||||
return Err(ShellError::GenericError(
|
||||
"Expected input".to_string(),
|
||||
@ -118,41 +116,11 @@ impl Command for Reduce {
|
||||
));
|
||||
};
|
||||
|
||||
let mut acc = if numbered {
|
||||
Value::Record {
|
||||
cols: vec!["index".to_string(), "item".to_string()],
|
||||
vals: vec![Value::Int { val: 0, span }, start_val],
|
||||
span,
|
||||
}
|
||||
} else {
|
||||
start_val
|
||||
};
|
||||
let mut acc = start_val;
|
||||
|
||||
let mut input_iter = input_iter
|
||||
.enumerate()
|
||||
.map(|(idx, x)| {
|
||||
if numbered {
|
||||
(
|
||||
idx,
|
||||
Value::Record {
|
||||
cols: vec!["index".to_string(), "item".to_string()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64 + off,
|
||||
span,
|
||||
},
|
||||
x,
|
||||
],
|
||||
span,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(idx, x)
|
||||
}
|
||||
})
|
||||
.peekable();
|
||||
let mut input_iter = input_iter.peekable();
|
||||
|
||||
while let Some((idx, x)) = input_iter.next() {
|
||||
while let Some(x) = input_iter.next() {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
// a different set of environment variables.
|
||||
// Hence, a 'cd' in the first loop won't affect the next loop.
|
||||
@ -168,41 +136,9 @@ impl Command for Reduce {
|
||||
// Accumulator argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
acc = if numbered {
|
||||
if let Value::Record { .. } = &acc {
|
||||
acc
|
||||
} else {
|
||||
Value::Record {
|
||||
cols: vec!["index".to_string(), "item".to_string()],
|
||||
vals: vec![
|
||||
Value::Int {
|
||||
val: idx as i64 + off,
|
||||
span,
|
||||
},
|
||||
acc,
|
||||
],
|
||||
span,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
acc
|
||||
};
|
||||
|
||||
stack.add_var(*var_id, acc);
|
||||
}
|
||||
}
|
||||
// Optional third index argument
|
||||
if let Some(var) = block.signature.get_positional(2) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
acc = eval_block(
|
||||
engine_state,
|
||||
|
@ -60,7 +60,7 @@ impl Command for Update {
|
||||
},
|
||||
Example {
|
||||
description: "Use in closure form for more involved updating logic",
|
||||
example: "[[count fruit]; [1 'apple']] | update count {|row index| ($row.fruit | str length) + $index }",
|
||||
example: "[[count fruit]; [1 'apple']] | enumerate | update item.count {|e| ($e.item.fruit | str length) + $e.index } | get item",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::Record {
|
||||
cols: vec!["count".into(), "fruit".into()],
|
||||
@ -105,9 +105,6 @@ fn update(
|
||||
let orig_env_vars = stack.env_vars.clone();
|
||||
let orig_env_hidden = stack.env_hidden.clone();
|
||||
|
||||
// enumerate() can't be used here because it converts records into tables
|
||||
// when combined with into_pipeline_data(). Hence, the index is tracked manually like so.
|
||||
let mut idx: i64 = 0;
|
||||
input.map(
|
||||
move |mut input| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
@ -120,13 +117,6 @@ fn update(
|
||||
stack.add_var(*var_id, input.clone())
|
||||
}
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(*var_id, Value::Int { val: idx, span });
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
let output = eval_block(
|
||||
&engine_state,
|
||||
|
@ -56,14 +56,25 @@ impl Command for Upsert {
|
||||
description: "Update a record's value",
|
||||
example: "{'name': 'nu', 'stars': 5} | upsert name 'Nushell'",
|
||||
result: Some(Value::Record { cols: vec!["name".into(), "stars".into()], vals: vec![Value::test_string("Nushell"), Value::test_int(5)], span: Span::test_data()}),
|
||||
}, Example {
|
||||
},
|
||||
Example {
|
||||
description: "Update each row of a table",
|
||||
example: "[[name lang]; [Nushell ''] [Reedline '']] | upsert lang 'Rust'",
|
||||
result: Some(Value::List { vals: vec![
|
||||
Value::Record { cols: vec!["name".into(), "lang".into()], vals: vec![Value::test_string("Nushell"), Value::test_string("Rust")], span: Span::test_data()},
|
||||
Value::Record { cols: vec!["name".into(), "lang".into()], vals: vec![Value::test_string("Reedline"), Value::test_string("Rust")], span: Span::test_data()}
|
||||
], span: Span::test_data()}),
|
||||
},
|
||||
Example {
|
||||
description: "Insert a new entry into a single record",
|
||||
example: "{'name': 'nu', 'stars': 5} | upsert language 'Rust'",
|
||||
result: Some(Value::Record { cols: vec!["name".into(), "stars".into(), "language".into()], vals: vec![Value::test_string("nu"), Value::test_int(5), Value::test_string("Rust")], span: Span::test_data()}),
|
||||
}, Example {
|
||||
description: "Use in closure form for more involved updating logic",
|
||||
example: "[[count fruit]; [1 'apple']] | upsert count {|row index| ($row.fruit | str length) + $index }",
|
||||
result: Some(Value::List { vals: vec![Value::Record { cols: vec!["count".into(), "fruit".into()], vals: vec![Value::test_int(5), Value::test_string("apple")], span: Span::test_data()}], span: Span::test_data()}),
|
||||
example: "[[count fruit]; [1 'apple']] | enumerate | upsert item.count {|e| ($e.item.fruit | str length) + $e.index } | get item",
|
||||
result: Some(Value::List { vals: vec![
|
||||
Value::Record { cols: vec!["count".into(), "fruit".into()], vals: vec![Value::test_int(5), Value::test_string("apple")], span: Span::test_data()}],
|
||||
span: Span::test_data()}),
|
||||
},
|
||||
Example {
|
||||
description: "Upsert an int into a list, updating an existing value based on the index",
|
||||
@ -116,9 +127,6 @@ fn upsert(
|
||||
let orig_env_vars = stack.env_vars.clone();
|
||||
let orig_env_hidden = stack.env_hidden.clone();
|
||||
|
||||
// enumerate() can't be used here because it converts records into tables
|
||||
// when combined with into_pipeline_data(). Hence, the index is tracked manually like so.
|
||||
let mut idx: i64 = 0;
|
||||
input.map(
|
||||
move |mut input| {
|
||||
// with_env() is used here to ensure that each iteration uses
|
||||
@ -131,13 +139,6 @@ fn upsert(
|
||||
stack.add_var(*var_id, input.clone())
|
||||
}
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(*var_id, Value::Int { val: idx, span });
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
let output = eval_block(
|
||||
&engine_state,
|
||||
|
@ -70,8 +70,7 @@ not supported."#
|
||||
let redirect_stderr = call.redirect_stderr;
|
||||
Ok(input
|
||||
.into_iter_strict(span)?
|
||||
.enumerate()
|
||||
.filter_map(move |(idx, value)| {
|
||||
.filter_map(move |value| {
|
||||
stack.with_env(&orig_env_vars, &orig_env_hidden);
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
@ -79,18 +78,6 @@ not supported."#
|
||||
stack.add_var(*var_id, value.clone());
|
||||
}
|
||||
}
|
||||
// Optional index argument
|
||||
if let Some(var) = block.signature.get_positional(1) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(
|
||||
*var_id,
|
||||
Value::Int {
|
||||
val: idx as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
let result = eval_block(
|
||||
&engine_state,
|
||||
&mut stack,
|
||||
@ -159,6 +146,11 @@ not supported."#
|
||||
example: "ls | where modified >= (date now) - 2wk",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Find files whose filenames don't begin with the correct sequential number",
|
||||
example: "ls | where type == file | sort-by name -n | enumerate | where {|e| $e.item.name !~ $'^($e.index + 1)' } | each { get item }",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -109,10 +109,10 @@ fn early_exits_with_0_param_blocks() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
fn all_uses_enumerate_index() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[7 8 9] | all {|el ind| print $ind | true }"#
|
||||
r#"[7 8 9] | enumerate | all {|el| print $el.index | true }"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "012true");
|
||||
|
@ -85,10 +85,10 @@ fn early_exits_with_0_param_blocks() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
fn any_uses_enumerate_index() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[7 8 9] | any {|el ind| print $ind | false }"#
|
||||
r#"[7 8 9] | enumerate | any {|el| print $el.index | false }"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "012false");
|
||||
|
@ -73,20 +73,20 @@ fn each_implicit_it_in_block() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
fn each_uses_enumerate_index() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[7 8 9 10] | each {|el ind| $ind } | to nuon"#
|
||||
r#"[7 8 9 10] | enumerate | each {|el| $el.index } | to nuon"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[0, 1, 2, 3]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn each_while_uses_optional_index_argument() {
|
||||
fn each_while_uses_enumerate_index() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[7 8 9 10] | each while {|el ind| $ind } | to nuon"#
|
||||
r#"[7 8 9 10] | enumerate | each while {|el| $el.index } | to nuon"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[0, 1, 2, 3]");
|
||||
|
@ -87,11 +87,11 @@ fn insert_past_end_list() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
fn insert_uses_enumerate_index() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[[a]; [7] [6]] | insert b {|el ind| $ind + 1 + $el.a } | to nuon"#
|
||||
r#"[[a]; [7] [6]] | enumerate | insert b {|el| $el.index + 1 + $el.item.a } | flatten | to nuon"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[[a, b]; [7, 8], [6, 8]]");
|
||||
assert_eq!(actual.out, "[[index, a, b]; [0, 7, 8], [1, 6, 8]]");
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ fn reduce_rows_example() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reduce_numbered_example() {
|
||||
fn reduce_enumerate_example() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo one longest three bar
|
||||
| reduce -n { |it, acc| if ($it.item | str length) > ($acc.item | str length) {echo $it} else {echo $acc}}
|
||||
echo one longest three bar | enumerate
|
||||
| reduce { |it, acc| if ($it.item | str length) > ($acc.item | str length) {echo $it} else {echo $acc}}
|
||||
| get index
|
||||
"#
|
||||
)
|
||||
@ -62,12 +62,14 @@ fn reduce_numbered_example() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reduce_numbered_integer_addition_example() {
|
||||
fn reduce_enumerate_integer_addition_example() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo [1 2 3 4]
|
||||
| reduce -n { |it, acc| $acc.item + $it.item }
|
||||
| enumerate
|
||||
| reduce { |it, acc| { index: ($it.index) item: ($acc.item + $it.item)} }
|
||||
| get item
|
||||
"#
|
||||
)
|
||||
);
|
||||
@ -121,11 +123,14 @@ fn error_reduce_empty() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
fn enumerate_reduce_example() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[18 19 20] | reduce -f 0 {|elem accum index| $accum + $index } | to nuon"#
|
||||
));
|
||||
r#"
|
||||
[one longest three bar] | enumerate | reduce {|it, acc| if ($it.item | str length) > ($acc.item | str length) { $it } else { $acc }} | get index
|
||||
"#
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "3");
|
||||
assert_eq!(actual.out, "1");
|
||||
}
|
||||
|
@ -135,7 +135,8 @@ mod columns {
|
||||
transpose bit --ignore-titles
|
||||
| get bit
|
||||
| reverse
|
||||
| each --numbered { |it|
|
||||
| enumerate
|
||||
| each { |it|
|
||||
$it.item * (2 ** $it.index)
|
||||
}
|
||||
| math sum
|
||||
|
@ -116,11 +116,11 @@ fn update_nonexistent_column() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
fn update_uses_enumerate_index() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[[a]; [7] [6]] | update a {|el ind| $ind + 1 + $el.a } | to nuon"#
|
||||
r#"[[a]; [7] [6]] | enumerate | update item.a {|el| $el.index + 1 + $el.item.a } | flatten | to nuon"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[[a]; [8], [8]]");
|
||||
assert_eq!(actual.out, "[[index, a]; [0, 8], [1, 8]]");
|
||||
}
|
||||
|
@ -69,23 +69,23 @@ fn sets_the_column_from_a_subexpression() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument_inserting() {
|
||||
fn upsert_uses_enumerate_index_inserting() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[[a]; [7] [6]] | upsert b {|el ind| $ind + 1 + $el.a } | to nuon"#
|
||||
r#"[[a]; [7] [6]] | enumerate | upsert b {|el| $el.index + 1 + $el.item.a } | flatten | to nuon"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[[a, b]; [7, 8], [6, 8]]");
|
||||
assert_eq!(actual.out, "[[index, a, b]; [0, 7, 8], [1, 6, 8]]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument_updating() {
|
||||
fn upsert_uses_enumerate_index_updating() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"[[a]; [7] [6]] | upsert a {|el ind| $ind + 1 + $el.a } | to nuon"#
|
||||
r#"[[a]; [7] [6]] | enumerate | upsert a {|el| $el.index + 1 + $el.item.a } | flatten | to nuon"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[[a]; [8], [8]]");
|
||||
assert_eq!(actual.out, "[[index, a]; [0, 8], [1, 8]]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -82,13 +82,13 @@ fn where_not_in_table() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_optional_index_argument() {
|
||||
fn where_uses_enumerate_index() {
|
||||
let actual = nu!(
|
||||
cwd: ".",
|
||||
r#"[7 8 9 10] | where {|el ind| $ind < 2 } | to nuon"#
|
||||
r#"[7 8 9 10] | enumerate | where {|el| $el.index < 2 } | to nuon"#
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "[7, 8]");
|
||||
assert_eq!(actual.out, "[[index, item]; [0, 7], [1, 8]]");
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
|
@ -3,7 +3,7 @@ use crate::tests::{run_test, TestResult};
|
||||
#[test]
|
||||
fn better_block_types() -> TestResult {
|
||||
run_test(
|
||||
r#"([1, 2, 3] | each -n { |it| $"($it.index) is ($it.item)" }).1"#,
|
||||
r#"([1, 2, 3] | enumerate | each { |e| $"($e.index) is ($e.item)" }).1"#,
|
||||
"1 is 2",
|
||||
)
|
||||
}
|
||||
@ -35,7 +35,7 @@ fn row_condition2() -> TestResult {
|
||||
#[test]
|
||||
fn par_each() -> TestResult {
|
||||
run_test(
|
||||
r#"1..10 | par-each --numbered { |it| ([[index, item]; [$it.index, ($it.item > 5)]]).0 } | where index == 4 | get item.0"#,
|
||||
r#"1..10 | enumerate | par-each { |it| ([[index, item]; [$it.index, ($it.item > 5)]]).0 } | where index == 4 | get item.0"#,
|
||||
"false",
|
||||
)
|
||||
}
|
||||
|
@ -147,8 +147,8 @@ fn bad_var_name2() -> TestResult {
|
||||
#[test]
|
||||
fn long_flag() -> TestResult {
|
||||
run_test(
|
||||
r#"([a, b, c] | each --numbered { |it| if $it.index == 1 { 100 } else { 0 } }).1"#,
|
||||
"100",
|
||||
r#"([a, b, c] | enumerate | each --keep-empty { |e| if $e.index != 1 { 100 }}).1 | to nuon"#,
|
||||
"null",
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user