Skip to main content

nu_command/filters/
append.rs

1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct Append;
5
6impl Command for Append {
7    fn name(&self) -> &str {
8        "append"
9    }
10
11    fn signature(&self) -> nu_protocol::Signature {
12        Signature::build("append")
13            .input_output_types(vec![(Type::Any, Type::List(Box::new(Type::Any)))])
14            .required(
15                "row",
16                SyntaxShape::Any,
17                "The row, list, or table to append.",
18            )
19            .rest("rest", SyntaxShape::Any, "Additional values to append.")
20            .allow_variants_without_examples(true)
21            .category(Category::Filters)
22    }
23
24    fn description(&self) -> &str {
25        "Append any number of rows to a table."
26    }
27
28    fn extra_description(&self) -> &str {
29        "Be aware that this command 'unwraps' lists passed to it. So, if you pass a variable to it,
30and you want the variable's contents to be appended without being unwrapped, it's wise to
31pre-emptively wrap the variable in a list, like so: `append [$val]`. This way, `append` will
32only unwrap the outer list, and leave the variable's contents untouched."
33    }
34
35    fn search_terms(&self) -> Vec<&str> {
36        vec!["add", "concatenate", "push"]
37    }
38
39    fn examples(&self) -> Vec<Example<'_>> {
40        vec![
41            Example {
42                example: "[0 1 2 3] | append 4",
43                description: "Append one int to a list.",
44                result: Some(Value::test_list(vec![
45                    Value::test_int(0),
46                    Value::test_int(1),
47                    Value::test_int(2),
48                    Value::test_int(3),
49                    Value::test_int(4),
50                ])),
51            },
52            Example {
53                example: "0 | append [1 2 3]",
54                description: "Append a list to an item.",
55                result: Some(Value::test_list(vec![
56                    Value::test_int(0),
57                    Value::test_int(1),
58                    Value::test_int(2),
59                    Value::test_int(3),
60                ])),
61            },
62            Example {
63                example: r#""a" | append ["b"] "#,
64                description: "Append a list of string to a string.",
65                result: Some(Value::test_list(vec![
66                    Value::test_string("a"),
67                    Value::test_string("b"),
68                ])),
69            },
70            Example {
71                example: "[0 1] | append [2 nu 4 shell]",
72                description: "Append ints and strings.",
73                result: Some(Value::test_list(vec![
74                    Value::test_int(0),
75                    Value::test_int(1),
76                    Value::test_int(2),
77                    Value::test_string("nu"),
78                    Value::test_int(4),
79                    Value::test_string("shell"),
80                ])),
81            },
82            Example {
83                example: "[0 1] | append 2..4",
84                description: "Append a range of ints to a list.",
85                result: Some(Value::test_list(vec![
86                    Value::test_int(0),
87                    Value::test_int(1),
88                    Value::test_int(2),
89                    Value::test_int(3),
90                    Value::test_int(4),
91                ])),
92            },
93            Example {
94                example: "[0] | append [1 2] [3] [] 4",
95                description: "Append multiple lists and values.",
96                result: Some(Value::test_list(vec![
97                    Value::test_int(0),
98                    Value::test_int(1),
99                    Value::test_int(2),
100                    Value::test_int(3),
101                    Value::test_int(4),
102                ])),
103            },
104        ]
105    }
106
107    fn run(
108        &self,
109        engine_state: &EngineState,
110        stack: &mut Stack,
111        call: &Call,
112        mut input: PipelineData,
113    ) -> Result<PipelineData, ShellError> {
114        let other: Value = call.req(engine_state, stack, 0)?;
115        let rest: Vec<Value> = call.rest(engine_state, stack, 1)?;
116        let metadata = input.take_metadata();
117
118        Ok(input
119            .into_iter()
120            .chain(other.into_pipeline_data())
121            .chain(
122                rest.into_iter()
123                    .flat_map(|value| value.into_pipeline_data()),
124            )
125            .into_pipeline_data_with_metadata(call.head, engine_state.signals().clone(), metadata))
126    }
127}
128
129#[cfg(test)]
130mod test {
131    use super::*;
132
133    #[test]
134    fn test_examples() -> nu_test_support::Result {
135        nu_test_support::test().examples(Append)
136    }
137}