diff --git a/crates/nu-command/src/system/exec.rs b/crates/nu-command/src/system/exec.rs index 8a2b24a113..ca0ae4d216 100644 --- a/crates/nu-command/src/system/exec.rs +++ b/crates/nu-command/src/system/exec.rs @@ -61,6 +61,16 @@ On Windows based systems, Nushell will wait for the command to finish and then e let envs = env_to_strings(engine_state, stack)?; command.env_clear(); command.envs(envs); + // Decrement SHLVL as removing the current shell from the stack + // (only works in interactive mode, same as initialization) + if engine_state.is_interactive { + let shlvl = engine_state + .get_env_var("SHLVL") + .and_then(|shlvl_env| shlvl_env.coerce_str().ok()?.parse::().ok()) + .unwrap_or(1) + .saturating_sub(1); + command.env("SHLVL", shlvl.to_string()); + } // Configure args. let args = crate::eval_arguments_from_call(engine_state, stack, call)?; diff --git a/tests/shell/environment/env.rs b/tests/shell/environment/env.rs index 7e628a92e7..eab193684f 100644 --- a/tests/shell/environment/env.rs +++ b/tests/shell/environment/env.rs @@ -229,3 +229,23 @@ fn std_log_env_vars_have_defaults() { assert!(actual.err.contains("%MSG%")); assert!(actual.err.contains("%Y-")); } + +#[test] +fn env_shlvl() { + let actual = nu!(" + $env.SHLVL = 5 + nu -i -c 'print $env.SHLVL' + "); + + assert_eq!(actual.out, "6"); +} + +#[test] +fn env_shlvl_in_exec() { + let actual = nu!(" + $env.SHLVL = 29 + nu -i -c \"exec nu -i -c 'print $env.SHLVL'\" + "); + + assert_eq!(actual.out, "30"); +}