From d9ff02b7a5a414380a7edbabc815aef14c43ffe1 Mon Sep 17 00:00:00 2001 From: pagedmov Date: Mon, 23 Feb 2026 19:04:31 -0500 Subject: [PATCH] Fixed mutation of variables created by the local command --- src/prompt/readline/highlight.rs | 1 - src/prompt/readline/mod.rs | 4 ---- src/state.rs | 27 +++++++++++++++++++++++---- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/prompt/readline/highlight.rs b/src/prompt/readline/highlight.rs index c3ee4e8..e5d7310 100644 --- a/src/prompt/readline/highlight.rs +++ b/src/prompt/readline/highlight.rs @@ -45,7 +45,6 @@ impl Highlighter { /// indicating token types and sub-token constructs (strings, variables, etc.) pub fn load_input(&mut self, input: &str, linebuf_cursor_pos: usize) { let input = annotate_input(input); - log::debug!("Annotated input: {:?}", input); self.input = input; self.linebuf_cursor_pos = linebuf_cursor_pos; } diff --git a/src/prompt/readline/mod.rs b/src/prompt/readline/mod.rs index ebb365c..47f8d53 100644 --- a/src/prompt/readline/mod.rs +++ b/src/prompt/readline/mod.rs @@ -323,10 +323,8 @@ impl FernVi { _ => unreachable!(), }; let entry = self.history.scroll(count); - log::info!("Scrolled history, got entry: {:?}", entry.as_ref()); if let Some(entry) = entry { let cursor_pos = self.editor.cursor.get(); - log::info!("Saving pending command to history: {:?} at cursor pos {}", self.editor.as_str(), cursor_pos); let pending = self.editor.take_buf(); self.editor.set_buffer(entry.command().to_string()); if self.history.pending.is_none() { @@ -335,7 +333,6 @@ impl FernVi { self.editor.set_hint(None); self.editor.move_cursor_to_end(); } else if let Some(pending) = self.history.pending.take() { - log::info!("Setting buffer to pending command: {:?}", &pending); self.editor.set_buffer(pending.0); self.editor.cursor.set(pending.1); self.editor.set_hint(None); @@ -378,7 +375,6 @@ impl FernVi { self.highlighter.load_input(&line,self.editor.cursor_byte_pos()); self.highlighter.highlight(); let highlighted = self.highlighter.take(); - log::info!("Highlighting line. highlighted: {:?}, hint: {:?}", highlighted, hint); format!("{highlighted}{hint}") } else { format!("{line}{hint}") diff --git a/src/state.rs b/src/state.rs index 979c063..27e7bc1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -194,10 +194,11 @@ impl ScopeStack { flat_vars } pub fn set_var(&mut self, var_name: &str, val: &str, flags: VarFlags) { - if flags.contains(VarFlags::LOCAL) { + let is_local = self.is_local_var(var_name); + if flags.contains(VarFlags::LOCAL) || is_local { self.set_var_local(var_name, val, flags); - } else { - self.set_var_global(var_name, val, flags); + } else { + self.set_var_global(var_name, val, flags); } } fn set_var_global(&mut self, var_name: &str, val: &str, flags: VarFlags) { @@ -222,6 +223,21 @@ impl ScopeStack { // Fallback to env var std::env::var(var_name).unwrap_or_default() } + pub fn is_local_var(&self, var_name: &str) -> bool { + self.scopes + .last() + .is_some_and(|s| + s.get_var_flags(var_name).is_some_and(|flags| flags.contains(VarFlags::LOCAL)) + ) + } + pub fn get_var_flags(&self, var_name: &str) -> Option { + for scope in self.scopes.iter().rev() { + if scope.var_exists(var_name) { + return scope.get_var_flags(var_name); + } + } + None + } pub fn get_param(&self, param: ShellParam) -> String { if param.is_global() && let Some(val) = self.global_params.get(¶m.to_string()) @@ -644,6 +660,9 @@ impl VarTab { std::env::var(var).unwrap_or_default() } } + pub fn get_var_flags(&self, var_name: &str) -> Option { + self.vars.get(var_name).map(|var| var.flags) + } pub fn unset_var(&mut self, var_name: &str) { self.vars.remove(var_name); unsafe { env::remove_var(var_name) }; @@ -658,7 +677,7 @@ impl VarTab { unsafe { env::set_var(var_name, val) }; } } else { - let mut var = Var::new(VarKind::Str(val.to_string()), VarFlags::NONE); + let mut var = Var::new(VarKind::Str(val.to_string()), flags); if flags.contains(VarFlags::EXPORT) { var.mark_for_export(); unsafe { env::set_var(var_name, var.to_string()) };