nu_command/formats/from/
nuon.rs

1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct FromNuon;
5
6impl Command for FromNuon {
7    fn name(&self) -> &str {
8        "from nuon"
9    }
10
11    fn description(&self) -> &str {
12        "Convert from nuon to structured data."
13    }
14
15    fn signature(&self) -> nu_protocol::Signature {
16        Signature::build("from nuon")
17            .input_output_types(vec![(Type::String, Type::Any)])
18            .category(Category::Formats)
19    }
20
21    fn examples(&self) -> Vec<Example<'_>> {
22        vec![
23            Example {
24                example: "'{ a:1 }' | from nuon",
25                description: "Converts nuon formatted string to table",
26                result: Some(Value::test_record(record! {
27                    "a" => Value::test_int(1),
28                })),
29            },
30            Example {
31                example: "'{ a:1, b: [1, 2] }' | from nuon",
32                description: "Converts nuon formatted string to table",
33                result: Some(Value::test_record(record! {
34                    "a" => Value::test_int(1),
35                    "b" => Value::test_list(vec![Value::test_int(1), Value::test_int(2)]),
36                })),
37            },
38            Example {
39                example: "'{a:1,b:[1,2]}' | from nuon",
40                description: "Converts raw nuon formatted string to table",
41                result: Some(Value::test_record(record! {
42                    "a" => Value::test_int(1),
43                    "b" => Value::test_list(vec![Value::test_int(1), Value::test_int(2)]),
44                })),
45            },
46        ]
47    }
48
49    fn run(
50        &self,
51        _engine_state: &EngineState,
52        _stack: &mut Stack,
53        call: &Call,
54        input: PipelineData,
55    ) -> Result<PipelineData, ShellError> {
56        let head = call.head;
57        let (string_input, _span, metadata) = input.collect_string_strict(head)?;
58
59        match nuon::from_nuon(&string_input, Some(head)) {
60            Ok(result) => Ok(result
61                .into_pipeline_data_with_metadata(metadata.map(|md| md.with_content_type(None)))),
62            Err(err) => Err(ShellError::GenericError {
63                error: "error when loading nuon text".into(),
64                msg: "could not load nuon text".into(),
65                span: Some(head),
66                help: None,
67                inner: vec![err],
68            }),
69        }
70    }
71}
72
73#[cfg(test)]
74mod test {
75    use nu_cmd_lang::eval_pipeline_without_terminal_expression;
76
77    use crate::Reject;
78    use crate::{Metadata, MetadataSet};
79
80    use super::*;
81
82    #[test]
83    fn test_examples() {
84        use crate::test_examples;
85
86        test_examples(FromNuon {})
87    }
88
89    #[test]
90    fn test_content_type_metadata() {
91        let mut engine_state = Box::new(EngineState::new());
92        let delta = {
93            let mut working_set = StateWorkingSet::new(&engine_state);
94
95            working_set.add_decl(Box::new(FromNuon {}));
96            working_set.add_decl(Box::new(Metadata {}));
97            working_set.add_decl(Box::new(MetadataSet {}));
98            working_set.add_decl(Box::new(Reject {}));
99
100            working_set.render()
101        };
102
103        engine_state
104            .merge_delta(delta)
105            .expect("Error merging delta");
106
107        let cmd = r#"'[[a, b]; [1, 2]]' | metadata set --content-type 'application/x-nuon' --datasource-ls | from nuon | metadata | reject span | $in"#;
108        let result = eval_pipeline_without_terminal_expression(
109            cmd,
110            std::env::temp_dir().as_ref(),
111            &mut engine_state,
112        );
113        assert_eq!(
114            Value::test_record(record!("source" => Value::test_string("ls"))),
115            result.expect("There should be a result")
116        )
117    }
118}