# HG changeset patch # User Christian Brabandt # Date 1697055304 -7200 # Node ID 59879206a13d7e20d8795af09998934ac3da0175 # Parent 26e2c7ba4943b642cd5587f3349c0790f9cfe351 patch 9.0.2018: complete_info() returns wrong index Commit: https://github.com/vim/vim/commit/69fb5afb3bc9da24c2fb0eafb0027ba9c6502fc2 Author: LemonBoy Date: Wed Oct 11 21:55:56 2023 +0200 patch 9.0.2018: complete_info() returns wrong index Problem: complete_info() returns wrong index Solution: Make order of 'info' in completion_info consistent Start the iteration from the same point and follow the same direction as done when assigning the completion numbers. This way we remove the dependence on the completion direction and make the order of 'info' consistent. closes: #12230 closes: #12971 Signed-off-by: Christian Brabandt Co-authored-by: LemonBoy diff --git a/src/insexpand.c b/src/insexpand.c --- a/src/insexpand.c +++ b/src/insexpand.c @@ -3040,6 +3040,43 @@ ins_compl_update_sequence_numbers(void) } } + static int +info_add_completion_info(list_T *li) +{ + compl_T *match; + + if (compl_first_match == NULL) + return OK; + + // 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. + match = compl_dir_forward() + ? compl_first_match->cp_next : compl_first_match->cp_prev->cp_prev; + while (match != NULL && !match_at_original_text(match)) + { + dict_T *di = dict_alloc(); + + if (di == NULL) + return FAIL; + if (list_append_dict(li, di) == FAIL) + return FAIL; + dict_add_string(di, "word", match->cp_str); + dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]); + dict_add_string(di, "menu", match->cp_text[CPT_MENU]); + dict_add_string(di, "kind", match->cp_text[CPT_KIND]); + dict_add_string(di, "info", match->cp_text[CPT_INFO]); + if (match->cp_user_data.v_type == VAR_UNKNOWN) + // Add an empty string for backwards compatibility + dict_add_string(di, "user_data", (char_u *)""); + else + dict_add_tv(di, "user_data", &match->cp_user_data); + + match = compl_dir_forward() ? match->cp_next : match->cp_prev; + } + + return OK; +} + /* * Get complete information */ @@ -3088,41 +3125,13 @@ get_complete_info(list_T *what_list, dic if (ret == OK && (what_flag & CI_WHAT_ITEMS)) { list_T *li; - dict_T *di; - compl_T *match; li = list_alloc(); if (li == NULL) return; ret = dict_add_list(retdict, "items", li); - if (ret == OK && compl_first_match != NULL) - { - match = compl_first_match; - do - { - if (!match_at_original_text(match)) - { - di = dict_alloc(); - if (di == NULL) - return; - ret = list_append_dict(li, di); - if (ret != OK) - return; - dict_add_string(di, "word", match->cp_str); - dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]); - dict_add_string(di, "menu", match->cp_text[CPT_MENU]); - dict_add_string(di, "kind", match->cp_text[CPT_KIND]); - dict_add_string(di, "info", match->cp_text[CPT_INFO]); - if (match->cp_user_data.v_type == VAR_UNKNOWN) - // Add an empty string for backwards compatibility - dict_add_string(di, "user_data", (char_u *)""); - else - dict_add_tv(di, "user_data", &match->cp_user_data); - } - match = match->cp_next; - } - while (match != NULL && !is_first_match(match)); - } + if (ret == OK) + ret = info_add_completion_info(li); } if (ret == OK && (what_flag & CI_WHAT_SELECTED)) diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -2243,5 +2243,43 @@ func Test_ins_complete_popup_position() call StopVimInTerminal(buf) endfunc +func GetCompleteInfo() + let g:compl_info = complete_info() + return '' +endfunc + +func Test_complete_info_index() + new + call setline(1, ["aaa", "bbb", "ccc", "ddd", "eee", "fff"]) + inoremap =GetCompleteInfo() + + " Ensure 'index' in complete_info() is coherent with the 'items' array. + + set completeopt=menu,preview + " Search forward. + call feedkeys("Go\\\\_dd", 'tx') + call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word']) + call feedkeys("Go\\\\\_dd", 'tx') + call assert_equal("bbb", g:compl_info['items'][g:compl_info['selected']]['word']) + + " Search backward. + call feedkeys("Go\\\\_dd", 'tx') + call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) + call feedkeys("Go\\\\\_dd", 'tx') + call assert_equal("eee", g:compl_info['items'][g:compl_info['selected']]['word']) + + " Add 'noselect', check that 'selected' is -1 when nothing is selected. + set completeopt+=noselect + " Search forward. + call feedkeys("Go\\\\_dd", 'tx') + call assert_equal(-1, g:compl_info['selected']) + + " Search backward. + call feedkeys("Go\\\\_dd", 'tx') + call assert_equal(-1, g:compl_info['selected']) + + set completeopt& + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2018, +/**/ 2017, /**/ 2016,