improvement on parsing accuracy for case patterns

This commit is contained in:
2026-03-04 18:27:40 -05:00
parent 7b5337367b
commit 22af5fd623
2 changed files with 21 additions and 2 deletions

View File

@@ -500,6 +500,7 @@ pub fn expand_var(chars: &mut Peekable<Chars<'_>>) -> ShResult<String> {
let mut idx_brace_depth: i32 = 0; let mut idx_brace_depth: i32 = 0;
let mut idx_raw = String::new(); let mut idx_raw = String::new();
let mut idx = None; let mut idx = None;
let mut in_operator = false;
while let Some(&ch) = chars.peek() { while let Some(&ch) = chars.peek() {
match ch { match ch {
markers::SUBSH if var_name.is_empty() => { markers::SUBSH if var_name.is_empty() => {
@@ -555,7 +556,7 @@ pub fn expand_var(chars: &mut Peekable<Chars<'_>>) -> ShResult<String> {
}; };
return Ok(val); return Ok(val);
} }
'[' if brace_depth > 0 && bracket_depth == 0 && inner_brace_depth == 0 => { '[' if brace_depth > 0 && bracket_depth == 0 && inner_brace_depth == 0 && !in_operator => {
chars.next(); // consume the bracket chars.next(); // consume the bracket
bracket_depth += 1; bracket_depth += 1;
} }
@@ -590,6 +591,9 @@ pub fn expand_var(chars: &mut Peekable<Chars<'_>>) -> ShResult<String> {
if ch == '}' { if ch == '}' {
inner_brace_depth -= 1; inner_brace_depth -= 1;
} }
if !in_operator && matches!(ch, '#' | '%' | ':' | '/' | '-' | '+' | '=' | '?' | '!') {
in_operator = true;
}
var_name.push(ch); var_name.push(ch);
} }
ch if var_name.is_empty() && PARAMETERS.contains(&ch) => { ch if var_name.is_empty() && PARAMETERS.contains(&ch) => {

View File

@@ -1087,11 +1087,26 @@ pub fn case_pat_lookahead(mut chars: Peekable<Chars>) -> Option<usize> {
while let Some(ch) = chars.next() { while let Some(ch) = chars.next() {
pos += ch.len_utf8(); pos += ch.len_utf8();
match ch { match ch {
_ if is_hard_sep(ch) => return None, _ if qt_state.outside() && is_hard_sep(ch) => return None,
'\\' => { '\\' => {
if let Some(esc) = chars.next() { if let Some(esc) = chars.next() {
pos += esc.len_utf8(); pos += esc.len_utf8();
} }
}
'$' if qt_state.outside() && chars.peek() == Some(&'\'') => {
// $'...' ANSI-C quoting — skip through to closing quote
chars.next(); // consume opening '
pos += 1;
while let Some(c) = chars.next() {
pos += c.len_utf8();
if c == '\\' {
if let Some(esc) = chars.next() {
pos += esc.len_utf8();
}
} else if c == '\'' {
break;
}
}
} }
'\'' => { '\'' => {
qt_state.toggle_single(); qt_state.toggle_single();