Try to make hide-env respects overlays (#15904)

# Description
Closes: #15755
I think it's a good feature, to achieve this, we need to get all hidden
envs(it's defined in `get_hidden_env_vars`, and then restore these envs
back to stack)

# User-Facing Changes
### Before
```nushell
> $env.foo = 'bar'
> overlay new xxx
> hide-env foo
> overlay hide xxx
> $env.foo
Error: nu:🐚:column_not_found

  × Cannot find column 'foo'
   ╭─[entry #21:5:1]
 4 │ overlay hide xxx
 5 │ $env.foo
   · ────┬───┬
   ·     │   ╰── value originates here
   ·     ╰── cannot find column 'foo'
   ╰────
```

### After
```nushell
> $env.foo = 'bar'
> overlay new xxx
> hide-env foo
> overlay hide xxx
> $env.foo
bar
```

## Note
But it doesn't work if it runs the example code in script:
`nu -c "$env.foo = 'bar'; overlay new xxx; hide-env foo; overlay hide
xxx; $env.foo"`
still raises an error says `foo` doesn't found. That's because if we run
the script at once, the envs in stack doesn't have a chance to merge
back into `engine_state`, which is only called in `repl`.

It introduces some sort of inconsistency, but I think users use overlays
mostly in repl, so it's good to have such feature first.

# Tests + Formatting
Added 2 tests

# After Submitting
NaN
This commit is contained in:
Wind
2025-06-13 07:22:23 +08:00
committed by GitHub
parent 2fe25d6299
commit 81e86c40e1
3 changed files with 66 additions and 1 deletions

View File

@ -414,6 +414,37 @@ impl Stack {
result
}
/// Get hidden envs, but without envs defined previously in `excluded_overlay_name`.
pub fn get_hidden_env_vars(
&self,
excluded_overlay_name: &str,
engine_state: &EngineState,
) -> HashMap<String, Value> {
let mut result = HashMap::new();
for overlay_name in self.active_overlays.iter().rev() {
if overlay_name == excluded_overlay_name {
continue;
}
if let Some(env_names) = self.env_hidden.get(overlay_name) {
for n in env_names {
if result.contains_key(n) {
continue;
}
// get env value.
if let Some(Some(v)) = engine_state
.env_vars
.get(overlay_name)
.map(|env_vars| env_vars.get(n))
{
result.insert(n.to_string(), v.clone());
}
}
}
}
result
}
/// Same as get_env_vars, but returns only the names as a HashSet
pub fn get_env_var_names(&self, engine_state: &EngineState) -> HashSet<String> {
let mut result = HashSet::new();