Skip to main content

nu_command/math/
min.rs

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}