From ebce62629e9f6fa3d68ba13f27d5d672997f7850 Mon Sep 17 00:00:00 2001 From: Rikuki IX <52599939+rikukiix@users.noreply.github.com> Date: Fri, 13 Dec 2024 01:19:03 +0800 Subject: [PATCH] fix: make exec command decrement SHLVL correctly (#14570) # Description fixes #14567 Now NuShell's `exec` command will decrement `SHLVL` env value before passing it to target executable. It only works in interactive session, the same as `SHLVL` initialization. In addition, this PR also make a simple change to `SHLVL` initialization (only remove an unnecessary type conversion). # User-Facing Changes None. # Tests + Formatting Formatted. With interactively tested with several shells (bash, zsh, fish) and cross-exec-ing them, it works well this time. # After Submitting --- crates/nu-command/src/system/exec.rs | 10 ++++++++++ src/main.rs | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/nu-command/src/system/exec.rs b/crates/nu-command/src/system/exec.rs index 8a2b24a113..e9f49b86c1 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 { + if let Some(shlvl) = engine_state.get_env_var("SHLVL") { + let shlvl = shlvl.as_int().unwrap_or(1) - 1; + command.env("SHLVL", shlvl.to_string()); + } else { + command.env("SHLVL", "0"); + } + } // Configure args. let args = crate::eval_arguments_from_call(engine_state, stack, call)?; diff --git a/src/main.rs b/src/main.rs index 7d39aef02b..db55db3ff2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -325,7 +325,7 @@ fn main() -> Result<()> { if engine_state.is_interactive { let mut shlvl = engine_state .get_env_var("SHLVL") - .map(|x| x.as_str().unwrap_or("0").parse::().unwrap_or(0)) + .map(|x| x.as_int().unwrap_or(0)) .unwrap_or(0); shlvl += 1; engine_state.add_env_var("SHLVL".to_string(), Value::int(shlvl, Span::unknown()));