Correct handling of unescapable entities in quotes

Prior to this fix, if you attempt to complete from inside a quote and the
completion contained an entity that cannot be represented inside quotes
(i.e. \n \r \t \b), the result would be a broken mess of quotes. Rewrite
the implementation so that it exits the quotes, emits the correct unquoted
escape, and then re-enters the quotes.
This commit is contained in:
ridiculousfish
2018-02-17 15:04:31 -08:00
parent 01d87455e1
commit 81b3baaa9c
2 changed files with 26 additions and 17 deletions

View File

@@ -517,29 +517,33 @@ wcstring parse_util_escape_string_with_quote(const wcstring &cmd, wchar_t quote,
escape_flags_t flags = ESCAPE_ALL | ESCAPE_NO_QUOTED | (no_tilde ? ESCAPE_NO_TILDE : 0);
result = escape_string(cmd, flags);
} else {
bool unescapable = false;
for (size_t i = 0; i < cmd.size(); i++) {
wchar_t c = cmd.at(i);
// Here we are going to escape a string with quotes.
// A few characters cannot be represented inside quotes, e.g. newlines. In that case,
// terminate the quote and then re-enter it.
result.reserve(cmd.size());
for (wchar_t c : cmd) {
switch (c) {
case L'\n':
case L'\t':
case L'\b':
case L'\r': {
unescapable = true;
result.append({quote, L'\\', L'n', quote});
break;
}
default: {
case L'\t':
result.append({quote, L'\\', L't', quote});
break;
case L'\b':
result.append({quote, L'\\', L'b', quote});
break;
case L'\r':
result.append({quote, L'\\', L'r', quote});
break;
case L'\\':
result.append({L'\\', L'\\'});
break;
default:
if (c == quote) result.push_back(L'\\');
result.push_back(c);
break;
}
}
}
if (unescapable) {
result = escape_string(cmd, ESCAPE_ALL | ESCAPE_NO_QUOTED);
result.insert(0, &quote, 1);
}
}
return result;
}