1
0
forked from aniani/vim

patch 8.1.1068: cannot get all the information about current completion

Problem:    Cannot get all the information about current completion.
Solution:   Add complete_info(). (Shougo, Hirohito Higashi, closes #4106)
This commit is contained in:
Bram Moolenaar
2019-03-29 12:20:27 +01:00
parent 723d165c2f
commit fd133323d4
8 changed files with 328 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.1. Last change: 2019 Mar 23 *eval.txt* For Vim version 8.1. Last change: 2019 Mar 29
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -2267,6 +2267,7 @@ col({expr}) Number column nr of cursor or mark
complete({startcol}, {matches}) none set Insert mode completion complete({startcol}, {matches}) none set Insert mode completion
complete_add({expr}) Number add completion match complete_add({expr}) Number add completion match
complete_check() Number check for key typed during completion complete_check() Number check for key typed during completion
complete_info([{what}]) Dict get current completion information
confirm({msg} [, {choices} [, {default} [, {type}]]]) confirm({msg} [, {choices} [, {default} [, {type}]]])
Number number of choice picked by user Number number of choice picked by user
copy({expr}) any make a shallow copy of {expr} copy({expr}) any make a shallow copy of {expr}
@@ -3452,8 +3453,8 @@ cindent({lnum}) *cindent()*
See |C-indenting|. See |C-indenting|.
clearmatches() *clearmatches()* clearmatches() *clearmatches()*
Clears all matches previously defined by |matchadd()| and the Clears all matches previously defined for the current window
|:match| commands. by |matchadd()| and the |:match| commands.
*col()* *col()*
col({expr}) The result is a Number, which is the byte index of the column col({expr}) The result is a Number, which is the byte index of the column
@@ -3538,6 +3539,55 @@ complete_check() *complete_check()*
Only to be used by the function specified with the Only to be used by the function specified with the
'completefunc' option. 'completefunc' option.
*complete_info()*
complete_info([{what}])
Returns a Dictionary with information about Insert mode
completion. See |ins-completion|.
The items are:
mode Current completion mode name string.
See |completion_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",
"abbr", "menu", "kind", "info" and "user_data".
See |complete-items|.
selected Selected item index. First index is zero.
Index is -1 if no item is selected (showing
typed text only)
inserted Inserted string. [NOT IMPLEMENT YET]
*complete_info_mode*
mode values are:
"" Not in completion mode
"keyword" Keyword completion |i_CTRL-X_CTRL-N|
"ctrl_x" Just pressed CTRL-X |i_CTRL-X|
"whole_line" Whole lines |i_CTRL-X_CTRL-L|
"files" File names |i_CTRL-X_CTRL-F|
"tags" Tags |i_CTRL-X_CTRL-]|
"path_defines" Definition completion |i_CTRL-X_CTRL-D|
"path_patterns" Include completion |i_CTRL-X_CTRL-I|
"dictionary" Dictionary |i_CTRL-X_CTRL-K|
"thesaurus" Thesaurus |i_CTRL-X_CTRL-T|
"cmdline" Vim Command line |i_CTRL-X_CTRL-V|
"function" User defined completion |i_CTRL-X_CTRL-U|
"omni" Omni completion |i_CTRL-X_CTRL-O|
"spell" Spelling suggestions |i_CTRL-X_s|
"eval" |complete()| completion
"unknown" Other internal modes
If the optional {what} list argument is supplied, then only
the items listed in {what} are returned. Unsupported items in
{what} are silently ignored.
Examples: >
" Get all items
call complete_info()
" Get only 'mode'
call complete_info(['mode'])
" Get only 'mode' and 'pum_visible'
call complete_info(['mode', 'pum_visible'])
<
*confirm()* *confirm()*
confirm({msg} [, {choices} [, {default} [, {type}]]]) confirm({msg} [, {choices} [, {default} [, {type}]]])
confirm() offers the user a dialog, from which a choice can be confirm() offers the user a dialog, from which a choice can be
@@ -4978,10 +5028,11 @@ getloclist({nr} [, {what}]) *getloclist()*
details. details.
getmatches() *getmatches()* getmatches() *getmatches()*
Returns a |List| with all matches previously defined by Returns a |List| with all matches previously defined for the
|matchadd()| and the |:match| commands. |getmatches()| is current window by |matchadd()| and the |:match| commands.
useful in combination with |setmatches()|, as |setmatches()| |getmatches()| is useful in combination with |setmatches()|,
can restore a list of matches saved by |getmatches()|. as |setmatches()| can restore a list of matches saved by
|getmatches()|.
Example: > Example: >
:echo getmatches() :echo getmatches()
< [{'group': 'MyGroup1', 'pattern': 'TODO', < [{'group': 'MyGroup1', 'pattern': 'TODO',
@@ -7839,9 +7890,10 @@ setloclist({nr}, {list} [, {action} [, {what}]]) *setloclist()*
for the list of supported keys in {what}. for the list of supported keys in {what}.
setmatches({list}) *setmatches()* setmatches({list}) *setmatches()*
Restores a list of matches saved by |getmatches()|. Returns 0 Restores a list of matches saved by |getmatches() for the
if successful, otherwise -1. All current matches are cleared current window|. Returns 0 if successful, otherwise -1. All
before the list is restored. See example for |getmatches()|. current matches are cleared before the list is restored. See
example for |getmatches()|.
*setpos()* *setpos()*
setpos({expr}, {list}) setpos({expr}, {list})

View File

@@ -1,4 +1,4 @@
*insert.txt* For Vim version 8.1. Last change: 2019 Jan 29 *insert.txt* For Vim version 8.1. Last change: 2019 Mar 26
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -379,8 +379,8 @@ CTRL-\ CTRL-O like CTRL-O but don't move the cursor *i_CTRL-\_CTRL-O*
CTRL-L when 'insertmode' is set: go to Normal mode *i_CTRL-L* CTRL-L when 'insertmode' is set: go to Normal mode *i_CTRL-L*
CTRL-G u break undo sequence, start new change *i_CTRL-G_u* CTRL-G u break undo sequence, start new change *i_CTRL-G_u*
CTRL-G U don't break undo with next left/right cursor *i_CTRL-G_U* CTRL-G U don't break undo with next left/right cursor *i_CTRL-G_U*
movement (but only if the cursor stays movement, if the cursor stays within
within same the line) same the line
----------------------------------------------------------------------- -----------------------------------------------------------------------
Note: If the cursor keys take you out of Insert mode, check the 'noesckeys' Note: If the cursor keys take you out of Insert mode, check the 'noesckeys'
@@ -642,6 +642,7 @@ and one of the CTRL-X commands. You exit CTRL-X mode by typing a key that is
not a valid CTRL-X mode command. Valid keys are the CTRL-X command itself, not a valid CTRL-X mode command. Valid keys are the CTRL-X command itself,
CTRL-N (next), and CTRL-P (previous). CTRL-N (next), and CTRL-P (previous).
To get the current completion information, |complete_info()| can be used.
Also see the 'infercase' option if you want to adjust the case of the match. Also see the 'infercase' option if you want to adjust the case of the match.
*complete_CTRL-E* *complete_CTRL-E*

View File

@@ -834,6 +834,7 @@ Insert mode completion: *completion-functions*
complete() set found matches complete() set found matches
complete_add() add to found matches complete_add() add to found matches
complete_check() check if completion should be aborted complete_check() check if completion should be aborted
complete_info() get current completion information
pumvisible() check if the popup menu is displayed pumvisible() check if the popup menu is displayed
Folding: *folding-functions* Folding: *folding-functions*

View File

@@ -15,7 +15,9 @@
#ifdef FEAT_INS_EXPAND #ifdef FEAT_INS_EXPAND
/* /*
* definitions used for CTRL-X submode * Definitions used for CTRL-X submode.
* Note: If you change CTRL-X submode, you must also maintain ctrl_x_msgs[] and
* ctrl_x_mode_names[].
*/ */
# define CTRL_X_WANT_IDENT 0x100 # define CTRL_X_WANT_IDENT 0x100
@@ -40,18 +42,18 @@
# define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT] # define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
# define CTRL_X_MODE_LINE_OR_EVAL(m) ((m) == CTRL_X_WHOLE_LINE || (m) == CTRL_X_EVAL) # define CTRL_X_MODE_LINE_OR_EVAL(m) ((m) == CTRL_X_WHOLE_LINE || (m) == CTRL_X_EVAL)
/* Message for CTRL-X mode, index is ctrl_x_mode. */ // Message for CTRL-X mode, index is ctrl_x_mode.
static char *ctrl_x_msgs[] = static char *ctrl_x_msgs[] =
{ {
N_(" Keyword completion (^N^P)"), /* CTRL_X_NORMAL, ^P/^N compl. */ N_(" Keyword completion (^N^P)"), // CTRL_X_NORMAL, ^P/^N compl.
N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"), N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"),
NULL, /* CTRL_X_SCROLL: depends on state */ NULL, // CTRL_X_SCROLL: depends on state
N_(" Whole line completion (^L^N^P)"), N_(" Whole line completion (^L^N^P)"),
N_(" File name completion (^F^N^P)"), N_(" File name completion (^F^N^P)"),
N_(" Tag completion (^]^N^P)"), N_(" Tag completion (^]^N^P)"),
N_(" Path pattern completion (^N^P)"), N_(" Path pattern completion (^N^P)"),
N_(" Definition completion (^D^N^P)"), N_(" Definition completion (^D^N^P)"),
NULL, /* CTRL_X_FINISHED */ NULL, // CTRL_X_FINISHED
N_(" Dictionary completion (^K^N^P)"), N_(" Dictionary completion (^K^N^P)"),
N_(" Thesaurus completion (^T^N^P)"), N_(" Thesaurus completion (^T^N^P)"),
N_(" Command-line completion (^V^N^P)"), N_(" Command-line completion (^V^N^P)"),
@@ -59,9 +61,30 @@ static char *ctrl_x_msgs[] =
N_(" Omni completion (^O^N^P)"), N_(" Omni completion (^O^N^P)"),
N_(" Spelling suggestion (s^N^P)"), N_(" Spelling suggestion (s^N^P)"),
N_(" Keyword Local completion (^N^P)"), N_(" Keyword Local completion (^N^P)"),
NULL, /* CTRL_X_EVAL doesn't use msg. */ NULL, // CTRL_X_EVAL doesn't use msg.
}; };
static char *ctrl_x_mode_names[] = {
"keyword",
"ctrl_x",
"unknown", // CTRL_X_SCROLL
"whole_line",
"files",
"tags",
"path_patterns",
"path_defines",
"unknown", // CTRL_X_FINISHED
"dictionary",
"thesaurus",
"cmdline",
"function",
"omni",
"spell",
NULL, // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
"eval"
};
static char e_hitend[] = N_("Hit end of paragraph"); static char e_hitend[] = N_("Hit end of paragraph");
# ifdef FEAT_COMPL_FUNC # ifdef FEAT_COMPL_FUNC
static char e_complwin[] = N_("E839: Completion function changed window"); static char e_complwin[] = N_("E839: Completion function changed window");
@@ -163,6 +186,7 @@ static void ins_compl_files(int count, char_u **files, int thesaurus, int flags,
static char_u *find_line_end(char_u *ptr); static char_u *find_line_end(char_u *ptr);
static void ins_compl_free(void); static void ins_compl_free(void);
static void ins_compl_clear(void); static void ins_compl_clear(void);
static char_u *ins_compl_mode(void);
static int ins_compl_bs(void); static int ins_compl_bs(void);
static int ins_compl_need_restart(void); static int ins_compl_need_restart(void);
static void ins_compl_new_leader(void); static void ins_compl_new_leader(void);
@@ -3525,6 +3549,108 @@ ins_compl_active(void)
return compl_started; return compl_started;
} }
/*
* Get complete information
*/
void
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_INSERTED 0x10
#define CI_WHAT_ALL 0xff
int what_flag;
if (what_list == NULL)
what_flag = CI_WHAT_ALL;
else
{
what_flag = 0;
for (item = what_list->lv_first; item != NULL; item = item->li_next)
{
char_u *what = tv_get_string(&item->li_tv);
if (STRCMP(what, "mode") == 0)
what_flag |= CI_WHAT_MODE;
else if (STRCMP(what, "pum_visible") == 0)
what_flag |= CI_WHAT_PUM_VISIBLE;
else if (STRCMP(what, "items") == 0)
what_flag |= CI_WHAT_ITEMS;
else if (STRCMP(what, "selected") == 0)
what_flag |= CI_WHAT_SELECTED;
else if (STRCMP(what, "inserted") == 0)
what_flag |= CI_WHAT_INSERTED;
}
}
if (ret == OK && (what_flag & CI_WHAT_MODE))
ret = dict_add_string(retdict, "mode", ins_compl_mode());
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))
{
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->cp_flags & ORIGINAL_TEXT))
{
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]);
dict_add_string(di, "user_data",
match->cp_text[CPT_USER_DATA]);
}
match = match->cp_next;
}
while (match != NULL && match != compl_first_match);
}
}
if (ret == OK && (what_flag & CI_WHAT_SELECTED))
ret = dict_add_number(retdict, "selected", (compl_curr_match != NULL) ?
compl_curr_match->cp_number - 1 : -1);
// TODO
// if (ret == OK && (what_flag & CI_WHAT_INSERTED))
}
/*
* Return Insert completion mode name string
*/
static char_u *
ins_compl_mode(void)
{
if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || compl_started)
return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT];
return (char_u *)"";
}
/* /*
* Delete one character before the cursor and show the subset of the matches * Delete one character before the cursor and show the subset of the matches
* that match the word that is now before the cursor. * that match the word that is now before the cursor.

View File

@@ -113,6 +113,7 @@ static void f_col(typval_T *argvars, typval_T *rettv);
static void f_complete(typval_T *argvars, typval_T *rettv); static void f_complete(typval_T *argvars, typval_T *rettv);
static void f_complete_add(typval_T *argvars, typval_T *rettv); static void f_complete_add(typval_T *argvars, typval_T *rettv);
static void f_complete_check(typval_T *argvars, typval_T *rettv); static void f_complete_check(typval_T *argvars, typval_T *rettv);
static void f_complete_info(typval_T *argvars, typval_T *rettv);
#endif #endif
static void f_confirm(typval_T *argvars, typval_T *rettv); static void f_confirm(typval_T *argvars, typval_T *rettv);
static void f_copy(typval_T *argvars, typval_T *rettv); static void f_copy(typval_T *argvars, typval_T *rettv);
@@ -593,6 +594,7 @@ static struct fst
{"complete", 2, 2, f_complete}, {"complete", 2, 2, f_complete},
{"complete_add", 1, 1, f_complete_add}, {"complete_add", 1, 1, f_complete_add},
{"complete_check", 0, 0, f_complete_check}, {"complete_check", 0, 0, f_complete_check},
{"complete_info", 0, 1, f_complete_info},
#endif #endif
{"confirm", 1, 4, f_confirm}, {"confirm", 1, 4, f_confirm},
{"copy", 1, 1, f_copy}, {"copy", 1, 1, f_copy},
@@ -2600,6 +2602,29 @@ f_complete_check(typval_T *argvars UNUSED, typval_T *rettv)
rettv->vval.v_number = compl_interrupted; rettv->vval.v_number = compl_interrupted;
RedrawingDisabled = saved; RedrawingDisabled = saved;
} }
/*
* "complete_info()" function
*/
static void
f_complete_info(typval_T *argvars, typval_T *rettv)
{
list_T *what_list = NULL;
if (rettv_dict_alloc(rettv) != OK)
return;
if (argvars[0].v_type != VAR_UNKNOWN)
{
if (argvars[0].v_type != VAR_LIST)
{
emsg(_(e_listreq));
return;
}
what_list = argvars[0].vval.v_list;
}
get_complete_info(what_list, rettv->vval.v_dict);
}
#endif #endif
/* /*

View File

@@ -18,6 +18,7 @@ void ins_compl_show_pum(void);
char_u *find_word_start(char_u *ptr); char_u *find_word_start(char_u *ptr);
char_u *find_word_end(char_u *ptr); char_u *find_word_end(char_u *ptr);
int ins_compl_active(void); int ins_compl_active(void);
void get_complete_info(list_T *what_list, dict_T *retdict);
int ins_compl_add_tv(typval_T *tv, int dir); int ins_compl_add_tv(typval_T *tv, int dir);
void ins_compl_check_keys(int frequency, int in_compl_func); void ins_compl_check_keys(int frequency, int in_compl_func);
int get_literal(void); int get_literal(void);

View File

@@ -896,4 +896,105 @@ func Test_menu_only_exists_in_terminal()
endtry endtry
endfunc endfunc
func Test_popup_complete_info_01()
new
inoremap <buffer><F5> <C-R>=complete_info().mode<CR>
func s:complTestEval() abort
call complete(1, ['aa', 'ab'])
return ''
endfunc
inoremap <buffer><F6> <C-R>=s:complTestEval()<CR>
call writefile([
\ 'dummy dummy.txt 1',
\], 'Xdummy.txt')
setlocal tags=Xdummy.txt
setlocal dictionary=Xdummy.txt
setlocal thesaurus=Xdummy.txt
setlocal omnifunc=syntaxcomplete#Complete
setlocal completefunc=syntaxcomplete#Complete
setlocal spell
for [keys, mode_name] in [
\ ["", ''],
\ ["\<C-X>", 'ctrl_x'],
\ ["\<C-X>\<C-N>", 'keyword'],
\ ["\<C-X>\<C-P>", 'keyword'],
\ ["\<C-X>\<C-L>", 'whole_line'],
\ ["\<C-X>\<C-F>", 'files'],
\ ["\<C-X>\<C-]>", 'tags'],
\ ["\<C-X>\<C-D>", 'path_defines'],
\ ["\<C-X>\<C-I>", 'path_patterns'],
\ ["\<C-X>\<C-K>", 'dictionary'],
\ ["\<C-X>\<C-T>", 'thesaurus'],
\ ["\<C-X>\<C-V>", 'cmdline'],
\ ["\<C-X>\<C-U>", 'function'],
\ ["\<C-X>\<C-O>", 'omni'],
\ ["\<C-X>s", 'spell'],
\ ["\<F6>", 'eval'],
\]
call feedkeys("i" . keys . "\<F5>\<Esc>", 'tx')
call assert_equal(mode_name, getline('.'))
%d
endfor
call delete('Xdummy.txt')
bwipe!
endfunc
func UserDefinedComplete(findstart, base)
if a:findstart
return 0
else
return [
\ { 'word': 'Jan', 'menu': 'January' },
\ { 'word': 'Feb', 'menu': 'February' },
\ { 'word': 'Mar', 'menu': 'March' },
\ { 'word': 'Apr', 'menu': 'April' },
\ { 'word': 'May', 'menu': 'May' },
\ ]
endif
endfunc
func GetCompleteInfo()
if empty(g:compl_what)
let g:compl_info = complete_info()
else
let g:compl_info = complete_info(g:compl_what)
endif
return ''
endfunc
func Test_popup_complete_info_02()
new
inoremap <buffer><F5> <C-R>=GetCompleteInfo()<CR>
setlocal completefunc=UserDefinedComplete
let d = {
\ 'mode': 'function',
\ 'pum_visible': 1,
\ 'items': [
\ {'word': 'Jan', 'menu': 'January', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
\ {'word': 'Feb', 'menu': 'February', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
\ {'word': 'Mar', 'menu': 'March', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
\ {'word': 'Apr', 'menu': 'April', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
\ {'word': 'May', 'menu': 'May', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}
\ ],
\ 'selected': 0,
\ }
let g:compl_what = []
call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
call assert_equal(d, g:compl_info)
let g:compl_what = ['mode', 'pum_visible', 'selected']
call remove(d, 'items')
call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
call assert_equal(d, g:compl_info)
let g:compl_what = ['mode']
call remove(d, 'selected')
call remove(d, 'pum_visible')
call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
call assert_equal(d, g:compl_info)
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -775,6 +775,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1068,
/**/ /**/
1067, 1067,
/**/ /**/