diff options
author | glepnir <glephunter@gmail.com> | 2024-11-30 18:24:31 +0800 |
---|---|---|
committer | glepnir <glephunter@gmail.com> | 2024-11-30 20:22:53 +0800 |
commit | 1af1e918d30c062dfcb7d4ce2f4cfbca1d11e2ab (patch) | |
tree | 388fa541dd330e0ee004d34ea991434c55104d18 | |
parent | d512479115296a2df246ef7afbfa55f057fecae2 (diff) | |
download | rneovim-1af1e918d30c062dfcb7d4ce2f4cfbca1d11e2ab.tar.gz rneovim-1af1e918d30c062dfcb7d4ce2f4cfbca1d11e2ab.tar.bz2 rneovim-1af1e918d30c062dfcb7d4ce2f4cfbca1d11e2ab.zip |
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
https://github.com/vim/vim/commit/a49c077a883b2566882df9069385ed1e1277ca64
-rw-r--r-- | src/nvim/insexpand.c | 136 | ||||
-rw-r--r-- | test/old/testdir/test_popup.vim | 25 |
2 files changed, 87 insertions, 74 deletions
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 6a45a06fb9..820647df97 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -1176,6 +1176,20 @@ static int ins_compl_build_pum(void) bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0; bool compl_fuzzy_match = (cur_cot_flags & kOptCotFlagFuzzy) != 0; 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 { // When 'completeopt' contains "fuzzy" and leader is not NULL or empty, // 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 = 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; } while (comp != NULL && !is_first_match(comp)); @@ -1205,65 +1266,9 @@ static int ins_compl_build_pum(void) assert(compl_match_arraysize >= 0); 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 - // 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; + i = 0; comp = match_head; 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) { compl_match_array[i].pum_text = comp->cp_text[CPT_ABBR]; } else { @@ -1279,23 +1284,6 @@ static int ins_compl_build_pum(void) } else { 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; comp->cp_match_next = NULL; comp = match_next; diff --git a/test/old/testdir/test_popup.vim b/test/old/testdir/test_popup.vim index 601ba6c688..33e86678c8 100644 --- a/test/old/testdir/test_popup.vim +++ b/test/old/testdir/test_popup.vim @@ -1675,4 +1675,29 @@ func Test_pum_completeitemalign() call StopVimInTerminal(buf) 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 |