changeset 13238:e0dcfd3dbb52 v8.0.1493

patch 8.0.1493: completion items cannot be annotated commit https://github.com/vim/vim/commit/9b56a57cdae31f7a2c85d440392bf63d3253a158 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 10 16:19:32 2018 +0100 patch 8.0.1493: completion items cannot be annotated Problem: Completion items cannot be annotated. Solution: Add a "user_data" entry to the completion item. (Ben Jackson, coses #2608, closes #2508)
author Christian Brabandt <cb@256bit.org>
date Sat, 10 Feb 2018 16:30:06 +0100
parents ffad83212c90
children cb07abe792ae
files runtime/doc/insert.txt src/edit.c src/structs.h src/testdir/test_ins_complete.vim src/version.c
diffstat 5 files changed, 137 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1,4 +1,4 @@
-*insert.txt*    For Vim version 8.0.  Last change: 2018 Jan 26
+*insert.txt*    For Vim version 8.0.  Last change: 2018 Feb 10
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1103,6 +1103,8 @@ items:
 			item with the same word is already present.
 	empty		when non-zero this match will be added even when it is
 			an empty string
+	user_data 	custom data which is associated with the item and
+			available in |v:completed_item|
 
 All of these except "icase", "dup" and "empty" must be a string.  If an item
 does not meet these requirements then an error message is given and further
@@ -1196,6 +1198,8 @@ The menu is used when:
 
 The 'pumheight' option can be used to set a maximum height.  The default is to
 use all space available.
+The 'pumwidth' option can be used to set a minimum width.  The default is 15
+characters.
 
 There are three states:
 1. A complete match has been inserted, e.g., after using CTRL-N or CTRL-P.
--- a/src/edit.c
+++ b/src/edit.c
@@ -4236,6 +4236,8 @@ ins_compl_add_tv(typval_T *tv, int dir)
 						     (char_u *)"kind", FALSE);
 	cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict,
 						     (char_u *)"info", FALSE);
+	cptext[CPT_USER_DATA] = get_dict_string(tv->vval.v_dict,
+						 (char_u *)"user_data", FALSE);
 	if (get_dict_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL)
 	    icase = get_dict_number(tv->vval.v_dict, (char_u *)"icase");
 	if (get_dict_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL)
@@ -4758,6 +4760,8 @@ ins_compl_insert(int in_compl_func)
 		    EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND]));
 	dict_add_nr_str(dict, "info", 0L,
 		    EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
+	dict_add_nr_str(dict, "user_data", 0L,
+		    EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_USER_DATA]));
     }
     set_vim_var_dict(VV_COMPLETED_ITEM, dict);
     if (!in_compl_func)
--- a/src/structs.h
+++ b/src/structs.h
@@ -3240,11 +3240,12 @@ typedef struct
 /*
  * Array indexes used for cptext argument of ins_compl_add().
  */
-#define CPT_ABBR    0	/* "abbr" */
-#define CPT_MENU    1	/* "menu" */
-#define CPT_KIND    2	/* "kind" */
-#define CPT_INFO    3	/* "info" */
-#define CPT_COUNT   4	/* Number of entries */
+#define CPT_ABBR	0	/* "abbr" */
+#define CPT_MENU	1	/* "menu" */
+#define CPT_KIND	2	/* "kind" */
+#define CPT_INFO	3	/* "info" */
+#define CPT_USER_DATA	4	/* "user data" */
+#define CPT_COUNT	5	/* Number of entries */
 
 typedef struct {
   UINT32_T total[2];
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -117,6 +117,126 @@ func Test_omni_dash()
   set omnifunc=
 endfunc
 
+function! s:CompleteDone_CompleteFuncDict( findstart, base )
+  if a:findstart
+    return 0
+  endif
+
+  return {
+          \ 'words': [
+            \ {
+              \ 'word': 'aword',
+              \ 'abbr': 'wrd',
+              \ 'menu': 'extra text',
+              \ 'info': 'words are cool',
+              \ 'kind': 'W',
+              \ 'user_data': 'test'
+            \ }
+          \ ]
+        \ }
+endfunction
+
+function! s:CompleteDone_CheckCompletedItemDict()
+  call assert_equal( 'aword',          v:completed_item[ 'word' ] )
+  call assert_equal( 'wrd',            v:completed_item[ 'abbr' ] )
+  call assert_equal( 'extra text',     v:completed_item[ 'menu' ] )
+  call assert_equal( 'words are cool', v:completed_item[ 'info' ] )
+  call assert_equal( 'W',              v:completed_item[ 'kind' ] )
+  call assert_equal( 'test',           v:completed_item[ 'user_data' ] )
+
+  let s:called_completedone = 1
+endfunction
+
+function Test_CompleteDoneDict()
+  au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDict()
+
+  set completefunc=<SID>CompleteDone_CompleteFuncDict
+  execute "normal a\<C-X>\<C-U>\<C-Y>"
+  set completefunc&
+
+  call assert_equal( 'test', v:completed_item[ 'user_data' ] )
+  call assert_true( s:called_completedone )
+
+  let s:called_completedone = 0
+  au! CompleteDone
+endfunc
+
+function! s:CompleteDone_CompleteFuncDictNoUserData( findstart, base )
+  if a:findstart
+    return 0
+  endif
+
+  return {
+          \ 'words': [
+            \ {
+              \ 'word': 'aword',
+              \ 'abbr': 'wrd',
+              \ 'menu': 'extra text',
+              \ 'info': 'words are cool',
+              \ 'kind': 'W'
+            \ }
+          \ ]
+        \ }
+endfunction
+
+function! s:CompleteDone_CheckCompletedItemDictNoUserData()
+  call assert_equal( 'aword',          v:completed_item[ 'word' ] )
+  call assert_equal( 'wrd',            v:completed_item[ 'abbr' ] )
+  call assert_equal( 'extra text',     v:completed_item[ 'menu' ] )
+  call assert_equal( 'words are cool', v:completed_item[ 'info' ] )
+  call assert_equal( 'W',              v:completed_item[ 'kind' ] )
+  call assert_equal( '',               v:completed_item[ 'user_data' ] )
+
+  let s:called_completedone = 1
+endfunction
+
+function Test_CompleteDoneDictNoUserData()
+  au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDictNoUserData()
+
+  set completefunc=<SID>CompleteDone_CompleteFuncDictNoUserData
+  execute "normal a\<C-X>\<C-U>\<C-Y>"
+  set completefunc&
+
+  call assert_equal( '', v:completed_item[ 'user_data' ] )
+  call assert_true( s:called_completedone )
+
+  let s:called_completedone = 0
+  au! CompleteDone
+endfunc
+
+function! s:CompleteDone_CompleteFuncList( findstart, base )
+  if a:findstart
+    return 0
+  endif
+
+  return [ 'aword' ]
+endfunction
+
+function! s:CompleteDone_CheckCompletedItemList()
+  call assert_equal( 'aword', v:completed_item[ 'word' ] )
+  call assert_equal( '',      v:completed_item[ 'abbr' ] )
+  call assert_equal( '',      v:completed_item[ 'menu' ] )
+  call assert_equal( '',      v:completed_item[ 'info' ] )
+  call assert_equal( '',      v:completed_item[ 'kind' ] )
+  call assert_equal( '',      v:completed_item[ 'user_data' ] )
+
+  let s:called_completedone = 1
+endfunction
+
+function Test_CompleteDoneList()
+  au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemList()
+
+  set completefunc=<SID>CompleteDone_CompleteFuncList
+  execute "normal a\<C-X>\<C-U>\<C-Y>"
+  set completefunc&
+
+  call assert_equal( '', v:completed_item[ 'user_data' ] )
+  call assert_true( s:called_completedone )
+
+  let s:called_completedone = 0
+  au! CompleteDone
+endfunc
+
 " Check that when using feedkeys() typeahead does not interrupt searching for
 " completions.
 func Test_compl_feedkeys()
--- a/src/version.c
+++ b/src/version.c
@@ -772,6 +772,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1493,
+/**/
     1492,
 /**/
     1491,