]> granicus.if.org Git - vim/commitdiff
patch 8.1.1068: cannot get all the information about current completion v8.1.1068
authorBram Moolenaar <Bram@vim.org>
Fri, 29 Mar 2019 11:20:27 +0000 (12:20 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 29 Mar 2019 11:20:27 +0000 (12:20 +0100)
Problem:    Cannot get all the information about current completion.
Solution:   Add complete_info(). (Shougo, Hirohito Higashi, closes #4106)

runtime/doc/eval.txt
runtime/doc/insert.txt
runtime/doc/usr_41.txt
src/edit.c
src/evalfunc.c
src/proto/edit.pro
src/testdir/test_popup.vim
src/version.c

index db63a229909bd2d0e2ea6458144bf2df84be20c7..623da9efac88e836e16996e5f893407446b50a23 100644 (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
@@ -2267,6 +2267,7 @@ col({expr})                       Number  column nr of cursor or mark
 complete({startcol}, {matches}) none   set Insert mode completion
 complete_add({expr})           Number  add completion match
 complete_check()               Number  check for key typed during completion
+complete_info([{what}])                Dict    get current completion information
 confirm({msg} [, {choices} [, {default} [, {type}]]])
                                Number  number of choice picked by user
 copy({expr})                   any     make a shallow copy of {expr}
@@ -3452,8 +3453,8 @@ cindent({lnum})                                           *cindent()*
                See |C-indenting|.
 
 clearmatches()                                         *clearmatches()*
-               Clears all matches previously defined by |matchadd()| and the
-               |:match| commands.
+               Clears all matches previously defined for the current window
+               by |matchadd()| and the |:match| commands.
 
                                                        *col()*
 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
                '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({msg} [, {choices} [, {default} [, {type}]]])
                confirm() offers the user a dialog, from which a choice can be
@@ -4978,10 +5028,11 @@ getloclist({nr} [, {what}])                             *getloclist()*
                                        details.
 
 getmatches()                                           *getmatches()*
-               Returns a |List| with all matches previously defined by
-               |matchadd()| and the |:match| commands.  |getmatches()| is
-               useful in combination with |setmatches()|, as |setmatches()|
-               can restore a list of matches saved by |getmatches()|.
+               Returns a |List| with all matches previously defined for the
+               current window by |matchadd()| and the |:match| commands.
+               |getmatches()| is useful in combination with |setmatches()|,
+               as |setmatches()| can restore a list of matches saved by
+               |getmatches()|.
                Example: >
                        :echo getmatches()
 <                      [{'group': 'MyGroup1', 'pattern': 'TODO',
@@ -7839,9 +7890,10 @@ setloclist({nr}, {list} [, {action} [, {what}]])         *setloclist()*
                for the list of supported keys in {what}.
 
 setmatches({list})                                     *setmatches()*
-               Restores a list of matches saved by |getmatches()|.  Returns 0
-               if successful, otherwise -1.  All current matches are cleared
-               before the list is restored.  See example for |getmatches()|.
+               Restores a list of matches saved by |getmatches() for the
+               current window|.  Returns 0 if successful, otherwise -1.  All
+               current matches are cleared before the list is restored.  See
+               example for |getmatches()|.
 
                                                        *setpos()*
 setpos({expr}, {list})
index bd4fad2c29214c2aa4a8c0be11da2e4ddca9edf5..b747abec4876eec6ca7d65448fd883fd5c039d13 100644 (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
@@ -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-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*
-               movement (but only if the cursor stays
-               within same the line)
+               movement, if the cursor stays within
+               same the line
 -----------------------------------------------------------------------
 
 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,
 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.
 
                                                        *complete_CTRL-E*
index 07d11f8f77ff796000c517461bc0cc2559bd73ea..31beded6bb58bc23f41fe8e471c21042e4a6c576 100644 (file)
@@ -834,6 +834,7 @@ Insert mode completion:                             *completion-functions*
        complete()              set found matches
        complete_add()          add to found matches
        complete_check()        check if completion should be aborted
+       complete_info()         get current completion information
        pumvisible()            check if the popup menu is displayed
 
 Folding:                                       *folding-functions*
index f15ee8d4c528e91020036e469a2fa3e0562b9ce9..dcead23f54929a529ad882f157aad9b271cd9e69 100644 (file)
@@ -15,7 +15,9 @@
 
 #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_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)
 
-/* 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[] =
 {
-    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)"),
-    NULL, /* CTRL_X_SCROLL: depends on state */
+    NULL, // CTRL_X_SCROLL: depends on state
     N_(" Whole line completion (^L^N^P)"),
     N_(" File name completion (^F^N^P)"),
     N_(" Tag completion (^]^N^P)"),
     N_(" Path pattern completion (^N^P)"),
     N_(" Definition completion (^D^N^P)"),
-    NULL, /* CTRL_X_FINISHED */
+    NULL, // CTRL_X_FINISHED
     N_(" Dictionary completion (^K^N^P)"),
     N_(" Thesaurus completion (^T^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_(" Spelling suggestion (s^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");
 # ifdef FEAT_COMPL_FUNC
 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 void ins_compl_free(void);
 static void ins_compl_clear(void);
+static char_u *ins_compl_mode(void);
 static int  ins_compl_bs(void);
 static int  ins_compl_need_restart(void);
 static void ins_compl_new_leader(void);
@@ -3525,6 +3549,108 @@ ins_compl_active(void)
     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
  * that match the word that is now before the cursor.
index c1a32f3c2736bd60556576c99301f5a2a658151c..6aff4994cadaaa6c86d9b0c09e92d909f70c3531 100644 (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_add(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
 static void f_confirm(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_add",   1, 1, f_complete_add},
     {"complete_check", 0, 0, f_complete_check},
+    {"complete_info",  0, 1, f_complete_info},
 #endif
     {"confirm",                1, 4, f_confirm},
     {"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;
     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
 
 /*
index 3a1573fb8ef84864821e4fbdde569a8e78737b11..3f82bff70a91d1570cd7dabe1bab06c52ad2771b 100644 (file)
@@ -18,6 +18,7 @@ void ins_compl_show_pum(void);
 char_u *find_word_start(char_u *ptr);
 char_u *find_word_end(char_u *ptr);
 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);
 void ins_compl_check_keys(int frequency, int in_compl_func);
 int get_literal(void);
index 663a6a8e0192d277d9d187b799487d6799797dd7..c69c3b00c91660fc53bc35492cb4ee25e7e05de0 100644 (file)
@@ -896,4 +896,105 @@ func Test_menu_only_exists_in_terminal()
   endtry
 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
index b1d79b97d39e40d4bcd6cf0e2711fea476227650..ff18ac58f4f33403b254a1dee63eb30b87172486 100644 (file)
@@ -775,6 +775,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1068,
 /**/
     1067,
 /**/