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
132
133
134
135
136
137
138
139
use crate::prelude::*;
use nu_engine::evaluate_baseline_expr;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{
hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue,
};
pub struct Command;
struct AllArgs {
predicate: CapturedBlock,
}
impl WholeStreamCommand for Command {
fn name(&self) -> &str {
"all?"
}
fn signature(&self) -> Signature {
Signature::build("all?").required(
"condition",
SyntaxShape::RowCondition,
"the condition that must match",
)
}
fn usage(&self) -> &str {
"Find if the table rows matches the condition."
}
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
all(args)
}
fn examples(&self) -> Vec<Example> {
use nu_protocol::Value;
vec![
Example {
description: "Find if services are running",
example: "echo [[status]; [UP] [UP]] | all? status == UP",
result: Some(vec![Value::from(true)]),
},
Example {
description: "Check that all values are even",
example: "echo [2 4 6 8] | all? ($it mod 2) == 0",
result: Some(vec![Value::from(true)]),
},
]
}
}
fn all(args: CommandArgs) -> Result<OutputStream, ShellError> {
let ctx = &args.context;
let tag = args.call_info.name_tag.clone();
let all_args = AllArgs {
predicate: args.req(0)?,
};
let err = Err(ShellError::labeled_error(
"Expected a condition",
"expected a condition",
args.call_info.name_tag.clone(),
));
let condition = {
if all_args.predicate.block.block.len() != 1 {
return err;
}
match all_args.predicate.block.block[0].pipelines.get(0) {
Some(item) => match item.list.get(0) {
Some(ClassifiedCommand::Expr(expr)) => expr.clone(),
_ => {
return err;
}
},
None => {
return err;
}
}
};
let scope = args.scope().clone();
let init = Ok(InputStream::one(
UntaggedValue::boolean(true).into_value(&tag),
));
scope.enter_scope();
scope.add_vars(&all_args.predicate.captured.entries);
let result = args.input.fold(init, move |acc, row| {
let condition = condition.clone();
let ctx = ctx.clone();
if let Some(positional) = all_args.predicate.block.params.positional.get(0) {
ctx.scope.add_var(positional.0.name(), row);
} else {
ctx.scope.add_var("$it", row);
}
let condition = evaluate_baseline_expr(&condition, &ctx);
let curr = acc?.drain_vec();
let curr = curr
.get(0)
.ok_or_else(|| ShellError::unexpected("No value to check with"))?;
let cond = curr.as_bool()?;
match condition {
Ok(condition) => match condition.as_bool() {
Ok(b) => Ok(InputStream::one(
UntaggedValue::boolean(cond && b).into_value(&curr.tag),
)),
Err(e) => Err(e),
},
Err(e) => Err(e),
}
});
scope.exit_scope();
Ok(result?.into_output_stream())
}
#[cfg(test)]
mod tests {
use super::Command;
use super::ShellError;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;
test_examples(Command {})
}
}