nu_command/filters/
every.rs

1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct Every;
5
6impl Command for Every {
7    fn name(&self) -> &str {
8        "every"
9    }
10
11    fn signature(&self) -> Signature {
12        Signature::build("every")
13            .input_output_types(vec![(
14                Type::List(Box::new(Type::Any)),
15                Type::List(Box::new(Type::Any)),
16            )])
17            .required(
18                "stride",
19                SyntaxShape::Int,
20                "How many rows to skip between (and including) each row returned.",
21            )
22            .switch(
23                "skip",
24                "skip the rows that would be returned, instead of selecting them",
25                Some('s'),
26            )
27            .category(Category::Filters)
28    }
29
30    fn description(&self) -> &str {
31        "Show (or skip) every n-th row, starting from the first one."
32    }
33
34    fn examples(&self) -> Vec<Example<'_>> {
35        vec![
36            Example {
37                example: "[1 2 3 4 5] | every 2",
38                description: "Get every second row",
39                result: Some(Value::list(
40                    vec![Value::test_int(1), Value::test_int(3), Value::test_int(5)],
41                    Span::test_data(),
42                )),
43            },
44            Example {
45                example: "[1 2 3 4 5] | every 2 --skip",
46                description: "Skip every second row",
47                result: Some(Value::list(
48                    vec![Value::test_int(2), Value::test_int(4)],
49                    Span::test_data(),
50                )),
51            },
52        ]
53    }
54
55    fn run(
56        &self,
57        engine_state: &EngineState,
58        stack: &mut Stack,
59        call: &Call,
60        input: PipelineData,
61    ) -> Result<PipelineData, ShellError> {
62        let stride = match call.req::<usize>(engine_state, stack, 0)? {
63            0 => 1,
64            stride => stride,
65        };
66
67        let skip = call.has_flag(engine_state, stack, "skip")?;
68
69        let metadata = input.metadata();
70
71        Ok(input
72            .into_iter()
73            .enumerate()
74            .filter_map(move |(i, value)| {
75                if (i % stride != 0) == skip {
76                    Some(value)
77                } else {
78                    None
79                }
80            })
81            .into_pipeline_data_with_metadata(call.head, engine_state.signals().clone(), metadata))
82    }
83}
84
85#[cfg(test)]
86mod test {
87    use super::*;
88
89    #[test]
90    fn test_examples() {
91        use crate::test_examples;
92
93        test_examples(Every {})
94    }
95}