Skip to content
Snippets Groups Projects
Commit a052b800 authored by gwenn's avatar gwenn
Browse files

Fix find_unclosed_quote

On windows, '\' is used both as a path separator and to escape '"'.
So a single '\' is valid (nothin to escape).
parent 3790133f
No related branches found
No related tags found
No related merge requests found
...@@ -138,7 +138,7 @@ static DOUBLE_QUOTES_SPECIAL_CHARS: [u8; 4] = [b'"', b'$', b'\\', b'`']; ...@@ -138,7 +138,7 @@ static DOUBLE_QUOTES_SPECIAL_CHARS: [u8; 4] = [b'"', b'$', b'\\', b'`'];
#[cfg(windows)] #[cfg(windows)]
static DOUBLE_QUOTES_SPECIAL_CHARS: [u8; 1] = [b'"']; // TODO Validate static DOUBLE_QUOTES_SPECIAL_CHARS: [u8; 1] = [b'"']; // TODO Validate
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum Quote { pub enum Quote {
Double, Double,
Single, Single,
...@@ -165,15 +165,15 @@ impl Completer for FilenameCompleter { ...@@ -165,15 +165,15 @@ impl Completer for FilenameCompleter {
fn complete(&self, line: &str, pos: usize) -> Result<(usize, Vec<Pair>)> { fn complete(&self, line: &str, pos: usize) -> Result<(usize, Vec<Pair>)> {
let (start, path, esc_char, break_chars, quote) = let (start, path, esc_char, break_chars, quote) =
if let Some((idx, double_quote)) = find_unclosed_quote(&line[..pos]) { if let Some((idx, quote)) = find_unclosed_quote(&line[..pos]) {
let start = idx + 1; let start = idx + 1;
if double_quote { if quote == Quote::Double {
( (
start, start,
unescape(&line[start..pos], DOUBLE_QUOTES_ESCAPE_CHAR), unescape(&line[start..pos], DOUBLE_QUOTES_ESCAPE_CHAR),
DOUBLE_QUOTES_ESCAPE_CHAR, DOUBLE_QUOTES_ESCAPE_CHAR,
&self.double_quotes_special_chars, &self.double_quotes_special_chars,
Quote::Double, quote,
) )
} else { } else {
( (
...@@ -181,7 +181,7 @@ impl Completer for FilenameCompleter { ...@@ -181,7 +181,7 @@ impl Completer for FilenameCompleter {
Borrowed(&line[start..pos]), Borrowed(&line[start..pos]),
None, None,
&self.break_chars, &self.break_chars,
Quote::Single, quote,
) )
} }
} else { } else {
...@@ -395,7 +395,7 @@ enum ScanMode { ...@@ -395,7 +395,7 @@ enum ScanMode {
/// try to find an unclosed single/double quote in `s`. /// try to find an unclosed single/double quote in `s`.
/// Return `None` if no unclosed quote is found. /// Return `None` if no unclosed quote is found.
/// Return the unclosed quote position and if it is a double quote. /// Return the unclosed quote position and if it is a double quote.
fn find_unclosed_quote(s: &str) -> Option<(usize, bool)> { fn find_unclosed_quote(s: &str) -> Option<(usize, Quote)> {
let char_indices = s.char_indices(); let char_indices = s.char_indices();
let mut mode = ScanMode::Normal; let mut mode = ScanMode::Normal;
let mut quote_index = 0; let mut quote_index = 0;
...@@ -405,6 +405,7 @@ fn find_unclosed_quote(s: &str) -> Option<(usize, bool)> { ...@@ -405,6 +405,7 @@ fn find_unclosed_quote(s: &str) -> Option<(usize, bool)> {
if char == '"' { if char == '"' {
mode = ScanMode::Normal; mode = ScanMode::Normal;
} else if char == '\\' { } else if char == '\\' {
// both windows and unix support escape in double quote
mode = ScanMode::EscapeInDoubleQuote; mode = ScanMode::EscapeInDoubleQuote;
} }
} }
...@@ -432,8 +433,10 @@ fn find_unclosed_quote(s: &str) -> Option<(usize, bool)> { ...@@ -432,8 +433,10 @@ fn find_unclosed_quote(s: &str) -> Option<(usize, bool)> {
} }
}; };
} }
if ScanMode::DoubleQuote == mode || ScanMode::SingleQuote == mode { if ScanMode::DoubleQuote == mode || ScanMode::EscapeInDoubleQuote == mode {
return Some((quote_index, ScanMode::DoubleQuote == mode)); return Some((quote_index, Quote::Double));
} else if ScanMode::SingleQuote == mode {
return Some((quote_index, Quote::Single));
} }
None None
} }
...@@ -520,12 +523,16 @@ mod tests { ...@@ -520,12 +523,16 @@ mod tests {
pub fn find_unclosed_quote() { pub fn find_unclosed_quote() {
assert_eq!(None, super::find_unclosed_quote("ls /etc")); assert_eq!(None, super::find_unclosed_quote("ls /etc"));
assert_eq!( assert_eq!(
Some((3, true)), Some((3, super::Quote::Double)),
super::find_unclosed_quote("ls \"User Information") super::find_unclosed_quote("ls \"User Information")
); );
assert_eq!( assert_eq!(
None, None,
super::find_unclosed_quote("ls \"/User Information\" /etc") super::find_unclosed_quote("ls \"/User Information\" /etc")
); );
assert_eq!(
Some((0, super::Quote::Double)),
super::find_unclosed_quote("\"c:\\users\\All Users\\")
)
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment