Correct escaping and add tests for bracket completion

Add some tests for new bracket completion behavior, and fix an escaping
bug where \\[ was incorrectly marked as escaping.
This commit is contained in:
ridiculousfish 2019-09-08 15:39:50 -07:00
parent bc3dde997d
commit b2fe2f9ff3
2 changed files with 41 additions and 5 deletions

View file

@ -1362,12 +1362,19 @@ void completer_t::escape_opening_brackets(const wcstring &argument) {
bool escaped = false;
for (wchar_t c : argument) {
have_unquoted_unescaped_bracket |= (c == L'[') && !quote && !escaped;
if (quote) {
if (c == quote && !escaped) quote = L'\0';
} else {
if ((c == L'\'' || c == L'"') && !escaped) quote = c;
if (escaped) {
escaped = false;
} else if (c == L'\\') {
escaped = true;
} else if (c == L'\'' || c == L'"') {
if (quote == c) {
// Closing a quote.
quote = L'\0';
} else if (quote == L'\0') {
// Opening a quote.
quote = c;
}
}
escaped = c == L'\\';
}
if (!have_unquoted_unescaped_bracket) return;
// Since completion_apply_to_command_line will escape the completion, we need to provide an

View file

@ -2619,6 +2619,8 @@ static void test_complete() {
if (system("mkdir -p 'test/complete_test'")) err(L"mkdir failed");
if (system("touch 'test/complete_test/has space'")) err(L"touch failed");
if (system("touch 'test/complete_test/bracket[abc]'")) err(L"touch failed");
if (system(R"(touch 'test/complete_test/gnarlybracket\[abc]')")) err(L"touch failed");
if (system("touch 'test/complete_test/testfile'")) err(L"touch failed");
if (system("chmod 700 'test/complete_test/testfile'")) err(L"chmod failed");
@ -2643,6 +2645,33 @@ static void test_complete() {
do_test(completions.size() == 1);
do_test(completions.at(0).completion == L"space");
// Brackets - see #5831
completions.clear();
complete(L"echo (ls test/complete_test/bracket[", &completions, {}, vars, parser);
do_test(completions.size() == 1);
fprintf(stderr, "sup: %ls\n", completions.front().completion.c_str());
do_test(completions.at(0).completion == L"test/complete_test/bracket[abc]");
wcstring cmdline = L"touch test/complete_test/bracket[";
completions.clear();
complete(cmdline, &completions, {}, vars, parser);
do_test(completions.size() == 1);
do_test(completions.front().completion == L"test/complete_test/bracket[abc]");
size_t where = cmdline.size();
wcstring newcmdline = completion_apply_to_command_line(
completions.front().completion, completions.front().flags, cmdline, &where, false);
do_test(newcmdline == L"touch test/complete_test/bracket\\[abc\\] ");
completions.clear();
cmdline = LR"(touch test/complete_test/gnarlybracket\\[)";
complete(cmdline, &completions, {}, vars, parser);
do_test(completions.size() == 1);
do_test(completions.front().completion == LR"(test/complete_test/gnarlybracket\[abc])");
where = cmdline.size();
newcmdline = completion_apply_to_command_line(
completions.front().completion, completions.front().flags, cmdline, &where, false);
do_test(newcmdline == LR"(touch test/complete_test/gnarlybracket\\\[abc\] )");
// Add a function and test completing it in various ways.
// Note we're depending on function_data_t not complaining when given missing parsed_source /
// body_node.