diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 7389a86b9d69d7..3a181f27e52ed8 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1866,6 +1866,8 @@ cmdcomplete_info() *cmdcomplete_info()* typed text only, or the last completion after no item is selected when using the or keys) + preinserted_text + The actual text that is pre-inserted. Returns an empty |Dictionary| if no completion was attempted, if there was only one candidate and it was fully completed, or diff --git a/src/insexpand.c b/src/insexpand.c index 4edcfe53e04302..321700414b7ee7 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -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))) { diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 6d492373c4c320..02a193cad21e33 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -572,15 +572,15 @@ func Test_completefunc_info() set completeopt=menuone set completefunc=CompleteTest call feedkeys("i\\\\=string(complete_info())\\", "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\\\=string(complete_info())\\", "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\\\=string(complete_info())\\", "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\\" . a:mvmt . "\\=string(complete_info())\\", "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\" . a:mvmt . "\\=string(complete_info())\\", "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\" . a:mvmt . "\\=string(complete_info())\\", "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 =GetPreinsert() + call setline(1, ["foo_bar_xyz", "foo__xyz"]) + + set completeopt& completeopt+=preinsert + call feedkeys("G4li\\", 'tx') + call assert_equal("bar_xyz", g:cinfo.preinserted_text) + + set completeopt& completeopt+=longest + call feedkeys("Gof\\", '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 diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index f88cac29e514a7..330cbdf42c16c5 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -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\\\", '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\\\", '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\\\", '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() ) diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 4d537d38020a7d..c06672b2358e15 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -819,7 +819,7 @@ enddef def Test_complete_info() v9.CheckSourceDefAndScriptFailure(['complete_info("")'], ['E1013: Argument 1: type mismatch, expected list but got string', 'E1211: List required for argument 1']) v9.CheckSourceDefAndScriptFailure(['complete_info({})'], ['E1013: Argument 1: type mismatch, expected list but got dict', '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