]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.2018: complete_info() returns wrong index v9.0.2018
authorLemonBoy <thatlemon@gmail.com>
Wed, 11 Oct 2023 19:55:56 +0000 (21:55 +0200)
committerChristian Brabandt <cb@256bit.org>
Wed, 11 Oct 2023 19:55:56 +0000 (21:55 +0200)
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 <cb@256bit.org>
Co-authored-by: LemonBoy <thatlemon@gmail.com>
src/insexpand.c
src/testdir/test_ins_complete.vim
src/version.c

index 3b06ee02de5e587559e8bd2eaeb15891e2bbffd1..f225cd3844663eea2e01f1e3134291e5469c1c64 100644 (file)
@@ -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, dict_T *retdict)
     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))
index cedc09f7ad689c789d681c4465c182fc64f6459b..c7f9e9b28bd5cf7cc3b7d5d717f0eebe4af08fa0 100644 (file)
@@ -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 <buffer><F5> <C-R>=GetCompleteInfo()<CR>
+
+  " Ensure 'index' in complete_info() is coherent with the 'items' array.
+
+  set completeopt=menu,preview
+  " 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 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'])
+
+  " 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 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'])
+
+  " Add 'noselect', check that 'selected' is -1 when nothing is selected.
+  set completeopt+=noselect
+  " Search forward.
+  call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx')
+  call assert_equal(-1, g:compl_info['selected'])
+
+  " Search backward.
+  call feedkeys("Go\<C-X>\<C-P>\<F5>\<Esc>_dd", 'tx')
+  call assert_equal(-1, g:compl_info['selected'])
+
+  set completeopt&
+  bwipe!
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
index 7db93c42b3d0f6e58b4f2985fe58ca506eb06ae6..d05016389ad7426e551fb494ee29dcb766796299 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2018,
 /**/
     2017,
 /**/