Increment SHLVL before run_repl() (#14732)

# Description

A follow-on to #14727:

* Instead of using `is-interactive` as the trigger for incrementing
`SHLVL`, this change puts the increment logic just before `run_repl()`
is called.
* Tests are changed to use `-e`
* Moves the `confirm_stdin_is_terminal()` call immediately **after** the
`prerun_cmd` (which executes `--execute (-e) <commandstring>`. The fact
that it was **before** that call seems to be a bug, since the error
message says *"or provide arguments to invoke a script"* even if
`--execute` was used. This change enables REPL testing using `--execute
(-e)`.
* Added a test to ensure `-c` does *not* increment SHLVL.

# User-Facing Changes

`$env.SHLVL` runs before the REPL is started, rather than when
`is-interactive`

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting

N/A
This commit is contained in:
Douglas 2025-01-03 16:16:57 -05:00 committed by GitHub
parent 6325bc5e54
commit d702c4605a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 53 additions and 35 deletions

View file

@ -63,8 +63,6 @@ pub fn evaluate_repl(
let config = engine_state.get_config();
let use_color = config.use_ansi_coloring.get(engine_state);
confirm_stdin_is_terminal()?;
let mut entry_num = 0;
// Let's grab the shell_integration configs
@ -104,6 +102,8 @@ pub fn evaluate_repl(
engine_state.merge_env(&mut unique_stack)?;
}
confirm_stdin_is_terminal()?;
let hostname = System::host_name();
if shell_integration_osc2 {
run_shell_integration_osc2(None, engine_state, &mut unique_stack, use_color);

View file

@ -323,36 +323,6 @@ fn main() -> Result<()> {
"NU_VERSION".to_string(),
Value::string(env!("CARGO_PKG_VERSION"), Span::unknown()),
);
// Add SHLVL if interactive
if engine_state.is_interactive {
engine_state.add_env_var("PROMPT_INDICATOR".to_string(), Value::test_string("> "));
engine_state.add_env_var(
"PROMPT_INDICATOR_VI_NORMAL".to_string(),
Value::test_string("> "),
);
engine_state.add_env_var(
"PROMPT_INDICATOR_VI_INSERT".to_string(),
Value::test_string(": "),
);
engine_state.add_env_var(
"PROMPT_MULTILINE_INDICATOR".to_string(),
Value::test_string("::: "),
);
engine_state.add_env_var(
"TRANSIENT_PROMPT_MULTILINE_INDICATOR".to_string(),
Value::test_string(""),
);
engine_state.add_env_var(
"TRANSIENT_PROMPT_COMMAND_RIGHT".to_string(),
Value::test_string(""),
);
let mut shlvl = engine_state
.get_env_var("SHLVL")
.map(|x| x.as_str().unwrap_or("0").parse::<i64>().unwrap_or(0))
.unwrap_or(0);
shlvl += 1;
engine_state.add_env_var("SHLVL".to_string(), Value::int(shlvl, Span::unknown()));
}
if parsed_nu_cli_args.no_std_lib.is_none() {
load_standard_library(&mut engine_state)?;
@ -510,6 +480,35 @@ fn main() -> Result<()> {
input,
);
} else {
// Environment variables that apply only when in REPL
engine_state.add_env_var("PROMPT_INDICATOR".to_string(), Value::test_string("> "));
engine_state.add_env_var(
"PROMPT_INDICATOR_VI_NORMAL".to_string(),
Value::test_string("> "),
);
engine_state.add_env_var(
"PROMPT_INDICATOR_VI_INSERT".to_string(),
Value::test_string(": "),
);
engine_state.add_env_var(
"PROMPT_MULTILINE_INDICATOR".to_string(),
Value::test_string("::: "),
);
engine_state.add_env_var(
"TRANSIENT_PROMPT_MULTILINE_INDICATOR".to_string(),
Value::test_string(""),
);
engine_state.add_env_var(
"TRANSIENT_PROMPT_COMMAND_RIGHT".to_string(),
Value::test_string(""),
);
let mut shlvl = engine_state
.get_env_var("SHLVL")
.map(|x| x.as_str().unwrap_or("0").parse::<i64>().unwrap_or(0))
.unwrap_or(0);
shlvl += 1;
engine_state.add_env_var("SHLVL".to_string(), Value::int(shlvl, Span::unknown()));
run_repl(&mut engine_state, parsed_nu_cli_args, entire_start_time)?
}

View file

@ -231,17 +231,36 @@ fn std_log_env_vars_have_defaults() {
}
#[test]
fn env_shlvl() {
fn env_shlvl_commandstring_does_not_increment() {
let actual = nu!("
$env.SHLVL = 5
nu -i -c 'print $env.SHLVL'
nu -c 'print $env.SHLVL; exit'
");
assert_eq!(actual.out, "5");
}
// Note: Do not use -i / --interactive in tests.
// -i attempts to acquire a terminal, and if more than one
// test tries to obtain a terminal at the same time, the
// test run will likely hang, at least for some users.
// Instead, use -e / --execute with an `exit` to test REPL
// functionality as demonstrated below.
#[test]
fn env_shlvl_in_repl() {
let actual = nu!("
$env.SHLVL = 5
nu --no-std-lib -n -e 'print $env.SHLVL; exit'
");
assert_eq!(actual.out, "6");
}
#[test]
fn env_shlvl_in_exec_repl() {
let actual = nu!("
$env.SHLVL = 29
nu -i -c \"exec nu -i -c 'print $env.SHLVL'\"
nu -c \"exec nu --no-std-lib -n -e 'print $env.SHLVL; exit'\"
");
assert_eq!(actual.out, "30");