1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use nu_engine::{eval_block, CallExt};
use nu_protocol::{
ast::Call,
engine::{Closure, Command, EngineState, Stack},
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
Value,
};
#[derive(Clone)]
pub struct All;
impl Command for All {
fn name(&self) -> &str {
"all"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![
(Type::List(Box::new(Type::Any)), Type::Bool),
(Type::Table(vec![]), Type::Bool),
])
.required(
"predicate",
SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])),
"a closure that must evaluate to a boolean",
)
.category(Category::Filters)
}
fn usage(&self) -> &str {
"Test if every element of the input fulfills a predicate expression."
}
fn search_terms(&self) -> Vec<&str> {
vec!["every", "and"]
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Check if each row's status is the string 'UP'",
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] | enumerate | all {|i| $i.item == $i.index * 2 }",
result: Some(Value::test_bool(true)),
},
Example {
description: "Check that all of the values are even, using a stored closure",
example: "let cond = {|el| ($el mod 2) == 0 }; [2 4 6 8] | all $cond",
result: Some(Value::test_bool(true)),
},
]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let span = call.head;
let capture_block: Closure = call.req(engine_state, stack, 0)?;
let block_id = capture_block.block_id;
let block = engine_state.get_block(block_id);
let var_id = block.signature.get_positional(0).and_then(|arg| arg.var_id);
let mut stack = stack.captures_to_stack(&capture_block.captures);
let orig_env_vars = stack.env_vars.clone();
let orig_env_hidden = stack.env_hidden.clone();
let ctrlc = engine_state.ctrlc.clone();
let engine_state = engine_state.clone();
for value in input.into_interruptible_iter(ctrlc) {
stack.with_env(&orig_env_vars, &orig_env_hidden);
if let Some(var_id) = var_id {
stack.add_var(var_id, value.clone());
}
let eval = eval_block(
&engine_state,
&mut stack,
block,
value.into_pipeline_data(),
call.redirect_stdout,
call.redirect_stderr,
);
match eval {
Err(e) => {
return Err(e);
}
Ok(pipeline_data) => {
if !pipeline_data.into_value(span).is_true() {
return Ok(Value::Bool { val: false, span }.into_pipeline_data());
}
}
}
}
Ok(Value::Bool { val: true, span }.into_pipeline_data())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(All)
}
}