1use crate::math::{
2 reducers::{Reduce, reducer_for},
3 utils::{run_with_function_with_cell_paths, run_with_function_with_cell_paths_const},
4};
5use nu_engine::command_prelude::*;
6
7#[derive(Clone)]
8pub struct MathMin;
9
10impl Command for MathMin {
11 fn name(&self) -> &str {
12 "math min"
13 }
14
15 fn signature(&self) -> Signature {
16 Signature::build("math min")
17 .input_output_types(vec![
18 (Type::List(Box::new(Type::Number)), Type::Number),
19 (Type::List(Box::new(Type::Duration)), Type::Duration),
20 (Type::List(Box::new(Type::Filesize)), Type::Filesize),
21 (Type::List(Box::new(Type::Any)), Type::Any),
22 (Type::Range, Type::Number),
23 (Type::table(), Type::record()),
24 (Type::record(), Type::record()),
25 ])
26 .allow_variants_without_examples(true)
27 .rest(
28 "columns",
29 SyntaxShape::CellPath,
30 "The cell-paths/columns to operate on.",
31 )
32 .category(Category::Math)
33 }
34
35 fn description(&self) -> &str {
36 "Finds the minimum within a list of values or tables."
37 }
38
39 fn search_terms(&self) -> Vec<&str> {
40 vec!["minimum", "smallest"]
41 }
42
43 fn is_const(&self) -> bool {
44 true
45 }
46
47 fn run(
48 &self,
49 engine_state: &EngineState,
50 stack: &mut Stack,
51 call: &Call,
52 input: PipelineData,
53 ) -> Result<PipelineData, ShellError> {
54 run_with_function_with_cell_paths(engine_state, stack, call, input, minimum)
55 }
56
57 fn run_const(
58 &self,
59 working_set: &StateWorkingSet,
60 call: &Call,
61 input: PipelineData,
62 ) -> Result<PipelineData, ShellError> {
63 run_with_function_with_cell_paths_const(working_set, call, input, minimum)
64 }
65
66 fn examples(&self) -> Vec<Example<'_>> {
67 vec![
68 Example {
69 description: "Compute the minimum of a list of numbers.",
70 example: "[-50 100 25] | math min",
71 result: Some(Value::test_int(-50)),
72 },
73 Example {
74 description: "Compute the minima of the columns of a table.",
75 example: "[{a: 1 b: 3} {a: 2 b: -1}] | math min",
76 result: Some(Value::test_record(record! {
77 "a" => Value::test_int(1),
78 "b" => Value::test_int(-1),
79 })),
80 },
81 Example {
82 description: "Find the minimum of a list of arbitrary values (Warning: Weird).",
83 example: "[-50 'hello' true] | math min",
84 result: Some(Value::test_bool(true)),
85 },
86 Example {
87 description: "Compute the minimum of list-valued columns in a record.",
88 example: "{alice: [5 3 9], bob: [2 7]} | math min",
89 result: Some(Value::test_record(record! {
90 "alice" => Value::test_int(3),
91 "bob" => Value::test_int(2),
92 })),
93 },
94 Example {
95 description: "Compute the minimum of a single column using a cell path.",
96 example: "{alice: [5 3 9], bob: [2 7]} | math min alice",
97 result: Some(Value::test_record(record! {
98 "alice" => Value::test_int(3),
99 "bob" => Value::list(
100 vec![Value::test_int(2), Value::test_int(7)],
101 Span::test_data(),
102 ),
103 })),
104 },
105 ]
106 }
107}
108
109pub fn minimum(values: &[Value], span: Span, head: Span) -> Result<Value, ShellError> {
110 let min_func = reducer_for(Reduce::Minimum);
111 min_func(Value::nothing(head), values.to_vec(), span, head)
112}
113
114#[cfg(test)]
115mod test {
116 use super::*;
117
118 #[test]
119 fn test_examples() -> nu_test_support::Result {
120 nu_test_support::test().examples(MathMin)
121 }
122}