mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 21:44:16 +00:00
parent
fb3c839a15
commit
f08ac969e9
2 changed files with 21 additions and 12 deletions
|
@ -1265,16 +1265,16 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
|
||||||
parse_flag_include_comments,
|
parse_flag_include_comments,
|
||||||
&tree, NULL);
|
&tree, NULL);
|
||||||
|
|
||||||
// Find any plain statement that contains the position. We have to backtrack past spaces
|
// Find the plain statement to operate on. The cursor may be past it (#1261), so backtrack until
|
||||||
// (issue #1261). So this will be at either the last space character, or after the end of
|
// we know we're no longer in a space. But the space may actually be part of the argument (#2477)
|
||||||
// the string.
|
// so
|
||||||
size_t adjusted_pos = pos;
|
size_t position_in_statement = pos;
|
||||||
while (adjusted_pos > 0 && cmd.at(adjusted_pos - 1) == L' ') {
|
while (position_in_statement > 0 && cmd.at(position_in_statement - 1) == L' ') {
|
||||||
adjusted_pos--;
|
position_in_statement--;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parse_node_t *plain_statement =
|
const parse_node_t *plain_statement =
|
||||||
tree.find_node_matching_source_location(symbol_plain_statement, adjusted_pos, NULL);
|
tree.find_node_matching_source_location(symbol_plain_statement, position_in_statement, NULL);
|
||||||
|
|
||||||
if (plain_statement == NULL) {
|
if (plain_statement == NULL) {
|
||||||
// Not part of a plain statement. This could be e.g. a for loop header, case expression,
|
// Not part of a plain statement. This could be e.g. a for loop header, case expression,
|
||||||
// etc. Do generic file completions (issue #1309). If we had to backtrack, it means
|
// etc. Do generic file completions (issue #1309). If we had to backtrack, it means
|
||||||
|
@ -1287,7 +1287,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
|
||||||
// tree).
|
// tree).
|
||||||
bool do_file = true;
|
bool do_file = true;
|
||||||
if (flags & COMPLETION_REQUEST_AUTOSUGGESTION) {
|
if (flags & COMPLETION_REQUEST_AUTOSUGGESTION) {
|
||||||
if (adjusted_pos < pos) {
|
if (position_in_statement < pos) {
|
||||||
do_file = false;
|
do_file = false;
|
||||||
} else if (pos > 0) {
|
} else if (pos > 0) {
|
||||||
// If the previous character is in one of these types, we don't do file
|
// If the previous character is in one of these types, we don't do file
|
||||||
|
@ -1356,7 +1356,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
|
||||||
size_t matching_arg_index = -1;
|
size_t matching_arg_index = -1;
|
||||||
for (size_t i = 0; i < all_arguments.size(); i++) {
|
for (size_t i = 0; i < all_arguments.size(); i++) {
|
||||||
const parse_node_t *node = all_arguments.at(i);
|
const parse_node_t *node = all_arguments.at(i);
|
||||||
if (node->location_in_or_at_end_of_source_range(adjusted_pos)) {
|
if (node->location_in_or_at_end_of_source_range(position_in_statement)) {
|
||||||
matching_arg_index = i;
|
matching_arg_index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1372,7 +1372,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
|
||||||
// previous argument is the matching one. But if the cursor was in or at the end
|
// previous argument is the matching one. But if the cursor was in or at the end
|
||||||
// of the argument, then the current argument is the matching one, and the
|
// of the argument, then the current argument is the matching one, and the
|
||||||
// previous argument is the one before it.
|
// previous argument is the one before it.
|
||||||
bool cursor_in_whitespace = (adjusted_pos < pos);
|
bool cursor_in_whitespace = ! plain_statement->location_in_or_at_end_of_source_range(pos);
|
||||||
if (cursor_in_whitespace) {
|
if (cursor_in_whitespace) {
|
||||||
current_argument = L"";
|
current_argument = L"";
|
||||||
previous_argument = matching_arg;
|
previous_argument = matching_arg;
|
||||||
|
@ -1397,7 +1397,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
|
||||||
bool in_redirection = false;
|
bool in_redirection = false;
|
||||||
if (matching_arg_index == (size_t)(-1)) {
|
if (matching_arg_index == (size_t)(-1)) {
|
||||||
const parse_node_t *redirection = tree.find_node_matching_source_location(
|
const parse_node_t *redirection = tree.find_node_matching_source_location(
|
||||||
symbol_redirection, adjusted_pos, plain_statement);
|
symbol_redirection, position_in_statement, plain_statement);
|
||||||
in_redirection = (redirection != NULL);
|
in_redirection = (redirection != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1818,6 +1818,7 @@ static void test_complete(void) {
|
||||||
|
|
||||||
if (system("mkdir -p '/tmp/complete_test/'")) err(L"mkdir failed");
|
if (system("mkdir -p '/tmp/complete_test/'")) err(L"mkdir failed");
|
||||||
if (system("touch '/tmp/complete_test/testfile'")) err(L"touch failed");
|
if (system("touch '/tmp/complete_test/testfile'")) err(L"touch failed");
|
||||||
|
if (system("touch '/tmp/complete_test/has space'")) err(L"touch failed");
|
||||||
if (system("chmod 700 '/tmp/complete_test/testfile'")) err(L"chmod failed");
|
if (system("chmod 700 '/tmp/complete_test/testfile'")) err(L"chmod failed");
|
||||||
|
|
||||||
completions.clear();
|
completions.clear();
|
||||||
|
@ -1837,6 +1838,14 @@ static void test_complete(void) {
|
||||||
do_test(completions.size() == 1);
|
do_test(completions.size() == 1);
|
||||||
do_test(completions.at(0).completion == L"e");
|
do_test(completions.at(0).completion == L"e");
|
||||||
|
|
||||||
|
// Completing after spaces - see #2447
|
||||||
|
completions.clear();
|
||||||
|
complete(L"echo (ls /tmp/complete_test/has\\ ", &completions, COMPLETION_REQUEST_DEFAULT,
|
||||||
|
vars);
|
||||||
|
do_test(completions.size() == 1);
|
||||||
|
do_test(completions.at(0).completion == L"space");
|
||||||
|
|
||||||
|
|
||||||
// Add a function and test completing it in various ways.
|
// Add a function and test completing it in various ways.
|
||||||
struct function_data_t func_data = {};
|
struct function_data_t func_data = {};
|
||||||
func_data.name = L"scuttlebutt";
|
func_data.name = L"scuttlebutt";
|
||||||
|
|
Loading…
Reference in a new issue