Patch 8.1.1138
Problem: Plugins don't get notified when the popup menu changes.
Solution: Add the CompleteChanged event. (Andy Massimino. closes #4176)
Files: runtime/doc/autocmd.txt, src/autocmd.c, src/dict.c,
src/insexpand.c, src/popupmnu.c, src/proto/autocmd.pro,
src/proto/dict.pro, src/proto/popupmnu.pro,
src/testdir/test_popup.vim, src/vim.h
*** ../vim-8.1.1137/runtime/doc/autocmd.txt 2019-04-04 15:04:32.962792211
+0200
--- runtime/doc/autocmd.txt 2019-04-08 18:00:41.100946679 +0200
***************
*** 365,370 ****
--- 367,373 ----
|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"
***************
*** 577,583 ****
--- 580,601 ----
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
*** ../vim-8.1.1137/src/autocmd.c 2019-04-04 15:40:53.011337945 +0200
--- src/autocmd.c 2019-04-08 17:45:52.897440559 +0200
***************
*** 112,117 ****
--- 112,118 ----
{"CmdUndefined", EVENT_CMDUNDEFINED},
{"ColorScheme", EVENT_COLORSCHEME},
{"ColorSchemePre", EVENT_COLORSCHEMEPRE},
+ {"CompleteChanged", EVENT_COMPLETECHANGED},
{"CompleteDone", EVENT_COMPLETEDONE},
{"CursorHold", EVENT_CURSORHOLD},
{"CursorHoldI", EVENT_CURSORHOLDI},
***************
*** 1794,1799 ****
--- 1795,1811 ----
}
#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.
*** ../vim-8.1.1137/src/dict.c 2019-02-11 22:00:07.667917634 +0100
--- src/dict.c 2019-04-08 17:45:52.897440559 +0200
***************
*** 342,359 ****
}
/*
! * 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)
{
dictitem_T *item;
item = dictitem_alloc((char_u *)key);
if (item == NULL)
return FAIL;
! item->di_tv.v_type = VAR_NUMBER;
item->di_tv.vval.v_number = nr;
if (dict_add(d, item) == FAIL)
{
--- 342,359 ----
}
/*
! * Add a number or special entry to dictionary "d".
* Returns FAIL when out of memory and when key already exists.
*/
! 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 = special ? VAR_SPECIAL : VAR_NUMBER;
item->di_tv.vval.v_number = nr;
if (dict_add(d, item) == FAIL)
{
***************
*** 364,369 ****
--- 364,389 ----
}
/*
+ * 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.
*/
*** ../vim-8.1.1137/src/insexpand.c 2019-04-06 14:22:17.754642647 +0200
--- src/insexpand.c 2019-04-08 18:09:25.454100998 +0200
***************
*** 203,208 ****
--- 203,209 ----
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,999 ****
--- 995,1031 ----
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,1141 ****
--- 1168,1176 ----
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,2921 ****
compl_used_match = FALSE;
else
compl_used_match = TRUE;
- // 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]);
}
! set_vim_var_dict(VV_COMPLETED_ITEM, dict);
! if (!in_compl_func)
! compl_curr_match = compl_shown_match;
}
/*
--- 2934,2964 ----
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);
if (dict != NULL)
{
! 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]);
}
! return dict;
}
/*
*** ../vim-8.1.1137/src/popupmnu.c 2019-03-02 10:13:36.796974835 +0100
--- src/popupmnu.c 2019-04-08 18:05:53.751263571 +0200
***************
*** 923,928 ****
--- 923,944 ----
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)
*** ../vim-8.1.1137/src/proto/autocmd.pro 2019-01-26 16:20:44.264683546
+0100
--- src/proto/autocmd.pro 2019-04-08 18:01:19.088781927 +0200
***************
*** 26,31 ****
--- 26,32 ----
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);
*** ../vim-8.1.1137/src/proto/dict.pro 2018-12-26 22:57:37.978550895 +0100
--- src/proto/dict.pro 2019-04-08 17:45:52.905440501 +0200
***************
*** 14,19 ****
--- 14,20 ----
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);
*** ../vim-8.1.1137/src/proto/popupmnu.pro 2019-01-17 21:09:02.045706371
+0100
--- src/proto/popupmnu.pro 2019-04-08 18:06:01.919216971 +0200
***************
*** 8,13 ****
--- 8,14 ----
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);
*** ../vim-8.1.1137/src/testdir/test_popup.vim 2019-04-06 13:45:51.568756943
+0200
--- src/testdir/test_popup.vim 2019-04-08 17:45:52.909440473 +0200
***************
*** 1029,1032 ****
--- 1029,1066 ----
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
*** ../vim-8.1.1137/src/vim.h 2019-04-02 22:15:51.348273497 +0200
--- src/vim.h 2019-04-08 17:45:52.909440473 +0200
***************
*** 1270,1275 ****
--- 1270,1276 ----
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
*** ../vim-8.1.1137/src/version.c 2019-04-07 21:55:03.736116273 +0200
--- src/version.c 2019-04-08 18:14:25.904569298 +0200
***************
*** 773,774 ****
--- 773,776 ----
{ /* Add new patch number below this line */
+ /**/
+ 1138,
/**/
--
hundred-and-one symptoms of being an internet addict:
230. You spend your Friday nights typing away at your keyboard
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.