forked from extern/nushell
Numbered each
(#2100)
* Add --numbered to each * Fix example tester and add numbered each
This commit is contained in:
parent
5cafead4a4
commit
de8e2841a0
@ -40,7 +40,7 @@ impl WholeStreamCommand for Compact {
|
||||
vec![
|
||||
Example {
|
||||
description: "Filter out all null entries in a list",
|
||||
example: "echo [1 2 $null 3 $null $null] | compact target",
|
||||
example: "echo [1 2 $null 3 $null $null] | compact",
|
||||
result: Some(vec![
|
||||
UntaggedValue::int(1).into(),
|
||||
UntaggedValue::int(2).into(),
|
||||
|
@ -7,14 +7,16 @@ use futures::stream::once;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
hir::Block, hir::Expression, hir::SpannedExpression, hir::Synthetic, Scope, Signature,
|
||||
SyntaxShape, UntaggedValue, Value,
|
||||
SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct Each;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct EachArgs {
|
||||
block: Block,
|
||||
numbered: Tagged<bool>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@ -24,11 +26,13 @@ impl WholeStreamCommand for Each {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("each").required(
|
||||
"block",
|
||||
SyntaxShape::Block,
|
||||
"the block to run on each row",
|
||||
)
|
||||
Signature::build("each")
|
||||
.required("block", SyntaxShape::Block, "the block to run on each row")
|
||||
.switch(
|
||||
"numbered",
|
||||
"returned a numbered item ($it.index and $it.item)",
|
||||
Some('n'),
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
@ -45,6 +49,11 @@ impl WholeStreamCommand for Each {
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Echo the sum of each row",
|
||||
example: "echo [[1 2] [3 4]] | each { echo $it | math sum }",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Echo the square of each integer",
|
||||
example: "echo [1 2 3] | each { echo $(= $it * $it) }",
|
||||
@ -55,12 +64,10 @@ impl WholeStreamCommand for Each {
|
||||
]),
|
||||
},
|
||||
Example {
|
||||
description: "Echo the sum of each row",
|
||||
example: "echo [[1 2] [3 4]] | each { echo $it | math sum }",
|
||||
result: Some(vec![
|
||||
UntaggedValue::int(3).into(),
|
||||
UntaggedValue::int(7).into(),
|
||||
]),
|
||||
description: "Number each item and echo a message",
|
||||
example:
|
||||
"echo ['bob' 'fred'] | each --numbered { echo `{{$it.index}} is {{$it.item}}` }",
|
||||
result: Some(vec![Value::from("0 is bob"), Value::from("1 is fred")]),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -111,21 +118,47 @@ async fn each(
|
||||
let context = Arc::new(Context::from_raw(&raw_args, ®istry));
|
||||
let (each_args, input): (EachArgs, _) = raw_args.process(®istry).await?;
|
||||
let block = Arc::new(each_args.block);
|
||||
Ok(input
|
||||
.then(move |input| {
|
||||
let block = block.clone();
|
||||
let scope = scope.clone();
|
||||
let head = head.clone();
|
||||
let context = context.clone();
|
||||
async {
|
||||
match process_row(block, scope, head, context, input).await {
|
||||
Ok(s) => s,
|
||||
Err(e) => OutputStream::one(Err(e)),
|
||||
|
||||
if each_args.numbered.item {
|
||||
Ok(input
|
||||
.enumerate()
|
||||
.then(move |input| {
|
||||
let block = block.clone();
|
||||
let scope = scope.clone();
|
||||
let head = head.clone();
|
||||
let context = context.clone();
|
||||
|
||||
let mut dict = TaggedDictBuilder::new(input.1.tag());
|
||||
dict.insert_untagged("index", UntaggedValue::int(input.0));
|
||||
dict.insert_value("item", input.1);
|
||||
|
||||
async {
|
||||
match process_row(block, scope, head, context, dict.into_value()).await {
|
||||
Ok(s) => s,
|
||||
Err(e) => OutputStream::one(Err(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.to_output_stream())
|
||||
})
|
||||
.flatten()
|
||||
.to_output_stream())
|
||||
} else {
|
||||
Ok(input
|
||||
.then(move |input| {
|
||||
let block = block.clone();
|
||||
let scope = scope.clone();
|
||||
let head = head.clone();
|
||||
let context = context.clone();
|
||||
|
||||
async {
|
||||
match process_row(block, scope, head, context, input).await {
|
||||
Ok(s) => s,
|
||||
Err(e) => OutputStream::one(Err(e)),
|
||||
}
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.to_output_stream())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -6,7 +6,7 @@ use nu_protocol::hir::ClassifiedBlock;
|
||||
use nu_protocol::{ShellTypeName, Value};
|
||||
|
||||
use crate::commands::classified::block::run_block;
|
||||
use crate::commands::{whole_stream_command, Echo};
|
||||
use crate::commands::{whole_stream_command, BuildString, Echo};
|
||||
use crate::context::Context;
|
||||
use crate::stream::InputStream;
|
||||
use crate::WholeStreamCommand;
|
||||
@ -14,8 +14,10 @@ use crate::WholeStreamCommand;
|
||||
pub fn test(cmd: impl WholeStreamCommand + 'static) {
|
||||
let examples = cmd.examples();
|
||||
let mut base_context = Context::basic().expect("could not create basic context");
|
||||
|
||||
base_context.add_commands(vec![
|
||||
whole_stream_command(Echo {}),
|
||||
whole_stream_command(BuildString {}),
|
||||
whole_stream_command(cmd),
|
||||
]);
|
||||
|
||||
@ -24,12 +26,27 @@ pub fn test(cmd: impl WholeStreamCommand + 'static) {
|
||||
let block = parse_line(example.example, &mut ctx).expect("failed to parse example");
|
||||
if let Some(expected) = example.result {
|
||||
let result = block_on(evaluate_block(block, &mut ctx)).expect("failed to run example");
|
||||
|
||||
let errors = ctx.get_errors();
|
||||
|
||||
assert!(
|
||||
errors.is_empty(),
|
||||
"errors while running command.\ncommand: {}\nerrors: {:?}",
|
||||
example.example,
|
||||
errors
|
||||
);
|
||||
|
||||
assert!(expected.len() == result.len(), "example command produced unexpected number of results.\ncommand: {}\nexpected number: {}\nactual: {}",
|
||||
example.example,
|
||||
expected.len(),
|
||||
result.len(),);
|
||||
|
||||
assert!(
|
||||
expected
|
||||
.iter()
|
||||
.zip(result.iter())
|
||||
.all(|(e, a)| values_equal(e, a)),
|
||||
"example command produced unexpected result.\ncommand: {}\nexpected: {:?}\nactual:{:?}",
|
||||
"example command produced unexpected result.\ncommand: {}\nexpected: {:?}\nactual: {:?}",
|
||||
example.example,
|
||||
expected,
|
||||
result,
|
||||
|
Loading…
Reference in New Issue
Block a user