mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 04:18:18 +00:00
vim-patch:9.1.0896: completion list wrong after v9.1.0891
Problem: completion list wrong after v9.1.0891
Solution: update compl_mach_array after leader change
(glepnir)
compl_shown_match update not correct after refactoring in v9.1.0891
Unfortunately, this regressed what item is selected after leader change.
So generate compl_match_array before updating compl_shown_match range,
and split generate compl_match_array into range match_head
fixes: https://github.com/vim/vim/issues/16128
closes: https://github.com/vim/vim/pull/16129
a49c077a88
This commit is contained in:
@@ -1176,6 +1176,20 @@ static int ins_compl_build_pum(void)
|
|||||||
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0;
|
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0;
|
||||||
bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0;
|
bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0;
|
||||||
compl_T *match_head = NULL, *match_tail = NULL;
|
compl_T *match_head = NULL, *match_tail = NULL;
|
||||||
|
|
||||||
|
// If the current match is the original text don't find the first
|
||||||
|
// match after it, don't highlight anything.
|
||||||
|
bool shown_match_ok = match_at_original_text(compl_shown_match);
|
||||||
|
|
||||||
|
if (strequal(compl_leader, compl_orig_text) && !shown_match_ok) {
|
||||||
|
compl_shown_match = compl_no_select ? compl_first_match : compl_first_match->cp_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool did_find_shown_match = false;
|
||||||
|
compl_T *shown_compl = NULL;
|
||||||
|
int i = 0;
|
||||||
|
int cur = -1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
|
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
|
||||||
// set the cp_score for later comparisons.
|
// set the cp_score for later comparisons.
|
||||||
@@ -1194,6 +1208,53 @@ static int ins_compl_build_pum(void)
|
|||||||
match_tail->cp_match_next = comp;
|
match_tail->cp_match_next = comp;
|
||||||
}
|
}
|
||||||
match_tail = comp;
|
match_tail = comp;
|
||||||
|
if (!shown_match_ok && !compl_fuzzy_match) {
|
||||||
|
if (comp == compl_shown_match || did_find_shown_match) {
|
||||||
|
// This item is the shown match or this is the
|
||||||
|
// first displayed item after the shown match.
|
||||||
|
compl_shown_match = comp;
|
||||||
|
did_find_shown_match = true;
|
||||||
|
shown_match_ok = true;
|
||||||
|
} else {
|
||||||
|
// Remember this displayed match for when the
|
||||||
|
// shown match is just below it.
|
||||||
|
shown_compl = comp;
|
||||||
|
}
|
||||||
|
cur = i;
|
||||||
|
} else if (compl_fuzzy_match) {
|
||||||
|
if (i == 0) {
|
||||||
|
shown_compl = comp;
|
||||||
|
}
|
||||||
|
// Update the maximum fuzzy score and the shown match
|
||||||
|
// if the current item's score is higher
|
||||||
|
if (comp->cp_score > max_fuzzy_score) {
|
||||||
|
did_find_shown_match = true;
|
||||||
|
max_fuzzy_score = comp->cp_score;
|
||||||
|
if (!compl_no_select) {
|
||||||
|
compl_shown_match = comp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!shown_match_ok && comp == compl_shown_match && !compl_no_select) {
|
||||||
|
cur = i;
|
||||||
|
shown_match_ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp == compl_shown_match && !compl_fuzzy_match) {
|
||||||
|
did_find_shown_match = true;
|
||||||
|
// When the original text is the shown match don't set
|
||||||
|
// compl_shown_match.
|
||||||
|
if (match_at_original_text(comp)) {
|
||||||
|
shown_match_ok = true;
|
||||||
|
}
|
||||||
|
if (!shown_match_ok && shown_compl != NULL) {
|
||||||
|
// The shown match isn't displayed, set it to the
|
||||||
|
// previously displayed match.
|
||||||
|
compl_shown_match = shown_compl;
|
||||||
|
shown_match_ok = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
comp = comp->cp_next;
|
comp = comp->cp_next;
|
||||||
} while (comp != NULL && !is_first_match(comp));
|
} while (comp != NULL && !is_first_match(comp));
|
||||||
@@ -1205,65 +1266,9 @@ static int ins_compl_build_pum(void)
|
|||||||
assert(compl_match_arraysize >= 0);
|
assert(compl_match_arraysize >= 0);
|
||||||
compl_match_array = xcalloc((size_t)compl_match_arraysize, sizeof(pumitem_T));
|
compl_match_array = xcalloc((size_t)compl_match_arraysize, sizeof(pumitem_T));
|
||||||
|
|
||||||
// If the current match is the original text don't find the first
|
i = 0;
|
||||||
// match after it, don't highlight anything.
|
|
||||||
bool shown_match_ok = match_at_original_text(compl_shown_match);
|
|
||||||
|
|
||||||
if (strequal(compl_leader, compl_orig_text) && !shown_match_ok) {
|
|
||||||
compl_shown_match = compl_no_select ? compl_first_match : compl_first_match->cp_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
compl_T *shown_compl = NULL;
|
|
||||||
bool did_find_shown_match = match_head == match_tail ? true : false;
|
|
||||||
int cur = -1;
|
|
||||||
int i = 0;
|
|
||||||
comp = match_head;
|
comp = match_head;
|
||||||
while (comp != NULL) {
|
while (comp != NULL) {
|
||||||
if (!shown_match_ok && !compl_fuzzy_match) {
|
|
||||||
if (comp == compl_shown_match || did_find_shown_match) {
|
|
||||||
// This item is the shown match or this is the
|
|
||||||
// first displayed item after the shown match.
|
|
||||||
compl_shown_match = comp;
|
|
||||||
did_find_shown_match = true;
|
|
||||||
shown_match_ok = true;
|
|
||||||
} else {
|
|
||||||
// Remember this displayed match for when the
|
|
||||||
// shown match is just below it.
|
|
||||||
shown_compl = comp;
|
|
||||||
}
|
|
||||||
cur = i;
|
|
||||||
} else if (compl_fuzzy_match) {
|
|
||||||
if (i == 0) {
|
|
||||||
shown_compl = comp;
|
|
||||||
}
|
|
||||||
// Update the maximum fuzzy score and the shown match
|
|
||||||
// if the current item's score is higher
|
|
||||||
if (comp->cp_score > max_fuzzy_score) {
|
|
||||||
did_find_shown_match = true;
|
|
||||||
max_fuzzy_score = comp->cp_score;
|
|
||||||
if (!compl_no_select) {
|
|
||||||
compl_shown_match = comp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shown_match_ok && comp == compl_shown_match && !compl_no_select) {
|
|
||||||
cur = i;
|
|
||||||
shown_match_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no "no select" condition and the max fuzzy
|
|
||||||
// score is positive, or there is no completion leader or the
|
|
||||||
// leader length is zero, mark the shown match as valid and
|
|
||||||
// reset the current index.
|
|
||||||
if (!compl_no_select
|
|
||||||
&& (max_fuzzy_score > 0
|
|
||||||
|| (compl_leader == NULL || lead_len == 0))) {
|
|
||||||
if (match_at_original_text(compl_shown_match)) {
|
|
||||||
compl_shown_match = shown_compl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comp->cp_text[CPT_ABBR] != NULL) {
|
if (comp->cp_text[CPT_ABBR] != NULL) {
|
||||||
compl_match_array[i].pum_text = comp->cp_text[CPT_ABBR];
|
compl_match_array[i].pum_text = comp->cp_text[CPT_ABBR];
|
||||||
} else {
|
} else {
|
||||||
@@ -1279,23 +1284,6 @@ static int ins_compl_build_pum(void)
|
|||||||
} else {
|
} else {
|
||||||
compl_match_array[i++].pum_extra = comp->cp_fname;
|
compl_match_array[i++].pum_extra = comp->cp_fname;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp == compl_shown_match && !compl_fuzzy_match) {
|
|
||||||
did_find_shown_match = true;
|
|
||||||
|
|
||||||
// When the original text is the shown match don't set
|
|
||||||
// compl_shown_match.
|
|
||||||
if (match_at_original_text(comp)) {
|
|
||||||
shown_match_ok = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shown_match_ok && shown_compl != NULL) {
|
|
||||||
// The shown match isn't displayed, set it to the
|
|
||||||
// previously displayed match.
|
|
||||||
compl_shown_match = shown_compl;
|
|
||||||
shown_match_ok = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compl_T *match_next = comp->cp_match_next;
|
compl_T *match_next = comp->cp_match_next;
|
||||||
comp->cp_match_next = NULL;
|
comp->cp_match_next = NULL;
|
||||||
comp = match_next;
|
comp = match_next;
|
||||||
|
@@ -1675,4 +1675,29 @@ func Test_pum_completeitemalign()
|
|||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_pum_keep_select()
|
||||||
|
CheckScreendump
|
||||||
|
let lines =<< trim END
|
||||||
|
set completeopt=menu,menuone,noinsert
|
||||||
|
END
|
||||||
|
call writefile(lines, 'Xscript', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S Xscript', {})
|
||||||
|
call TermWait(buf)
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "ggSFab\<CR>Five\<CR>find\<CR>film\<CR>\<C-X>\<C-P>")
|
||||||
|
call TermWait(buf, 50)
|
||||||
|
call VerifyScreenDump(buf, 'Test_pum_keep_select_01', {})
|
||||||
|
call term_sendkeys(buf, "\<C-E>\<Esc>")
|
||||||
|
call TermWait(buf, 50)
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "S\<C-X>\<C-P>")
|
||||||
|
call TermWait(buf, 50)
|
||||||
|
call term_sendkeys(buf, "F")
|
||||||
|
call VerifyScreenDump(buf, 'Test_pum_keep_select_02', {})
|
||||||
|
call term_sendkeys(buf, "\<C-E>\<Esc>")
|
||||||
|
|
||||||
|
call TermWait(buf, 50)
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user