Don't complete variables when single quoted. Fixes #1023

This commit is contained in:
ridiculousfish 2014-02-09 15:27:04 -08:00
parent 414530c9c2
commit 5ea7f52df2
2 changed files with 65 additions and 18 deletions

View File

@ -1712,29 +1712,67 @@ bool completer_t::complete_variable(const wcstring &str, size_t start_offset)
return res;
}
/**
Search the specified string for the \$ sign. If found, try to
complete as an environment variable.
\return 0 if unable to complete, 1 otherwise
*/
bool completer_t::try_complete_variable(const wcstring &str)
{
size_t i = str.size();
while (i--)
enum {e_unquoted, e_single_quoted, e_double_quoted} mode = e_unquoted;
const size_t len = str.size();
/* Get the position of the dollar heading a run of valid variable characters. -1 means none. */
size_t variable_start = -1;
for (size_t in_pos=0; in_pos<len; in_pos++)
{
wchar_t c = str.at(i);
if (c == L'$')
wchar_t c = str.at(in_pos);
if (! wcsvarchr(c))
{
/* wprintf( L"Var prefix \'%ls\'\n", &cmd[i+1] );*/
return this->complete_variable(str, i+1);
/* This character cannot be in a variable, reset the dollar */
variable_start = -1;
}
if (!isalnum(c) && c != L'_')
switch (c)
{
return false;
case L'\\':
in_pos++;
break;
case L'$':
if (mode == e_unquoted || mode == e_double_quoted)
{
variable_start = in_pos;
}
break;
case L'\'':
if (mode == e_single_quoted)
{
mode = e_unquoted;
}
else if (mode == e_unquoted)
{
mode = e_single_quoted;
}
break;
case L'"':
if (mode == e_double_quoted)
{
mode = e_unquoted;
}
else if (mode == e_unquoted)
{
mode = e_double_quoted;
}
break;
}
}
return false;
/* Now complete if we have a variable start that's also not the last character */
bool result = false;
if (variable_start != static_cast<size_t>(-1) && variable_start + 1 < len)
{
result = this->complete_variable(str, variable_start + 1);
}
return result;
}
/**
@ -1822,7 +1860,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> &comps
bool use_function = 1;
bool use_builtin = 1;
// debug( 1, L"Complete '%ls'", cmd );
//debug( 1, L"Complete '%ls'", cmd.c_str() );
const wchar_t *cmd_cstr = cmd.c_str();
const wchar_t *tok_begin = NULL, *prev_begin = NULL, *prev_end = NULL;
@ -1832,9 +1870,11 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> &comps
If we are completing a variable name or a tilde expansion user
name, we do that and return. No need for any other completions.
*/
const wcstring current_token = tok_begin;
/* Get the quote type of the current token */
if (!done)
{
done = completer.try_complete_variable(current_token) || completer.try_complete_user(current_token);

View File

@ -1535,7 +1535,14 @@ static void test_complete(void)
complete(L"foobarbaz ", completions, COMPLETION_REQUEST_DEFAULT);
do_test(completions.size() == 1);
do_test(completions.at(0).completion == L"qux");
/* Don't complete variable names in single quotes (#1023) */
completions.clear();
complete(L"echo '$Foo", completions, COMPLETION_REQUEST_DEFAULT);
do_test(completions.empty());
completions.clear();
complete(L"echo \\$Foo", completions, COMPLETION_REQUEST_DEFAULT);
do_test(completions.empty());
complete_set_variable_names(NULL);
}