Implemented scoping for expansions

This commit is contained in:
2025-03-08 01:38:42 -05:00
parent eccdafb11e
commit 4f58c1c3fd
18 changed files with 271 additions and 141 deletions

View File

@@ -1,5 +1,7 @@
use crate::{parse::lex::Token, prelude::*};
use super::cmdsub::expand_cmdsub_string;
pub fn expand_var(var_sub: Token, shenv: &mut ShEnv) -> Vec<Token> {
let var_name = var_sub.as_raw(shenv);
let var_name = var_name.trim_start_matches('$').trim_matches(['{','}']);
@@ -8,7 +10,7 @@ pub fn expand_var(var_sub: Token, shenv: &mut ShEnv) -> Vec<Token> {
shenv.expand_input(&value, var_sub.span())
}
pub fn expand_string(s: &str, shenv: &mut ShEnv) -> String {
pub fn expand_string(s: &str, shenv: &mut ShEnv) -> ShResult<String> {
let mut result = String::new();
let mut var_name = String::new();
let mut chars = s.chars().peekable();
@@ -38,6 +40,30 @@ pub fn expand_string(s: &str, shenv: &mut ShEnv) -> String {
expanded = true;
break
}
'(' if var_name.is_empty() => {
let mut paren_count = 1;
var_name.push_str("$(");
while let Some(ch) = chars.next() {
match ch {
'(' => {
paren_count += 1;
var_name.push(ch);
}
')' => {
paren_count -= 1;
var_name.push(ch);
if paren_count == 0 {
break
}
}
_ => var_name.push(ch)
}
}
let value = expand_cmdsub_string(&var_name, shenv)?;
result.push_str(&value);
expanded = true;
break
}
_ if ch.is_ascii_digit() && var_name.is_empty() && !in_brace => {
var_name.push(ch);
let value = shenv.vars().get_var(&var_name);
@@ -72,5 +98,5 @@ pub fn expand_string(s: &str, shenv: &mut ShEnv) -> String {
_ => result.push(ch)
}
}
result
Ok(result)
}