patch 9.1.0983: not able to get the displayed items in complete_info()
Problem: not able to get the displayed items in complete_info()
(Evgeni Chasnovski)
Solution: return the visible items via the "matches" key for
complete_info() (glepnir)
fixes: #10007
closes: #16307
Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index c82ff81..9d01015 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1,4 +1,4 @@
-*builtin.txt* For Vim version 9.1. Last change: 2024 Dec 30
+*builtin.txt* For Vim version 9.1. Last change: 2024 Dec 31
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1896,10 +1896,15 @@
See |complete_info_mode| for the values.
pum_visible |TRUE| if popup menu is visible.
See |pumvisible()|.
- items List of completion matches. Each item is a
- dictionary containing the entries "word",
+ items List of all completion candidates. Each item
+ is a dictionary containing the entries "word",
"abbr", "menu", "kind", "info" and "user_data".
See |complete-items|.
+ matches Same as "items", but only returns items that
+ are matching current query. If both "matches"
+ and "items" are in "what", the returned list
+ will still be named "items", but each item
+ will have an additional "match" field.
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
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index f025d81..a5d245f 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1,4 +1,4 @@
-*insert.txt* For Vim version 9.1. Last change: 2024 Dec 28
+*insert.txt* For Vim version 9.1. Last change: 2024 Dec 31
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1195,6 +1195,7 @@
|hl-PmenuKind| highlight group, allowing for the
customization of ctermfg and guifg properties for the
completion kind
+ match See "matches" in |complete_info()|.
All of these except "icase", "equal", "dup" and "empty" must be a string. If
an item does not meet these requirements then an error message is given and
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index af63702..3477c91 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt* For Vim version 9.1. Last change: 2024 Dec 30
+*version9.txt* For Vim version 9.1. Last change: 2024 Dec 31
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -41621,6 +41621,8 @@
instead of the "sh" filetype
- the default value of the 'keyprotocol' option has been updated by support
for the ghostty terminal emulator (using kitty protocol)
+- |complete_info()| returns the list of matches shown in the poppu menu via
+ the "matches" key
*added-9.2*
Added ~
diff --git a/src/insexpand.c b/src/insexpand.c
index 522b7f7..818b1b9 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -106,6 +106,7 @@
int cp_flags; // CP_ values
int cp_number; // sequence number
int cp_score; // fuzzy match score
+ int cp_in_match_array; // collected by compl_match_array
int cp_user_abbr_hlattr; // highlight attribute for abbr
int cp_user_kind_hlattr; // highlight attribute for kind
};
@@ -1282,6 +1283,7 @@
do
{
+ compl->cp_in_match_array = FALSE;
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
// set the cp_score for later comparisons.
if (compl_fuzzy_match && compl_leader.string != NULL && compl_leader.length > 0)
@@ -1293,6 +1295,7 @@
|| (compl_fuzzy_match && compl->cp_score > 0)))
{
++compl_match_arraysize;
+ compl->cp_in_match_array = TRUE;
if (match_head == NULL)
match_head = compl;
else
@@ -3259,11 +3262,12 @@
#define CI_WHAT_ITEMS 0x04
#define CI_WHAT_SELECTED 0x08
#define CI_WHAT_INSERTED 0x10
+#define CI_WHAT_MATCHES 0x20
#define CI_WHAT_ALL 0xff
int what_flag;
if (what_list == NULL)
- what_flag = CI_WHAT_ALL;
+ what_flag = CI_WHAT_ALL & ~CI_WHAT_MATCHES;
else
{
what_flag = 0;
@@ -3282,6 +3286,8 @@
what_flag |= CI_WHAT_SELECTED;
else if (STRCMP(what, "inserted") == 0)
what_flag |= CI_WHAT_INSERTED;
+ else if (STRCMP(what, "matches") == 0)
+ what_flag |= CI_WHAT_MATCHES;
}
}
@@ -3291,19 +3297,23 @@
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_ITEMS || what_flag & CI_WHAT_SELECTED))
+ if (ret == OK && (what_flag & CI_WHAT_ITEMS || what_flag & CI_WHAT_SELECTED
+ || what_flag & CI_WHAT_MATCHES))
{
list_T *li = NULL;
dict_T *di;
compl_T *match;
int selected_idx = -1;
+ int has_items = what_flag & CI_WHAT_ITEMS;
+ int has_matches = what_flag & CI_WHAT_MATCHES;
- if (what_flag & CI_WHAT_ITEMS)
+ if (has_items || has_matches)
{
li = list_alloc();
if (li == NULL)
return;
- ret = dict_add_list(retdict, "items", li);
+ ret = dict_add_list(retdict, (has_matches && !has_items)
+ ? "matches" : "items", li);
}
if (ret == OK && what_flag & CI_WHAT_SELECTED)
if (compl_curr_match != NULL && compl_curr_match->cp_number == -1)
@@ -3316,7 +3326,8 @@
{
if (!match_at_original_text(match))
{
- if (what_flag & CI_WHAT_ITEMS)
+ if (has_items
+ || (has_matches && match->cp_in_match_array))
{
di = dict_alloc();
if (di == NULL)
@@ -3329,13 +3340,16 @@
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 (has_matches && has_items)
+ dict_add_bool(di, "match", match->cp_in_match_array);
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);
}
- if (compl_curr_match != NULL && compl_curr_match->cp_number == match->cp_number)
+ if (compl_curr_match != NULL
+ && compl_curr_match->cp_number == match->cp_number)
selected_idx = list_idx;
list_idx += 1;
}
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index ad2d421..8b26666 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2931,4 +2931,48 @@
bw!
endfunc
+func Test_complete_info_matches()
+ let g:what = ['matches']
+ func ShownInfo()
+ let g:compl_info = complete_info(g:what)
+ return ''
+ endfunc
+ set completeopt+=noinsert
+
+ new
+ call setline(1, ['aaa', 'aab', 'aba', 'abb'])
+ inoremap <buffer><F5> <C-R>=ShownInfo()<CR>
+
+ call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>dd", 'tx')
+ call assert_equal([
+ \ {'word': 'aaa', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
+ \ {'word': 'aab', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
+ \ {'word': 'aba', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
+ \ {'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
+ \], g:compl_info['matches'])
+
+ call feedkeys("Goa\<C-X>\<C-N>b\<F5>\<Esc>dd", 'tx')
+ call assert_equal([
+ \ {'word': 'aba', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
+ \ {'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
+ \], g:compl_info['matches'])
+
+ " items and matches both in what
+ let g:what = ['items', 'matches']
+ call feedkeys("Goa\<C-X>\<C-N>b\<F5>\<Esc>dd", 'tx')
+ call assert_equal([
+ \ {'word': 'aaa', 'menu': '', 'user_data': '', 'match': v:false, 'info': '', 'kind': '', 'abbr': ''},
+ \ {'word': 'aab', 'menu': '', 'user_data': '', 'match': v:false, 'info': '', 'kind': '', 'abbr': ''},
+ \ {'word': 'aba', 'menu': '', 'user_data': '', 'match': v:true, 'info': '', 'kind': '', 'abbr': ''},
+ \ {'word': 'abb', 'menu': '', 'user_data': '', 'match': v:true, 'info': '', 'kind': '', 'abbr': ''},
+ \], g:compl_info['items'])
+ call assert_false(has_key(g:compl_info, 'matches'))
+
+ bw!
+ bw!
+ unlet g:what
+ delfunc ShownInfo
+ set cot&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/src/version.c b/src/version.c
index a4b0fc4..48a0606 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 983,
+/**/
982,
/**/
981,