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:
1 parent
563ab483fc
commit
217d3d5fd3
1 file changed
+23
-16
@@ -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
|
||||
// Eat backslash as much as possible and count it.
|
||||
let mut backslashes: usize = 1;
|
||||
while self.chars.peek().copied() == Some('\\') {
|
||||
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);
|
||||
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