mirror of
https://github.com/fish-shell/fish-shell
synced 2024-09-21 06:51:58 +00:00
Do not stomp token if tab-expansion of wildcards exceeds limit or is canceled
Hitting tab on "echo **" will often result in more than 256 matches.
Commit 143757e8c
(Expand wildcards on tab, 2021-11-27) describes this scenario
> If the expansion would produce more than 256 items, we flash the command
> line and do nothing, since it would make the commandline overfull.
Yet we actually erase the "**" token, which seems wrong since we already
flash the command line. Fix this, at the cost of making the code a bit uglier.
I tried to write a test in tests/pexpects/wildcard_tab.py but that doesn't
seem to work because pexpect provides only a "dumb" terminal. I wonder if we
can test what we write to the screen without depending on a terminal emulator.
This commit is contained in:
parent
8bfc987705
commit
bfd5e8dfbe
1 changed files with 26 additions and 28 deletions
|
@ -778,9 +778,7 @@ class reader_data_t : public std::enable_shared_from_this<reader_data_t> {
|
|||
|
||||
/// Given that the user is tab-completing a token \p wc whose cursor is at \p pos in the token,
|
||||
/// try expanding it as a wildcard, populating \p result with the expanded string.
|
||||
/// \return true to suppress completions (e.g. because we expanded the wildcard, or the user
|
||||
/// cancelled), false to allow normal completions.
|
||||
bool try_expand_wildcard(wcstring wc, size_t pos, wcstring *result);
|
||||
expand_result_t::result_t try_expand_wildcard(wcstring wc, size_t pos, wcstring *result);
|
||||
|
||||
void move_word(editable_line_t *el, bool move_right, bool erase, enum move_word_style_t style,
|
||||
bool newv);
|
||||
|
@ -2788,7 +2786,8 @@ void reader_data_t::apply_commandline_state_changes() {
|
|||
}
|
||||
}
|
||||
|
||||
bool reader_data_t::try_expand_wildcard(wcstring wc, size_t position, wcstring *result) {
|
||||
expand_result_t::result_t reader_data_t::try_expand_wildcard(wcstring wc, size_t position,
|
||||
wcstring *result) {
|
||||
// Hacky from #8593: only expand if there are wildcards in the "current path component."
|
||||
// Find the "current path component" by looking for an unescaped slash before and after
|
||||
// our position.
|
||||
|
@ -2805,7 +2804,7 @@ bool reader_data_t::try_expand_wildcard(wcstring wc, size_t position, wcstring *
|
|||
comp_end++;
|
||||
}
|
||||
if (!wildcard_has(wc.c_str() + comp_start, comp_end - comp_start)) {
|
||||
return false;
|
||||
return expand_result_t::wildcard_no_match;
|
||||
}
|
||||
|
||||
result->clear();
|
||||
|
@ -2818,21 +2817,8 @@ bool reader_data_t::try_expand_wildcard(wcstring wc, size_t position, wcstring *
|
|||
expand_flag::preserve_home_tildes};
|
||||
completion_list_t expanded;
|
||||
expand_result_t ret = expand_string(std::move(wc), &expanded, flags, ctx);
|
||||
switch (ret.result) {
|
||||
case expand_result_t::error:
|
||||
// This may come about if we exceeded the max number of matches.
|
||||
// Return "success" to suppress normal completions.
|
||||
flash();
|
||||
return true;
|
||||
case expand_result_t::wildcard_no_match:
|
||||
// Allow normal completions.
|
||||
return false;
|
||||
case expand_result_t::cancel:
|
||||
// e.g. the user hit control-C. Suppress normal completions.
|
||||
return true;
|
||||
case expand_result_t::ok:
|
||||
break;
|
||||
}
|
||||
if (ret != expand_result_t::ok) return ret.result;
|
||||
|
||||
// Insert all matches (escaped) and a trailing space.
|
||||
wcstring joined;
|
||||
for (const auto &match : expanded) {
|
||||
|
@ -2848,7 +2834,7 @@ bool reader_data_t::try_expand_wildcard(wcstring wc, size_t position, wcstring *
|
|||
}
|
||||
|
||||
*result = std::move(joined);
|
||||
return true;
|
||||
return expand_result_t::ok;
|
||||
}
|
||||
|
||||
void reader_data_t::compute_and_apply_completions(readline_cmd_t c, readline_loop_state_t &rls) {
|
||||
|
@ -2886,13 +2872,25 @@ void reader_data_t::compute_and_apply_completions(readline_cmd_t c, readline_loo
|
|||
// Check if we have a wildcard within this string; if so we first attempt to expand the
|
||||
// wildcard; if that succeeds we don't then apply user completions (#8593).
|
||||
wcstring wc_expanded;
|
||||
if (try_expand_wildcard(wcstring(token_begin, token_end), position_in_token, &wc_expanded)) {
|
||||
rls.comp.clear();
|
||||
rls.complete_did_insert = false;
|
||||
size_t tok_off = static_cast<size_t>(token_begin - buff);
|
||||
size_t tok_len = static_cast<size_t>(token_end - token_begin);
|
||||
el->push_edit(edit_t{tok_off, tok_len, std::move(wc_expanded)});
|
||||
return;
|
||||
switch (
|
||||
try_expand_wildcard(wcstring(token_begin, token_end), position_in_token, &wc_expanded)) {
|
||||
case expand_result_t::error:
|
||||
// This may come about if we exceeded the max number of matches.
|
||||
// Return "success" to suppress normal completions.
|
||||
flash();
|
||||
return;
|
||||
case expand_result_t::wildcard_no_match:
|
||||
break;
|
||||
case expand_result_t::cancel:
|
||||
// e.g. the user hit control-C. Suppress normal completions.
|
||||
return;
|
||||
case expand_result_t::ok:
|
||||
rls.comp.clear();
|
||||
rls.complete_did_insert = false;
|
||||
size_t tok_off = static_cast<size_t>(token_begin - buff);
|
||||
size_t tok_len = static_cast<size_t>(token_end - token_begin);
|
||||
el->push_edit(edit_t{tok_off, tok_len, std::move(wc_expanded)});
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct a copy of the string from the beginning of the command substitution
|
||||
|
|
Loading…
Reference in a new issue