diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/edit.c | 37 | ||||
-rw-r--r-- | src/nvim/edit.h | 3 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 37 | ||||
-rw-r--r-- | src/nvim/testdir/test_ins_complete.vim | 6 |
4 files changed, 66 insertions, 17 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index a291ed0401..a4c4bf4ce8 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -143,6 +143,7 @@ struct compl_S { compl_T *cp_prev; char_u *cp_str; // matched text char_u *(cp_text[CPT_COUNT]); // text for the menu + typval_T cp_user_data; char_u *cp_fname; // file containing the match, allocated when // cp_flags has CP_FREE_FNAME int cp_flags; // CP_ values @@ -2291,7 +2292,7 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname, flags |= CP_ICASE; } - return ins_compl_add(str, len, fname, NULL, false, dir, flags, false); + return ins_compl_add(str, len, fname, NULL, false, NULL, dir, flags, false); } /// Add a match to the list of matches @@ -2315,6 +2316,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname, char_u *const *const cptext, const bool cptext_allocated, + typval_T *user_data, const Direction cdir, int flags_arg, const bool adup) FUNC_ATTR_NONNULL_ARG(1) { @@ -2403,6 +2405,10 @@ static int ins_compl_add(char_u *const str, int len, } } + if (user_data != NULL) { + match->cp_user_data = *user_data; + } + /* * Link the new match structure in the list of matches. */ @@ -2521,7 +2527,7 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase) int dir = compl_direction; for (int i = 0; i < num_matches && add_r != FAIL; i++) { - if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, dir, + if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir, icase ? CP_ICASE : 0, false)) == OK) { // If dir was BACKWARD then honor it just once. dir = FORWARD; @@ -2596,7 +2602,7 @@ void set_completion(colnr_T startcol, list_T *list) if (p_ic) { flags |= CP_ICASE; } - if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, 0, + if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0, flags, false) != OK) { return; } @@ -3120,6 +3126,7 @@ static void ins_compl_free(void) for (int i = 0; i < CPT_COUNT; i++) { xfree(match->cp_text[i]); } + tv_clear(&match->cp_user_data); xfree(match); } while (compl_curr_match != NULL && compl_curr_match != compl_first_match); compl_first_match = compl_curr_match = NULL; @@ -3215,8 +3222,11 @@ void get_complete_info(list_T *what_list, dict_T *retdict) (char *)EMPTY_IF_NULL(match->cp_text[CPT_KIND])); tv_dict_add_str(di, S_LEN("info"), (char *)EMPTY_IF_NULL(match->cp_text[CPT_INFO])); - tv_dict_add_str(di, S_LEN("user_data"), - (char *)EMPTY_IF_NULL(match->cp_text[CPT_USER_DATA])); + if (match->cp_user_data.v_type == VAR_UNKNOWN) { + tv_dict_add_str(di, S_LEN("user_data"), ""); + } else { + tv_dict_add_tv(di, S_LEN("user_data"), &match->cp_user_data); + } } match = match->cp_next; } while (match != NULL && match != compl_first_match); @@ -3930,15 +3940,16 @@ int ins_compl_add_tv(typval_T *const tv, const Direction dir) bool empty = false; int flags = 0; char *(cptext[CPT_COUNT]); + typval_T user_data; + user_data.v_type = VAR_UNKNOWN; if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) { word = tv_dict_get_string(tv->vval.v_dict, "word", false); cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true); cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true); cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true); cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true); - cptext[CPT_USER_DATA] = tv_dict_get_string(tv->vval.v_dict, - "user_data", true); + tv_dict_get_tv(tv->vval.v_dict, "user_data", &user_data); if (tv_dict_get_number(tv->vval.v_dict, "icase")) { flags |= CP_ICASE; @@ -3960,7 +3971,7 @@ int ins_compl_add_tv(typval_T *const tv, const Direction dir) return FAIL; } return ins_compl_add((char_u *)word, -1, NULL, - (char_u **)cptext, true, dir, flags, dup); + (char_u **)cptext, true, &user_data, dir, flags, dup); } // Get the next expansion(s), using "compl_pattern". @@ -4450,9 +4461,11 @@ static dict_T *ins_compl_dict_alloc(compl_T *match) tv_dict_add_str( dict, S_LEN("info"), (const char *)EMPTY_IF_NULL(match->cp_text[CPT_INFO])); - tv_dict_add_str( - dict, S_LEN("user_data"), - (const char *)EMPTY_IF_NULL(match->cp_text[CPT_USER_DATA])); + if (match->cp_user_data.v_type == VAR_UNKNOWN) { + tv_dict_add_str(dict, S_LEN("user_data"), ""); + } else { + tv_dict_add_tv(dict, S_LEN("user_data"), &match->cp_user_data); + } return dict; } @@ -5155,7 +5168,7 @@ static int ins_complete(int c, bool enable_pum) if (p_ic) { flags |= CP_ICASE; } - if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, 0, + if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0, flags, false) != OK) { XFREE_CLEAR(compl_pattern); XFREE_CLEAR(compl_orig_text); diff --git a/src/nvim/edit.h b/src/nvim/edit.h index 92dab37a70..09f401ee82 100644 --- a/src/nvim/edit.h +++ b/src/nvim/edit.h @@ -10,8 +10,7 @@ #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 +#define CPT_COUNT 4 // Number of entries // values for cp_flags typedef enum { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 773e493d0b..35130f6f40 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1429,6 +1429,23 @@ dictitem_T *tv_dict_find(const dict_T *const d, const char *const key, return TV_DICT_HI2DI(hi); } +/// Get a typval item from a dictionary and copy it into "rettv". +/// +/// @param[in] d Dictionary to check. +/// @param[in] key Dictionary key. +/// @param[in] rettv Return value. +/// @return OK in case of success or FAIL if nothing was found. +int tv_dict_get_tv(dict_T *d, const char *const key, typval_T *rettv) +{ + dictitem_T *const di = tv_dict_find(d, key, -1); + if (di == NULL) { + return FAIL; + } + + tv_copy(&di->di_tv, rettv); + return OK; +} + /// Get a number item from a dictionary /// /// Returns 0 if the entry does not exist. @@ -1588,6 +1605,26 @@ int tv_dict_add_list(dict_T *const d, const char *const key, return OK; } +/// Add a typval entry to dictionary. +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// +/// @return FAIL if out of memory or key already exists. +int tv_dict_add_tv(dict_T *d, const char *key, const size_t key_len, + typval_T *tv) +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + tv_copy(tv, &item->di_tv); + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + /// Add a dictionary entry to dictionary /// /// @param[out] d Dictionary to add entry to. diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index f4e6b698c6..1c275d5bd1 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -120,7 +120,7 @@ function! s:CompleteDone_CompleteFuncDict( findstart, base ) \ 'menu': 'extra text', \ 'info': 'words are cool', \ 'kind': 'W', - \ 'user_data': 'test' + \ 'user_data': ['one', 'two'] \ } \ ] \ } @@ -136,7 +136,7 @@ func s:CompleteDone_CheckCompletedItemDict(pre) 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' ] ) + call assert_equal( ['one', 'two'], v:completed_item[ 'user_data' ] ) if a:pre call assert_equal('function', complete_info().mode) @@ -170,7 +170,7 @@ func Test_CompleteDoneDict() execute "normal a\<C-X>\<C-U>\<C-Y>" set completefunc& - call assert_equal('test', v:completed_item[ 'user_data' ]) + call assert_equal(['one', 'two'], v:completed_item[ 'user_data' ]) call assert_true(s:called_completedone) let s:called_completedone = 0 |