vim-patch:partial:8.2.4001: insert complete code uses global variables

Problem:    Insert complete code uses global variables.
Solution:   Make variables local to the file and use accessor functions.
            (Yegappan Lakshmanan, closes vim/vim#9470)
d94fbfc74a

Skip changes in comments for callback-related functions (not ported).
Also make compl_busy static again.
This commit is contained in:
zeertzjq
2022-08-25 09:22:44 +08:00
parent 45d09b46ce
commit b1833bb33b
6 changed files with 160 additions and 106 deletions

View File

@@ -92,6 +92,10 @@ typedef struct insert_state {
#define BACKSPACE_WORD_NOT_SPACE 3 #define BACKSPACE_WORD_NOT_SPACE 3
#define BACKSPACE_LINE 4 #define BACKSPACE_LINE 4
/// Set when doing something for completion that may call edit() recursively,
/// which is not allowed.
static bool compl_busy = false;
static colnr_T Insstart_textlen; // length of line when insert started static colnr_T Insstart_textlen; // length of line when insert started
static colnr_T Insstart_blank_vcol; // vcol for first inserted blank static colnr_T Insstart_blank_vcol; // vcol for first inserted blank
static bool update_Insstart_orig = true; // set Insstart_orig to Insstart static bool update_Insstart_orig = true; // set Insstart_orig to Insstart
@@ -1091,7 +1095,7 @@ check_pum:
// but it is under other ^X modes // but it is under other ^X modes
if (*curbuf->b_p_cpt == NUL if (*curbuf->b_p_cpt == NUL
&& (ctrl_x_mode_normal() || ctrl_x_mode_whole_line()) && (ctrl_x_mode_normal() || ctrl_x_mode_whole_line())
&& !(compl_cont_status & CONT_LOCAL)) { && !compl_status_local()) {
goto normalchar; goto normalchar;
} }
@@ -1177,9 +1181,11 @@ normalchar:
static void insert_do_complete(InsertState *s) static void insert_do_complete(InsertState *s)
{ {
compl_busy = true; compl_busy = true;
disable_fold_update++; // don't redraw folds here
if (ins_complete(s->c, true) == FAIL) { if (ins_complete(s->c, true) == FAIL) {
compl_cont_status = 0; compl_status_clear();
} }
disable_fold_update--;
compl_busy = false; compl_busy = false;
can_si = may_do_si(); // allow smartindenting can_si = may_do_si(); // allow smartindenting
} }

View File

@@ -757,7 +757,7 @@ void clearFolding(win_T *win)
/// The changes in lines from top to bot (inclusive). /// The changes in lines from top to bot (inclusive).
void foldUpdate(win_T *wp, linenr_T top, linenr_T bot) void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
{ {
if (disable_fold_update || compl_busy || State & MODE_INSERT) { if (disable_fold_update || State & MODE_INSERT) {
return; return;
} }

View File

@@ -1881,7 +1881,7 @@ static bool at_ins_compl_key(void)
c = p[3] & 0x1f; c = p[3] & 0x1f;
} }
return (ctrl_x_mode_not_default() && vim_is_ctrl_x_key(c)) return (ctrl_x_mode_not_default() && vim_is_ctrl_x_key(c))
|| ((compl_cont_status & CONT_LOCAL) && (c == Ctrl_N || c == Ctrl_P)); || (compl_status_local() && (c == Ctrl_N || c == Ctrl_P));
} }
/// Check if typebuf.tb_buf[] contains a modifier plus key that can be changed /// Check if typebuf.tb_buf[] contains a modifier plus key that can be changed

View File

@@ -159,27 +159,6 @@ EXTERN colnr_T dollar_vcol INIT(= -1);
// Variables for Insert mode completion. // Variables for Insert mode completion.
// Length in bytes of the text being completed (this is deleted to be replaced
// by the match.)
EXTERN int compl_length INIT(= 0);
// Set when doing something for completion that may call edit() recursively,
// which is not allowed. Also used to disable folding during completion
EXTERN bool compl_busy INIT(= false);
// List of flags for method of completion.
EXTERN int compl_cont_status INIT(= 0);
#define CONT_ADDING 1 // "normal" or "adding" expansion
#define CONT_INTRPT (2 + 4) // a ^X interrupted the current expansion
// it's set only iff N_ADDS is set
#define CONT_N_ADDS 4 // next ^X<> will add-new or expand-current
#define CONT_S_IPOS 8 // next ^X<> will set initial_pos?
// if so, word-wise-expansion will set SOL
#define CONT_SOL 16 // pattern includes start of line, just for
// word-wise expansion, not set for ^X^L
#define CONT_LOCAL 32 // for ctrl_x_mode 0, ^X^P/^X^N do a local
// expansion, (eg use complete=.)
EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode
EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode
EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode

View File

@@ -219,12 +219,15 @@ static bool compl_started = false;
///< Which Ctrl-X mode are we in? ///< Which Ctrl-X mode are we in?
static int ctrl_x_mode = CTRL_X_NORMAL; static int ctrl_x_mode = CTRL_X_NORMAL;
static int compl_matches = 0; static int compl_matches = 0; ///< number of completion matches
static char *compl_pattern = NULL; static char *compl_pattern = NULL;
static Direction compl_direction = FORWARD; static Direction compl_direction = FORWARD;
static Direction compl_shows_dir = FORWARD; static Direction compl_shows_dir = FORWARD;
static int compl_pending = 0; ///< > 1 for postponed CTRL-N static int compl_pending = 0; ///< > 1 for postponed CTRL-N
static pos_T compl_startpos; static pos_T compl_startpos;
/// Length in bytes of the text being completed (this is deleted to be replaced
/// by the match.)
static int compl_length = 0;
static colnr_T compl_col = 0; ///< column where the text starts static colnr_T compl_col = 0; ///< column where the text starts
///< that is being completed ///< that is being completed
static char_u *compl_orig_text = NULL; ///< text as it was before static char_u *compl_orig_text = NULL; ///< text as it was before
@@ -232,6 +235,20 @@ static char_u *compl_orig_text = NULL; ///< text as it was before
static int compl_cont_mode = 0; static int compl_cont_mode = 0;
static expand_T compl_xp; static expand_T compl_xp;
// List of flags for method of completion.
static int compl_cont_status = 0;
#define CONT_ADDING 1 ///< "normal" or "adding" expansion
#define CONT_INTRPT (2 + 4) ///< a ^X interrupted the current expansion
///< it's set only iff N_ADDS is set
#define CONT_N_ADDS 4 ///< next ^X<> will add-new or expand-current
#define CONT_S_IPOS 8 ///< next ^X<> will set initial_pos?
///< if so, word-wise-expansion will set SOL
#define CONT_SOL 16 ///< pattern includes start of line, just for
///< word-wise expansion, not set for ^X^L
#define CONT_LOCAL 32 ///< for ctrl_x_mode 0, ^X^P/^X^N do a local
///< expansion, (eg use complete=.)
static bool compl_opt_refresh_always = false; static bool compl_opt_refresh_always = false;
static size_t spell_bad_len = 0; // length of located bad word static size_t spell_bad_len = 0; // length of located bad word
@@ -375,9 +392,52 @@ bool ctrl_x_mode_not_defined_yet(void)
return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET; return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
} }
/// Check that the "dict" or "tsr" option can be used. /// @return true if currently in "normal" or "adding" insert completion matches state
bool compl_status_adding(void)
{
return compl_cont_status & CONT_ADDING;
}
/// @return true if the completion pattern includes start of line, just for
/// word-wise expansion.
bool compl_status_sol(void)
{
return compl_cont_status & CONT_SOL;
}
/// @return true if ^X^P/^X^N will do a local completion (i.e. use complete=.)
bool compl_status_local(void)
{
return compl_cont_status & CONT_LOCAL;
}
/// Clear the completion status flags
void compl_status_clear(void)
{
compl_cont_status = 0;
}
// @return true if completion is using the forward direction matches
static bool compl_dir_forward(void)
{
return compl_direction == FORWARD;
}
/// @return true if currently showing forward completion matches
static bool compl_shows_dir_forward(void)
{
return compl_shows_dir == FORWARD;
}
/// @return true if currently showing backward completion matches
static bool compl_shows_dir_backward(void)
{
return compl_shows_dir == BACKWARD;
}
/// Check that the 'dictionary' or 'thesaurus' option can be used.
/// ///
/// @param dict_opt check "dict" when true, "tsr" when false. /// @param dict_opt check 'dictionary' when true, 'thesaurus' when false.
bool check_compl_option(bool dict_opt) bool check_compl_option(bool dict_opt)
{ {
if (dict_opt if (dict_opt
@@ -467,6 +527,12 @@ static bool match_at_original_text(const compl_T *const match)
return match->cp_flags & CP_ORIGINAL_TEXT; return match->cp_flags & CP_ORIGINAL_TEXT;
} }
/// @return true if "match" is the first match in the completion list.
static bool is_first_match(const compl_T *const match)
{
return match == compl_first_match;
}
/// Check that character "c" is part of the item currently being /// Check that character "c" is part of the item currently being
/// completed. Used to decide whether to abandon complete mode when the menu /// completed. Used to decide whether to abandon complete mode when the menu
/// is visible. /// is visible.
@@ -721,7 +787,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname,
return NOTDONE; return NOTDONE;
} }
match = match->cp_next; match = match->cp_next;
} while (match != NULL && match != compl_first_match); } while (match != NULL && !is_first_match(match));
} }
// Remove any popup menu before changing the list of matches. // Remove any popup menu before changing the list of matches.
@@ -911,7 +977,7 @@ static int ins_compl_make_cyclic(void)
compl_T *match = compl_first_match; compl_T *match = compl_first_match;
int count = 0; int count = 0;
// there's always an entry for the compl_orig_text, it doesn't count. // there's always an entry for the compl_orig_text, it doesn't count.
while (match->cp_next != NULL && match->cp_next != compl_first_match) { while (match->cp_next != NULL && !is_first_match(match->cp_next)) {
match = match->cp_next; match = match->cp_next;
count++; count++;
} }
@@ -986,7 +1052,7 @@ static bool pum_enough_matches(void)
break; break;
} }
compl = compl->cp_next; compl = compl->cp_next;
} while (compl != compl_first_match); } while (!is_first_match(compl));
if (strstr((char *)p_cot, "menuone") != NULL) { if (strstr((char *)p_cot, "menuone") != NULL) {
return i >= 1; return i >= 1;
@@ -1086,7 +1152,7 @@ void ins_compl_show_pum(void)
compl_match_arraysize++; compl_match_arraysize++;
} }
compl = compl->cp_next; compl = compl->cp_next;
} while (compl != NULL && compl != compl_first_match); } while (compl != NULL && !is_first_match(compl));
if (compl_match_arraysize == 0) { if (compl_match_arraysize == 0) {
return; return;
} }
@@ -1153,7 +1219,7 @@ void ins_compl_show_pum(void)
} }
} }
compl = compl->cp_next; compl = compl->cp_next;
} while (compl != NULL && compl != compl_first_match); } while (compl != NULL && !is_first_match(compl));
if (!shown_match_ok) { // no displayed match at all if (!shown_match_ok) { // no displayed match at all
cur = -1; cur = -1;
@@ -1471,12 +1537,13 @@ static void ins_compl_free(void)
} }
tv_clear(&match->cp_user_data); tv_clear(&match->cp_user_data);
xfree(match); xfree(match);
} while (compl_curr_match != NULL && compl_curr_match != compl_first_match); } while (compl_curr_match != NULL && !is_first_match(compl_curr_match));
compl_first_match = compl_curr_match = NULL; compl_first_match = compl_curr_match = NULL;
compl_shown_match = NULL; compl_shown_match = NULL;
compl_old_match = NULL; compl_old_match = NULL;
} }
/// Reset/clear the completion state.
void ins_compl_clear(void) void ins_compl_clear(void)
{ {
compl_cont_status = 0; compl_cont_status = 0;
@@ -1530,6 +1597,12 @@ colnr_T ins_compl_col(void)
return compl_col; return compl_col;
} }
/// Return the length in bytes of the text being completed
int ins_compl_len(void)
{
return compl_length;
}
/// Delete one character before the cursor and show the subset of the matches /// Delete one character before the cursor and show the subset of the matches
/// that match the word that is now before the cursor. /// that match the word that is now before the cursor.
/// Returns the character to be used, NUL if the work is done and another char /// Returns the character to be used, NUL if the work is done and another char
@@ -1714,7 +1787,7 @@ void ins_compl_addfrommatch(void)
p = NULL; p = NULL;
for (cp = compl_shown_match->cp_next; cp != NULL for (cp = compl_shown_match->cp_next; cp != NULL
&& cp != compl_first_match; cp = cp->cp_next) { && !is_first_match(cp); cp = cp->cp_next) {
if (compl_leader == NULL if (compl_leader == NULL
|| ins_compl_equal(cp, compl_leader, STRLEN(compl_leader))) { || ins_compl_equal(cp, compl_leader, STRLEN(compl_leader))) {
p = cp->cp_str; p = cp->cp_str;
@@ -1730,7 +1803,7 @@ void ins_compl_addfrommatch(void)
ins_compl_addleader(c); ins_compl_addleader(c);
} }
/// Set the CTRL-X completion mode based on the key 'c' typed after a CTRL-X. /// Set the CTRL-X completion mode based on the key "c" typed after a CTRL-X.
/// Uses the global variables: ctrl_x_mode, edit_submode, edit_submode_pre, /// Uses the global variables: ctrl_x_mode, edit_submode, edit_submode_pre,
/// compl_cont_mode and compl_cont_status. /// compl_cont_mode and compl_cont_status.
/// ///
@@ -2135,7 +2208,7 @@ static buf_T *ins_compl_next_buf(buf_T *buf, int flag)
return buf; return buf;
} }
/// Get the user-defined completion function name for completion 'type' /// Get the user-defined completion function name for completion "type"
static char_u *get_complete_funcname(int type) static char_u *get_complete_funcname(int type)
{ {
switch (type) { switch (type) {
@@ -2442,13 +2515,12 @@ static void ins_compl_update_sequence_numbers(void)
int number = 0; int number = 0;
compl_T *match; compl_T *match;
if (compl_direction == FORWARD) { if (compl_dir_forward()) {
// search backwards for the first valid (!= -1) number. // search backwards for the first valid (!= -1) number.
// This should normally succeed already at the first loop // This should normally succeed already at the first loop
// cycle, so it's fast! // cycle, so it's fast!
for (match = compl_curr_match->cp_prev; for (match = compl_curr_match->cp_prev;
match != NULL && match != compl_first_match; match != NULL && !is_first_match(match); match = match->cp_prev) {
match = match->cp_prev) {
if (match->cp_number != -1) { if (match->cp_number != -1) {
number = match->cp_number; number = match->cp_number;
break; break;
@@ -2468,8 +2540,7 @@ static void ins_compl_update_sequence_numbers(void)
// number. This should normally succeed already at the // number. This should normally succeed already at the
// first loop cycle, so it's fast! // first loop cycle, so it's fast!
for (match = compl_curr_match->cp_next; for (match = compl_curr_match->cp_next;
match != NULL && match != compl_first_match; match != NULL && !is_first_match(match); match = match->cp_next) {
match = match->cp_next) {
if (match->cp_number != -1) { if (match->cp_number != -1) {
number = match->cp_number; number = match->cp_number;
break; break;
@@ -2554,7 +2625,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
} }
} }
match = match->cp_next; match = match->cp_next;
} while (match != NULL && match != compl_first_match); } while (match != NULL && !is_first_match(match));
} }
} }
@@ -2838,7 +2909,7 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p
char_u *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, false) + cur_match_pos->col; char_u *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, false) + cur_match_pos->col;
int len; int len;
if (ctrl_x_mode_line_or_eval()) { if (ctrl_x_mode_line_or_eval()) {
if (compl_cont_status & CONT_ADDING) { if (compl_status_adding()) {
if (cur_match_pos->lnum >= ins_buf->b_ml.ml_line_count) { if (cur_match_pos->lnum >= ins_buf->b_ml.ml_line_count) {
return NULL; return NULL;
} }
@@ -2851,7 +2922,7 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p
} else { } else {
char_u *tmp_ptr = ptr; char_u *tmp_ptr = ptr;
if (compl_cont_status & CONT_ADDING && compl_length <= (int)STRLEN(tmp_ptr)) { if (compl_status_adding() && compl_length <= (int)STRLEN(tmp_ptr)) {
tmp_ptr += compl_length; tmp_ptr += compl_length;
// Skip if already inside a word. // Skip if already inside a word.
if (vim_iswordp(tmp_ptr)) { if (vim_iswordp(tmp_ptr)) {
@@ -2864,7 +2935,7 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p
tmp_ptr = find_word_end(tmp_ptr); tmp_ptr = find_word_end(tmp_ptr);
len = (int)(tmp_ptr - ptr); len = (int)(tmp_ptr - ptr);
if ((compl_cont_status & CONT_ADDING) && len == compl_length) { if (compl_status_adding() && len == compl_length) {
if (cur_match_pos->lnum < ins_buf->b_ml.ml_line_count) { if (cur_match_pos->lnum < ins_buf->b_ml.ml_line_count) {
// Try next line, if any. the new word will be "join" as if the // Try next line, if any. the new word will be "join" as if the
// normal command "J" was used. IOSIZE is always greater than // normal command "J" was used. IOSIZE is always greater than
@@ -2945,8 +3016,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
msg_silent++; // Don't want messages for wrapscan. msg_silent++; // Don't want messages for wrapscan.
// ctrl_x_mode_line_or_eval() || word-wise search that // ctrl_x_mode_line_or_eval() || word-wise search that
// has added a word that was at the beginning of the line. // has added a word that was at the beginning of the line.
if (ctrl_x_mode_line_or_eval() if (ctrl_x_mode_line_or_eval() || (compl_cont_status & CONT_SOL)) {
|| (compl_cont_status & CONT_SOL)) {
found_new_match = search_for_exact_line(st->ins_buf, st->cur_match_pos, found_new_match = search_for_exact_line(st->ins_buf, st->cur_match_pos,
compl_direction, (char_u *)compl_pattern); compl_direction, (char_u *)compl_pattern);
} else { } else {
@@ -2964,7 +3034,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
} else if (st->first_match_pos.lnum == st->last_match_pos.lnum } else if (st->first_match_pos.lnum == st->last_match_pos.lnum
&& st->first_match_pos.col == st->last_match_pos.col) { && st->first_match_pos.col == st->last_match_pos.col) {
found_new_match = FAIL; found_new_match = FAIL;
} else if ((compl_direction == FORWARD) } else if (compl_dir_forward()
&& (st->prev_match_pos.lnum > st->cur_match_pos->lnum && (st->prev_match_pos.lnum > st->cur_match_pos->lnum
|| (st->prev_match_pos.lnum == st->cur_match_pos->lnum || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
&& st->prev_match_pos.col >= st->cur_match_pos->col))) { && st->prev_match_pos.col >= st->cur_match_pos->col))) {
@@ -2973,7 +3043,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
} else { } else {
looped_around = true; looped_around = true;
} }
} else if ((compl_direction != FORWARD) } else if (!compl_dir_forward()
&& (st->prev_match_pos.lnum < st->cur_match_pos->lnum && (st->prev_match_pos.lnum < st->cur_match_pos->lnum
|| (st->prev_match_pos.lnum == st->cur_match_pos->lnum || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
&& st->prev_match_pos.col <= st->cur_match_pos->col))) { && st->prev_match_pos.col <= st->cur_match_pos->col))) {
@@ -2989,7 +3059,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
} }
// when ADDING, the text before the cursor matches, skip it // when ADDING, the text before the cursor matches, skip it
if ((compl_cont_status & CONT_ADDING) && st->ins_buf == curbuf if (compl_status_adding() && st->ins_buf == curbuf
&& start_pos->lnum == st->cur_match_pos->lnum && start_pos->lnum == st->cur_match_pos->lnum
&& start_pos->col == st->cur_match_pos->col) { && start_pos->col == st->cur_match_pos->col) {
continue; continue;
@@ -3013,7 +3083,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
return found_new_match; return found_new_match;
} }
/// get the next set of completion matches for 'type'. /// get the next set of completion matches for "type".
/// @return true if a new match is found, otherwise false. /// @return true if a new match is found, otherwise false.
static bool get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini) static bool get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini)
{ {
@@ -3101,8 +3171,7 @@ static int ins_compl_get_exp(pos_T *ini)
assert(st.ins_buf != NULL); assert(st.ins_buf != NULL);
compl_old_match = compl_curr_match; // remember the last current match compl_old_match = compl_curr_match; // remember the last current match
st.cur_match_pos = (compl_direction == FORWARD st.cur_match_pos = (compl_dir_forward() ? &st.last_match_pos : &st.first_match_pos);
? &st.last_match_pos : &st.first_match_pos);
// For ^N/^P loop over all the flags/windows/buffers in 'complete' // For ^N/^P loop over all the flags/windows/buffers in 'complete'
for (;;) { for (;;) {
@@ -3134,8 +3203,7 @@ static int ins_compl_get_exp(pos_T *ini)
// break the loop for specialized modes (use 'complete' just for the // break the loop for specialized modes (use 'complete' just for the
// generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new match // generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new match
if ((ctrl_x_mode_not_default() if ((ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())
&& !ctrl_x_mode_line_or_eval())
|| found_new_match != FAIL) { || found_new_match != FAIL) {
if (got_int) { if (got_int) {
break; break;
@@ -3145,8 +3213,7 @@ static int ins_compl_get_exp(pos_T *ini)
ins_compl_check_keys(0, false); ins_compl_check_keys(0, false);
} }
if ((ctrl_x_mode_not_default() if ((ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())
&& !ctrl_x_mode_line_or_eval())
|| compl_interrupted) { || compl_interrupted) {
break; break;
} }
@@ -3163,16 +3230,14 @@ static int ins_compl_get_exp(pos_T *ini)
} }
compl_started = true; compl_started = true;
if ((ctrl_x_mode_normal() if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
|| ctrl_x_mode_line_or_eval())
&& *st.e_cpt == NUL) { // Got to end of 'complete' && *st.e_cpt == NUL) { // Got to end of 'complete'
found_new_match = FAIL; found_new_match = FAIL;
} }
i = -1; // total of matches, unknown i = -1; // total of matches, unknown
if (found_new_match == FAIL if (found_new_match == FAIL
|| (ctrl_x_mode_not_default() || (ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())) {
&& !ctrl_x_mode_line_or_eval())) {
i = ins_compl_make_cyclic(); i = ins_compl_make_cyclic();
} }
@@ -3180,7 +3245,7 @@ static int ins_compl_get_exp(pos_T *ini)
// If several matches were added (FORWARD) or the search failed and has // If several matches were added (FORWARD) or the search failed and has
// just been made cyclic then we have to move compl_curr_match to the // just been made cyclic then we have to move compl_curr_match to the
// next or previous entry (if any) -- Acevedo // next or previous entry (if any) -- Acevedo
compl_curr_match = compl_direction == FORWARD compl_curr_match = compl_dir_forward()
? compl_old_match->cp_next ? compl_old_match->cp_next
: compl_old_match->cp_prev; : compl_old_match->cp_prev;
if (compl_curr_match == NULL) { if (compl_curr_match == NULL) {
@@ -3199,19 +3264,19 @@ static void ins_compl_update_shown_match(void)
while (!ins_compl_equal(compl_shown_match, while (!ins_compl_equal(compl_shown_match,
compl_leader, STRLEN(compl_leader)) compl_leader, STRLEN(compl_leader))
&& compl_shown_match->cp_next != NULL && compl_shown_match->cp_next != NULL
&& compl_shown_match->cp_next != compl_first_match) { && !is_first_match(compl_shown_match->cp_next)) {
compl_shown_match = compl_shown_match->cp_next; compl_shown_match = compl_shown_match->cp_next;
} }
// If we didn't find it searching forward, and compl_shows_dir is // If we didn't find it searching forward, and compl_shows_dir is
// backward, find the last match. // backward, find the last match.
if (compl_shows_dir == BACKWARD if (compl_shows_dir_backward()
&& !ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader)) && !ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader))
&& (compl_shown_match->cp_next == NULL && (compl_shown_match->cp_next == NULL
|| compl_shown_match->cp_next == compl_first_match)) { || 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, STRLEN(compl_leader))
&& compl_shown_match->cp_prev != NULL && compl_shown_match->cp_prev != NULL
&& compl_shown_match->cp_prev != compl_first_match) { && !is_first_match(compl_shown_match->cp_prev)) {
compl_shown_match = compl_shown_match->cp_prev; compl_shown_match = compl_shown_match->cp_prev;
} }
} }
@@ -3224,7 +3289,7 @@ void ins_compl_delete(void)
// In insert mode: Delete the typed part. // In insert mode: Delete the typed part.
// In replace mode: Put the old characters back, if any. // In replace mode: Put the old characters back, if any.
col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0); col = compl_col + (compl_status_adding() ? compl_length : 0);
if ((int)curwin->w_cursor.col > col) { if ((int)curwin->w_cursor.col > col) {
if (stop_arrow() == FAIL) { if (stop_arrow() == FAIL) {
return; return;
@@ -3283,7 +3348,7 @@ static void ins_compl_show_filename(void)
redraw_cmdline = false; // don't overwrite! redraw_cmdline = false; // don't overwrite!
} }
/// Find the next set of matches for completion. Repeat the completion 'todo' /// Find the next set of matches for completion. Repeat the completion "todo"
/// times. The number of matches found is returned in 'num_matches'. /// times. The number of matches found is returned in 'num_matches'.
/// ///
/// @param allow_get_expansion If true, then ins_compl_get_exp() may be called to /// @param allow_get_expansion If true, then ins_compl_get_exp() may be called to
@@ -3302,20 +3367,20 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a
compl_T *found_compl = NULL; compl_T *found_compl = NULL;
while (--todo >= 0) { while (--todo >= 0) {
if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL) { if (compl_shows_dir_forward() && compl_shown_match->cp_next != NULL) {
compl_shown_match = compl_shown_match->cp_next; compl_shown_match = compl_shown_match->cp_next;
found_end = (compl_first_match != NULL found_end = (compl_first_match != NULL
&& (compl_shown_match->cp_next == compl_first_match && (is_first_match(compl_shown_match->cp_next)
|| compl_shown_match == compl_first_match)); || is_first_match(compl_shown_match)));
} else if (compl_shows_dir == BACKWARD } else if (compl_shows_dir_backward()
&& compl_shown_match->cp_prev != NULL) { && compl_shown_match->cp_prev != NULL) {
found_end = (compl_shown_match == compl_first_match); found_end = is_first_match(compl_shown_match);
compl_shown_match = compl_shown_match->cp_prev; compl_shown_match = compl_shown_match->cp_prev;
found_end |= (compl_shown_match == compl_first_match); found_end |= is_first_match(compl_shown_match);
} else { } else {
if (!allow_get_expansion) { if (!allow_get_expansion) {
if (advance) { if (advance) {
if (compl_shows_dir == BACKWARD) { if (compl_shows_dir_backward()) {
compl_pending -= todo + 1; compl_pending -= todo + 1;
} else { } else {
compl_pending += todo + 1; compl_pending += todo + 1;
@@ -3325,7 +3390,7 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a
} }
if (!compl_no_select && advance) { if (!compl_no_select && advance) {
if (compl_shows_dir == BACKWARD) { if (compl_shows_dir_backward()) {
compl_pending--; compl_pending--;
} else { } else {
compl_pending++; compl_pending++;
@@ -3405,8 +3470,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
return -1; return -1;
} }
if (compl_leader != NULL if (compl_leader != NULL && !match_at_original_text(compl_shown_match)) {
&& !match_at_original_text(compl_shown_match)) {
// Update "compl_shown_match" to the actually shown match // Update "compl_shown_match" to the actually shown match
ins_compl_update_shown_match(); ins_compl_update_shown_match();
} }
@@ -3623,7 +3687,7 @@ static bool ins_compl_use_match(int c)
static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col) static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
{ {
if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) { if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) {
if (!(compl_cont_status & CONT_ADDING)) { if (!compl_status_adding()) {
while (--startcol >= 0 && vim_isIDc(line[startcol])) {} while (--startcol >= 0 && vim_isIDc(line[startcol])) {}
compl_col += ++startcol; compl_col += ++startcol;
compl_length = curs_col - startcol; compl_length = curs_col - startcol;
@@ -3633,7 +3697,7 @@ static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
} else { } else {
compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length); compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length);
} }
} else if (compl_cont_status & CONT_ADDING) { } else if (compl_status_adding()) {
char_u *prefix = (char_u *)"\\<"; char_u *prefix = (char_u *)"\\<";
// we need up to 2 extra chars for the prefix // we need up to 2 extra chars for the prefix
@@ -3849,6 +3913,14 @@ static int get_spell_compl_info(int startcol, colnr_T curs_col)
} }
/// Get the completion pattern, column and length. /// Get the completion pattern, column and length.
///
/// @param startcol start column number of the completion pattern/text
/// @param cur_col current cursor column
///
/// On return, "line_invalid" is set to true, if the current line may have
/// become invalid and needs to be fetched again.
///
/// @return OK on success.
static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *line_invalid) static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *line_invalid)
{ {
if (ctrl_x_mode_normal() if (ctrl_x_mode_normal()
@@ -3866,12 +3938,12 @@ static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *li
if (get_userdefined_compl_info(curs_col) == FAIL) { if (get_userdefined_compl_info(curs_col) == FAIL) {
return FAIL; return FAIL;
} }
*line_invalid = true; // 'line' may have become invalid *line_invalid = true; // "line" may have become invalid
} else if (ctrl_x_mode_spell()) { } else if (ctrl_x_mode_spell()) {
if (get_spell_compl_info(startcol, curs_col) == FAIL) { if (get_spell_compl_info(startcol, curs_col) == FAIL) {
return FAIL; return FAIL;
} }
*line_invalid = true; // 'line' may have become invalid *line_invalid = true; // "line" may have become invalid
} else { } else {
internal_error("ins_complete()"); internal_error("ins_complete()");
return FAIL; return FAIL;
@@ -3965,7 +4037,7 @@ static int ins_compl_start(void)
} }
int startcol = 0; // column where searched text starts int startcol = 0; // column where searched text starts
if (!(compl_cont_status & CONT_ADDING)) { // normal expansion if (!compl_status_adding()) { // normal expansion
compl_cont_mode = ctrl_x_mode; compl_cont_mode = ctrl_x_mode;
if (ctrl_x_mode_not_default()) { if (ctrl_x_mode_not_default()) {
// Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL // Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL
@@ -3992,7 +4064,7 @@ static int ins_compl_start(void)
line = ml_get(curwin->w_cursor.lnum); line = ml_get(curwin->w_cursor.lnum);
} }
if (compl_cont_status & CONT_ADDING) { if (compl_status_adding()) {
edit_submode_pre = (char_u *)_(" Adding"); edit_submode_pre = (char_u *)_(" Adding");
if (ctrl_x_mode_line_or_eval()) { if (ctrl_x_mode_line_or_eval()) {
// Insert a new line, keep indentation but ignore 'comments'. // Insert a new line, keep indentation but ignore 'comments'.
@@ -4051,9 +4123,8 @@ static int ins_compl_start(void)
static void ins_compl_show_statusmsg(void) static void ins_compl_show_statusmsg(void)
{ {
// we found no match if the list has only the "compl_orig_text"-entry // we found no match if the list has only the "compl_orig_text"-entry
if (compl_first_match == compl_first_match->cp_next) { if (is_first_match(compl_first_match->cp_next)) {
edit_submode_extra = (compl_cont_status & CONT_ADDING) edit_submode_extra = compl_status_adding() && compl_length > 1
&& compl_length > 1
? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf); ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
edit_submode_highl = HLF_E; edit_submode_highl = HLF_E;
} }
@@ -4160,13 +4231,13 @@ int ins_complete(int c, bool enable_pum)
} }
// we found no match if the list has only the "compl_orig_text"-entry // we found no match if the list has only the "compl_orig_text"-entry
if (compl_first_match == compl_first_match->cp_next) { if (is_first_match(compl_first_match->cp_next)) {
// remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode, // remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
// because we couldn't expand anything at first place, but if we used // because we couldn't expand anything at first place, but if we used
// ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word // ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
// (such as M in M'exico) if not tried already. -- Acevedo // (such as M in M'exico) if not tried already. -- Acevedo
if (compl_length > 1 if (compl_length > 1
|| (compl_cont_status & CONT_ADDING) || compl_status_adding()
|| (ctrl_x_mode_not_default() || (ctrl_x_mode_not_default()
&& !ctrl_x_mode_path_patterns() && !ctrl_x_mode_path_patterns()
&& !ctrl_x_mode_path_defines())) { && !ctrl_x_mode_path_defines())) {

View File

@@ -1499,16 +1499,15 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
// when adding lines the matching line may be empty but it is not // when adding lines the matching line may be empty but it is not
// ignored because we are interested in the next line -- Acevedo // ignored because we are interested in the next line -- Acevedo
if ((compl_cont_status & CONT_ADDING) if (compl_status_adding() && !compl_status_sol()) {
&& !(compl_cont_status & CONT_SOL)) {
if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) { if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) {
return OK; return OK;
} }
} else if (*p != NUL) { // Ignore empty lines. } else if (*p != NUL) { // Ignore empty lines.
// Expanding lines or words. // Expanding lines or words.
assert(compl_length >= 0); assert(ins_compl_len() >= 0);
if ((p_ic ? mb_strnicmp(p, pat, (size_t)compl_length) if ((p_ic ? mb_strnicmp(p, pat, (size_t)ins_compl_len())
: STRNCMP(p, pat, compl_length)) == 0) { : STRNCMP(p, pat, ins_compl_len())) == 0) {
return OK; return OK;
} }
} }
@@ -5309,7 +5308,7 @@ static char_u *get_line_and_copy(linenr_T lnum, char_u *buf)
} }
/// Find identifiers or defines in included files. /// Find identifiers or defines in included files.
/// If p_ic && (compl_cont_status & CONT_SOL) then ptr must be in lowercase. /// If p_ic && compl_status_sol() then ptr must be in lowercase.
/// ///
/// @param ptr pointer to search pattern /// @param ptr pointer to search pattern
/// @param dir direction of expansion /// @param dir direction of expansion
@@ -5362,9 +5361,9 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
file_line = xmalloc(LSIZE); file_line = xmalloc(LSIZE);
if (type != CHECK_PATH && type != FIND_DEFINE if (type != CHECK_PATH && type != FIND_DEFINE
// when CONT_SOL is set compare "ptr" with the beginning of the line // when CONT_SOL is set compare "ptr" with the beginning of the
// is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo // line is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo
&& !(compl_cont_status & CONT_SOL)) { && !compl_status_sol()) {
pat = xmalloc(len + 5); pat = xmalloc(len + 5);
assert(len <= INT_MAX); assert(len <= INT_MAX);
sprintf((char *)pat, whole ? "\\<%.*s\\>" : "%.*s", (int)len, ptr); sprintf((char *)pat, whole ? "\\<%.*s\\>" : "%.*s", (int)len, ptr);
@@ -5604,8 +5603,7 @@ search_line:
* define and this line didn't match define_prog above. * define and this line didn't match define_prog above.
*/ */
if (def_regmatch.regprog == NULL || define_matched) { if (def_regmatch.regprog == NULL || define_matched) {
if (define_matched if (define_matched || compl_status_sol()) {
|| (compl_cont_status & CONT_SOL)) {
// compare the first "len" chars from "ptr" // compare the first "len" chars from "ptr"
startp = (char_u *)skipwhite((char *)p); startp = (char_u *)skipwhite((char *)p);
if (p_ic) { if (p_ic) {
@@ -5671,8 +5669,8 @@ search_line:
} }
found = true; found = true;
aux = p = startp; aux = p = startp;
if (compl_cont_status & CONT_ADDING) { if (compl_status_adding()) {
p += compl_length; p += ins_compl_len();
if (vim_iswordp(p)) { if (vim_iswordp(p)) {
goto exit_matched; goto exit_matched;
} }
@@ -5681,7 +5679,7 @@ search_line:
p = find_word_end(p); p = find_word_end(p);
i = (int)(p - aux); i = (int)(p - aux);
if ((compl_cont_status & CONT_ADDING) && i == compl_length) { if (compl_status_adding() && i == ins_compl_len()) {
// IOSIZE > compl_length, so the STRNCPY works // IOSIZE > compl_length, so the STRNCPY works
STRNCPY(IObuff, aux, i); STRNCPY(IObuff, aux, i);
@@ -5728,7 +5726,7 @@ search_line:
IObuff[i] = NUL; IObuff[i] = NUL;
aux = IObuff; aux = IObuff;
if (i == compl_length) { if (i == ins_compl_len()) {
goto exit_matched; goto exit_matched;
} }
} }
@@ -5838,7 +5836,7 @@ exit_matched:
// are not at the end of it already // are not at the end of it already
if (def_regmatch.regprog == NULL if (def_regmatch.regprog == NULL
&& action == ACTION_EXPAND && action == ACTION_EXPAND
&& !(compl_cont_status & CONT_SOL) && !compl_status_sol()
&& *startp != NUL && *startp != NUL
&& *(p = startp + utfc_ptr2len((char *)startp)) != NUL) { && *(p = startp + utfc_ptr2len((char *)startp)) != NUL) {
goto search_line; goto search_line;