mirror of
https://github.com/neovim/neovim.git
synced 2025-10-03 08:28:34 +00:00
vim-patch:partial:8.2.3953: insert completion code is too complicated (#19923)
Problem: Insert completion code is too complicated.
Solution: More refactoring. Move function arguments into a struct.
(Yegappan Lakshmanan, closes vim/vim#9437)
6ad84ab3e4
Skip most pum-related refactoring.
Cherry-pick rename to match_at_original_text() from patch 8.2.4001.
This commit is contained in:
@@ -140,6 +140,21 @@ struct compl_S {
|
|||||||
int cp_number; ///< sequence number
|
int cp_number; ///< sequence number
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// state information used for getting the next set of insert completion
|
||||||
|
/// matches.
|
||||||
|
typedef struct {
|
||||||
|
char *e_cpt; ///< current entry in 'complete'
|
||||||
|
buf_T *ins_buf; ///< buffer being scanned
|
||||||
|
pos_T *cur_match_pos; ///< current match position
|
||||||
|
pos_T prev_match_pos; ///< previous match position
|
||||||
|
bool set_match_pos; ///< save first_match_pos/last_match_pos
|
||||||
|
pos_T first_match_pos; ///< first match position
|
||||||
|
pos_T last_match_pos; ///< last match position
|
||||||
|
bool found_all; ///< found all matches of a certain type.
|
||||||
|
char_u *dict; ///< dictionary file to search
|
||||||
|
int dict_f; ///< "dict" is an exact file name or not
|
||||||
|
} ins_compl_next_state_T;
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "insexpand.c.generated.h"
|
# include "insexpand.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -162,6 +177,7 @@ static char e_compldel[] = N_("E840: Completion function deleted text");
|
|||||||
// "compl_curr_match" points to the currently selected entry.
|
// "compl_curr_match" points to the currently selected entry.
|
||||||
// "compl_shown_match" is different from compl_curr_match during
|
// "compl_shown_match" is different from compl_curr_match during
|
||||||
// ins_compl_get_exp().
|
// ins_compl_get_exp().
|
||||||
|
// "compl_old_match" points to previous "compl_curr_match".
|
||||||
|
|
||||||
static compl_T *compl_first_match = NULL;
|
static compl_T *compl_first_match = NULL;
|
||||||
static compl_T *compl_curr_match = NULL;
|
static compl_T *compl_curr_match = NULL;
|
||||||
@@ -445,6 +461,12 @@ bool vim_is_ctrl_x_key(int c)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return true if "match" is the original text when the completion began.
|
||||||
|
static bool match_at_original_text(const compl_T *const match)
|
||||||
|
{
|
||||||
|
return match->cp_flags & CP_ORIGINAL_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
@@ -479,6 +501,88 @@ bool ins_compl_accept_char(int c)
|
|||||||
return vim_iswordc(c);
|
return vim_iswordc(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the completed text by inferring the case of the originally typed text.
|
||||||
|
static char_u *ins_compl_infercase_gettext(char_u *str, int actual_len, int actual_compl_length,
|
||||||
|
int min_len)
|
||||||
|
{
|
||||||
|
bool has_lower = false;
|
||||||
|
bool was_letter = false;
|
||||||
|
|
||||||
|
// Allocate wide character array for the completion and fill it.
|
||||||
|
int *const wca = xmalloc((size_t)actual_len * sizeof(*wca));
|
||||||
|
{
|
||||||
|
const char_u *p = str;
|
||||||
|
for (int i = 0; i < actual_len; i++) {
|
||||||
|
wca[i] = mb_ptr2char_adv(&p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rule 1: Were any chars converted to lower?
|
||||||
|
{
|
||||||
|
const char_u *p = compl_orig_text;
|
||||||
|
for (int i = 0; i < min_len; i++) {
|
||||||
|
const int c = mb_ptr2char_adv(&p);
|
||||||
|
if (mb_islower(c)) {
|
||||||
|
has_lower = true;
|
||||||
|
if (mb_isupper(wca[i])) {
|
||||||
|
// Rule 1 is satisfied.
|
||||||
|
for (i = actual_compl_length; i < actual_len; i++) {
|
||||||
|
wca[i] = mb_tolower(wca[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rule 2: No lower case, 2nd consecutive letter converted to
|
||||||
|
// upper case.
|
||||||
|
if (!has_lower) {
|
||||||
|
const char_u *p = compl_orig_text;
|
||||||
|
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])) {
|
||||||
|
// Rule 2 is satisfied.
|
||||||
|
for (i = actual_compl_length; i < actual_len; i++) {
|
||||||
|
wca[i] = mb_toupper(wca[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
was_letter = mb_islower(c) || mb_isupper(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the original case of the part we typed.
|
||||||
|
{
|
||||||
|
const char_u *p = compl_orig_text;
|
||||||
|
for (int i = 0; i < min_len; i++) {
|
||||||
|
const int c = mb_ptr2char_adv(&p);
|
||||||
|
if (mb_islower(c)) {
|
||||||
|
wca[i] = mb_tolower(wca[i]);
|
||||||
|
} else if (mb_isupper(c)) {
|
||||||
|
wca[i] = mb_toupper(wca[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate encoding specific output from wide character array.
|
||||||
|
// Multi-byte characters can occupy up to five bytes more than
|
||||||
|
// ASCII characters, and we also need one byte for NUL, so stay
|
||||||
|
// six bytes away from the edge of IObuff.
|
||||||
|
{
|
||||||
|
char_u *p = IObuff;
|
||||||
|
int i = 0;
|
||||||
|
while (i < actual_len && (p - IObuff + 6) < IOSIZE) {
|
||||||
|
p += utf_char2bytes(wca[i++], (char *)p);
|
||||||
|
}
|
||||||
|
*p = NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(wca);
|
||||||
|
|
||||||
|
return IObuff;
|
||||||
|
}
|
||||||
|
|
||||||
/// This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
|
/// This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
|
||||||
/// case of the originally typed text is used, and the case of the completed
|
/// case of the originally typed text is used, and the case of the completed
|
||||||
/// text is inferred, ie this tries to work out what case you probably wanted
|
/// text is inferred, ie this tries to work out what case you probably wanted
|
||||||
@@ -490,12 +594,9 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
|
|||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
char_u *str = str_arg;
|
char_u *str = str_arg;
|
||||||
int i, c;
|
|
||||||
int actual_len; // Take multi-byte characters
|
int actual_len; // Take multi-byte characters
|
||||||
int actual_compl_length; // into account.
|
int actual_compl_length; // into account.
|
||||||
int min_len;
|
int min_len;
|
||||||
bool has_lower = false;
|
|
||||||
bool was_letter = false;
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
if (p_ic && curbuf->b_p_inf && len > 0) {
|
if (p_ic && curbuf->b_p_inf && len > 0) {
|
||||||
@@ -526,79 +627,7 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
|
|||||||
min_len = actual_len < actual_compl_length
|
min_len = actual_len < actual_compl_length
|
||||||
? actual_len : actual_compl_length;
|
? actual_len : actual_compl_length;
|
||||||
|
|
||||||
// Allocate wide character array for the completion and fill it.
|
str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length, min_len);
|
||||||
int *const wca = xmalloc((size_t)actual_len * sizeof(*wca));
|
|
||||||
{
|
|
||||||
const char_u *p = str;
|
|
||||||
for (i = 0; i < actual_len; i++) {
|
|
||||||
wca[i] = mb_ptr2char_adv(&p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule 1: Were any chars converted to lower?
|
|
||||||
{
|
|
||||||
const char_u *p = compl_orig_text;
|
|
||||||
for (i = 0; i < min_len; i++) {
|
|
||||||
c = mb_ptr2char_adv(&p);
|
|
||||||
if (mb_islower(c)) {
|
|
||||||
has_lower = true;
|
|
||||||
if (mb_isupper(wca[i])) {
|
|
||||||
// Rule 1 is satisfied.
|
|
||||||
for (i = actual_compl_length; i < actual_len; i++) {
|
|
||||||
wca[i] = mb_tolower(wca[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule 2: No lower case, 2nd consecutive letter converted to
|
|
||||||
// upper case.
|
|
||||||
if (!has_lower) {
|
|
||||||
const char_u *p = compl_orig_text;
|
|
||||||
for (i = 0; i < min_len; i++) {
|
|
||||||
c = mb_ptr2char_adv(&p);
|
|
||||||
if (was_letter && mb_isupper(c) && mb_islower(wca[i])) {
|
|
||||||
// Rule 2 is satisfied.
|
|
||||||
for (i = actual_compl_length; i < actual_len; i++) {
|
|
||||||
wca[i] = mb_toupper(wca[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
was_letter = mb_islower(c) || mb_isupper(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the original case of the part we typed.
|
|
||||||
{
|
|
||||||
const char_u *p = compl_orig_text;
|
|
||||||
for (i = 0; i < min_len; i++) {
|
|
||||||
c = mb_ptr2char_adv(&p);
|
|
||||||
if (mb_islower(c)) {
|
|
||||||
wca[i] = mb_tolower(wca[i]);
|
|
||||||
} else if (mb_isupper(c)) {
|
|
||||||
wca[i] = mb_toupper(wca[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate encoding specific output from wide character array.
|
|
||||||
// Multi-byte characters can occupy up to five bytes more than
|
|
||||||
// ASCII characters, and we also need one byte for NUL, so stay
|
|
||||||
// six bytes away from the edge of IObuff.
|
|
||||||
{
|
|
||||||
char_u *p = IObuff;
|
|
||||||
i = 0;
|
|
||||||
while (i < actual_len && (p - IObuff + 6) < IOSIZE) {
|
|
||||||
p += utf_char2bytes(wca[i++], (char *)p);
|
|
||||||
}
|
|
||||||
*p = NUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree(wca);
|
|
||||||
|
|
||||||
str = IObuff;
|
|
||||||
}
|
}
|
||||||
if (cont_s_ipos) {
|
if (cont_s_ipos) {
|
||||||
flags |= CP_CONT_S_IPOS;
|
flags |= CP_CONT_S_IPOS;
|
||||||
@@ -661,7 +690,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname,
|
|||||||
if (compl_first_match != NULL && !adup) {
|
if (compl_first_match != NULL && !adup) {
|
||||||
match = compl_first_match;
|
match = compl_first_match;
|
||||||
do {
|
do {
|
||||||
if (!(match->cp_flags & CP_ORIGINAL_TEXT)
|
if (!match_at_original_text(match)
|
||||||
&& STRNCMP(match->cp_str, str, len) == 0
|
&& STRNCMP(match->cp_str, str, len) == 0
|
||||||
&& match->cp_str[len] == NUL) {
|
&& match->cp_str[len] == NUL) {
|
||||||
FREE_CPTEXT(cptext, cptext_allocated);
|
FREE_CPTEXT(cptext, cptext_allocated);
|
||||||
@@ -777,6 +806,7 @@ static void ins_compl_longest_match(compl_T *match)
|
|||||||
if (compl_leader == NULL) {
|
if (compl_leader == NULL) {
|
||||||
// First match, use it as a whole.
|
// First match, use it as a whole.
|
||||||
compl_leader = vim_strsave(match->cp_str);
|
compl_leader = vim_strsave(match->cp_str);
|
||||||
|
|
||||||
had_match = (curwin->w_cursor.col > compl_col);
|
had_match = (curwin->w_cursor.col > compl_col);
|
||||||
ins_compl_delete();
|
ins_compl_delete();
|
||||||
ins_bytes(compl_leader + get_compl_len());
|
ins_bytes(compl_leader + get_compl_len());
|
||||||
@@ -788,7 +818,10 @@ static void ins_compl_longest_match(compl_T *match)
|
|||||||
ins_compl_delete();
|
ins_compl_delete();
|
||||||
}
|
}
|
||||||
compl_used_match = false;
|
compl_used_match = false;
|
||||||
} else {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Reduce the text if this match differs from compl_leader.
|
// Reduce the text if this match differs from compl_leader.
|
||||||
p = compl_leader;
|
p = compl_leader;
|
||||||
s = match->cp_str;
|
s = match->cp_str;
|
||||||
@@ -822,7 +855,6 @@ static void ins_compl_longest_match(compl_T *match)
|
|||||||
|
|
||||||
compl_used_match = false;
|
compl_used_match = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Add an array of matches to the list of matches.
|
/// Add an array of matches to the list of matches.
|
||||||
/// Frees matches[].
|
/// Frees matches[].
|
||||||
@@ -846,12 +878,13 @@ static void ins_compl_add_matches(int num_matches, char **matches, int icase)
|
|||||||
/// Return the number of matches (excluding the original).
|
/// Return the number of matches (excluding the original).
|
||||||
static int ins_compl_make_cyclic(void)
|
static int ins_compl_make_cyclic(void)
|
||||||
{
|
{
|
||||||
compl_T *match;
|
if (compl_first_match == NULL) {
|
||||||
int count = 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (compl_first_match != NULL) {
|
|
||||||
// Find the end of the list.
|
// Find the end of the list.
|
||||||
match = compl_first_match;
|
compl_T *match = compl_first_match;
|
||||||
|
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 && match->cp_next != compl_first_match) {
|
||||||
match = match->cp_next;
|
match = match->cp_next;
|
||||||
@@ -859,7 +892,7 @@ static int ins_compl_make_cyclic(void)
|
|||||||
}
|
}
|
||||||
match->cp_next = compl_first_match;
|
match->cp_next = compl_first_match;
|
||||||
compl_first_match->cp_prev = match;
|
compl_first_match->cp_prev = match;
|
||||||
}
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -898,11 +931,13 @@ static int compl_match_arraysize;
|
|||||||
/// Remove any popup menu.
|
/// Remove any popup menu.
|
||||||
static void ins_compl_del_pum(void)
|
static void ins_compl_del_pum(void)
|
||||||
{
|
{
|
||||||
if (compl_match_array != NULL) {
|
if (compl_match_array == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pum_undisplay(false);
|
pum_undisplay(false);
|
||||||
XFREE_CLEAR(compl_match_array);
|
XFREE_CLEAR(compl_match_array);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the popup menu should be displayed.
|
/// Check if the popup menu should be displayed.
|
||||||
bool pum_wanted(void)
|
bool pum_wanted(void)
|
||||||
@@ -919,15 +954,14 @@ static bool pum_enough_matches(void)
|
|||||||
{
|
{
|
||||||
// Don't display the popup menu if there are no matches or there is only
|
// Don't display the popup menu if there are no matches or there is only
|
||||||
// one (ignoring the original text).
|
// one (ignoring the original text).
|
||||||
compl_T *comp = compl_first_match;
|
compl_T *compl = compl_first_match;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
do {
|
do {
|
||||||
if (comp == NULL
|
if (compl == NULL || (!match_at_original_text(compl) && ++i == 2)) {
|
||||||
|| ((comp->cp_flags & CP_ORIGINAL_TEXT) == 0 && ++i == 2)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
comp = comp->cp_next;
|
compl = compl->cp_next;
|
||||||
} while (comp != compl_first_match);
|
} while (compl != compl_first_match);
|
||||||
|
|
||||||
if (strstr((char *)p_cot, "menuone") != NULL) {
|
if (strstr((char *)p_cot, "menuone") != NULL) {
|
||||||
return i >= 1;
|
return i >= 1;
|
||||||
@@ -1019,7 +1053,7 @@ void ins_compl_show_pum(void)
|
|||||||
lead_len = (int)STRLEN(compl_leader);
|
lead_len = (int)STRLEN(compl_leader);
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
if ((compl->cp_flags & CP_ORIGINAL_TEXT) == 0
|
if (!match_at_original_text(compl)
|
||||||
&& (compl_leader == NULL
|
&& (compl_leader == NULL
|
||||||
|| ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
|
|| ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
|
||||||
compl_match_arraysize++;
|
compl_match_arraysize++;
|
||||||
@@ -1034,14 +1068,14 @@ void ins_compl_show_pum(void)
|
|||||||
compl_match_array = xcalloc((size_t)compl_match_arraysize, sizeof(pumitem_T));
|
compl_match_array = xcalloc((size_t)compl_match_arraysize, sizeof(pumitem_T));
|
||||||
// If the current match is the original text don't find the first
|
// If the current match is the original text don't find the first
|
||||||
// match after it, don't highlight anything.
|
// match after it, don't highlight anything.
|
||||||
if (compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) {
|
if (match_at_original_text(compl_shown_match)) {
|
||||||
shown_match_ok = true;
|
shown_match_ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
compl = compl_first_match;
|
compl = compl_first_match;
|
||||||
do {
|
do {
|
||||||
if ((compl->cp_flags & CP_ORIGINAL_TEXT) == 0
|
if (!match_at_original_text(compl)
|
||||||
&& (compl_leader == NULL
|
&& (compl_leader == NULL
|
||||||
|| ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
|
|| ins_compl_equal(compl, compl_leader, (size_t)lead_len))) {
|
||||||
if (!shown_match_ok) {
|
if (!shown_match_ok) {
|
||||||
@@ -1080,7 +1114,7 @@ void ins_compl_show_pum(void)
|
|||||||
|
|
||||||
// When the original text is the shown match don't set
|
// When the original text is the shown match don't set
|
||||||
// compl_shown_match.
|
// compl_shown_match.
|
||||||
if (compl->cp_flags & CP_ORIGINAL_TEXT) {
|
if (match_at_original_text(compl)) {
|
||||||
shown_match_ok = true;
|
shown_match_ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1255,8 +1289,7 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r
|
|||||||
|
|
||||||
// Read dictionary file line by line.
|
// Read dictionary file line by line.
|
||||||
// Check each line for a match.
|
// Check each line for a match.
|
||||||
while (!got_int && !compl_interrupted
|
while (!got_int && !compl_interrupted && !vim_fgets(buf, LSIZE, fp)) {
|
||||||
&& !vim_fgets(buf, LSIZE, fp)) {
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
while (vim_regexec(regmatch, (char *)buf, (colnr_T)(ptr - buf))) {
|
while (vim_regexec(regmatch, (char *)buf, (colnr_T)(ptr - buf))) {
|
||||||
ptr = regmatch->startp[0];
|
ptr = regmatch->startp[0];
|
||||||
@@ -1603,13 +1636,13 @@ static void ins_compl_set_original_text(char_u *str)
|
|||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
// Replace the original text entry.
|
// Replace the original text entry.
|
||||||
// The CP_ORIGINAL_TEXT flag is either at the first item or might possibly be
|
// The CP_ORIGINAL_TEXT flag is either at the first item or might possibly
|
||||||
// at the last item for backward completion
|
// be at the last item for backward completion
|
||||||
if (compl_first_match->cp_flags & CP_ORIGINAL_TEXT) { // safety check
|
if (match_at_original_text(compl_first_match)) { // safety check
|
||||||
xfree(compl_first_match->cp_str);
|
xfree(compl_first_match->cp_str);
|
||||||
compl_first_match->cp_str = vim_strsave(str);
|
compl_first_match->cp_str = vim_strsave(str);
|
||||||
} else if (compl_first_match->cp_prev != NULL
|
} else if (compl_first_match->cp_prev != NULL
|
||||||
&& (compl_first_match->cp_prev->cp_flags & CP_ORIGINAL_TEXT)) {
|
&& match_at_original_text(compl_first_match->cp_prev)) {
|
||||||
xfree(compl_first_match->cp_prev->cp_str);
|
xfree(compl_first_match->cp_prev->cp_str);
|
||||||
compl_first_match->cp_prev->cp_str = vim_strsave(str);
|
compl_first_match->cp_prev->cp_str = vim_strsave(str);
|
||||||
}
|
}
|
||||||
@@ -1628,7 +1661,10 @@ void ins_compl_addfrommatch(void)
|
|||||||
if ((int)STRLEN(p) <= len) { // the match is too short
|
if ((int)STRLEN(p) <= len) { // the match is too short
|
||||||
// When still at the original match use the first entry that matches
|
// When still at the original match use the first entry that matches
|
||||||
// the leader.
|
// the leader.
|
||||||
if (compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) {
|
if (!match_at_original_text(compl_shown_match)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
&& cp != compl_first_match; cp = cp->cp_next) {
|
||||||
@@ -1641,9 +1677,6 @@ void ins_compl_addfrommatch(void)
|
|||||||
if (p == NULL || (int)STRLEN(p) <= len) {
|
if (p == NULL || (int)STRLEN(p) <= len) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
p += len;
|
p += len;
|
||||||
c = utf_ptr2char((char *)p);
|
c = utf_ptr2char((char *)p);
|
||||||
@@ -2451,7 +2484,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
|
|||||||
if (ret == OK && compl_first_match != NULL) {
|
if (ret == OK && compl_first_match != NULL) {
|
||||||
compl_T *match = compl_first_match;
|
compl_T *match = compl_first_match;
|
||||||
do {
|
do {
|
||||||
if (!(match->cp_flags & CP_ORIGINAL_TEXT)) {
|
if (!match_at_original_text(match)) {
|
||||||
dict_T *di = tv_dict_alloc();
|
dict_T *di = tv_dict_alloc();
|
||||||
|
|
||||||
tv_list_append_dict(li, di);
|
tv_list_append_dict(li, di);
|
||||||
@@ -2516,105 +2549,101 @@ enum {
|
|||||||
INS_COMPL_CPT_END,
|
INS_COMPL_CPT_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Process the next 'complete' option value in "e_cpt_arg".
|
/// Process the next 'complete' option value in st->e_cpt.
|
||||||
///
|
///
|
||||||
/// If successful, the arguments are set as below:
|
/// If successful, the arguments are set as below:
|
||||||
/// e_cpt_arg - pointer to the next option value in 'e_cpt_arg'
|
/// st->cpt - pointer to the next option value in "st->cpt"
|
||||||
/// compl_type_arg - type of insert mode completion to use
|
/// compl_type_arg - type of insert mode completion to use
|
||||||
/// found_all_arg - all matches of this type are found
|
/// st->found_all - all matches of this type are found
|
||||||
/// buf_arg - search for completions in this buffer
|
/// st->ins_buf - search for completions in this buffer
|
||||||
/// first_match_pos - position of the first completion match
|
/// st->first_match_pos - position of the first completion match
|
||||||
/// last_match_pos - position of the last completion match
|
/// st->last_match_pos - position of the last completion match
|
||||||
/// set_match_pos - true if the first match position should be saved to avoid
|
/// st->set_match_pos - true if the first match position should be saved to
|
||||||
/// loops after the search wraps around.
|
/// avoid loops after the search wraps around.
|
||||||
/// dict - name of the dictionary or thesaurus file to search
|
/// st->dict - name of the dictionary or thesaurus file to search
|
||||||
/// dict_f - flag specifying whether "dict" is an exact file name or not
|
/// st->dict_f - flag specifying whether "dict" is an exact file name or not
|
||||||
///
|
///
|
||||||
/// @return INS_COMPL_CPT_OK if the next value is processed successfully.
|
/// @return INS_COMPL_CPT_OK if the next value is processed successfully.
|
||||||
/// INS_COMPL_CPT_CONT to skip the current value and process the next
|
/// INS_COMPL_CPT_CONT to skip the current value and process the next
|
||||||
/// option value.
|
/// option value.
|
||||||
/// INS_COMPL_CPT_END if all the values in "e_cpt" are processed.
|
/// INS_COMPL_CPT_END if all the values in "st->e_cpt" are processed.
|
||||||
static int process_next_cpt_value(char **e_cpt_arg, int *compl_type_arg, bool *found_all_arg,
|
static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_arg,
|
||||||
buf_T **buf_arg, pos_T *start_match_pos, pos_T *first_match_pos,
|
pos_T *start_match_pos)
|
||||||
pos_T *last_match_pos, bool *set_match_pos, char_u **dict_arg,
|
|
||||||
int *dict_flag)
|
|
||||||
{
|
{
|
||||||
char *e_cpt = *e_cpt_arg;
|
|
||||||
int compl_type = -1;
|
int compl_type = -1;
|
||||||
int status = INS_COMPL_CPT_OK;
|
int status = INS_COMPL_CPT_OK;
|
||||||
buf_T *buf = *buf_arg;
|
|
||||||
bool found_all = false;
|
|
||||||
char_u *dict = NULL;
|
|
||||||
int dict_f = 0;
|
|
||||||
|
|
||||||
while (*e_cpt == ',' || *e_cpt == ' ') {
|
st->found_all = false;
|
||||||
e_cpt++;
|
|
||||||
|
while (*st->e_cpt == ',' || *st->e_cpt == ' ') {
|
||||||
|
st->e_cpt++;
|
||||||
}
|
}
|
||||||
if (*e_cpt == '.' && !curbuf->b_scanned) {
|
|
||||||
buf = curbuf;
|
if (*st->e_cpt == '.' && !curbuf->b_scanned) {
|
||||||
*first_match_pos = *start_match_pos;
|
st->ins_buf = curbuf;
|
||||||
|
st->first_match_pos = *start_match_pos;
|
||||||
// Move the cursor back one character so that ^N can match the
|
// Move the cursor back one character so that ^N can match the
|
||||||
// word immediately after the cursor.
|
// word immediately after the cursor.
|
||||||
if (ctrl_x_mode_normal() && dec(first_match_pos) < 0) {
|
if (ctrl_x_mode_normal() && dec(&st->first_match_pos) < 0) {
|
||||||
// Move the cursor to after the last character in the
|
// Move the cursor to after the last character in the
|
||||||
// buffer, so that word at start of buffer is found
|
// buffer, so that word at start of buffer is found
|
||||||
// correctly.
|
// correctly.
|
||||||
first_match_pos->lnum = buf->b_ml.ml_line_count;
|
st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count;
|
||||||
first_match_pos->col = (colnr_T)STRLEN(ml_get(first_match_pos->lnum));
|
st->first_match_pos.col = (colnr_T)STRLEN(ml_get(st->first_match_pos.lnum));
|
||||||
}
|
}
|
||||||
*last_match_pos = *first_match_pos;
|
st->last_match_pos = st->first_match_pos;
|
||||||
compl_type = 0;
|
compl_type = 0;
|
||||||
|
|
||||||
// Remember the first match so that the loop stops when we
|
// Remember the first match so that the loop stops when we
|
||||||
// wrap and come back there a second time.
|
// wrap and come back there a second time.
|
||||||
*set_match_pos = true;
|
st->set_match_pos = true;
|
||||||
} else if (vim_strchr("buwU", *e_cpt) != NULL
|
} else if (vim_strchr("buwU", *st->e_cpt) != NULL
|
||||||
&& (buf = ins_compl_next_buf(buf, *e_cpt)) != curbuf) {
|
&& (st->ins_buf = ins_compl_next_buf(st->ins_buf, *st->e_cpt)) != curbuf) {
|
||||||
// Scan a buffer, but not the current one.
|
// Scan a buffer, but not the current one.
|
||||||
if (buf->b_ml.ml_mfp != NULL) { // loaded buffer
|
if (st->ins_buf->b_ml.ml_mfp != NULL) { // loaded buffer
|
||||||
compl_started = true;
|
compl_started = true;
|
||||||
first_match_pos->col = last_match_pos->col = 0;
|
st->first_match_pos.col = st->last_match_pos.col = 0;
|
||||||
first_match_pos->lnum = buf->b_ml.ml_line_count + 1;
|
st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count + 1;
|
||||||
last_match_pos->lnum = 0;
|
st->last_match_pos.lnum = 0;
|
||||||
compl_type = 0;
|
compl_type = 0;
|
||||||
} else { // unloaded buffer, scan like dictionary
|
} else { // unloaded buffer, scan like dictionary
|
||||||
found_all = true;
|
st->found_all = true;
|
||||||
if (buf->b_fname == NULL) {
|
if (st->ins_buf->b_fname == NULL) {
|
||||||
status = INS_COMPL_CPT_CONT;
|
status = INS_COMPL_CPT_CONT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
compl_type = CTRL_X_DICTIONARY;
|
compl_type = CTRL_X_DICTIONARY;
|
||||||
dict = (char_u *)buf->b_fname;
|
st->dict = (char_u *)st->ins_buf->b_fname;
|
||||||
dict_f = DICT_EXACT;
|
st->dict_f = DICT_EXACT;
|
||||||
}
|
}
|
||||||
msg_hist_off = true; // reset in msg_trunc_attr()
|
msg_hist_off = true; // reset in msg_trunc_attr()
|
||||||
vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
|
vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
|
||||||
buf->b_fname == NULL
|
st->ins_buf->b_fname == NULL
|
||||||
? buf_spname(buf)
|
? buf_spname(st->ins_buf)
|
||||||
: buf->b_sfname == NULL
|
: st->ins_buf->b_sfname == NULL
|
||||||
? buf->b_fname
|
? st->ins_buf->b_fname
|
||||||
: buf->b_sfname);
|
: st->ins_buf->b_sfname);
|
||||||
(void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R));
|
(void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R));
|
||||||
} else if (*e_cpt == NUL) {
|
} else if (*st->e_cpt == NUL) {
|
||||||
status = INS_COMPL_CPT_END;
|
status = INS_COMPL_CPT_END;
|
||||||
} else {
|
} else {
|
||||||
if (ctrl_x_mode_line_or_eval()) {
|
if (ctrl_x_mode_line_or_eval()) {
|
||||||
compl_type = -1;
|
compl_type = -1;
|
||||||
} else if (*e_cpt == 'k' || *e_cpt == 's') {
|
} else if (*st->e_cpt == 'k' || *st->e_cpt == 's') {
|
||||||
if (*e_cpt == 'k') {
|
if (*st->e_cpt == 'k') {
|
||||||
compl_type = CTRL_X_DICTIONARY;
|
compl_type = CTRL_X_DICTIONARY;
|
||||||
} else {
|
} else {
|
||||||
compl_type = CTRL_X_THESAURUS;
|
compl_type = CTRL_X_THESAURUS;
|
||||||
}
|
}
|
||||||
if (*++e_cpt != ',' && *e_cpt != NUL) {
|
if (*++st->e_cpt != ',' && *st->e_cpt != NUL) {
|
||||||
dict = (char_u *)e_cpt;
|
st->dict = (char_u *)st->e_cpt;
|
||||||
dict_f = DICT_FIRST;
|
st->dict_f = DICT_FIRST;
|
||||||
}
|
}
|
||||||
} else if (*e_cpt == 'i') {
|
} else if (*st->e_cpt == 'i') {
|
||||||
compl_type = CTRL_X_PATH_PATTERNS;
|
compl_type = CTRL_X_PATH_PATTERNS;
|
||||||
} else if (*e_cpt == 'd') {
|
} else if (*st->e_cpt == 'd') {
|
||||||
compl_type = CTRL_X_PATH_DEFINES;
|
compl_type = CTRL_X_PATH_DEFINES;
|
||||||
} else if (*e_cpt == ']' || *e_cpt == 't') {
|
} else if (*st->e_cpt == ']' || *st->e_cpt == 't') {
|
||||||
msg_hist_off = true; // reset in msg_trunc_attr()
|
msg_hist_off = true; // reset in msg_trunc_attr()
|
||||||
compl_type = CTRL_X_TAGS;
|
compl_type = CTRL_X_TAGS;
|
||||||
vim_snprintf((char *)IObuff, IOSIZE, "%s", _("Scanning tags."));
|
vim_snprintf((char *)IObuff, IOSIZE, "%s", _("Scanning tags."));
|
||||||
@@ -2624,21 +2653,16 @@ static int process_next_cpt_value(char **e_cpt_arg, int *compl_type_arg, bool *f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// in any case e_cpt is advanced to the next entry
|
// in any case e_cpt is advanced to the next entry
|
||||||
(void)copy_option_part(&e_cpt, (char *)IObuff, IOSIZE, ",");
|
(void)copy_option_part(&st->e_cpt, (char *)IObuff, IOSIZE, ",");
|
||||||
|
|
||||||
found_all = true;
|
st->found_all = true;
|
||||||
if (compl_type == -1) {
|
if (compl_type == -1) {
|
||||||
status = INS_COMPL_CPT_CONT;
|
status = INS_COMPL_CPT_CONT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
*e_cpt_arg = e_cpt;
|
|
||||||
*compl_type_arg = compl_type;
|
*compl_type_arg = compl_type;
|
||||||
*found_all_arg = found_all;
|
|
||||||
*buf_arg = buf;
|
|
||||||
*dict_arg = dict;
|
|
||||||
*dict_flag = dict_f;
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2656,20 +2680,19 @@ static void get_next_include_file_completion(int compl_type)
|
|||||||
|
|
||||||
/// Get the next set of words matching "compl_pattern" in dictionary or
|
/// Get the next set of words matching "compl_pattern" in dictionary or
|
||||||
/// thesaurus files.
|
/// thesaurus files.
|
||||||
static void get_next_dict_tsr_completion(int compl_type, char_u **dict, int dict_f)
|
static void get_next_dict_tsr_completion(int compl_type, char_u *dict, int dict_f)
|
||||||
{
|
{
|
||||||
if (thesaurus_func_complete(compl_type)) {
|
if (thesaurus_func_complete(compl_type)) {
|
||||||
expand_by_function(compl_type, (char_u *)compl_pattern);
|
expand_by_function(compl_type, (char_u *)compl_pattern);
|
||||||
} else {
|
} else {
|
||||||
ins_compl_dictionaries(*dict != NULL ? *dict
|
ins_compl_dictionaries(dict != NULL ? dict
|
||||||
: (compl_type == CTRL_X_THESAURUS
|
: (compl_type == CTRL_X_THESAURUS
|
||||||
? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
|
? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
|
||||||
: (*curbuf->b_p_dict == NUL ? p_dict : curbuf->b_p_dict)),
|
: (*curbuf->b_p_dict == NUL ? p_dict : curbuf->b_p_dict)),
|
||||||
(char_u *)compl_pattern,
|
(char_u *)compl_pattern,
|
||||||
*dict != NULL ? dict_f : 0,
|
dict != NULL ? dict_f : 0,
|
||||||
compl_type == CTRL_X_THESAURUS);
|
compl_type == CTRL_X_THESAURUS);
|
||||||
}
|
}
|
||||||
*dict = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next set of tag names matching "compl_pattern".
|
/// Get the next set of tag names matching "compl_pattern".
|
||||||
@@ -2833,29 +2856,18 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p
|
|||||||
|
|
||||||
/// Get the next set of words matching "compl_pattern" for default completion(s)
|
/// Get the next set of words matching "compl_pattern" for default completion(s)
|
||||||
/// (normal ^P/^N and ^X^L).
|
/// (normal ^P/^N and ^X^L).
|
||||||
/// Search for "compl_pattern" in the buffer "ins_buf" starting from the
|
/// Search for "compl_pattern" in the buffer "st->ins_buf" starting from the
|
||||||
/// position "start_pos" in the "compl_direction" direction. If "save_match_pos"
|
/// position "st->start_pos" in the "compl_direction" direction. If
|
||||||
/// is true, then set the "first_match_pos" and "last_match_pos".
|
/// "st->set_match_pos" is true, then set the "st->first_match_pos" and
|
||||||
///
|
/// "st->last_match_pos".
|
||||||
/// @param ins_buf buffer being scanned
|
|
||||||
/// @param start_pos search start position
|
|
||||||
/// @param cur_match_pos current match position
|
|
||||||
/// @param prev_match_pos previous match position
|
|
||||||
/// @param save_match_pos set first_match_pos/last_match_pos
|
|
||||||
/// @param first_match_pos first match position
|
|
||||||
/// @param last_match_pos last match position
|
|
||||||
/// @param scan_curbuf scan current buffer for completion
|
|
||||||
///
|
///
|
||||||
/// @return OK if a new next match is found, otherwise FAIL.
|
/// @return OK if a new next match is found, otherwise FAIL.
|
||||||
static int get_next_default_completion(buf_T *ins_buf, pos_T *start_pos, pos_T *cur_match_pos,
|
static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
|
||||||
pos_T *prev_match_pos, bool *save_match_pos,
|
|
||||||
pos_T *first_match_pos, pos_T *last_match_pos,
|
|
||||||
bool scan_curbuf)
|
|
||||||
{
|
{
|
||||||
// If 'infercase' is set, don't use 'smartcase' here
|
// If 'infercase' is set, don't use 'smartcase' here
|
||||||
const int save_p_scs = p_scs;
|
const int save_p_scs = p_scs;
|
||||||
assert(ins_buf);
|
assert(st->ins_buf);
|
||||||
if (ins_buf->b_p_inf) {
|
if (st->ins_buf->b_p_inf) {
|
||||||
p_scs = false;
|
p_scs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2864,9 +2876,9 @@ static int get_next_default_completion(buf_T *ins_buf, pos_T *start_pos, pos_T *
|
|||||||
// buffers is a good idea, on the other hand, we always set
|
// buffers is a good idea, on the other hand, we always set
|
||||||
// wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
|
// wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
|
||||||
const int save_p_ws = p_ws;
|
const int save_p_ws = p_ws;
|
||||||
if (ins_buf != curbuf) {
|
if (st->ins_buf != curbuf) {
|
||||||
p_ws = false;
|
p_ws = false;
|
||||||
} else if (scan_curbuf) {
|
} else if (*st->e_cpt == '.') {
|
||||||
p_ws = true;
|
p_ws = true;
|
||||||
}
|
}
|
||||||
bool looped_around = false;
|
bool looped_around = false;
|
||||||
@@ -2879,62 +2891,61 @@ static int get_next_default_completion(buf_T *ins_buf, pos_T *start_pos, pos_T *
|
|||||||
// 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(ins_buf, 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 {
|
||||||
found_new_match = searchit(NULL, ins_buf, cur_match_pos, NULL,
|
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
|
||||||
compl_direction,
|
NULL, compl_direction, (char_u *)compl_pattern, 1L,
|
||||||
(char_u *)compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
|
SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
|
||||||
RE_LAST, NULL);
|
|
||||||
}
|
}
|
||||||
msg_silent--;
|
msg_silent--;
|
||||||
if (!compl_started || *save_match_pos) {
|
if (!compl_started || st->set_match_pos) {
|
||||||
// set "compl_started" even on fail
|
// set "compl_started" even on fail
|
||||||
compl_started = true;
|
compl_started = true;
|
||||||
*first_match_pos = *cur_match_pos;
|
st->first_match_pos = *st->cur_match_pos;
|
||||||
*last_match_pos = *cur_match_pos;
|
st->last_match_pos = *st->cur_match_pos;
|
||||||
*save_match_pos = false;
|
st->set_match_pos = false;
|
||||||
} else if (first_match_pos->lnum == last_match_pos->lnum
|
} else if (st->first_match_pos.lnum == st->last_match_pos.lnum
|
||||||
&& first_match_pos->col == 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_direction == FORWARD)
|
||||||
&& (prev_match_pos->lnum > cur_match_pos->lnum
|
&& (st->prev_match_pos.lnum > st->cur_match_pos->lnum
|
||||||
|| (prev_match_pos->lnum == cur_match_pos->lnum
|
|| (st->prev_match_pos.lnum == st->cur_match_pos->lnum
|
||||||
&& prev_match_pos->col >= cur_match_pos->col))) {
|
&& st->prev_match_pos.col >= st->cur_match_pos->col))) {
|
||||||
if (looped_around) {
|
if (looped_around) {
|
||||||
found_new_match = FAIL;
|
found_new_match = FAIL;
|
||||||
} else {
|
} else {
|
||||||
looped_around = true;
|
looped_around = true;
|
||||||
}
|
}
|
||||||
} else if ((compl_direction != FORWARD)
|
} else if ((compl_direction != FORWARD)
|
||||||
&& (prev_match_pos->lnum < cur_match_pos->lnum
|
&& (st->prev_match_pos.lnum < st->cur_match_pos->lnum
|
||||||
|| (prev_match_pos->lnum == cur_match_pos->lnum
|
|| (st->prev_match_pos.lnum == st->cur_match_pos->lnum
|
||||||
&& prev_match_pos->col <= cur_match_pos->col))) {
|
&& st->prev_match_pos.col <= st->cur_match_pos->col))) {
|
||||||
if (looped_around) {
|
if (looped_around) {
|
||||||
found_new_match = FAIL;
|
found_new_match = FAIL;
|
||||||
} else {
|
} else {
|
||||||
looped_around = true;
|
looped_around = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*prev_match_pos = *cur_match_pos;
|
st->prev_match_pos = *st->cur_match_pos;
|
||||||
if (found_new_match == FAIL) {
|
if (found_new_match == FAIL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) && ins_buf == curbuf
|
if ((compl_cont_status & CONT_ADDING) && st->ins_buf == curbuf
|
||||||
&& start_pos->lnum == cur_match_pos->lnum
|
&& start_pos->lnum == st->cur_match_pos->lnum
|
||||||
&& start_pos->col == cur_match_pos->col) {
|
&& start_pos->col == st->cur_match_pos->col) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int len;
|
int len;
|
||||||
char_u *ptr = ins_comp_get_next_word_or_line(ins_buf, cur_match_pos, &len,
|
char_u *ptr = ins_comp_get_next_word_or_line(st->ins_buf, st->cur_match_pos,
|
||||||
&cont_s_ipos);
|
&len, &cont_s_ipos);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ins_compl_add_infercase(ptr, len, p_ic,
|
if (ins_compl_add_infercase(ptr, len, p_ic,
|
||||||
ins_buf == curbuf ? NULL : (char_u *)ins_buf->b_sfname,
|
st->ins_buf == curbuf ? NULL : (char_u *)st->ins_buf->b_sfname,
|
||||||
0, cont_s_ipos) != NOTDONE) {
|
0, cont_s_ipos) != NOTDONE) {
|
||||||
found_new_match = OK;
|
found_new_match = OK;
|
||||||
break;
|
break;
|
||||||
@@ -2946,75 +2957,11 @@ static int get_next_default_completion(buf_T *ins_buf, pos_T *start_pos, pos_T *
|
|||||||
return found_new_match;
|
return found_new_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next expansion(s), using "compl_pattern".
|
/// get the next set of completion matches for 'type'.
|
||||||
/// The search starts at position "ini" in curbuf and in the direction
|
/// @return true if a new match is found, otherwise false.
|
||||||
/// compl_direction.
|
static bool get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini)
|
||||||
/// When "compl_started" is false start at that position, otherwise continue
|
|
||||||
/// where we stopped searching before.
|
|
||||||
/// This may return before finding all the matches.
|
|
||||||
/// Return the total number of matches or -1 if still unknown -- Acevedo
|
|
||||||
static int ins_compl_get_exp(pos_T *ini)
|
|
||||||
{
|
{
|
||||||
static pos_T first_match_pos;
|
int found_new_match = FAIL;
|
||||||
static pos_T last_match_pos;
|
|
||||||
static char *e_cpt = ""; // curr. entry in 'complete'
|
|
||||||
static bool found_all = false; // Found all matches of a
|
|
||||||
// certain type.
|
|
||||||
static buf_T *ins_buf = NULL; // buffer being scanned
|
|
||||||
|
|
||||||
pos_T *pos;
|
|
||||||
int i;
|
|
||||||
int found_new_match;
|
|
||||||
int type = ctrl_x_mode;
|
|
||||||
char_u *dict = NULL;
|
|
||||||
int dict_f = 0;
|
|
||||||
bool set_match_pos;
|
|
||||||
pos_T prev_pos = { 0, 0, 0 };
|
|
||||||
|
|
||||||
assert(curbuf != NULL);
|
|
||||||
|
|
||||||
if (!compl_started) {
|
|
||||||
FOR_ALL_BUFFERS(buf) {
|
|
||||||
buf->b_scanned = false;
|
|
||||||
}
|
|
||||||
found_all = false;
|
|
||||||
ins_buf = curbuf;
|
|
||||||
e_cpt = (compl_cont_status & CONT_LOCAL) ? "." : (char *)curbuf->b_p_cpt;
|
|
||||||
last_match_pos = first_match_pos = *ini;
|
|
||||||
} else if (ins_buf != curbuf && !buf_valid(ins_buf)) {
|
|
||||||
ins_buf = curbuf; // In case the buffer was wiped out.
|
|
||||||
}
|
|
||||||
assert(ins_buf != NULL);
|
|
||||||
|
|
||||||
compl_old_match = compl_curr_match; // remember the last current match
|
|
||||||
pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
|
|
||||||
|
|
||||||
// For ^N/^P loop over all the flags/windows/buffers in 'complete'
|
|
||||||
for (;;) {
|
|
||||||
found_new_match = FAIL;
|
|
||||||
set_match_pos = false;
|
|
||||||
|
|
||||||
// For ^N/^P pick a new entry from e_cpt if compl_started is off,
|
|
||||||
// or if found_all says this entry is done. For ^X^L only use the
|
|
||||||
// entries from 'complete' that look in loaded buffers.
|
|
||||||
if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
|
|
||||||
&& (!compl_started || found_all)) {
|
|
||||||
int status = process_next_cpt_value(&e_cpt, &type, &found_all,
|
|
||||||
&ins_buf, ini, &first_match_pos, &last_match_pos,
|
|
||||||
&set_match_pos, &dict, &dict_f);
|
|
||||||
if (status == INS_COMPL_CPT_END) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (status == INS_COMPL_CPT_CONT) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If complete() was called then compl_pattern has been reset.
|
|
||||||
// The following won't work then, bail out.
|
|
||||||
if (compl_pattern == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case -1:
|
case -1:
|
||||||
@@ -3026,7 +2973,8 @@ static int ins_compl_get_exp(pos_T *ini)
|
|||||||
|
|
||||||
case CTRL_X_DICTIONARY:
|
case CTRL_X_DICTIONARY:
|
||||||
case CTRL_X_THESAURUS:
|
case CTRL_X_THESAURUS:
|
||||||
get_next_dict_tsr_completion(type, &dict, dict_f);
|
get_next_dict_tsr_completion(type, st->dict, st->dict_f);
|
||||||
|
st->dict = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_X_TAGS:
|
case CTRL_X_TAGS:
|
||||||
@@ -3048,15 +2996,13 @@ static int ins_compl_get_exp(pos_T *ini)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_X_SPELL:
|
case CTRL_X_SPELL:
|
||||||
get_next_spell_completion(first_match_pos.lnum);
|
get_next_spell_completion(st->first_match_pos.lnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // normal ^P/^N and ^X^L
|
default: // normal ^P/^N and ^X^L
|
||||||
found_new_match = get_next_default_completion(ins_buf, ini, pos, &prev_pos,
|
found_new_match = get_next_default_completion(st, ini);
|
||||||
&set_match_pos, &first_match_pos,
|
if (found_new_match == FAIL && st->ins_buf == curbuf) {
|
||||||
&last_match_pos, (*e_cpt == '.'));
|
st->found_all = true;
|
||||||
if (found_new_match == FAIL && ins_buf == curbuf) {
|
|
||||||
found_all = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3066,6 +3012,70 @@ static int ins_compl_get_exp(pos_T *ini)
|
|||||||
found_new_match = OK;
|
found_new_match = OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return found_new_match;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the next expansion(s), using "compl_pattern".
|
||||||
|
/// The search starts at position "ini" in curbuf and in the direction
|
||||||
|
/// compl_direction.
|
||||||
|
/// When "compl_started" is false start at that position, otherwise continue
|
||||||
|
/// where we stopped searching before.
|
||||||
|
/// This may return before finding all the matches.
|
||||||
|
/// Return the total number of matches or -1 if still unknown -- Acevedo
|
||||||
|
static int ins_compl_get_exp(pos_T *ini)
|
||||||
|
{
|
||||||
|
static ins_compl_next_state_T st;
|
||||||
|
int i;
|
||||||
|
int found_new_match;
|
||||||
|
int type = ctrl_x_mode;
|
||||||
|
|
||||||
|
assert(curbuf != NULL);
|
||||||
|
|
||||||
|
if (!compl_started) {
|
||||||
|
FOR_ALL_BUFFERS(buf) {
|
||||||
|
buf->b_scanned = false;
|
||||||
|
}
|
||||||
|
st.found_all = false;
|
||||||
|
st.ins_buf = curbuf;
|
||||||
|
st.e_cpt = (compl_cont_status & CONT_LOCAL) ? "." : (char *)curbuf->b_p_cpt;
|
||||||
|
st.last_match_pos = st.first_match_pos = *ini;
|
||||||
|
} else if (st.ins_buf != curbuf && !buf_valid(st.ins_buf)) {
|
||||||
|
st.ins_buf = curbuf; // In case the buffer was wiped out.
|
||||||
|
}
|
||||||
|
assert(st.ins_buf != NULL);
|
||||||
|
|
||||||
|
compl_old_match = compl_curr_match; // remember the last current match
|
||||||
|
st.cur_match_pos = (compl_direction == FORWARD
|
||||||
|
? &st.last_match_pos : &st.first_match_pos);
|
||||||
|
|
||||||
|
// For ^N/^P loop over all the flags/windows/buffers in 'complete'
|
||||||
|
for (;;) {
|
||||||
|
found_new_match = FAIL;
|
||||||
|
st.set_match_pos = false;
|
||||||
|
|
||||||
|
// For ^N/^P pick a new entry from e_cpt if compl_started is off,
|
||||||
|
// or if found_all says this entry is done. For ^X^L only use the
|
||||||
|
// entries from 'complete' that look in loaded buffers.
|
||||||
|
if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
|
||||||
|
&& (!compl_started || st.found_all)) {
|
||||||
|
int status = process_next_cpt_value(&st, &type, ini);
|
||||||
|
if (status == INS_COMPL_CPT_END) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (status == INS_COMPL_CPT_CONT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If complete() was called then compl_pattern has been reset.
|
||||||
|
// The following won't work then, bail out.
|
||||||
|
if (compl_pattern == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next set of completion matches
|
||||||
|
found_new_match = get_next_completion_match(type, &st, 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()
|
||||||
@@ -3088,8 +3098,8 @@ static int ins_compl_get_exp(pos_T *ini)
|
|||||||
} else {
|
} else {
|
||||||
// Mark a buffer scanned when it has been scanned completely
|
// Mark a buffer scanned when it has been scanned completely
|
||||||
if (type == 0 || type == CTRL_X_PATH_PATTERNS) {
|
if (type == 0 || type == CTRL_X_PATH_PATTERNS) {
|
||||||
assert(ins_buf);
|
assert(st.ins_buf);
|
||||||
ins_buf->b_scanned = true;
|
st.ins_buf->b_scanned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
compl_started = false;
|
compl_started = false;
|
||||||
@@ -3099,7 +3109,7 @@ static int ins_compl_get_exp(pos_T *ini)
|
|||||||
|
|
||||||
if ((ctrl_x_mode_normal()
|
if ((ctrl_x_mode_normal()
|
||||||
|| ctrl_x_mode_line_or_eval())
|
|| ctrl_x_mode_line_or_eval())
|
||||||
&& *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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3178,7 +3188,7 @@ void ins_compl_delete(void)
|
|||||||
void ins_compl_insert(bool in_compl_func)
|
void ins_compl_insert(bool in_compl_func)
|
||||||
{
|
{
|
||||||
ins_bytes(compl_shown_match->cp_str + get_compl_len());
|
ins_bytes(compl_shown_match->cp_str + get_compl_len());
|
||||||
compl_used_match = !(compl_shown_match->cp_flags & CP_ORIGINAL_TEXT);
|
compl_used_match = !match_at_original_text(compl_shown_match);
|
||||||
|
|
||||||
dict_T *dict = ins_compl_dict_alloc(compl_shown_match);
|
dict_T *dict = ins_compl_dict_alloc(compl_shown_match);
|
||||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
|
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
|
||||||
@@ -3285,7 +3295,7 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a
|
|||||||
}
|
}
|
||||||
found_end = false;
|
found_end = false;
|
||||||
}
|
}
|
||||||
if ((compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) == 0
|
if (!match_at_original_text(compl_shown_match)
|
||||||
&& compl_leader != NULL
|
&& compl_leader != NULL
|
||||||
&& !ins_compl_equal(compl_shown_match,
|
&& !ins_compl_equal(compl_shown_match,
|
||||||
compl_leader, STRLEN(compl_leader))) {
|
compl_leader, STRLEN(compl_leader))) {
|
||||||
@@ -3340,7 +3350,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compl_leader != NULL
|
if (compl_leader != NULL
|
||||||
&& (compl_shown_match->cp_flags & CP_ORIGINAL_TEXT) == 0) {
|
&& !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();
|
||||||
}
|
}
|
||||||
@@ -3993,7 +4003,7 @@ static void ins_compl_show_statusmsg(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (edit_submode_extra == NULL) {
|
if (edit_submode_extra == NULL) {
|
||||||
if (compl_curr_match->cp_flags & CP_ORIGINAL_TEXT) {
|
if (match_at_original_text(compl_curr_match)) {
|
||||||
edit_submode_extra = (char_u *)_("Back at original");
|
edit_submode_extra = (char_u *)_("Back at original");
|
||||||
edit_submode_highl = HLF_W;
|
edit_submode_highl = HLF_W;
|
||||||
} else if (compl_cont_status & CONT_S_IPOS) {
|
} else if (compl_cont_status & CONT_S_IPOS) {
|
||||||
|
Reference in New Issue
Block a user