nu_command/env/
load_env.rs

1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct LoadEnv;
5
6impl Command for LoadEnv {
7    fn name(&self) -> &str {
8        "load-env"
9    }
10
11    fn description(&self) -> &str {
12        "Loads an environment update from a record."
13    }
14
15    fn signature(&self) -> nu_protocol::Signature {
16        Signature::build("load-env")
17            .input_output_types(vec![
18                (Type::record(), Type::Nothing),
19                (Type::Nothing, Type::Nothing),
20                // FIXME Type::Any input added to disable pipeline input type checking, as run-time checks can raise undesirable type errors
21                // which aren't caught by the parser. see https://github.com/nushell/nushell/pull/14922 for more details
22                (Type::Any, Type::Nothing),
23            ])
24            .allow_variants_without_examples(true)
25            .optional(
26                "update",
27                SyntaxShape::Record(vec![]),
28                "The record to use for updates.",
29            )
30            .category(Category::FileSystem)
31    }
32
33    fn run(
34        &self,
35        engine_state: &EngineState,
36        stack: &mut Stack,
37        call: &Call,
38        input: PipelineData,
39    ) -> Result<PipelineData, ShellError> {
40        let arg: Option<Record> = call.opt(engine_state, stack, 0)?;
41        let span = call.head;
42
43        let record = match arg {
44            Some(record) => record,
45            None => match input {
46                PipelineData::Value(Value::Record { val, .. }, ..) => val.into_owned(),
47                _ => {
48                    return Err(ShellError::UnsupportedInput {
49                        msg: "'load-env' expects a single record".into(),
50                        input: "value originated from here".into(),
51                        msg_span: span,
52                        input_span: input.span().unwrap_or(span),
53                    });
54                }
55            },
56        };
57
58        for prohibited in ["FILE_PWD", "CURRENT_FILE", "PWD"] {
59            if record.contains(prohibited) {
60                return Err(ShellError::AutomaticEnvVarSetManually {
61                    envvar_name: prohibited.to_string(),
62                    span: call.head,
63                });
64            }
65        }
66
67        for (env_var, rhs) in record {
68            stack.add_env_var(env_var, rhs);
69        }
70        Ok(PipelineData::empty())
71    }
72
73    fn examples(&self) -> Vec<Example> {
74        vec![
75            Example {
76                description: "Load variables from an input stream",
77                example: r#"{NAME: ABE, AGE: UNKNOWN} | load-env; $env.NAME"#,
78                result: Some(Value::test_string("ABE")),
79            },
80            Example {
81                description: "Load variables from an argument",
82                example: r#"load-env {NAME: ABE, AGE: UNKNOWN}; $env.NAME"#,
83                result: Some(Value::test_string("ABE")),
84            },
85        ]
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::LoadEnv;
92
93    #[test]
94    fn examples_work_as_expected() {
95        use crate::test_examples;
96
97        test_examples(LoadEnv {})
98    }
99}