summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-04-08 18:15:41 +0200
committerBram Moolenaar <Bram@vim.org>2019-04-08 18:15:41 +0200
commitd7f246c68cfb97406bcd4b098a2df2d870b3ef92 (patch)
tree54fb7c248c198f511947c45a8942302d8d2a041a
parent62e1bb4a111e7ce570c30965f40a68a07a9da5b0 (diff)
downloadvim-git-d7f246c68cfb97406bcd4b098a2df2d870b3ef92.tar.gz
patch 8.1.1138: plugins don't get notified when the popup menu changesv8.1.1138
Problem: Plugins don't get notified when the popup menu changes. Solution: Add the CompleteChanged event. (Andy Massimino. closes #4176)
-rw-r--r--runtime/doc/autocmd.txt16
-rw-r--r--src/autocmd.c12
-rw-r--r--src/dict.c28
-rw-r--r--src/insexpand.c69
-rw-r--r--src/popupmnu.c16
-rw-r--r--src/proto/autocmd.pro1
-rw-r--r--src/proto/dict.pro1
-rw-r--r--src/proto/popupmnu.pro1
-rw-r--r--src/testdir/test_popup.vim34
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h1
11 files changed, 164 insertions, 17 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 5eb1936c4..c4bc004d2 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -367,6 +367,7 @@ Name triggered by ~
|SessionLoadPost| after loading a session file
|MenuPopup| just before showing the popup menu
+|CompleteChanged| after Insert mode completion menu changed
|CompleteDone| after Insert mode completion is done
|User| to be used in combination with ":doautocmd"
@@ -579,7 +580,22 @@ ColorScheme After loading a color scheme. |:colorscheme|
ColorSchemePre Before loading a color scheme. |:colorscheme|
Useful to setup removing things added by a
color scheme, before another one is loaded.
+CompleteChanged *CompleteChanged*
+ After each time the Insert mode completion
+ menu changed. Not fired on popup menu hide,
+ use |CompleteDone| for that. Never triggered
+ recursively.
+
+ Sets these |v:event| keys:
+ completed_item
+ height nr of items visible
+ width screen cells
+ row top screen row
+ col leftmost screen column
+ size total nr of items
+ scrollbar TRUE if visible
+ It is not allowed to change the text |textlock|.
*CompleteDone*
CompleteDone After Insert mode completion is done. Either
when something was completed or abandoning
diff --git a/src/autocmd.c b/src/autocmd.c
index aa1114333..2ea23ccc4 100644
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -112,6 +112,7 @@ static struct event_name
{"CmdUndefined", EVENT_CMDUNDEFINED},
{"ColorScheme", EVENT_COLORSCHEME},
{"ColorSchemePre", EVENT_COLORSCHEMEPRE},
+ {"CompleteChanged", EVENT_COMPLETECHANGED},
{"CompleteDone", EVENT_COMPLETEDONE},
{"CursorHold", EVENT_CURSORHOLD},
{"CursorHoldI", EVENT_CURSORHOLDI},
@@ -1794,6 +1795,17 @@ has_textyankpost(void)
}
#endif
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return TRUE when there is a CompleteChanged autocommand defined.
+ */
+ int
+has_completechanged(void)
+{
+ return (first_autopat[(int)EVENT_COMPLETECHANGED] != NULL);
+}
+#endif
+
/*
* Execute autocommands for "event" and file name "fname".
* Return TRUE if some commands were executed.
diff --git a/src/dict.c b/src/dict.c
index 0bb9dfa87..7d49599ef 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -342,18 +342,18 @@ dict_add(dict_T *d, dictitem_T *item)
}
/*
- * Add a number entry to dictionary "d".
+ * Add a number or special entry to dictionary "d".
* Returns FAIL when out of memory and when key already exists.
*/
- int
-dict_add_number(dict_T *d, char *key, varnumber_T nr)
+ static int
+dict_add_number_special(dict_T *d, char *key, varnumber_T nr, int special)
{
dictitem_T *item;
item = dictitem_alloc((char_u *)key);
if (item == NULL)
return FAIL;
- item->di_tv.v_type = VAR_NUMBER;
+ item->di_tv.v_type = special ? VAR_SPECIAL : VAR_NUMBER;
item->di_tv.vval.v_number = nr;
if (dict_add(d, item) == FAIL)
{
@@ -364,6 +364,26 @@ dict_add_number(dict_T *d, char *key, varnumber_T nr)
}
/*
+ * Add a number entry to dictionary "d".
+ * Returns FAIL when out of memory and when key already exists.
+ */
+ int
+dict_add_number(dict_T *d, char *key, varnumber_T nr)
+{
+ return dict_add_number_special(d, key, nr, FALSE);
+}
+
+/*
+ * Add a special entry to dictionary "d".
+ * Returns FAIL when out of memory and when key already exists.
+ */
+ int
+dict_add_special(dict_T *d, char *key, varnumber_T nr)
+{
+ return dict_add_number_special(d, key, nr, TRUE);
+}
+
+/*
* Add a string entry to dictionary "d".
* Returns FAIL when out of memory and when key already exists.
*/
diff --git a/src/insexpand.c b/src/insexpand.c
index ac7f5322f..ad95acc2e 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -203,6 +203,7 @@ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg);
static void ins_compl_add_list(list_T *list);
static void ins_compl_add_dict(dict_T *dict);
# endif
+static dict_T *ins_compl_dict_alloc(compl_T *match);
static int ins_compl_key2dir(int c);
static int ins_compl_pum_key(int c);
static int ins_compl_key2count(int c);
@@ -994,6 +995,37 @@ pum_enough_matches(void)
return (i >= 2);
}
+ static void
+trigger_complete_changed_event(int cur)
+{
+ dict_T *v_event;
+ dict_T *item;
+ static int recursive = FALSE;
+
+ if (recursive)
+ return;
+
+ v_event = get_vim_var_dict(VV_EVENT);
+ if (cur < 0)
+ item = dict_alloc();
+ else
+ item = ins_compl_dict_alloc(compl_curr_match);
+ if (item == NULL)
+ return;
+ dict_add_dict(v_event, "completed_item", item);
+ pum_set_event_info(v_event);
+ dict_set_items_ro(v_event);
+
+ recursive = TRUE;
+ textlock++;
+ apply_autocmds(EVENT_COMPLETECHANGED, NULL, NULL, FALSE, curbuf);
+ textlock--;
+ recursive = FALSE;
+
+ dict_free_contents(v_event);
+ hash_init(&v_event->dv_hashtab);
+}
+
/*
* Show the popup menu for the list of matches.
* Also adjusts "compl_shown_match" to an entry that is actually displayed.
@@ -1136,6 +1168,9 @@ ins_compl_show_pum(void)
curwin->w_cursor.col = compl_col;
pum_display(compl_match_array, compl_match_arraysize, cur);
curwin->w_cursor.col = col;
+
+ if (has_completechanged())
+ trigger_complete_changed_event(cur);
}
}
@@ -2899,23 +2934,31 @@ ins_compl_insert(int in_compl_func)
compl_used_match = FALSE;
else
compl_used_match = TRUE;
+ dict = ins_compl_dict_alloc(compl_shown_match);
+ set_vim_var_dict(VV_COMPLETED_ITEM, dict);
+ if (!in_compl_func)
+ compl_curr_match = compl_shown_match;
+}
+
+/*
+ * Allocate Dict for the completed item.
+ * { word, abbr, menu, kind, info }
+ */
+ static dict_T *
+ins_compl_dict_alloc(compl_T *match)
+{
+ dict_T *dict = dict_alloc_lock(VAR_FIXED);
- // Set completed item.
- // { word, abbr, menu, kind, info }
- dict = dict_alloc_lock(VAR_FIXED);
if (dict != NULL)
{
- dict_add_string(dict, "word", compl_shown_match->cp_str);
- dict_add_string(dict, "abbr", compl_shown_match->cp_text[CPT_ABBR]);
- dict_add_string(dict, "menu", compl_shown_match->cp_text[CPT_MENU]);
- dict_add_string(dict, "kind", compl_shown_match->cp_text[CPT_KIND]);
- dict_add_string(dict, "info", compl_shown_match->cp_text[CPT_INFO]);
- dict_add_string(dict, "user_data",
- compl_shown_match->cp_text[CPT_USER_DATA]);
+ dict_add_string(dict, "word", match->cp_str);
+ dict_add_string(dict, "abbr", match->cp_text[CPT_ABBR]);
+ dict_add_string(dict, "menu", match->cp_text[CPT_MENU]);
+ dict_add_string(dict, "kind", match->cp_text[CPT_KIND]);
+ dict_add_string(dict, "info", match->cp_text[CPT_INFO]);
+ dict_add_string(dict, "user_data", match->cp_text[CPT_USER_DATA]);
}
- set_vim_var_dict(VV_COMPLETED_ITEM, dict);
- if (!in_compl_func)
- compl_curr_match = compl_shown_match;
+ return dict;
}
/*
diff --git a/src/popupmnu.c b/src/popupmnu.c
index 7be8a9be4..ba9c7adc7 100644
--- a/src/popupmnu.c
+++ b/src/popupmnu.c
@@ -923,6 +923,22 @@ pum_get_height(void)
return pum_height;
}
+/*
+ * Add size information about the pum to "dict".
+ */
+ void
+pum_set_event_info(dict_T *dict)
+{
+ if (!pum_visible())
+ return;
+ dict_add_number(dict, "height", pum_height);
+ dict_add_number(dict, "width", pum_width);
+ dict_add_number(dict, "row", pum_row);
+ dict_add_number(dict, "col", pum_col);
+ dict_add_number(dict, "size", pum_size);
+ dict_add_special(dict, "scrollbar", pum_scrollbar ? VVAL_TRUE : VVAL_FALSE);
+}
+
# if defined(FEAT_BEVAL_TERM) || defined(FEAT_TERM_POPUP_MENU) || defined(PROTO)
static void
pum_position_at_mouse(int min_width)
diff --git a/src/proto/autocmd.pro b/src/proto/autocmd.pro
index 8c6d18f75..a448dad04 100644
--- a/src/proto/autocmd.pro
+++ b/src/proto/autocmd.pro
@@ -26,6 +26,7 @@ int has_insertcharpre(void);
int has_cmdundefined(void);
int has_funcundefined(void);
int has_textyankpost(void);
+int has_completechanged(void);
void block_autocmds(void);
void unblock_autocmds(void);
int is_autocmd_blocked(void);
diff --git a/src/proto/dict.pro b/src/proto/dict.pro
index b09a647bd..6d9ae194a 100644
--- a/src/proto/dict.pro
+++ b/src/proto/dict.pro
@@ -14,6 +14,7 @@ void dictitem_free(dictitem_T *item);
dict_T *dict_copy(dict_T *orig, int deep, int copyID);
int dict_add(dict_T *d, dictitem_T *item);
int dict_add_number(dict_T *d, char *key, varnumber_T nr);
+int dict_add_special(dict_T *d, char *key, varnumber_T nr);
int dict_add_string(dict_T *d, char *key, char_u *str);
int dict_add_string_len(dict_T *d, char *key, char_u *str, int len);
int dict_add_list(dict_T *d, char *key, list_T *list);
diff --git a/src/proto/popupmnu.pro b/src/proto/popupmnu.pro
index e2ae92ae8..c01966396 100644
--- a/src/proto/popupmnu.pro
+++ b/src/proto/popupmnu.pro
@@ -8,6 +8,7 @@ void pum_clear(void);
int pum_visible(void);
void pum_may_redraw(void);
int pum_get_height(void);
+void pum_set_event_info(dict_T *dict);
int split_message(char_u *mesg, pumitem_T **array);
void ui_remove_balloon(void);
void ui_post_balloon(char_u *mesg, list_T *list);
diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim
index a8416788a..538dd220c 100644
--- a/src/testdir/test_popup.vim
+++ b/src/testdir/test_popup.vim
@@ -1029,4 +1029,38 @@ func Test_popup_complete_info_02()
bwipe!
endfunc
+func Test_CompleteChanged()
+ new
+ call setline(1, ['foo', 'bar', 'foobar', ''])
+ set complete=. completeopt=noinsert,noselect,menuone
+ function! OnPumChange()
+ let g:event = copy(v:event)
+ let g:item = get(v:event, 'completed_item', {})
+ let g:word = get(g:item, 'word', v:null)
+ endfunction
+ augroup AAAAA_Group
+ au!
+ autocmd CompleteChanged * :call OnPumChange()
+ augroup END
+ call cursor(4, 1)
+
+ call feedkeys("Sf\<C-N>", 'tx')
+ call assert_equal({'completed_item': {}, 'width': 15,
+ \ 'height': 2, 'size': 2,
+ \ 'col': 0, 'row': 4, 'scrollbar': v:false}, g:event)
+ call feedkeys("a\<C-N>\<C-N>\<C-E>", 'tx')
+ call assert_equal('foo', g:word)
+ call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-E>", 'tx')
+ call assert_equal('foobar', g:word)
+ call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-N>\<C-E>", 'tx')
+ call assert_equal(v:null, g:word)
+ call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 'tx')
+ call assert_equal('foobar', g:word)
+
+ autocmd! AAAAA_Group
+ set complete& completeopt&
+ delfunc! OnPumchange
+ bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index d2da9fcca..dadb01720 100644
--- 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 */
/**/
+ 1138,
+/**/
1137,
/**/
1136,
diff --git a/src/vim.h b/src/vim.h
index 01123e0c7..af779f361 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -1270,6 +1270,7 @@ enum auto_event
EVENT_CMDWINLEAVE, // before leaving the cmdline window
EVENT_COLORSCHEME, // after loading a colorscheme
EVENT_COLORSCHEMEPRE, // before loading a colorscheme
+ EVENT_COMPLETECHANGED, // after completion popup menu changed
EVENT_COMPLETEDONE, // after finishing insert complete
EVENT_CURSORHOLD, // cursor in same position for a while
EVENT_CURSORHOLDI, // idem, in Insert mode