mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 02:34:59 -07:00
vim-patch:9.1.0882: too many strlen() calls in insexpand.c
Problem: too many strlen() calls in insexpand.c
Solution: Refactor insexpand.c and reduce number of calls to STRLEN(),
fix a warning get_next_filename_completion(), add new function
ins_compl_leader_len() (John Marriott)
closes: vim/vim#16095
5e6ea92b2c
Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
parent
738320188f
commit
a1c14f8d81
@ -10,6 +10,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "klib/kvec.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/ascii_defs.h"
|
||||
#include "nvim/autocmd.h"
|
||||
#include "nvim/autocmd_defs.h"
|
||||
@ -157,7 +158,7 @@ struct compl_S {
|
||||
compl_T *cp_next;
|
||||
compl_T *cp_prev;
|
||||
compl_T *cp_match_next; ///< matched next compl_T
|
||||
char *cp_str; ///< matched text
|
||||
String cp_str; ///< matched text
|
||||
char *(cp_text[CPT_COUNT]); ///< text for the menu
|
||||
typval_T cp_user_data;
|
||||
char *cp_fname; ///< file containing the match, allocated when
|
||||
@ -220,7 +221,7 @@ static bool compl_enter_selects = false;
|
||||
|
||||
/// When "compl_leader" is not NULL only matches that start with this string
|
||||
/// are used.
|
||||
static char *compl_leader = NULL;
|
||||
static String compl_leader = STRING_INIT;
|
||||
|
||||
static bool compl_get_longest = false; ///< put longest common string in compl_leader
|
||||
|
||||
@ -245,8 +246,7 @@ static bool compl_started = false;
|
||||
static int ctrl_x_mode = CTRL_X_NORMAL;
|
||||
|
||||
static int compl_matches = 0; ///< number of completion matches
|
||||
static char *compl_pattern = NULL;
|
||||
static size_t compl_patternlen = 0;
|
||||
static String compl_pattern = STRING_INIT;
|
||||
static Direction compl_direction = FORWARD;
|
||||
static Direction compl_shows_dir = FORWARD;
|
||||
static int compl_pending = 0; ///< > 1 for postponed CTRL-N
|
||||
@ -257,8 +257,8 @@ static int compl_length = 0;
|
||||
static colnr_T compl_col = 0; ///< column where the text starts
|
||||
///< that is being completed
|
||||
static colnr_T compl_ins_end_col = 0;
|
||||
static char *compl_orig_text = NULL; ///< text as it was before
|
||||
///< completion started
|
||||
static String compl_orig_text = STRING_INIT; ///< text as it was before
|
||||
///< completion started
|
||||
/// Undo information to restore extmarks for original text.
|
||||
static extmark_undo_vec_t compl_orig_extmarks;
|
||||
static int compl_cont_mode = 0;
|
||||
@ -639,7 +639,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
|
||||
|
||||
// Rule 1: Were any chars converted to lower?
|
||||
{
|
||||
const char *p = compl_orig_text;
|
||||
const char *p = compl_orig_text.data;
|
||||
for (int i = 0; i < min_len; i++) {
|
||||
const int c = mb_ptr2char_adv(&p);
|
||||
if (mb_islower(c)) {
|
||||
@ -659,7 +659,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
|
||||
// upper case.
|
||||
if (!has_lower) {
|
||||
bool was_letter = false;
|
||||
const char *p = compl_orig_text;
|
||||
const char *p = compl_orig_text.data;
|
||||
for (int i = 0; i < min_len; i++) {
|
||||
const int c = mb_ptr2char_adv(&p);
|
||||
if (was_letter && mb_isupper(c) && mb_islower(wca[i])) {
|
||||
@ -675,7 +675,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
|
||||
|
||||
// Copy the original case of the part we typed.
|
||||
{
|
||||
const char *p = compl_orig_text;
|
||||
const char *p = compl_orig_text.data;
|
||||
for (int i = 0; i < min_len; i++) {
|
||||
const int c = mb_ptr2char_adv(&p);
|
||||
if (mb_islower(c)) {
|
||||
@ -705,7 +705,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
|
||||
ga_grow(&gap, IOSIZE);
|
||||
*p = NUL;
|
||||
STRCPY(gap.ga_data, IObuff);
|
||||
gap.ga_len = (int)strlen(IObuff);
|
||||
gap.ga_len = (int)(p - IObuff);
|
||||
} else {
|
||||
p += utf_char2bytes(wca[i++], p);
|
||||
}
|
||||
@ -752,7 +752,7 @@ int ins_compl_add_infercase(char *str_arg, int len, bool icase, char *fname, Dir
|
||||
|
||||
// Find actual length of original text.
|
||||
{
|
||||
const char *p = compl_orig_text;
|
||||
const char *p = compl_orig_text.data;
|
||||
compl_char_len = 0;
|
||||
while (*p != NUL) {
|
||||
MB_PTR_ADV(p);
|
||||
@ -841,8 +841,8 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons
|
||||
match = compl_first_match;
|
||||
do {
|
||||
if (!match_at_original_text(match)
|
||||
&& strncmp(match->cp_str, str, (size_t)len) == 0
|
||||
&& ((int)strlen(match->cp_str) <= len || match->cp_str[len] == NUL)) {
|
||||
&& strncmp(match->cp_str.data, str, (size_t)len) == 0
|
||||
&& ((int)match->cp_str.size <= len || match->cp_str.data[len] == NUL)) {
|
||||
if (cptext_allocated) {
|
||||
free_cptext(cptext);
|
||||
}
|
||||
@ -862,7 +862,7 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons
|
||||
if (flags & CP_ORIGINAL_TEXT) {
|
||||
match->cp_number = 0;
|
||||
}
|
||||
match->cp_str = xstrnsave(str, (size_t)len);
|
||||
match->cp_str = cbuf_to_string(str, (size_t)len);
|
||||
|
||||
// match-fname is:
|
||||
// - compl_curr_match->cp_fname if it is a string equal to fname.
|
||||
@ -944,9 +944,9 @@ static bool ins_compl_equal(compl_T *match, char *str, size_t len)
|
||||
return true;
|
||||
}
|
||||
if (match->cp_flags & CP_ICASE) {
|
||||
return STRNICMP(match->cp_str, str, len) == 0;
|
||||
return STRNICMP(match->cp_str.data, str, len) == 0;
|
||||
}
|
||||
return strncmp(match->cp_str, str, len) == 0;
|
||||
return strncmp(match->cp_str.data, str, len) == 0;
|
||||
}
|
||||
|
||||
/// when len is -1 mean use whole length of p otherwise part of p
|
||||
@ -976,13 +976,13 @@ int ins_compl_col_range_attr(int col)
|
||||
/// Reduce the longest common string for match "match".
|
||||
static void ins_compl_longest_match(compl_T *match)
|
||||
{
|
||||
if (compl_leader == NULL) {
|
||||
if (compl_leader.data == NULL) {
|
||||
// First match, use it as a whole.
|
||||
compl_leader = xstrdup(match->cp_str);
|
||||
compl_leader = copy_string(match->cp_str, NULL);
|
||||
|
||||
bool had_match = (curwin->w_cursor.col > compl_col);
|
||||
ins_compl_delete(false);
|
||||
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
|
||||
ins_compl_insert_bytes(compl_leader.data + get_compl_len(), -1);
|
||||
ins_redraw(false);
|
||||
|
||||
// When the match isn't there (to avoid matching itself) remove it
|
||||
@ -996,8 +996,8 @@ static void ins_compl_longest_match(compl_T *match)
|
||||
}
|
||||
|
||||
// Reduce the text if this match differs from compl_leader.
|
||||
char *p = compl_leader;
|
||||
char *s = match->cp_str;
|
||||
char *p = compl_leader.data;
|
||||
char *s = match->cp_str.data;
|
||||
while (*p != NUL) {
|
||||
int c1 = utf_ptr2char(p);
|
||||
int c2 = utf_ptr2char(s);
|
||||
@ -1014,9 +1014,11 @@ static void ins_compl_longest_match(compl_T *match)
|
||||
if (*p != NUL) {
|
||||
// Leader was shortened, need to change the inserted text.
|
||||
*p = NUL;
|
||||
compl_leader.size = (size_t)(p - compl_leader.data);
|
||||
|
||||
bool had_match = (curwin->w_cursor.col > compl_col);
|
||||
ins_compl_delete(false);
|
||||
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
|
||||
ins_compl_insert_bytes(compl_leader.data + get_compl_len(), -1);
|
||||
ins_redraw(false);
|
||||
|
||||
// When the match isn't there (to avoid matching itself) remove it
|
||||
@ -1078,8 +1080,8 @@ bool ins_compl_has_shown_match(void)
|
||||
/// Return whether the shown match is long enough.
|
||||
bool ins_compl_long_shown_match(void)
|
||||
{
|
||||
return compl_shown_match != NULL && compl_shown_match->cp_str != NULL
|
||||
&& (colnr_T)strlen(compl_shown_match->cp_str) > curwin->w_cursor.col - compl_col;
|
||||
return compl_shown_match != NULL && compl_shown_match->cp_str.data != NULL
|
||||
&& (colnr_T)compl_shown_match->cp_str.size > curwin->w_cursor.col - compl_col;
|
||||
}
|
||||
|
||||
/// Get the local or global value of 'completeopt' flags.
|
||||
@ -1134,7 +1136,7 @@ static dict_T *ins_compl_dict_alloc(compl_T *match)
|
||||
{
|
||||
// { word, abbr, menu, kind, info }
|
||||
dict_T *dict = tv_dict_alloc_lock(VAR_FIXED);
|
||||
tv_dict_add_str(dict, S_LEN("word"), match->cp_str);
|
||||
tv_dict_add_str(dict, S_LEN("word"), match->cp_str.data);
|
||||
tv_dict_add_str(dict, S_LEN("abbr"), match->cp_text[CPT_ABBR]);
|
||||
tv_dict_add_str(dict, S_LEN("menu"), match->cp_text[CPT_MENU]);
|
||||
tv_dict_add_str(dict, S_LEN("kind"), match->cp_text[CPT_KIND]);
|
||||
@ -1203,7 +1205,6 @@ static int ins_compl_build_pum(void)
|
||||
XFREE_CLEAR(compl_leader);
|
||||
}
|
||||
|
||||
const int lead_len = compl_leader != NULL ? (int)strlen(compl_leader) : 0;
|
||||
int max_fuzzy_score = 0;
|
||||
unsigned cur_cot_flags = get_cot_flags();
|
||||
bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0;
|
||||
@ -1214,7 +1215,7 @@ static int ins_compl_build_pum(void)
|
||||
// match after it, don't highlight anything.
|
||||
bool shown_match_ok = match_at_original_text(compl_shown_match);
|
||||
|
||||
if (strequal(compl_leader, compl_orig_text) && !shown_match_ok) {
|
||||
if (strequal(compl_leader.data, compl_orig_text.data) && !shown_match_ok) {
|
||||
compl_shown_match = compl_no_select ? compl_first_match : compl_first_match->cp_next;
|
||||
}
|
||||
|
||||
@ -1226,13 +1227,13 @@ static int ins_compl_build_pum(void)
|
||||
do {
|
||||
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
|
||||
// set the cp_score for later comparisons.
|
||||
if (compl_fuzzy_match && compl_leader != NULL && lead_len > 0) {
|
||||
comp->cp_score = fuzzy_match_str(comp->cp_str, compl_leader);
|
||||
if (compl_fuzzy_match && compl_leader.data != NULL && compl_leader.size > 0) {
|
||||
comp->cp_score = fuzzy_match_str(comp->cp_str.data, compl_leader.data);
|
||||
}
|
||||
|
||||
if (!match_at_original_text(comp)
|
||||
&& (compl_leader == NULL
|
||||
|| ins_compl_equal(comp, compl_leader, (size_t)lead_len)
|
||||
&& (compl_leader.data == NULL
|
||||
|| ins_compl_equal(comp, compl_leader.data, compl_leader.size)
|
||||
|| (compl_fuzzy_match && comp->cp_score > 0))) {
|
||||
compl_match_arraysize++;
|
||||
if (match_head == NULL) {
|
||||
@ -1303,7 +1304,7 @@ static int ins_compl_build_pum(void)
|
||||
comp = match_head;
|
||||
while (comp != NULL) {
|
||||
compl_match_array[i].pum_text = comp->cp_text[CPT_ABBR] != NULL
|
||||
? comp->cp_text[CPT_ABBR] : comp->cp_str;
|
||||
? comp->cp_text[CPT_ABBR] : comp->cp_str.data;
|
||||
compl_match_array[i].pum_kind = comp->cp_text[CPT_KIND];
|
||||
compl_match_array[i].pum_info = comp->cp_text[CPT_INFO];
|
||||
compl_match_array[i].pum_score = comp->cp_score;
|
||||
@ -1316,7 +1317,7 @@ static int ins_compl_build_pum(void)
|
||||
comp = match_next;
|
||||
}
|
||||
|
||||
if (compl_fuzzy_match && compl_leader != NULL && lead_len > 0) {
|
||||
if (compl_fuzzy_match && compl_leader.data != NULL && compl_leader.size > 0) {
|
||||
for (i = 0; i < compl_match_arraysize; i++) {
|
||||
compl_match_array[i].pum_idx = i;
|
||||
}
|
||||
@ -1354,7 +1355,7 @@ void ins_compl_show_pum(void)
|
||||
} else {
|
||||
// popup menu already exists, only need to find the current item.
|
||||
for (int i = 0; i < compl_match_arraysize; i++) {
|
||||
if (compl_match_array[i].pum_text == compl_shown_match->cp_str
|
||||
if (compl_match_array[i].pum_text == compl_shown_match->cp_str.data
|
||||
|| compl_match_array[i].pum_text == compl_shown_match->cp_text[CPT_ABBR]) {
|
||||
cur = i;
|
||||
break;
|
||||
@ -1423,7 +1424,13 @@ bool compl_match_curr_select(int selected)
|
||||
/// Get current completion leader
|
||||
char *ins_compl_leader(void)
|
||||
{
|
||||
return compl_leader != NULL ? compl_leader : compl_orig_text;
|
||||
return compl_leader.data != NULL ? compl_leader.data : compl_orig_text.data;
|
||||
}
|
||||
|
||||
/// Get current completion leader length
|
||||
size_t ins_compl_leader_len(void)
|
||||
{
|
||||
return compl_leader.data != NULL ? compl_leader.size : compl_orig_text.size;
|
||||
}
|
||||
|
||||
/// Add any identifiers that match the given pattern "pat" in the list of
|
||||
@ -1668,9 +1675,8 @@ static char *find_line_end(char *ptr)
|
||||
/// Free the list of completions
|
||||
static void ins_compl_free(void)
|
||||
{
|
||||
XFREE_CLEAR(compl_pattern);
|
||||
compl_patternlen = 0;
|
||||
XFREE_CLEAR(compl_leader);
|
||||
API_CLEAR_STRING(compl_pattern);
|
||||
API_CLEAR_STRING(compl_leader);
|
||||
|
||||
if (compl_first_match == NULL) {
|
||||
return;
|
||||
@ -1683,7 +1689,7 @@ static void ins_compl_free(void)
|
||||
do {
|
||||
compl_T *match = compl_curr_match;
|
||||
compl_curr_match = compl_curr_match->cp_next;
|
||||
xfree(match->cp_str);
|
||||
API_CLEAR_STRING(match->cp_str);
|
||||
// several entries may use the same fname, free it just once.
|
||||
if (match->cp_flags & CP_FREE_FNAME) {
|
||||
xfree(match->cp_fname);
|
||||
@ -1704,12 +1710,11 @@ void ins_compl_clear(void)
|
||||
compl_started = false;
|
||||
compl_matches = 0;
|
||||
compl_ins_end_col = 0;
|
||||
XFREE_CLEAR(compl_pattern);
|
||||
compl_patternlen = 0;
|
||||
XFREE_CLEAR(compl_leader);
|
||||
API_CLEAR_STRING(compl_pattern);
|
||||
API_CLEAR_STRING(compl_leader);
|
||||
edit_submode_extra = NULL;
|
||||
kv_destroy(compl_orig_extmarks);
|
||||
XFREE_CLEAR(compl_orig_text);
|
||||
API_CLEAR_STRING(compl_orig_text);
|
||||
compl_enter_selects = false;
|
||||
// clear v:completed_item
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc_lock(VAR_FIXED));
|
||||
@ -1793,8 +1798,9 @@ int ins_compl_bs(void)
|
||||
// TODO(bfredl): get rid of random update_screen() calls deep inside completion logic
|
||||
line = get_cursor_line_ptr();
|
||||
|
||||
xfree(compl_leader);
|
||||
compl_leader = xstrnsave(line + compl_col, (size_t)(p_off - (ptrdiff_t)compl_col));
|
||||
API_CLEAR_STRING(compl_leader);
|
||||
compl_leader = cbuf_to_string(line + compl_col,
|
||||
(size_t)(p_off - (ptrdiff_t)compl_col));
|
||||
|
||||
ins_compl_new_leader();
|
||||
if (compl_shown_match != NULL) {
|
||||
@ -1828,11 +1834,11 @@ static void ins_compl_new_leader(void)
|
||||
{
|
||||
ins_compl_del_pum();
|
||||
ins_compl_delete(true);
|
||||
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
|
||||
ins_compl_insert_bytes(compl_leader.data + get_compl_len(), -1);
|
||||
compl_used_match = false;
|
||||
|
||||
if (compl_started) {
|
||||
ins_compl_set_original_text(compl_leader);
|
||||
ins_compl_set_original_text(compl_leader.data, compl_leader.size);
|
||||
} else {
|
||||
spell_bad_len = 0; // need to redetect bad word
|
||||
// Matches were cleared, need to search for them now.
|
||||
@ -1892,9 +1898,9 @@ void ins_compl_addleader(int c)
|
||||
ins_compl_restart();
|
||||
}
|
||||
|
||||
xfree(compl_leader);
|
||||
compl_leader = xstrnsave(get_cursor_line_ptr() + compl_col,
|
||||
(size_t)(curwin->w_cursor.col - compl_col));
|
||||
API_CLEAR_STRING(compl_leader);
|
||||
compl_leader = cbuf_to_string(get_cursor_line_ptr() + compl_col,
|
||||
(size_t)(curwin->w_cursor.col - compl_col));
|
||||
ins_compl_new_leader();
|
||||
}
|
||||
|
||||
@ -1914,19 +1920,19 @@ static void ins_compl_restart(void)
|
||||
}
|
||||
|
||||
/// Set the first match, the original text.
|
||||
static void ins_compl_set_original_text(char *str)
|
||||
static void ins_compl_set_original_text(char *str, size_t len)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Replace the original text entry.
|
||||
// The CP_ORIGINAL_TEXT flag is either at the first item or might possibly
|
||||
// be at the last item for backward completion
|
||||
if (match_at_original_text(compl_first_match)) { // safety check
|
||||
xfree(compl_first_match->cp_str);
|
||||
compl_first_match->cp_str = xstrdup(str);
|
||||
API_CLEAR_STRING(compl_first_match->cp_str);
|
||||
compl_first_match->cp_str = cbuf_to_string(str, len);
|
||||
} else if (compl_first_match->cp_prev != NULL
|
||||
&& match_at_original_text(compl_first_match->cp_prev)) {
|
||||
xfree(compl_first_match->cp_prev->cp_str);
|
||||
compl_first_match->cp_prev->cp_str = xstrdup(str);
|
||||
API_CLEAR_STRING(compl_first_match->cp_prev->cp_str);
|
||||
compl_first_match->cp_prev->cp_str = cbuf_to_string(str, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1936,8 +1942,8 @@ void ins_compl_addfrommatch(void)
|
||||
{
|
||||
int len = (int)curwin->w_cursor.col - (int)compl_col;
|
||||
assert(compl_shown_match != NULL);
|
||||
char *p = compl_shown_match->cp_str;
|
||||
if ((int)strlen(p) <= len) { // the match is too short
|
||||
char *p = compl_shown_match->cp_str.data;
|
||||
if ((int)compl_shown_match->cp_str.size <= len) { // the match is too short
|
||||
// When still at the original match use the first entry that matches
|
||||
// the leader.
|
||||
if (!match_at_original_text(compl_shown_match)) {
|
||||
@ -1945,15 +1951,17 @@ void ins_compl_addfrommatch(void)
|
||||
}
|
||||
|
||||
p = NULL;
|
||||
size_t plen = 0;
|
||||
for (compl_T *cp = compl_shown_match->cp_next; cp != NULL
|
||||
&& !is_first_match(cp); cp = cp->cp_next) {
|
||||
if (compl_leader == NULL
|
||||
|| ins_compl_equal(cp, compl_leader, strlen(compl_leader))) {
|
||||
p = cp->cp_str;
|
||||
if (compl_leader.data == NULL
|
||||
|| ins_compl_equal(cp, compl_leader.data, compl_leader.size)) {
|
||||
p = cp->cp_str.data;
|
||||
plen = cp->cp_str.size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p == NULL || (int)strlen(p) <= len) {
|
||||
if (p == NULL || (int)plen <= len) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2093,7 +2101,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
|
||||
// Get here when we have finished typing a sequence of ^N and
|
||||
// ^P or other completion characters in CTRL-X mode. Free up
|
||||
// memory that was used, and make sure we can redo the insert.
|
||||
if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E) {
|
||||
if (compl_curr_match != NULL || compl_leader.data != NULL || c == Ctrl_E) {
|
||||
// If any of the original typed text has been changed, eg when
|
||||
// ignorecase is set, we must add back-spaces to the redo
|
||||
// buffer. We add as few as necessary to delete just the part
|
||||
@ -2102,7 +2110,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
|
||||
// CTRL-E then don't use the current match.
|
||||
char *ptr;
|
||||
if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E) {
|
||||
ptr = compl_curr_match->cp_str;
|
||||
ptr = compl_curr_match->cp_str.data;
|
||||
} else {
|
||||
ptr = NULL;
|
||||
}
|
||||
@ -2145,7 +2153,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
|
||||
if ((c == Ctrl_Y || (compl_enter_selects
|
||||
&& (c == CAR || c == K_KENTER || c == NL)))
|
||||
&& pum_visible()) {
|
||||
word = xstrdup(compl_shown_match->cp_str);
|
||||
word = xstrdup(compl_shown_match->cp_str.data);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
@ -2154,16 +2162,18 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
|
||||
if (c == Ctrl_E) {
|
||||
ins_compl_delete(false);
|
||||
char *p = NULL;
|
||||
if (compl_leader != NULL) {
|
||||
p = compl_leader;
|
||||
size_t plen = 0;
|
||||
if (compl_leader.data != NULL) {
|
||||
p = compl_leader.data;
|
||||
plen = compl_leader.size;
|
||||
} else if (compl_first_match != NULL) {
|
||||
p = compl_orig_text;
|
||||
p = compl_orig_text.data;
|
||||
plen = compl_orig_text.size;
|
||||
}
|
||||
if (p != NULL) {
|
||||
const int compl_len = get_compl_len();
|
||||
const int len = (int)strlen(p);
|
||||
if (len > compl_len) {
|
||||
ins_compl_insert_bytes(p + compl_len, len - compl_len);
|
||||
if ((int)plen > compl_len) {
|
||||
ins_compl_insert_bytes(p + compl_len, (int)plen - compl_len);
|
||||
}
|
||||
}
|
||||
restore_orig_extmarks();
|
||||
@ -2313,18 +2323,18 @@ bool ins_compl_prep(int c)
|
||||
/// "ptr" is the known leader text or NUL.
|
||||
static void ins_compl_fixRedoBufForLeader(char *ptr_arg)
|
||||
{
|
||||
int len;
|
||||
int len = 0;
|
||||
char *ptr = ptr_arg;
|
||||
|
||||
if (ptr == NULL) {
|
||||
if (compl_leader != NULL) {
|
||||
ptr = compl_leader;
|
||||
if (compl_leader.data != NULL) {
|
||||
ptr = compl_leader.data;
|
||||
} else {
|
||||
return; // nothing to do
|
||||
}
|
||||
}
|
||||
if (compl_orig_text != NULL) {
|
||||
char *p = compl_orig_text;
|
||||
if (compl_orig_text.data != NULL) {
|
||||
char *p = compl_orig_text.data;
|
||||
for (len = 0; p[len] != NUL && p[len] == ptr[len]; len++) {}
|
||||
if (len > 0) {
|
||||
len -= utf_head_off(p, p + len);
|
||||
@ -2332,8 +2342,6 @@ static void ins_compl_fixRedoBufForLeader(char *ptr_arg)
|
||||
for (p += len; *p != NUL; MB_PTR_ADV(p)) {
|
||||
AppendCharToRedobuff(K_BS);
|
||||
}
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
AppendToRedobuffLit(ptr + len, -1);
|
||||
}
|
||||
@ -2719,12 +2727,14 @@ static void set_completion(colnr_T startcol, list_T *list)
|
||||
compl_col = startcol;
|
||||
compl_length = curwin->w_cursor.col - startcol;
|
||||
// compl_pattern doesn't need to be set
|
||||
compl_orig_text = xstrnsave(get_cursor_line_ptr() + compl_col, (size_t)compl_length);
|
||||
compl_orig_text = cbuf_to_string(get_cursor_line_ptr() + compl_col,
|
||||
(size_t)compl_length);
|
||||
save_orig_extmarks();
|
||||
if (p_ic) {
|
||||
flags |= CP_ICASE;
|
||||
}
|
||||
if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0,
|
||||
if (ins_compl_add(compl_orig_text.data, (int)compl_orig_text.size,
|
||||
NULL, NULL, false, NULL, 0,
|
||||
flags | CP_FAST, false, NULL) != OK) {
|
||||
return;
|
||||
}
|
||||
@ -2922,7 +2932,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
|
||||
if (what_flag & CI_WHAT_ITEMS) {
|
||||
dict_T *di = tv_dict_alloc();
|
||||
tv_list_append_dict(li, di);
|
||||
tv_dict_add_str(di, S_LEN("word"), match->cp_str);
|
||||
tv_dict_add_str(di, S_LEN("word"), match->cp_str.data);
|
||||
tv_dict_add_str(di, S_LEN("abbr"), match->cp_text[CPT_ABBR]);
|
||||
tv_dict_add_str(di, S_LEN("menu"), match->cp_text[CPT_MENU]);
|
||||
tv_dict_add_str(di, S_LEN("kind"), match->cp_text[CPT_KIND]);
|
||||
@ -3114,8 +3124,8 @@ done:
|
||||
/// included files.
|
||||
static void get_next_include_file_completion(int compl_type)
|
||||
{
|
||||
find_pattern_in_path(compl_pattern, compl_direction,
|
||||
compl_patternlen, false, false,
|
||||
find_pattern_in_path(compl_pattern.data, compl_direction,
|
||||
compl_pattern.size, false, false,
|
||||
((compl_type == CTRL_X_PATH_DEFINES
|
||||
&& !(compl_cont_status & CONT_SOL))
|
||||
? FIND_DEFINE : FIND_ANY),
|
||||
@ -3127,14 +3137,14 @@ static void get_next_include_file_completion(int compl_type)
|
||||
static void get_next_dict_tsr_completion(int compl_type, char *dict, int dict_f)
|
||||
{
|
||||
if (thesaurus_func_complete(compl_type)) {
|
||||
expand_by_function(compl_type, compl_pattern);
|
||||
expand_by_function(compl_type, compl_pattern.data);
|
||||
} else {
|
||||
ins_compl_dictionaries(dict != NULL
|
||||
? dict
|
||||
: (compl_type == CTRL_X_THESAURUS
|
||||
? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
|
||||
: (*curbuf->b_p_dict == NUL ? p_dict : curbuf->b_p_dict)),
|
||||
compl_pattern,
|
||||
compl_pattern.data,
|
||||
dict != NULL ? dict_f : 0,
|
||||
compl_type == CTRL_X_THESAURUS);
|
||||
}
|
||||
@ -3145,14 +3155,14 @@ static void get_next_tag_completion(void)
|
||||
{
|
||||
// set p_ic according to p_ic, p_scs and pat for find_tags().
|
||||
const int save_p_ic = p_ic;
|
||||
p_ic = ignorecase(compl_pattern);
|
||||
p_ic = ignorecase(compl_pattern.data);
|
||||
|
||||
// Find up to TAG_MANY matches. Avoids that an enormous number
|
||||
// of matches is found when compl_pattern is empty
|
||||
g_tag_at_cursor = true;
|
||||
char **matches;
|
||||
int num_matches;
|
||||
if (find_tags(compl_pattern, &num_matches, &matches,
|
||||
if (find_tags(compl_pattern.data, &num_matches, &matches,
|
||||
TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
|
||||
| (ctrl_x_mode_not_default() ? TAG_VERBOSE : 0),
|
||||
TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) {
|
||||
@ -3167,13 +3177,13 @@ static void get_next_filename_completion(void)
|
||||
{
|
||||
char **matches;
|
||||
int num_matches;
|
||||
if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
|
||||
if (expand_wildcards(1, &compl_pattern.data, &num_matches, &matches,
|
||||
EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) != OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
// May change home directory back to "~".
|
||||
tilde_replace(compl_pattern, num_matches, matches);
|
||||
tilde_replace(compl_pattern.data, num_matches, matches);
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (curbuf->b_p_csl[0] != NUL) {
|
||||
for (int i = 0; i < num_matches; i++) {
|
||||
@ -3197,8 +3207,8 @@ static void get_next_cmdline_completion(void)
|
||||
{
|
||||
char **matches;
|
||||
int num_matches;
|
||||
if (expand_cmdline(&compl_xp, compl_pattern,
|
||||
(int)compl_patternlen, &num_matches, &matches) == EXPAND_OK) {
|
||||
if (expand_cmdline(&compl_xp, compl_pattern.data,
|
||||
(int)compl_pattern.size, &num_matches, &matches) == EXPAND_OK) {
|
||||
ins_compl_add_matches(num_matches, matches, false);
|
||||
}
|
||||
}
|
||||
@ -3207,7 +3217,7 @@ static void get_next_cmdline_completion(void)
|
||||
static void get_next_spell_completion(linenr_T lnum)
|
||||
{
|
||||
char **matches;
|
||||
int num_matches = expand_spelling(lnum, compl_pattern, &matches);
|
||||
int num_matches = expand_spelling(lnum, compl_pattern.data, &matches);
|
||||
if (num_matches > 0) {
|
||||
ins_compl_add_matches(num_matches, matches, p_ic);
|
||||
} else {
|
||||
@ -3226,22 +3236,24 @@ static char *ins_compl_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_po
|
||||
{
|
||||
*match_len = 0;
|
||||
char *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum) + cur_match_pos->col;
|
||||
int len;
|
||||
int len = ml_get_buf_len(ins_buf, cur_match_pos->lnum) - cur_match_pos->col;
|
||||
if (ctrl_x_mode_line_or_eval()) {
|
||||
if (compl_status_adding()) {
|
||||
if (cur_match_pos->lnum >= ins_buf->b_ml.ml_line_count) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1);
|
||||
len = ml_get_buf_len(ins_buf, cur_match_pos->lnum + 1);
|
||||
if (!p_paste) {
|
||||
ptr = skipwhite(ptr);
|
||||
char *tmp_ptr = ptr;
|
||||
ptr = skipwhite(tmp_ptr);
|
||||
len -= (int)(ptr - tmp_ptr);
|
||||
}
|
||||
}
|
||||
len = (int)strlen(ptr);
|
||||
} else {
|
||||
char *tmp_ptr = ptr;
|
||||
|
||||
if (compl_status_adding() && compl_length <= (int)strlen(tmp_ptr)) {
|
||||
if (compl_status_adding() && compl_length <= len) {
|
||||
tmp_ptr += compl_length;
|
||||
// Skip if already inside a word.
|
||||
if (vim_iswordp(tmp_ptr)) {
|
||||
@ -3337,10 +3349,11 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
|
||||
// has added a word that was at the beginning of the line.
|
||||
if (ctrl_x_mode_line_or_eval() || (compl_cont_status & CONT_SOL)) {
|
||||
found_new_match = search_for_exact_line(st->ins_buf, st->cur_match_pos,
|
||||
compl_direction, compl_pattern);
|
||||
compl_direction, compl_pattern.data);
|
||||
} else {
|
||||
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
|
||||
NULL, compl_direction, compl_pattern, compl_patternlen,
|
||||
NULL, compl_direction, compl_pattern.data,
|
||||
compl_pattern.size,
|
||||
1, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
|
||||
}
|
||||
msg_silent--;
|
||||
@ -3437,7 +3450,7 @@ static bool get_next_completion_match(int type, ins_compl_next_state_T *st, pos_
|
||||
|
||||
case CTRL_X_FUNCTION:
|
||||
case CTRL_X_OMNI:
|
||||
expand_by_function(type, compl_pattern);
|
||||
expand_by_function(type, compl_pattern.data);
|
||||
break;
|
||||
|
||||
case CTRL_X_SPELL:
|
||||
@ -3468,7 +3481,7 @@ static void get_next_bufname_token(void)
|
||||
FOR_ALL_BUFFERS(b) {
|
||||
if (b->b_p_bl && b->b_sfname != NULL) {
|
||||
char *tail = path_tail(b->b_sfname);
|
||||
if (strncmp(tail, compl_orig_text, strlen(compl_orig_text)) == 0) {
|
||||
if (strncmp(tail, compl_orig_text.data, compl_orig_text.size) == 0) {
|
||||
ins_compl_add(tail, (int)strlen(tail), NULL, NULL, false, NULL, 0,
|
||||
p_ic ? CP_ICASE : 0, false, NULL);
|
||||
}
|
||||
@ -3536,7 +3549,7 @@ static int ins_compl_get_exp(pos_T *ini)
|
||||
|
||||
// If complete() was called then compl_pattern has been reset.
|
||||
// The following won't work then, bail out.
|
||||
if (compl_pattern == NULL) {
|
||||
if (compl_pattern.data == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3604,7 +3617,7 @@ static int ins_compl_get_exp(pos_T *ini)
|
||||
static void ins_compl_update_shown_match(void)
|
||||
{
|
||||
while (!ins_compl_equal(compl_shown_match,
|
||||
compl_leader, strlen(compl_leader))
|
||||
compl_leader.data, compl_leader.size)
|
||||
&& compl_shown_match->cp_next != NULL
|
||||
&& !is_first_match(compl_shown_match->cp_next)) {
|
||||
compl_shown_match = compl_shown_match->cp_next;
|
||||
@ -3613,10 +3626,10 @@ static void ins_compl_update_shown_match(void)
|
||||
// If we didn't find it searching forward, and compl_shows_dir is
|
||||
// backward, find the last match.
|
||||
if (compl_shows_dir_backward()
|
||||
&& !ins_compl_equal(compl_shown_match, compl_leader, strlen(compl_leader))
|
||||
&& !ins_compl_equal(compl_shown_match, compl_leader.data, compl_leader.size)
|
||||
&& (compl_shown_match->cp_next == NULL
|
||||
|| is_first_match(compl_shown_match->cp_next))) {
|
||||
while (!ins_compl_equal(compl_shown_match, compl_leader, strlen(compl_leader))
|
||||
while (!ins_compl_equal(compl_shown_match, compl_leader.data, compl_leader.size)
|
||||
&& compl_shown_match->cp_prev != NULL
|
||||
&& !is_first_match(compl_shown_match->cp_prev)) {
|
||||
compl_shown_match = compl_shown_match->cp_prev;
|
||||
@ -3631,13 +3644,13 @@ void ins_compl_delete(bool new_leader)
|
||||
// allows marks present on the original text to shrink/grow appropriately.
|
||||
int orig_col = 0;
|
||||
if (new_leader) {
|
||||
char *orig = compl_orig_text;
|
||||
char *orig = compl_orig_text.data;
|
||||
char *leader = ins_compl_leader();
|
||||
while (*orig != NUL && utf_ptr2char(orig) == utf_ptr2char(leader)) {
|
||||
leader += utf_ptr2len(leader);
|
||||
orig += utf_ptr2len(orig);
|
||||
}
|
||||
orig_col = (int)(orig - compl_orig_text);
|
||||
orig_col = (int)(orig - compl_orig_text.data);
|
||||
}
|
||||
|
||||
// In insert mode: Delete the typed part.
|
||||
@ -3664,8 +3677,8 @@ void ins_compl_insert(bool in_compl_func)
|
||||
int compl_len = get_compl_len();
|
||||
// Make sure we don't go over the end of the string, this can happen with
|
||||
// illegal bytes.
|
||||
if (compl_len < (int)strlen(compl_shown_match->cp_str)) {
|
||||
ins_compl_insert_bytes(compl_shown_match->cp_str + compl_len, -1);
|
||||
if (compl_len < (int)compl_shown_match->cp_str.size) {
|
||||
ins_compl_insert_bytes(compl_shown_match->cp_str.data + compl_len, -1);
|
||||
}
|
||||
compl_used_match = !match_at_original_text(compl_shown_match);
|
||||
|
||||
@ -3735,7 +3748,7 @@ static compl_T *find_comp_when_fuzzy(void)
|
||||
comp = compl_first_match;
|
||||
do {
|
||||
if (comp->cp_score == score
|
||||
&& (str == comp->cp_str || str == comp->cp_text[CPT_ABBR])) {
|
||||
&& (str == comp->cp_str.data || str == comp->cp_text[CPT_ABBR])) {
|
||||
return comp;
|
||||
}
|
||||
comp = comp->cp_next;
|
||||
@ -3818,9 +3831,9 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a
|
||||
found_end = false;
|
||||
}
|
||||
if (!match_at_original_text(compl_shown_match)
|
||||
&& compl_leader != NULL
|
||||
&& compl_leader.data != NULL
|
||||
&& !ins_compl_equal(compl_shown_match,
|
||||
compl_leader, strlen(compl_leader))
|
||||
compl_leader.data, compl_leader.size)
|
||||
&& !(compl_fuzzy_match && compl_shown_match->cp_score > 0)) {
|
||||
todo++;
|
||||
} else {
|
||||
@ -3876,7 +3889,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (compl_leader != NULL
|
||||
if (compl_leader.data != NULL
|
||||
&& !match_at_original_text(compl_shown_match)
|
||||
&& !compl_fuzzy_match) {
|
||||
// Update "compl_shown_match" to the actually shown match
|
||||
@ -3914,17 +3927,17 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
|
||||
|
||||
// Insert the text of the new completion, or the compl_leader.
|
||||
if (compl_no_insert && !started) {
|
||||
ins_compl_insert_bytes(compl_orig_text + get_compl_len(), -1);
|
||||
ins_compl_insert_bytes(compl_orig_text.data + get_compl_len(), -1);
|
||||
compl_used_match = false;
|
||||
restore_orig_extmarks();
|
||||
} else if (insert_match) {
|
||||
if (!compl_get_longest || compl_used_match) {
|
||||
ins_compl_insert(in_compl_func);
|
||||
} else {
|
||||
assert(compl_leader != NULL);
|
||||
ins_compl_insert_bytes(compl_leader + get_compl_len(), -1);
|
||||
assert(compl_leader.data != NULL);
|
||||
ins_compl_insert_bytes(compl_leader.data + get_compl_len(), -1);
|
||||
}
|
||||
if (!strcmp(compl_curr_match->cp_str, compl_orig_text)) {
|
||||
if (strequal(compl_curr_match->cp_str.data, compl_orig_text.data)) {
|
||||
restore_orig_extmarks();
|
||||
}
|
||||
} else {
|
||||
@ -4088,8 +4101,7 @@ static bool ins_compl_use_match(int c)
|
||||
|
||||
/// Get the pattern, column and length for normal completion (CTRL-N CTRL-P
|
||||
/// completion)
|
||||
/// Sets the global variables: compl_col, compl_length, compl_pattern and
|
||||
/// compl_patternlen.
|
||||
/// Sets the global variables: compl_col, compl_length and compl_pattern.
|
||||
/// Uses the global variables: compl_cont_status and ctrl_x_mode
|
||||
static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
|
||||
{
|
||||
@ -4100,29 +4112,32 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
|
||||
compl_length = curs_col - startcol;
|
||||
}
|
||||
if (p_ic) {
|
||||
compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0);
|
||||
compl_pattern = cstr_as_string(str_foldcase(line + compl_col,
|
||||
compl_length, NULL, 0));
|
||||
} else {
|
||||
compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
|
||||
compl_pattern = cbuf_to_string(line + compl_col, (size_t)compl_length);
|
||||
}
|
||||
} else if (compl_status_adding()) {
|
||||
char *prefix = "\\<";
|
||||
size_t prefixlen = STRLEN_LITERAL("\\<");
|
||||
|
||||
// we need up to 2 extra chars for the prefix
|
||||
compl_pattern = xmalloc(quote_meta(NULL, line + compl_col,
|
||||
compl_length) + prefixlen);
|
||||
if (!vim_iswordp(line + compl_col)
|
||||
|| (compl_col > 0
|
||||
&& (vim_iswordp(mb_prevptr(line, line + compl_col))))) {
|
||||
prefix = "";
|
||||
prefixlen = 0;
|
||||
}
|
||||
STRCPY(compl_pattern, prefix);
|
||||
quote_meta(compl_pattern + prefixlen, line + compl_col, compl_length);
|
||||
|
||||
// we need up to 2 extra chars for the prefix
|
||||
size_t n = quote_meta(NULL, line + compl_col, compl_length) + prefixlen;
|
||||
compl_pattern.data = xmalloc(n);
|
||||
STRCPY(compl_pattern.data, prefix);
|
||||
quote_meta(compl_pattern.data + prefixlen, line + compl_col, compl_length);
|
||||
compl_pattern.size = n - 1;
|
||||
} else if (--startcol < 0
|
||||
|| !vim_iswordp(mb_prevptr(line, line + startcol + 1))) {
|
||||
// Match any word of at least two chars
|
||||
compl_pattern = xstrnsave(S_LEN("\\<\\k\\k"));
|
||||
compl_pattern = cbuf_to_string(S_LEN("\\<\\k\\k"));
|
||||
compl_col += curs_col;
|
||||
compl_length = 0;
|
||||
} else {
|
||||
@ -4143,19 +4158,20 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
|
||||
// Only match word with at least two chars -- webb
|
||||
// there's no need to call quote_meta,
|
||||
// xmalloc(7) is enough -- Acevedo
|
||||
compl_pattern = xmalloc(7);
|
||||
STRCPY(compl_pattern, "\\<");
|
||||
quote_meta(compl_pattern + 2, line + compl_col, 1);
|
||||
strcat(compl_pattern, "\\k");
|
||||
compl_pattern.data = xmalloc(7);
|
||||
STRCPY(compl_pattern.data, "\\<");
|
||||
quote_meta(compl_pattern.data + 2, line + compl_col, 1);
|
||||
strcat(compl_pattern.data, "\\k");
|
||||
compl_pattern.size = strlen(compl_pattern.data);
|
||||
} else {
|
||||
compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, compl_length) + 2);
|
||||
STRCPY(compl_pattern, "\\<");
|
||||
quote_meta(compl_pattern + 2, line + compl_col, compl_length);
|
||||
size_t n = quote_meta(NULL, line + compl_col, compl_length) + 2;
|
||||
compl_pattern.data = xmalloc(n);
|
||||
STRCPY(compl_pattern.data, "\\<");
|
||||
quote_meta(compl_pattern.data + 2, line + compl_col, compl_length);
|
||||
compl_pattern.size = n - 1;
|
||||
}
|
||||
}
|
||||
|
||||
compl_patternlen = strlen(compl_pattern);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -4170,13 +4186,12 @@ static int get_wholeline_compl_info(char *line, colnr_T curs_col)
|
||||
compl_length = 0;
|
||||
}
|
||||
if (p_ic) {
|
||||
compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0);
|
||||
compl_pattern = cstr_as_string(str_foldcase(line + compl_col,
|
||||
compl_length, NULL, 0));
|
||||
} else {
|
||||
compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
|
||||
compl_pattern = cbuf_to_string(line + compl_col, (size_t)compl_length);
|
||||
}
|
||||
|
||||
compl_patternlen = strlen(compl_pattern);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -4201,8 +4216,8 @@ static int get_filename_compl_info(char *line, int startcol, colnr_T curs_col)
|
||||
|
||||
compl_col += startcol;
|
||||
compl_length = (int)curs_col - startcol;
|
||||
compl_pattern = addstar(line + compl_col, (size_t)compl_length, EXPAND_FILES);
|
||||
compl_patternlen = strlen(compl_pattern);
|
||||
compl_pattern = cstr_as_string(addstar(line + compl_col,
|
||||
(size_t)compl_length, EXPAND_FILES));
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -4211,9 +4226,9 @@ static int get_filename_compl_info(char *line, int startcol, colnr_T curs_col)
|
||||
/// Sets the global variables: compl_col, compl_length and compl_pattern.
|
||||
static int get_cmdline_compl_info(char *line, colnr_T curs_col)
|
||||
{
|
||||
compl_pattern = xstrnsave(line, (size_t)curs_col);
|
||||
compl_patternlen = (size_t)curs_col;
|
||||
set_cmd_context(&compl_xp, compl_pattern, (int)compl_patternlen, curs_col, false);
|
||||
compl_pattern = cbuf_to_string(line, (size_t)curs_col);
|
||||
set_cmd_context(&compl_xp, compl_pattern.data,
|
||||
(int)compl_pattern.size, curs_col, false);
|
||||
if (compl_xp.xp_context == EXPAND_LUA) {
|
||||
nlua_expand_pat(&compl_xp);
|
||||
}
|
||||
@ -4223,7 +4238,7 @@ static int get_cmdline_compl_info(char *line, colnr_T curs_col)
|
||||
// "pattern not found" message.
|
||||
compl_col = curs_col;
|
||||
} else {
|
||||
compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
|
||||
compl_col = (int)(compl_xp.xp_pattern - compl_pattern.data);
|
||||
}
|
||||
compl_length = curs_col - compl_col;
|
||||
|
||||
@ -4301,8 +4316,7 @@ static int get_userdefined_compl_info(colnr_T curs_col)
|
||||
// it may have become invalid.
|
||||
char *line = ml_get(curwin->w_cursor.lnum);
|
||||
compl_length = curs_col - compl_col;
|
||||
compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
|
||||
compl_patternlen = (size_t)compl_length;
|
||||
compl_pattern = cbuf_to_string(line + compl_col, (size_t)compl_length);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -4327,8 +4341,7 @@ static int get_spell_compl_info(int startcol, colnr_T curs_col)
|
||||
}
|
||||
// Need to obtain "line" again, it may have become invalid.
|
||||
char *line = ml_get(curwin->w_cursor.lnum);
|
||||
compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
|
||||
compl_patternlen = (size_t)compl_length;
|
||||
compl_pattern = cbuf_to_string(line + compl_col, (size_t)compl_length);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -4513,19 +4526,19 @@ static int ins_compl_start(void)
|
||||
ins_compl_fixRedoBufForLeader(NULL);
|
||||
|
||||
// Always add completion for the original text.
|
||||
xfree(compl_orig_text);
|
||||
API_CLEAR_STRING(compl_orig_text);
|
||||
kv_destroy(compl_orig_extmarks);
|
||||
compl_orig_text = xstrnsave(line + compl_col, (size_t)compl_length);
|
||||
compl_orig_text = cbuf_to_string(line + compl_col, (size_t)compl_length);
|
||||
save_orig_extmarks();
|
||||
int flags = CP_ORIGINAL_TEXT;
|
||||
if (p_ic) {
|
||||
flags |= CP_ICASE;
|
||||
}
|
||||
if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0,
|
||||
if (ins_compl_add(compl_orig_text.data, (int)compl_orig_text.size,
|
||||
NULL, NULL, false, NULL, 0,
|
||||
flags, false, NULL) != OK) {
|
||||
XFREE_CLEAR(compl_pattern);
|
||||
compl_patternlen = 0;
|
||||
XFREE_CLEAR(compl_orig_text);
|
||||
API_CLEAR_STRING(compl_pattern);
|
||||
API_CLEAR_STRING(compl_orig_text);
|
||||
kv_destroy(compl_orig_extmarks);
|
||||
return FAIL;
|
||||
}
|
||||
@ -4758,7 +4771,7 @@ static unsigned quote_meta(char *dest, char *src, int len)
|
||||
#if defined(EXITFREE)
|
||||
void free_insexpand_stuff(void)
|
||||
{
|
||||
XFREE_CLEAR(compl_orig_text);
|
||||
API_CLEAR_STRING(compl_orig_text);
|
||||
kv_destroy(compl_orig_extmarks);
|
||||
callback_free(&cfu_cb);
|
||||
callback_free(&ofu_cb);
|
||||
|
101
todo.patch
Normal file
101
todo.patch
Normal file
@ -0,0 +1,101 @@
|
||||
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
|
||||
index fb67c489b2..94278946df 100644
|
||||
--- a/src/nvim/insexpand.c
|
||||
+++ b/src/nvim/insexpand.c
|
||||
@@ -3476,17 +3498,15 @@ static void get_next_filename_completion(void)
|
||||
char_u *ptr;
|
||||
garray_T fuzzy_indices;
|
||||
int i;
|
||||
int score;
|
||||
char_u *leader = ins_compl_leader();
|
||||
- size_t leader_len = STRLEN(leader);
|
||||
+ size_t leader_len = ins_compl_leader_len();
|
||||
int in_fuzzy = ((get_cot_flags() & COT_FUZZY) != 0 && leader_len > 0);
|
||||
char_u **sorted_matches;
|
||||
int *fuzzy_indices_data;
|
||||
char_u *last_sep = NULL;
|
||||
- size_t path_with_wildcard_len;
|
||||
- char_u *path_with_wildcard;
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
char pathsep = (curbuf->b_p_csl[0] == 's')
|
||||
? '/' : (curbuf->b_p_csl[0] == 'b') ? '\\' : PATHSEP;
|
||||
#else
|
||||
@@ -3494,58 +3514,62 @@ static void get_next_filename_completion(void)
|
||||
#endif
|
||||
|
||||
if (in_fuzzy) {
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (curbuf->b_p_csl[0] == 's') {
|
||||
- for (i = 0; i < leader_len; i++) {
|
||||
+ for (i = 0; i < (int)leader_len; i++) {
|
||||
if (leader[i] == '\\') {
|
||||
leader[i] = '/';
|
||||
}
|
||||
}
|
||||
} else if (curbuf->b_p_csl[0] == 'b') {
|
||||
- for (i = 0; i < leader_len; i++) {
|
||||
+ for (i = 0; i < (int)leader_len; i++) {
|
||||
if (leader[i] == '/') {
|
||||
leader[i] = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
last_sep = vim_strrchr(leader, pathsep);
|
||||
if (last_sep == NULL) {
|
||||
// No path separator or separator is the last character,
|
||||
// fuzzy match the whole leader
|
||||
- vim_free(compl_pattern);
|
||||
- compl_pattern = vim_strsave((char_u *)"*");
|
||||
- compl_patternlen = STRLEN(compl_pattern);
|
||||
+ VIM_CLEAR_STRING(compl_pattern);
|
||||
+ compl_pattern.string = vim_strnsave((char_u *)"*", 1);
|
||||
+ if (compl_pattern.string == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+ compl_pattern.length = 1;
|
||||
} else if (*(last_sep + 1) == '\0') {
|
||||
in_fuzzy = FALSE;
|
||||
} else {
|
||||
// Split leader into path and file parts
|
||||
int path_len = last_sep - leader + 1;
|
||||
- path_with_wildcard_len = path_len + 2;
|
||||
- path_with_wildcard = alloc(path_with_wildcard_len);
|
||||
+ char_u *path_with_wildcard;
|
||||
+
|
||||
+ path_with_wildcard = alloc(path_len + 2);
|
||||
if (path_with_wildcard != NULL) {
|
||||
- vim_strncpy(path_with_wildcard, leader, path_len);
|
||||
- vim_strcat(path_with_wildcard, (char_u *)"*", path_with_wildcard_len);
|
||||
- vim_free(compl_pattern);
|
||||
- compl_pattern = path_with_wildcard;
|
||||
- compl_patternlen = STRLEN(compl_pattern);
|
||||
+ vim_snprintf((char *)path_with_wildcard, path_len + 2, "%*.*s*", path_len, path_len,
|
||||
+ leader);
|
||||
+ VIM_CLEAR_STRING(compl_pattern);
|
||||
+ compl_pattern.string = path_with_wildcard;
|
||||
+ compl_pattern.length = path_len + 1;
|
||||
|
||||
// Move leader to the file part
|
||||
leader = last_sep + 1;
|
||||
- leader_len = STRLEN(leader);
|
||||
+ leader_len -= path_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
|
||||
+ if (expand_wildcards(1, &compl_pattern.string, &num_matches, &matches,
|
||||
EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) != OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
// May change home directory back to "~".
|
||||
- tilde_replace(compl_pattern, num_matches, matches);
|
||||
+ tilde_replace(compl_pattern.string, num_matches, matches);
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
if (curbuf->b_p_csl[0] != NUL) {
|
||||
for (i = 0; i < num_matches; ++i) {
|
||||
ptr = matches[i];
|
||||
while (*ptr != NUL) {
|
Loading…
Reference in New Issue
Block a user