diff --git a/crates/nu-command/src/env/with_env.rs b/crates/nu-command/src/env/with_env.rs index c9c7ae5648..2ad0c877e2 100644 --- a/crates/nu-command/src/env/with_env.rs +++ b/crates/nu-command/src/env/with_env.rs @@ -48,22 +48,22 @@ impl Command for WithEnv { vec![ Example { description: "Set the MYENV environment variable", - example: r#"with-env [MYENV "my env value"] { $nu.env.MYENV }"#, + example: r#"with-env [MYENV "my env value"] { $env.MYENV }"#, result: Some(Value::test_string("my env value")), }, Example { description: "Set by primitive value list", - example: r#"with-env [X Y W Z] { $nu.env.X }"#, + example: r#"with-env [X Y W Z] { $env.X }"#, result: Some(Value::test_string("Y")), }, Example { description: "Set by single row table", - example: r#"with-env [[X W]; [Y Z]] { $nu.env.W }"#, + example: r#"with-env [[X W]; [Y Z]] { $env.W }"#, result: Some(Value::test_string("Z")), }, Example { description: "Set by row(e.g. `open x.json` or `from json`)", - example: r#"echo '{"X":"Y","W":"Z"}'|from json|with-env $it { echo $nu.env.X $nu.env.W }"#, + example: r#"echo '{"X":"Y","W":"Z"}'|from json|with-env $it { echo $env.X $env.W }"#, result: None, }, ] diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 322f3b1156..3256313986 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -5,7 +5,7 @@ use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; use nu_protocol::engine::{EngineState, Stack}; use nu_protocol::{ IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Range, ShellError, Span, - Spanned, Type, Unit, Value, VarId, + Spanned, Type, Unit, Value, VarId, ENV_VARIABLE_ID, }; use crate::get_full_help; @@ -530,26 +530,6 @@ pub fn eval_variable( let mut output_cols = vec![]; let mut output_vals = vec![]; - let env_vars = stack.get_env_vars(); - let env_columns = env_vars.keys(); - let env_values = env_vars.values(); - - let mut pairs = env_columns - .map(|x| x.to_string()) - .zip(env_values.cloned()) - .collect::>(); - - pairs.sort_by(|a, b| a.0.cmp(&b.0)); - - let (env_columns, env_values) = pairs.into_iter().unzip(); - - output_cols.push("env".into()); - output_vals.push(Value::Record { - cols: env_columns, - vals: env_values, - span, - }); - if let Some(mut config_path) = nu_path::config_dir() { config_path.push("nushell"); @@ -905,6 +885,25 @@ pub fn eval_variable( vals: output_vals, span, }) + } else if var_id == ENV_VARIABLE_ID { + let env_vars = stack.get_env_vars(); + let env_columns = env_vars.keys(); + let env_values = env_vars.values(); + + let mut pairs = env_columns + .map(|x| x.to_string()) + .zip(env_values.cloned()) + .collect::>(); + + pairs.sort_by(|a, b| a.0.cmp(&b.0)); + + let (env_columns, env_values) = pairs.into_iter().unzip(); + + Ok(Value::Record { + cols: env_columns, + vals: env_values, + span, + }) } else { stack .get_var(var_id) diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index c7edf474be..5b3843f9d1 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -495,10 +495,10 @@ pub fn parse_module_block( // TODO: Exported env vars are usable iside the module only if correctly // exported by the user. For example: // - // > module foo { export env a { "2" }; export def b [] { $nu.env.a } } + // > module foo { export env a { "2" }; export def b [] { $env.a } } // // will work only if you call `use foo *; b` but not with `use foo; foo b` - // since in the second case, the name of the env var would be $nu.env."foo a". + // since in the second case, the name of the env var would be $env."foo a". b"export" => { let (stmt, exportable, err) = parse_export(working_set, &pipeline.commands[0].parts); diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index aa5ae7974c..9095a990c7 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1331,6 +1331,16 @@ pub fn parse_variable_expr( }, None, ); + } else if contents == b"$env" { + return ( + Expression { + expr: Expr::Var(nu_protocol::ENV_VARIABLE_ID), + span, + ty: Type::Unknown, + custom_completion: None, + }, + None, + ); } let (id, err) = parse_variable(working_set, span); diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 9bbde51bea..347ea0b2a0 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -148,13 +148,20 @@ pub const NU_VARIABLE_ID: usize = 0; pub const SCOPE_VARIABLE_ID: usize = 1; pub const IN_VARIABLE_ID: usize = 2; pub const CONFIG_VARIABLE_ID: usize = 3; +pub const ENV_VARIABLE_ID: usize = 4; impl EngineState { pub fn new() -> Self { Self { files: im::vector![], file_contents: im::vector![], - vars: im::vector![Type::Unknown, Type::Unknown, Type::Unknown, Type::Unknown], + vars: im::vector![ + Type::Unknown, + Type::Unknown, + Type::Unknown, + Type::Unknown, + Type::Unknown + ], decls: im::vector![], blocks: im::vector![], overlays: im::vector![], diff --git a/crates/nu-protocol/src/lib.rs b/crates/nu-protocol/src/lib.rs index 2e667f10c5..60e45b2bb5 100644 --- a/crates/nu-protocol/src/lib.rs +++ b/crates/nu-protocol/src/lib.rs @@ -15,7 +15,9 @@ mod value; pub use value::Value; pub use config::*; -pub use engine::{CONFIG_VARIABLE_ID, IN_VARIABLE_ID, NU_VARIABLE_ID, SCOPE_VARIABLE_ID}; +pub use engine::{ + CONFIG_VARIABLE_ID, ENV_VARIABLE_ID, IN_VARIABLE_ID, NU_VARIABLE_ID, SCOPE_VARIABLE_ID, +}; pub use example::*; pub use exportable::*; pub use id::*; diff --git a/docs/Environment_Variables.md b/docs/Environment_Variables.md index 6027ea2547..8fb34879e9 100644 --- a/docs/Environment_Variables.md +++ b/docs/Environment_Variables.md @@ -39,7 +39,7 @@ You can test the conversions by manually calling them: ``` > let-env FOO = "a:b:c" -> let list = (do $config.env_conversions.from_string $nu.env.FOO) +> let list = (do $config.env_conversions.from_string $env.FOO) > $list ╭───┬───╮ @@ -58,7 +58,7 @@ To verify the conversion works on startup, you can first set up `FOO`, then laun > nu ->> $nu.env.FOO +>> $env.FOO ╭───┬───╮ │ 0 │ a │ │ 1 │ b │ @@ -94,8 +94,8 @@ Out of the box, Nushell ships with several environment variables serving a speci ## Breaking Changes -* Setting environment variable to `$nothing` will no longer remove it -- it will be `$nothing`. Instead, you can use `hide $nu.env.FOO`. -* `$nu.env.PROMPT_COMMAND` is a block instead of a string containing the source of the command to run. You can put this into your `config.nu`, for example: `let-env PROMPT_COMMAND = { echo "foo" }`. +* Setting environment variable to `$nothing` will no longer remove it -- it will be `$nothing`. Instead, you can use `hide $env.FOO`. +* `$env.PROMPT_COMMAND` is a block instead of a string containing the source of the command to run. You can put this into your `config.nu`, for example: `let-env PROMPT_COMMAND = { echo "foo" }`. ## Future Directions diff --git a/docs/Modules_and_Overlays.md b/docs/Modules_and_Overlays.md index 781b06762e..930d86fa9a 100644 --- a/docs/Modules_and_Overlays.md +++ b/docs/Modules_and_Overlays.md @@ -163,10 +163,10 @@ export def hello [name: string] { ``` > use greetings.nu -> $nu.env."greetings MYNAME" +> $env."greetings MYNAME" Arthur, King of the Britons -> greetings hello $nu.env."greetings MYNAME" +> greetings hello $env."greetings MYNAME" hello Arthur, King of the Britons! ``` @@ -178,18 +178,18 @@ We can demonstrate this property for example with the `random` command: > use roll ROLL -> $nu.env.ROLL +> $env.ROLL 4 -> $nu.env.ROLL +> $env.ROLL 4 > use roll ROLL -> $nu.env.ROLL +> $env.ROLL 6 -> $nu.env.ROLL +> $env.ROLL 6 ``` @@ -227,18 +227,18 @@ Let's try environment variables: ``` > let-env FOO = "FOO" -> $nu.env.FOO +> $env.FOO FOO > hide FOO -> $nu.env.FOO # error! environment variable not found! +> $env.FOO # error! environment variable not found! ``` The first case also applies to commands / environment variables brought from a module (using the "greetings.nu" file defined above): ``` > use greetings.nu * -> $nu.env.MYNAME +> $env.MYNAME Arthur, King of the Britons > hello "world" @@ -246,7 +246,7 @@ hello world! > hide MYNAME -> $nu.env.MYNAME # error! environment variable not found! +> $env.MYNAME # error! environment variable not found! > hide hello @@ -256,7 +256,7 @@ And finally, when the name is the module name (assuming the previous `greetings` ``` > use greetings.nu -> $nu.env."greetings MYNAME" +> $env."greetings MYNAME" Arthur, King of the Britons > greetings hello "world" @@ -264,7 +264,7 @@ hello world! > hide greetings -> $nu.env."greetings MYNAME" # error! environment variable not found! +> $env."greetings MYNAME" # error! environment variable not found! > greetings hello "world" # error! command not found! ``` @@ -275,7 +275,7 @@ To demonstrate the other cases (again, assuming the same `greetings` module): > hide greetings hello -> $nu.env."greetings MYNAME" +> $env."greetings MYNAME" Arthur, King of the Britons > greetings hello "world" # error! command not found! @@ -285,7 +285,7 @@ Arthur, King of the Britons > hide greetings [ hello MYNAME ] -> $nu.env."greetings MYNAME" # error! environment variable not found! +> $env."greetings MYNAME" # error! environment variable not found! > greetings hello "world" # error! command not found! ``` @@ -294,7 +294,7 @@ Arthur, King of the Britons > hide greetings * -> $nu.env."greetings MYNAME" # error! environment variable not found! +> $env."greetings MYNAME" # error! environment variable not found! > greetings hello "world" # error! command not found! ``` diff --git a/src/tests/test_env.rs b/src/tests/test_env.rs index 050cd40da8..5604ee7e99 100644 --- a/src/tests/test_env.rs +++ b/src/tests/test_env.rs @@ -2,15 +2,15 @@ use crate::tests::{run_test, TestResult}; #[test] fn shorthand_env_1() -> TestResult { - run_test(r#"FOO=BAZ $nu.env.FOO"#, "BAZ") + run_test(r#"FOO=BAZ $env.FOO"#, "BAZ") } #[test] fn shorthand_env_2() -> TestResult { - run_test(r#"FOO=BAZ FOO=MOO $nu.env.FOO"#, "MOO") + run_test(r#"FOO=BAZ FOO=MOO $env.FOO"#, "MOO") } #[test] fn shorthand_env_3() -> TestResult { - run_test(r#"FOO=BAZ BAR=MOO $nu.env.FOO"#, "BAZ") + run_test(r#"FOO=BAZ BAR=MOO $env.FOO"#, "BAZ") } diff --git a/src/tests/test_hiding.rs b/src/tests/test_hiding.rs index 544a5fe93b..028d1a65ef 100644 --- a/src/tests/test_hiding.rs +++ b/src/tests/test_hiding.rs @@ -8,10 +8,7 @@ fn hides_def() -> TestResult { #[test] fn hides_env() -> TestResult { - fail_test( - r#"let-env foo = "foo"; hide foo; $nu.env.foo"#, - "did you mean", - ) + fail_test(r#"let-env foo = "foo"; hide foo; $env.foo"#, "did you mean") } #[test] @@ -27,7 +24,7 @@ fn hides_def_then_redefines() -> TestResult { #[test] fn hides_env_then_redefines() -> TestResult { run_test( - r#"let-env foo = "foo"; hide foo; let-env foo = "bar"; $nu.env.foo"#, + r#"let-env foo = "foo"; hide foo; let-env foo = "bar"; $env.foo"#, "bar", ) } @@ -67,7 +64,7 @@ fn hides_def_in_scope_4() -> TestResult { #[test] fn hides_env_in_scope_1() -> TestResult { fail_test( - r#"let-env foo = "foo"; do { hide foo; $nu.env.foo }"#, + r#"let-env foo = "foo"; do { hide foo; $env.foo }"#, "did you mean", ) } @@ -75,7 +72,7 @@ fn hides_env_in_scope_1() -> TestResult { #[test] fn hides_env_in_scope_2() -> TestResult { run_test( - r#"let-env foo = "foo"; do { let-env foo = "bar"; hide foo; $nu.env.foo }"#, + r#"let-env foo = "foo"; do { let-env foo = "bar"; hide foo; $env.foo }"#, "foo", ) } @@ -83,7 +80,7 @@ fn hides_env_in_scope_2() -> TestResult { #[test] fn hides_env_in_scope_3() -> TestResult { fail_test( - r#"let-env foo = "foo"; do { hide foo; let-env foo = "bar"; hide foo; $nu.env.foo }"#, + r#"let-env foo = "foo"; do { hide foo; let-env foo = "bar"; hide foo; $env.foo }"#, "did you mean", ) } @@ -91,7 +88,7 @@ fn hides_env_in_scope_3() -> TestResult { #[test] fn hides_env_in_scope_4() -> TestResult { fail_test( - r#"let-env foo = "foo"; do { let-env foo = "bar"; hide foo; hide foo; $nu.env.foo }"#, + r#"let-env foo = "foo"; do { let-env foo = "bar"; hide foo; hide foo; $env.foo }"#, "did you mean", ) } @@ -112,7 +109,7 @@ fn hide_env_twice_not_allowed() -> TestResult { #[test] fn hides_def_runs_env_1() -> TestResult { run_test( - r#"let-env foo = "bar"; def foo [] { "foo" }; hide foo; $nu.env.foo"#, + r#"let-env foo = "bar"; def foo [] { "foo" }; hide foo; $env.foo"#, "bar", ) } @@ -120,7 +117,7 @@ fn hides_def_runs_env_1() -> TestResult { #[test] fn hides_def_runs_env_2() -> TestResult { run_test( - r#"def foo [] { "foo" }; let-env foo = "bar"; hide foo; $nu.env.foo"#, + r#"def foo [] { "foo" }; let-env foo = "bar"; hide foo; $env.foo"#, "bar", ) } @@ -128,7 +125,7 @@ fn hides_def_runs_env_2() -> TestResult { #[test] fn hides_def_and_env() -> TestResult { fail_test( - r#"let-env foo = "bar"; def foo [] { "foo" }; hide foo; hide foo; $nu.env.foo"#, + r#"let-env foo = "bar"; def foo [] { "foo" }; hide foo; hide foo; $env.foo"#, "did you mean", ) } @@ -184,7 +181,7 @@ fn hides_def_import_6() -> TestResult { #[test] fn hides_env_import_1() -> TestResult { fail_test( - r#"module spam { export env foo { "foo" } }; use spam; hide spam foo; $nu.env.'spam foo'"#, + r#"module spam { export env foo { "foo" } }; use spam; hide spam foo; $env.'spam foo'"#, "did you mean", ) } @@ -192,7 +189,7 @@ fn hides_env_import_1() -> TestResult { #[test] fn hides_env_import_2() -> TestResult { fail_test( - r#"module spam { export env foo { "foo" } }; use spam; hide spam; $nu.env.'spam foo'"#, + r#"module spam { export env foo { "foo" } }; use spam; hide spam; $env.'spam foo'"#, "did you mean", ) } @@ -200,7 +197,7 @@ fn hides_env_import_2() -> TestResult { #[test] fn hides_env_import_3() -> TestResult { fail_test( - r#"module spam { export env foo { "foo" } }; use spam; hide spam [foo]; $nu.env.'spam foo'"#, + r#"module spam { export env foo { "foo" } }; use spam; hide spam [foo]; $env.'spam foo'"#, "did you mean", ) } @@ -208,7 +205,7 @@ fn hides_env_import_3() -> TestResult { #[test] fn hides_env_import_4() -> TestResult { fail_test( - r#"module spam { export env foo { "foo" } }; use spam foo; hide foo; $nu.env.foo"#, + r#"module spam { export env foo { "foo" } }; use spam foo; hide foo; $env.foo"#, "did you mean", ) } @@ -216,7 +213,7 @@ fn hides_env_import_4() -> TestResult { #[test] fn hides_env_import_5() -> TestResult { fail_test( - r#"module spam { export env foo { "foo" } }; use spam *; hide foo; $nu.env.foo"#, + r#"module spam { export env foo { "foo" } }; use spam *; hide foo; $env.foo"#, "did you mean", ) } @@ -224,7 +221,7 @@ fn hides_env_import_5() -> TestResult { #[test] fn hides_env_import_6() -> TestResult { fail_test( - r#"module spam { export env foo { "foo" } }; use spam *; hide spam *; $nu.env.foo"#, + r#"module spam { export env foo { "foo" } }; use spam *; hide spam *; $env.foo"#, "did you mean", ) } @@ -232,7 +229,7 @@ fn hides_env_import_6() -> TestResult { #[test] fn hides_def_runs_env_import() -> TestResult { run_test( - r#"module spam { export env foo { "foo" }; export def foo [] { "bar" } }; use spam foo; hide foo; $nu.env.foo"#, + r#"module spam { export env foo { "foo" }; export def foo [] { "bar" } }; use spam foo; hide foo; $env.foo"#, "foo", ) } @@ -240,7 +237,7 @@ fn hides_def_runs_env_import() -> TestResult { #[test] fn hides_def_and_env_import_1() -> TestResult { fail_test( - r#"module spam { export env foo { "foo" }; export def foo [] { "bar" } }; use spam foo; hide foo; hide foo; $nu.env.foo"#, + r#"module spam { export env foo { "foo" }; export def foo [] { "bar" } }; use spam foo; hide foo; hide foo; $env.foo"#, "did you mean", ) } @@ -264,7 +261,7 @@ fn use_def_import_after_hide() -> TestResult { #[test] fn use_env_import_after_hide() -> TestResult { run_test( - r#"module spam { export env foo { "foo" } }; use spam foo; hide foo; use spam foo; $nu.env.foo"#, + r#"module spam { export env foo { "foo" } }; use spam foo; hide foo; use spam foo; $env.foo"#, "foo", ) } @@ -280,7 +277,7 @@ fn hide_shadowed_decl() -> TestResult { #[test] fn hide_shadowed_env() -> TestResult { run_test( - r#"module spam { export env foo { "bar" } }; let-env foo = "foo"; do { use spam foo; hide foo; $nu.env.foo }"#, + r#"module spam { export env foo { "bar" } }; let-env foo = "foo"; do { use spam foo; hide foo; $env.foo }"#, "foo", ) } @@ -296,7 +293,7 @@ fn hides_all_decls_within_scope() -> TestResult { #[test] fn hides_all_envs_within_scope() -> TestResult { fail_test( - r#"module spam { export env foo { "bar" } }; let-env foo = "foo"; use spam foo; hide foo; $nu.env.foo"#, + r#"module spam { export env foo { "bar" } }; let-env foo = "foo"; use spam foo; hide foo; $env.foo"#, "did you mean", ) } diff --git a/src/tests/test_modules.rs b/src/tests/test_modules.rs index a4739c14e4..4c3bdca560 100644 --- a/src/tests/test_modules.rs +++ b/src/tests/test_modules.rs @@ -43,7 +43,7 @@ fn module_def_imports_5() -> TestResult { #[test] fn module_env_imports_1() -> TestResult { run_test( - r#"module foo { export env a { '1' } }; use foo; $nu.env.'foo a'"#, + r#"module foo { export env a { '1' } }; use foo; $env.'foo a'"#, "1", ) } @@ -51,7 +51,7 @@ fn module_env_imports_1() -> TestResult { #[test] fn module_env_imports_2() -> TestResult { run_test( - r#"module foo { export env a { '1' } }; use foo a; $nu.env.a"#, + r#"module foo { export env a { '1' } }; use foo a; $env.a"#, "1", ) } @@ -59,7 +59,7 @@ fn module_env_imports_2() -> TestResult { #[test] fn module_env_imports_3() -> TestResult { run_test( - r#"module foo { export env a { '1' }; export env b { '2' } }; use foo *; $nu.env.b"#, + r#"module foo { export env a { '1' }; export env b { '2' } }; use foo *; $env.b"#, "2", ) } @@ -75,7 +75,7 @@ fn module_env_imports_4() -> TestResult { #[test] fn module_env_imports_5() -> TestResult { run_test( - r#"module foo { export env a { '1' }; export env b { '2' }; export env c { '3' } }; use foo [a, c]; $nu.env.c"#, + r#"module foo { export env a { '1' }; export env b { '2' }; export env c { '3' } }; use foo [a, c]; $env.c"#, "3", ) } @@ -83,7 +83,7 @@ fn module_env_imports_5() -> TestResult { #[test] fn module_def_and_env_imports_1() -> TestResult { run_test( - r#"module spam { export env foo { "foo" }; export def foo [] { "bar" } }; use spam foo; $nu.env.foo"#, + r#"module spam { export env foo { "foo" }; export def foo [] { "bar" } }; use spam foo; $env.foo"#, "foo", ) } @@ -107,7 +107,7 @@ fn module_def_import_uses_internal_command() -> TestResult { #[test] fn module_env_import_uses_internal_command() -> TestResult { run_test( - r#"module foo { def b [] { "2" }; export env a { b } }; use foo; $nu.env.'foo a'"#, + r#"module foo { def b [] { "2" }; export env a { b } }; use foo; $env.'foo a'"#, "2", ) }