]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1876: pre-inserted text not exposed in cmdcomplete_info() v9.1.1876
authorGirish Palya <girishji@gmail.com>
Sun, 26 Oct 2025 18:30:40 +0000 (18:30 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 26 Oct 2025 18:37:57 +0000 (18:37 +0000)
Problem:  pre-inserted text not exposed in complete_info()
Solution: Add the pre-inserted text to the complete_info() Vim script
          function (Girish Palya)

closes: #18571

Signed-off-by: Girish Palya <girishji@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Feat: expose preinserted text in complete_info()

Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/builtin.txt
src/insexpand.c
src/testdir/test_ins_complete.vim
src/testdir/test_popup.vim
src/testdir/test_vim9_builtin.vim
src/version.c

index b37a08e21d56d4b401036cf4450006f9a621bfa0..8acdea970c5eff25db1e9ebb25926e100177ecb6 100644 (file)
@@ -2001,10 +2001,8 @@ complete_info([{what}])                                  *complete_info()*
                Returns a |Dictionary| with information about Insert mode
                completion.  See |ins-completion|.
                The items are:
-                  mode         Current completion mode name string.
-                               See |complete_info_mode| for the values.
-                  pum_visible  |TRUE| if popup menu is visible.
-                               See |pumvisible()|.
+                  completed    Return a dictionary containing the entries of
+                               the currently selected index item.
                   items        List of all completion candidates.  Each item
                                is a dictionary containing the entries "word",
                                "abbr", "menu", "kind", "info" and
@@ -2015,13 +2013,18 @@ complete_info([{what}])                                 *complete_info()*
                                and "items" are in "what", the returned list
                                will still be named "items", but each item
                                will have an additional "match" field.
+                  mode         Current completion mode name string.
+                               See |complete_info_mode| for the values.
+                  preinserted_text
+                               The actual text that is pre-inserted, see
+                               |preinserted()|.
+                  pum_visible  |TRUE| if popup menu is visible.
+                               See |pumvisible()|.
                   selected     Selected item index.  First index is zero.
                                Index is -1 if no item is selected (showing
                                typed text only, or the last completion after
                                no item is selected when using the <Up> or
                                <Down> keys)
-                  completed    Return a dictionary containing the entries of
-                               the currently selected index item.
 
                                                        *complete_info_mode*
                mode values are:
index 4edcfe53e043024fd79621b03c105766b7142767..321700414b7ee73007a463540bda5d4ac4e33213 100644 (file)
@@ -4186,13 +4186,14 @@ get_complete_info(list_T *what_list, dict_T *retdict)
 {
     int                ret = OK;
     listitem_T *item;
-#define CI_WHAT_MODE           0x01
-#define CI_WHAT_PUM_VISIBLE    0x02
-#define CI_WHAT_ITEMS          0x04
-#define CI_WHAT_SELECTED       0x08
-#define CI_WHAT_COMPLETED      0x10
-#define CI_WHAT_MATCHES                0x20
-#define CI_WHAT_ALL            0xff
+#define CI_WHAT_MODE               0x01
+#define CI_WHAT_PUM_VISIBLE        0x02
+#define CI_WHAT_ITEMS              0x04
+#define CI_WHAT_SELECTED           0x08
+#define CI_WHAT_COMPLETED          0x10
+#define CI_WHAT_MATCHES                    0x20
+#define CI_WHAT_PREINSERTED_TEXT    0x40
+#define CI_WHAT_ALL                0xff
     int                what_flag;
 
     if (what_list == NULL)
@@ -4215,6 +4216,8 @@ get_complete_info(list_T *what_list, dict_T *retdict)
                what_flag |= CI_WHAT_SELECTED;
            else if (STRCMP(what, "completed") == 0)
                what_flag |= CI_WHAT_COMPLETED;
+           else if (STRCMP(what, "preinserted_text") == 0)
+               what_flag |= CI_WHAT_PREINSERTED_TEXT;
            else if (STRCMP(what, "matches") == 0)
                what_flag |= CI_WHAT_MATCHES;
        }
@@ -4226,6 +4229,15 @@ get_complete_info(list_T *what_list, dict_T *retdict)
     if (ret == OK && (what_flag & CI_WHAT_PUM_VISIBLE))
        ret = dict_add_number(retdict, "pum_visible", pum_visible());
 
+    if (ret == OK && (what_flag & CI_WHAT_PREINSERTED_TEXT))
+    {
+       char_u  *line = ml_get_curline();
+       int     len = compl_ins_end_col - curwin->w_cursor.col;
+
+       ret = dict_add_string_len(retdict, "preinserted_text",
+               (len > 0) ? line + curwin->w_cursor.col : (char_u *)"", len);
+    }
+
     if (ret == OK && (what_flag & (CI_WHAT_ITEMS | CI_WHAT_SELECTED
                                    | CI_WHAT_MATCHES | CI_WHAT_COMPLETED)))
     {
index 6d492373c4c320abec83842a8123e6b594314b00..02a193cad21e335fd4e096cb99508046608c5a24 100644 (file)
@@ -572,15 +572,15 @@ func Test_completefunc_info()
   set completeopt=menuone
   set completefunc=CompleteTest
   call feedkeys("i\<C-X>\<C-U>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
-  call assert_equal("matched{'pum_visible': 1, 'mode': 'function', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
+  call assert_equal("matched{'preinserted_text': '', 'pum_visible': 1, 'mode': 'function', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
   %d
   set complete=.,FCompleteTest
   call feedkeys("i\<C-N>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
-  call assert_equal("matched{'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
+  call assert_equal("matched{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
   %d
   set complete=.,F
   call feedkeys("i\<C-N>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
-  call assert_equal("matched{'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
+  call assert_equal("matched{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
   set completeopt&
   set complete&
   set completefunc&
@@ -698,17 +698,17 @@ func CompleteInfoTestUserDefinedFn(mvmt, idx, noselect)
   set completefunc=CompleteInfoUserDefinedFn
   call feedkeys("i\<C-X>\<C-U>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
   let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : ''
-  call assert_equal(completed. "{'pum_visible': 1, 'mode': 'function', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
+  call assert_equal(completed. "{'preinserted_text': '', 'pum_visible': 1, 'mode': 'function', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
   %d
   set complete=.,FCompleteInfoUserDefinedFn
   call feedkeys("i\<C-N>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
   let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : ''
-  call assert_equal(completed. "{'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
+  call assert_equal(completed. "{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
   %d
   set complete=.,F
   call feedkeys("i\<C-N>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
   let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : ''
-  call assert_equal(completed. "{'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
+  call assert_equal(completed. "{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
   bwipe!
   set completeopt& completefunc& complete&
 endfunc
@@ -5904,6 +5904,26 @@ func Test_autocomplete_longest()
   call DoTest("f", 'foobar', 2)
   call assert_equal(1, g:preinserted)
 
+  " complete_info()
+  %delete
+  func GetPreinsert()
+    let g:cinfo = complete_info(['preinserted_text'])
+    return ""
+  endfunc
+  inoremap <buffer><F6> <C-R>=GetPreinsert()<CR>
+  call setline(1, ["foo_bar_xyz", "foo__xyz"])
+
+  set completeopt& completeopt+=preinsert
+  call feedkeys("G4li\<F6>\<C-Y>", 'tx')
+  call assert_equal("bar_xyz", g:cinfo.preinserted_text)
+
+  set completeopt& completeopt+=longest
+  call feedkeys("Gof\<F6>\<ESC>", 'tx')
+  call assert_equal("oo_bar_xyz", g:cinfo.preinserted_text)
+  unlet g:cinfo
+  delfunc GetPreinsert
+  set completeopt&
+
   " Undo
   %delete _
   let &l:undolevels = &l:undolevels
index 7b1b092c4d1799b94b43eca0ad0a9169d410ee94..b6e5accf73fb78284447fd9ec70c4581456a2994 100644 (file)
@@ -1163,6 +1163,7 @@ func Test_popup_complete_info_02()
     \     {'word': 'Apr', 'menu': 'April', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
     \     {'word': 'May', 'menu': 'May', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}
     \   ],
+    \   'preinserted_text': '',
     \   'selected': 0,
     \ }
 
@@ -1170,7 +1171,7 @@ func Test_popup_complete_info_02()
   call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
   call assert_equal(d, g:compl_info)
 
-  let g:compl_what = ['mode', 'pum_visible', 'selected']
+  let g:compl_what = ['mode', 'pum_visible', 'preinserted_text', 'selected']
   call remove(d, 'items')
   call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
   call assert_equal(d, g:compl_info)
@@ -1178,6 +1179,7 @@ func Test_popup_complete_info_02()
   let g:compl_what = ['mode']
   call remove(d, 'selected')
   call remove(d, 'pum_visible')
+  call remove(d, 'preinserted_text')
   call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
   call assert_equal(d, g:compl_info)
   bwipe!
@@ -1191,6 +1193,7 @@ func Test_popup_complete_info_no_pum()
         \   'mode': '',
         \   'pum_visible': 0,
         \   'items': [],
+        \   'preinserted_text': '',
         \   'selected': -1,
         \  }
   call assert_equal( d, complete_info() )
index 4d537d38020a7d9a50fbb1425b9c1dca9fbe3f11..c06672b2358e15ce238bc345272591e01e9890d4 100644 (file)
@@ -819,7 +819,7 @@ enddef
 def Test_complete_info()
   v9.CheckSourceDefAndScriptFailure(['complete_info("")'], ['E1013: Argument 1: type mismatch, expected list<string> but got string', 'E1211: List required for argument 1'])
   v9.CheckSourceDefAndScriptFailure(['complete_info({})'], ['E1013: Argument 1: type mismatch, expected list<string> but got dict<any>', 'E1211: List required for argument 1'])
-  assert_equal({'pum_visible': 0, 'mode': '', 'selected': -1, 'items': []}, complete_info())
+  assert_equal({'pum_visible': 0, 'mode': '', 'preinserted_text': '', 'selected': -1, 'items': []}, complete_info())
   assert_equal({'mode': '', 'items': []}, complete_info(['mode', 'items']))
 enddef
 
index 2fdb0871b5763ea12771e9ad9d13634b42e456b9..0ce44e9d46bbb353a6cee11b232a3db8509c5689 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1876,
 /**/
     1875,
 /**/