aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/edit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r--src/nvim/edit.c186
1 files changed, 112 insertions, 74 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 77d5b2c816..53b196c61f 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -2094,38 +2094,56 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
xfree(wca);
- return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
- flags, FALSE);
+ return ins_compl_add(IObuff, len, icase, fname, NULL, true, dir, flags,
+ false);
}
- return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
+ return ins_compl_add(str, len, icase, fname, NULL, false, dir, flags, false);
}
-/*
- * Add a match to the list of matches.
- * If the given string is already in the list of completions, then return
- * NOTDONE, otherwise add it to the list and return OK. If there is an error
- * then FAIL is returned.
- */
-static int
-ins_compl_add (
- char_u *str,
- int len,
- int icase,
- char_u *fname,
- char_u **cptext, /* extra text for popup menu or NULL */
- int cdir,
- int flags,
- int adup /* accept duplicate match */
-)
+/// Add a match to the list of matches
+///
+/// @param[in] str Match to add.
+/// @param[in] len Match length, -1 to use #STRLEN.
+/// @param[in] icase Whether case is to be ignored.
+/// @param[in] fname File name match comes from. May be NULL.
+/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL,
+/// must have exactly #CPT_COUNT items.
+/// @param[in] cptext_allocated If true, will not copy cptext strings.
+///
+/// @note Will free strings in case of error.
+/// cptext itself will not be freed.
+/// @param[in] cdir Completion direction.
+/// @param[in] adup True if duplicate matches are to be accepted.
+///
+/// @return NOTDONE if the given string is already in the list of completions,
+/// otherwise it is added to the list and OK is returned. FAIL will be
+/// returned in case of error.
+static int ins_compl_add(char_u *const str, int len,
+ const bool icase, char_u *const fname,
+ char_u *const *const cptext,
+ const bool cptext_allocated,
+ const Direction cdir, int flags, const bool adup)
+ FUNC_ATTR_NONNULL_ARG(1)
{
compl_T *match;
- int dir = (cdir == 0 ? compl_direction : cdir);
+ int dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
os_breakcheck();
- if (got_int)
+#define FREE_CPTEXT(cptext, cptext_allocated) \
+ do { \
+ if (cptext_allocated) { \
+ for (size_t i = 0; i < CPT_COUNT; i++) { \
+ xfree(cptext[i]); \
+ } \
+ } \
+ } while (0)
+ if (got_int) {
+ FREE_CPTEXT(cptext, cptext_allocated);
return FAIL;
- if (len < 0)
+ }
+ if (len < 0) {
len = (int)STRLEN(str);
+ }
/*
* If the same match is already present, don't add it.
@@ -2133,10 +2151,12 @@ ins_compl_add (
if (compl_first_match != NULL && !adup) {
match = compl_first_match;
do {
- if ( !(match->cp_flags & ORIGINAL_TEXT)
- && STRNCMP(match->cp_str, str, len) == 0
- && match->cp_str[len] == NUL)
+ if (!(match->cp_flags & ORIGINAL_TEXT)
+ && STRNCMP(match->cp_str, str, len) == 0
+ && match->cp_str[len] == NUL) {
+ FREE_CPTEXT(cptext, cptext_allocated);
return NOTDONE;
+ }
match = match->cp_next;
} while (match != NULL && match != compl_first_match);
}
@@ -2167,16 +2187,26 @@ ins_compl_add (
else if (fname != NULL) {
match->cp_fname = vim_strsave(fname);
flags |= FREE_FNAME;
- } else
+ } else {
match->cp_fname = NULL;
+ }
match->cp_flags = flags;
if (cptext != NULL) {
int i;
- for (i = 0; i < CPT_COUNT; ++i)
- if (cptext[i] != NULL && *cptext[i] != NUL)
- match->cp_text[i] = vim_strsave(cptext[i]);
+ for (i = 0; i < CPT_COUNT; i++) {
+ if (cptext[i] == NULL) {
+ continue;
+ }
+ if (*cptext[i] != NUL) {
+ match->cp_text[i] = (cptext_allocated
+ ? cptext[i]
+ : (char_u *)xstrdup((char *)cptext[i]));
+ } else if (cptext_allocated) {
+ xfree(cptext[i]);
+ }
+ }
}
/*
@@ -2299,9 +2329,10 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
for (i = 0; i < num_matches && add_r != FAIL; i++)
if ((add_r = ins_compl_add(matches[i], -1, icase,
- NULL, NULL, dir, 0, FALSE)) == OK)
- /* if dir was BACKWARD then honor it just once */
+ NULL, NULL, false, dir, 0, false)) == OK) {
+ // If dir was BACKWARD then honor it just once.
dir = FORWARD;
+ }
FreeWild(num_matches, matches);
}
@@ -2365,8 +2396,8 @@ void set_completion(colnr_T startcol, list_T *list)
/* compl_pattern doesn't need to be set */
compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col,
compl_length);
- if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
- ORIGINAL_TEXT, FALSE) != OK) {
+ if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
+ ORIGINAL_TEXT, false) != OK) {
return;
}
@@ -2888,7 +2919,7 @@ static void ins_compl_clear(void)
compl_orig_text = NULL;
compl_enter_selects = FALSE;
// clear v:completed_item
- set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
+ set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
}
/// Check that Insert completion is active.
@@ -3486,7 +3517,7 @@ expand_by_function (
theend:
if (matchdict != NULL) {
- dict_unref(matchdict);
+ tv_dict_unref(matchdict);
}
if (matchlist != NULL) {
tv_list_unref(matchlist);
@@ -3519,53 +3550,60 @@ static void ins_compl_add_dict(dict_T *dict)
dictitem_T *di_refresh;
dictitem_T *di_words;
- /* Check for optional "refresh" item. */
- compl_opt_refresh_always = FALSE;
- di_refresh = dict_find(dict, (char_u *)"refresh", 7);
+ // Check for optional "refresh" item.
+ compl_opt_refresh_always = false;
+ di_refresh = tv_dict_find(dict, S_LEN("refresh"));
if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) {
- char_u *v = di_refresh->di_tv.vval.v_string;
+ const char *v = (const char *)di_refresh->di_tv.vval.v_string;
- if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
- compl_opt_refresh_always = TRUE;
+ if (v != NULL && strcmp(v, "always") == 0) {
+ compl_opt_refresh_always = true;
+ }
}
- /* Add completions from a "words" list. */
- di_words = dict_find(dict, (char_u *)"words", 5);
- if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
+ // Add completions from a "words" list.
+ di_words = tv_dict_find(dict, S_LEN("words"));
+ if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) {
ins_compl_add_list(di_words->di_tv.vval.v_list);
+ }
}
-/*
- * Add a match to the list of matches from a typeval_T.
- * If the given string is already in the list of completions, then return
- * NOTDONE, otherwise add it to the list and return OK. If there is an error
- * then FAIL is returned.
- */
-int ins_compl_add_tv(typval_T *tv, int dir)
-{
- char_u *word;
- int icase = FALSE;
- int adup = FALSE;
- int aempty = FALSE;
- char_u *(cptext[CPT_COUNT]);
+/// Add a match to the list of matches from VimL object
+///
+/// @param[in] tv Object to get matches from.
+/// @param[in] dir Completion direction.
+///
+/// @return NOTDONE if the given string is already in the list of completions,
+/// otherwise it is added to the list and OK is returned. FAIL will be
+/// returned in case of error.
+int ins_compl_add_tv(typval_T *const tv, const Direction dir)
+ FUNC_ATTR_NONNULL_ALL
+{
+ const char *word;
+ bool icase = false;
+ bool adup = false;
+ bool aempty = false;
+ char *(cptext[CPT_COUNT]);
if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
- word = get_dict_string(tv->vval.v_dict, "word", false);
- cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false);
- cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false);
- cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false);
- cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false);
-
- icase = get_dict_number(tv->vval.v_dict, "icase");
- adup = get_dict_number(tv->vval.v_dict, "dup");
- aempty = get_dict_number(tv->vval.v_dict, "empty");
+ 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);
+
+ icase = (bool)tv_dict_get_number(tv->vval.v_dict, "icase");
+ adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup");
+ aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty");
} else {
- word = get_tv_string_chk(tv);
+ word = (const char *)get_tv_string_chk(tv);
memset(cptext, 0, sizeof(cptext));
}
- if (word == NULL || (!aempty && *word == NUL))
+ if (word == NULL || (!aempty && *word == NUL)) {
return FAIL;
- return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
+ }
+ return ins_compl_add((char_u *)word, -1, icase, NULL,
+ (char_u **)cptext, true, dir, 0, adup);
}
/*
@@ -3980,7 +4018,7 @@ static void ins_compl_delete(void)
// causes flicker, thus we can't do that.
changed_cline_bef_curs();
// clear v:completed_item
- set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
+ set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
}
// Insert the new text being completed.
@@ -3995,7 +4033,7 @@ static void ins_compl_insert(int in_compl_func)
// Set completed item.
// { word, abbr, menu, kind, info }
- dict_T *dict = dict_alloc();
+ dict_T *dict = tv_dict_alloc();
dict_add_nr_str(dict, "word", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_str));
dict_add_nr_str(dict, "abbr", 0L,
@@ -4667,8 +4705,8 @@ static int ins_complete(int c, bool enable_pum)
/* Always add completion for the original text. */
xfree(compl_orig_text);
compl_orig_text = vim_strnsave(line + compl_col, compl_length);
- if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
- ORIGINAL_TEXT, FALSE) != OK) {
+ if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
+ ORIGINAL_TEXT, false) != OK) {
xfree(compl_pattern);
compl_pattern = NULL;
xfree(compl_orig_text);