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:
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user