1
0

fix(windows): improve backslash handling in command lexer

Handle multiple backslashes before quotes correctly by counting them and applying Windows command line parsing rules. Even number of backslashes before quote are treated as escape sequences, odd number as literal quotes.
This commit is contained in:
2025-10-22 20:27:40 +08:00
parent 563ab483fc
commit 217d3d5fd3

View File

@ -251,26 +251,33 @@ impl<I: Iterator<Item = char>> Iterator for CmdLexer<I> {
// Handle backslash
'\\' => {
if let Some(pc) = self.chars.peek().copied() {
match pc {
'\\' => {
// Double backslash are treated as single backslash
self.chars.next();
token.push(pc);
}
'"' => {
// Backslash with an quote is interpreted as an literal quote
self.chars.next();
token.push(pc);
}
_ => {
// Treated as normal backslash
token.push(c);
}
// Eat backslash as much as possible and count it.
let mut backslashes: usize = 1;
while self.chars.peek().copied() == Some('\\') {
self.chars.next();
backslashes += 1;
}
if self.chars.peek().copied() == Some('"') {
// Rule: backslashes before a double quote are special
// consume the "
let quote = self.chars.next().unwrap();
// Even number: backslashes become half, quote is delimiter
// Odd number: backslashes become half, quote is literal
let num_slashes = backslashes / 2;
let is_literal_quote = backslashes % 2 != 0;
token.push_str(&"\\".repeat(num_slashes));
if is_literal_quote {
token.push(quote);
} else {
in_quotes = !in_quotes;
}
} else {
// There is no more chars, treat it as normal.
token.push(c);
// Not followed by quote: treat all backslashes literally
token.push_str(&"\\".repeat(backslashes));
}
}