Merge pull request #25806 from zeertzjq/vim-9.0.2074

vim-patch:9.0.{2074,2077}: Completion menu may be wrong
This commit is contained in:
zeertzjq 2023-10-28 06:44:08 +08:00 committed by GitHub
commit d2e7cc68e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 5 deletions

View File

@ -2702,10 +2702,41 @@ static int info_add_completion_info(list_T *li)
return OK;
}
bool forward = compl_dir_forward();
compl_T *match = compl_first_match;
// There are four cases to consider here:
// 1) when just going forward through the menu,
// compl_first_match should point to the initial entry with
// number zero and CP_ORIGINAL_TEXT flag set
// 2) when just going backwards,
// compl-first_match should point to the last entry before
// the entry with the CP_ORIGINAL_TEXT flag set
// 3) when first going forwards and then backwards, e.g.
// pressing C-N, C-P, compl_first_match points to the
// last entry before the entry with the CP_ORIGINAL_TEXT
// flag set and next-entry moves opposite through the list
// compared to case 2, so pretend the direction is forward again
// 4) when first going backwards and then forwards, e.g.
// pressing C-P, C-N, compl_first_match points to the
// first entry with the CP_ORIGINAL_TEXT
// flag set and next-entry moves in opposite direction through the list
// compared to case 1, so pretend the direction is backwards again
//
// But only do this when the 'noselect' option is not active!
if (!compl_no_select) {
if (forward && !match_at_original_text(match)) {
forward = false;
} else if (!forward && match_at_original_text(match)) {
forward = true;
}
}
// Skip the element with the CP_ORIGINAL_TEXT flag at the beginning, in case of
// forward completion, or at the end, in case of backward completion.
compl_T *match = compl_dir_forward() ? compl_first_match->cp_next
: compl_first_match->cp_prev->cp_prev;
match = forward ? match->cp_next
: (compl_no_select ? match->cp_prev : match->cp_prev->cp_prev);
while (match != NULL && !match_at_original_text(match)) {
dict_T *di = tv_dict_alloc();
@ -2722,7 +2753,7 @@ static int info_add_completion_info(list_T *li)
tv_dict_add_tv(di, S_LEN("user_data"), &match->cp_user_data);
}
match = compl_dir_forward() ? match->cp_next : match->cp_prev;
match = forward ? match->cp_next : match->cp_prev;
}
return OK;

View File

@ -2315,17 +2315,72 @@ func Test_complete_info_index()
" Ensure 'index' in complete_info() is coherent with the 'items' array.
set completeopt=menu,preview
" Search forward.
" Search forward
call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("bbb", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("ccc", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("ddd", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("eee", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
" Search forward: unselected item
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal(6 , len(g:compl_info['items']))
call assert_equal(-1 , g:compl_info['selected'])
" Search backward.
" Search backward
call feedkeys("Go\<C-X>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("eee", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("ddd", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("ccc", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("bbb", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
" search backwards: unselected item
call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal(6 , len(g:compl_info['items']))
call assert_equal(-1 , g:compl_info['selected'])
" switch direction: forwards, then backwards
call feedkeys("Go\<C-X>\<C-N>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
" switch direction: forwards, then backwards, then forwards again
call feedkeys("Go\<C-X>\<C-N>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-P>\<C-P>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
" switch direction: backwards, then forwards
call feedkeys("Go\<C-X>\<C-P>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
" switch direction: backwards, then forwards, then backwards again
call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-N>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
" Add 'noselect', check that 'selected' is -1 when nothing is selected.
set completeopt+=noselect
@ -2337,6 +2392,16 @@ func Test_complete_info_index()
call feedkeys("Go\<C-X>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal(-1, g:compl_info['selected'])
" Check if index out of range
" https://github.com/vim/vim/pull/12971
call feedkeys("Go\<C-X>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx')
call assert_equal(0, g:compl_info['selected'])
call assert_equal(6 , len(g:compl_info['items']))
call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
call assert_equal(6 , len(g:compl_info['items']))
set completeopt&
bwipe!
endfunc