vim-patch:9.1.0983: not able to get the displayed items in complete_i… (#31796)

vim-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: vim/vim#10007
closes: vim/vim#16307

d4088edae2
This commit is contained in:
glepnir
2024-12-31 19:12:50 +08:00
committed by GitHub
parent 57f10abbc2
commit bdc0b5f505
6 changed files with 84 additions and 11 deletions

View File

@ -1174,10 +1174,15 @@ complete_info([{what}]) *complete_info()*
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

View File

@ -1189,6 +1189,7 @@ items:
|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

View File

@ -1023,10 +1023,15 @@ function vim.fn.complete_check() end
--- 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

View File

@ -1384,10 +1384,15 @@ M.funcs = {
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

View File

@ -164,6 +164,7 @@ struct compl_S {
int cp_flags; ///< CP_ values
int cp_number; ///< sequence number
int cp_score; ///< fuzzy match score
bool 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
};
@ -1223,6 +1224,7 @@ static int ins_compl_build_pum(void)
int cur = -1;
do {
comp->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 != NULL && lead_len > 0) {
@ -1234,6 +1236,7 @@ static int ins_compl_build_pum(void)
|| ins_compl_equal(comp, compl_leader, (size_t)lead_len)
|| (compl_fuzzy_match && comp->cp_score > 0))) {
compl_match_arraysize++;
comp->cp_in_match_array = true;
if (match_head == NULL) {
match_head = comp;
} else {
@ -2875,11 +2878,12 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
#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;
for (listitem_T *item = tv_list_first(what_list)
@ -2897,6 +2901,8 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
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;
}
}
}
@ -2910,12 +2916,16 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
ret = tv_dict_add_nr(retdict, S_LEN("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;
int selected_idx = -1;
if (what_flag & CI_WHAT_ITEMS) {
bool has_items = what_flag & CI_WHAT_ITEMS;
bool has_matches = what_flag & CI_WHAT_MATCHES;
if (has_items || has_matches) {
li = tv_list_alloc(kListLenMayKnow);
ret = tv_dict_add_list(retdict, S_LEN("items"), li);
const char *key = (has_matches && !has_items) ? "matches" : "items";
ret = tv_dict_add_list(retdict, key, strlen(key), li);
}
if (ret == OK && what_flag & CI_WHAT_SELECTED) {
if (compl_curr_match != NULL && compl_curr_match->cp_number == -1) {
@ -2927,7 +2937,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
compl_T *match = compl_first_match;
do {
if (!match_at_original_text(match)) {
if (what_flag & CI_WHAT_ITEMS) {
if (has_items || (has_matches && match->cp_in_match_array)) {
dict_T *di = tv_dict_alloc();
tv_list_append_dict(li, di);
tv_dict_add_str(di, S_LEN("word"), match->cp_str);
@ -2935,6 +2945,9 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
tv_dict_add_str(di, S_LEN("menu"), match->cp_text[CPT_MENU]);
tv_dict_add_str(di, S_LEN("kind"), match->cp_text[CPT_KIND]);
tv_dict_add_str(di, S_LEN("info"), match->cp_text[CPT_INFO]);
if (has_matches && has_items) {
tv_dict_add_bool(di, S_LEN("match"), match->cp_in_match_array);
}
if (match->cp_user_data.v_type == VAR_UNKNOWN) {
// Add an empty string for backwards compatibility
tv_dict_add_str(di, S_LEN("user_data"), "");

View File

@ -2870,4 +2870,48 @@ func Test_complete_fuzzy_match_tie()
set completeopt&
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