diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/autocmd.c | 12 | ||||
-rw-r--r-- | src/dict.c | 28 | ||||
-rw-r--r-- | src/insexpand.c | 69 | ||||
-rw-r--r-- | src/popupmnu.c | 16 | ||||
-rw-r--r-- | src/proto/autocmd.pro | 1 | ||||
-rw-r--r-- | src/proto/dict.pro | 1 | ||||
-rw-r--r-- | src/proto/popupmnu.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_popup.vim | 34 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim.h | 1 |
10 files changed, 148 insertions, 17 deletions
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, @@ -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 |