mirror of
https://github.com/nushell/nushell
synced 2025-01-28 12:55:40 +00:00
Add a couple more tests to for
This commit is contained in:
parent
b28f876095
commit
8df9ea6c68
2 changed files with 87 additions and 55 deletions
|
@ -1,7 +1,7 @@
|
||||||
use nu_engine::{eval_block, eval_expression};
|
use nu_engine::{eval_block, eval_expression};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EvaluationContext};
|
use nu_protocol::engine::{Command, EvaluationContext};
|
||||||
use nu_protocol::{Example, IntoValueStream, Signature, Span, SyntaxShape, Value};
|
use nu_protocol::{Example, Signature, Span, SyntaxShape, Value};
|
||||||
|
|
||||||
pub struct For;
|
pub struct For;
|
||||||
|
|
||||||
|
@ -23,10 +23,7 @@ impl Command for For {
|
||||||
)
|
)
|
||||||
.required(
|
.required(
|
||||||
"range",
|
"range",
|
||||||
SyntaxShape::Keyword(
|
SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Any)),
|
||||||
b"in".to_vec(),
|
|
||||||
Box::new(SyntaxShape::List(Box::new(SyntaxShape::Int))),
|
|
||||||
),
|
|
||||||
"range of the loop",
|
"range of the loop",
|
||||||
)
|
)
|
||||||
.required(
|
.required(
|
||||||
|
@ -55,42 +52,22 @@ impl Command for For {
|
||||||
let block = call.positional[2]
|
let block = call.positional[2]
|
||||||
.as_block()
|
.as_block()
|
||||||
.expect("internal error: expected block");
|
.expect("internal error: expected block");
|
||||||
|
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
|
|
||||||
match values {
|
Ok(values.map(call.head, move |x| {
|
||||||
Value::Stream { stream, .. } => Ok(Value::Stream {
|
let engine_state = context.engine_state.borrow();
|
||||||
stream: stream
|
let block = engine_state.get_block(block);
|
||||||
.map(move |x| {
|
|
||||||
let engine_state = context.engine_state.borrow();
|
|
||||||
let block = engine_state.get_block(block);
|
|
||||||
|
|
||||||
let state = context.enter_scope();
|
let state = context.enter_scope();
|
||||||
state.add_var(var_id, x);
|
|
||||||
|
|
||||||
//FIXME: DON'T UNWRAP
|
state.add_var(var_id, x);
|
||||||
eval_block(&state, block, Value::nothing()).unwrap()
|
|
||||||
})
|
|
||||||
.into_value_stream(),
|
|
||||||
span: call.head,
|
|
||||||
}),
|
|
||||||
Value::List { vals: val, .. } => Ok(Value::List {
|
|
||||||
vals: val
|
|
||||||
.into_iter()
|
|
||||||
.map(move |x| {
|
|
||||||
let engine_state = context.engine_state.borrow();
|
|
||||||
let block = engine_state.get_block(block);
|
|
||||||
|
|
||||||
let state = context.enter_scope();
|
match eval_block(&state, block, Value::nothing()) {
|
||||||
state.add_var(var_id, x);
|
Ok(value) => value,
|
||||||
|
Err(error) => Value::Error { error },
|
||||||
//FIXME: DON'T UNWRAP
|
}
|
||||||
eval_block(&state, block, Value::nothing()).unwrap()
|
}))
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
span: call.head,
|
|
||||||
}),
|
|
||||||
_ => Ok(Value::nothing()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -120,23 +97,36 @@ impl Command for For {
|
||||||
span: Span::unknown(),
|
span: Span::unknown(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
Example {
|
// FIXME? Numbered `for` is kinda strange, but was supported in previous nushell
|
||||||
description: "Number each item and echo a message",
|
// Example {
|
||||||
example: "for $it in ['bob' 'fred'] --numbered { $\"($it.index) is ($it.item)\" }",
|
// description: "Number each item and echo a message",
|
||||||
result: Some(Value::List {
|
// example: "for $it in ['bob' 'fred'] --numbered { $\"($it.index) is ($it.item)\" }",
|
||||||
vals: vec![
|
// result: Some(Value::List {
|
||||||
Value::String {
|
// vals: vec![
|
||||||
val: "0 is bob".into(),
|
// Value::String {
|
||||||
span,
|
// val: "0 is bob".into(),
|
||||||
},
|
// span,
|
||||||
Value::String {
|
// },
|
||||||
val: "0 is fred".into(),
|
// Value::String {
|
||||||
span,
|
// val: "0 is fred".into(),
|
||||||
},
|
// span,
|
||||||
],
|
// },
|
||||||
span: Span::unknown(),
|
// ],
|
||||||
}),
|
// span: Span::unknown(),
|
||||||
},
|
// }),
|
||||||
|
// },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
use crate::test_examples;
|
||||||
|
|
||||||
|
test_examples(For {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -379,6 +379,10 @@ impl Value {
|
||||||
stream: stream.map(f).into_value_stream(),
|
stream: stream.map(f).into_value_stream(),
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
|
Value::Range { val, .. } => Value::Stream {
|
||||||
|
stream: val.into_iter().map(f).into_value_stream(),
|
||||||
|
span,
|
||||||
|
},
|
||||||
v => {
|
v => {
|
||||||
if v.as_string().is_ok() {
|
if v.as_string().is_ok() {
|
||||||
Value::List {
|
Value::List {
|
||||||
|
@ -413,6 +417,10 @@ impl Value {
|
||||||
stream: stream.map(f).flatten().into_value_stream(),
|
stream: stream.map(f).flatten().into_value_stream(),
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
|
Value::Range { val, .. } => Value::Stream {
|
||||||
|
stream: val.into_iter().map(f).flatten().into_value_stream(),
|
||||||
|
span,
|
||||||
|
},
|
||||||
v => {
|
v => {
|
||||||
if v.as_string().is_ok() {
|
if v.as_string().is_ok() {
|
||||||
Value::List {
|
Value::List {
|
||||||
|
@ -482,8 +490,42 @@ impl PartialEq for Value {
|
||||||
stream: stream_rhs, ..
|
stream: stream_rhs, ..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
let vals_lhs = stream_lhs.clone().collect_string();
|
let vals_lhs: Vec<Value> = stream_lhs.clone().collect();
|
||||||
let vals_rhs = stream_rhs.clone().collect_string();
|
let vals_rhs: Vec<Value> = stream_rhs.clone().collect();
|
||||||
|
|
||||||
|
vals_lhs == vals_rhs
|
||||||
|
}
|
||||||
|
// Note: This may look a bit strange, but a Stream is still just a List,
|
||||||
|
// it just happens to be in an iterator form instead of a concrete form. If the contained
|
||||||
|
// values are the same then it should be treated as equal
|
||||||
|
(
|
||||||
|
Value::Stream {
|
||||||
|
stream: stream_lhs, ..
|
||||||
|
},
|
||||||
|
Value::List {
|
||||||
|
vals: stream_rhs, ..
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
let vals_lhs: Vec<Value> = stream_lhs.clone().collect();
|
||||||
|
let vals_rhs: Vec<Value> =
|
||||||
|
stream_rhs.clone().into_iter().into_value_stream().collect();
|
||||||
|
|
||||||
|
vals_lhs == vals_rhs
|
||||||
|
}
|
||||||
|
// Note: This may look a bit strange, but a Stream is still just a List,
|
||||||
|
// it just happens to be in an iterator form instead of a concrete form. If the contained
|
||||||
|
// values are the same then it should be treated as equal
|
||||||
|
(
|
||||||
|
Value::List {
|
||||||
|
vals: stream_lhs, ..
|
||||||
|
},
|
||||||
|
Value::Stream {
|
||||||
|
stream: stream_rhs, ..
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
let vals_lhs: Vec<Value> =
|
||||||
|
stream_lhs.clone().into_iter().into_value_stream().collect();
|
||||||
|
let vals_rhs: Vec<Value> = stream_rhs.clone().collect();
|
||||||
|
|
||||||
vals_lhs == vals_rhs
|
vals_lhs == vals_rhs
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue