📄 edit.c
字号:
{
done_info = 0;
while (*e_cpt == ',' || *e_cpt == ' ')
e_cpt++;
if (*e_cpt == '.' && !curbuf->b_scanned)
{
ins_buf = curbuf;
first_match_pos = *ini;
/* So that ^N can match word immediately after cursor */
if (ctrl_x_mode == 0)
dec(&first_match_pos);
last_match_pos = first_match_pos;
type = 0;
}
else if (vim_strchr((char_u *)"buw", *e_cpt) != NULL
&& (ins_buf = next_buf(ins_buf, *e_cpt)) != curbuf)
{
if (*e_cpt != 'u')
{
started_completion = TRUE;
first_match_pos.col = last_match_pos.col = 0;
first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
last_match_pos.lnum = 0;
type = 0;
}
else
{
done_info = 6;
if (ins_buf->b_fname == NULL)
continue;
type = CTRL_X_DICTIONARY;
dict = ins_buf->b_fname;
dict_f = DICT_EXACT;
}
sprintf((char*)IObuff, "Scanning: %s",
ins_buf->b_sfname == NULL ? "No File"
: (char *)ins_buf->b_sfname);
msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
}
else if (*e_cpt == NUL)
break;
else
{
if (*e_cpt == 'k')
{
type = CTRL_X_DICTIONARY;
if (*++e_cpt != ',' && *e_cpt != NUL)
{
dict = e_cpt;
dict_f = DICT_FIRST;
}
}
#ifdef FIND_IN_PATH
else if (*e_cpt == 'i')
type = CTRL_X_PATH_PATTERNS;
#endif
else if (*e_cpt == ']' || *e_cpt == 't')
{
type = CTRL_X_TAGS;
sprintf((char*)IObuff, "Scanning tags.");
msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
}
else
type = -1;
/* in any case e_cpt is advanced to the next entry */
(void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
done_info = 6;
if (type == -1)
continue;
}
}
switch (type)
{
case -1:
break;
#ifdef FIND_IN_PATH
case CTRL_X_PATH_PATTERNS:
case CTRL_X_PATH_DEFINES:
find_pattern_in_path(complete_pat, dir,
(int)STRLEN(complete_pat), FALSE, FALSE,
(type == CTRL_X_PATH_DEFINES
&& !(continue_status & CONT_SOL))
? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
(linenr_t)1, (linenr_t)MAXLNUM);
break;
#endif
case CTRL_X_DICTIONARY:
complete_dictionaries(dict ? dict : p_dict, complete_pat, dir,
dict ? dict_f : 0);
dict = NULL;
break;
case CTRL_X_TAGS:
/* set reg_ic according to p_ic, p_scs and pat */
set_reg_ic(complete_pat);
if (find_tags(complete_pat, &temp, &matches,
TAG_REGEXP | TAG_NAMES | (ctrl_x_mode ? TAG_VERBOSE : 0),
MAXCOL) == OK && temp > 0)
{
int add_r = OK;
int ldir = dir;
for (i = 0; i < temp && add_r != RET_ERROR; i++)
if ((add_r = add_completion(matches[i], -1, NULL, ldir, 0))
== OK)
/* if dir was BACKWARD then honor it just once */
ldir = FORWARD;
FreeWild(temp, matches);
}
break;
case CTRL_X_FILES:
expand_interactively = TRUE;
if (expand_wildcards(1, &complete_pat, &temp, &matches,
EW_FILE|EW_DIR) == OK)
{
int add_r = OK;
int ldir = dir;
/* May change home directory back to "~". */
tilde_replace(complete_pat, temp, matches);
for (i = 0; i < temp && add_r != RET_ERROR; i++)
if ((add_r = add_completion(matches[i], -1, NULL, ldir, 0))
== OK)
/* if dir was BACKWARD then honor it just once */
ldir = FORWARD;
FreeWild(temp, matches);
}
expand_interactively = FALSE;
break;
default: /* normal ^P/^N and ^X^L */
/*
* If 'infercase' is set, don't use 'smartcase' here
*/
save_p_scs = p_scs;
if (ins_buf->b_p_inf)
p_scs = FALSE;
/* buffers other than curbuf are scanned from the beginning or the
* end but never from the middle, thus setting nowrapscan in this
* buffers is a good idea -- Acevedo */
save_p_ws = p_ws;
if (ins_buf != curbuf)
p_ws = FALSE;
for (;;)
{
int reuse = 0;
/* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that has
* added a word that was at the beginning of the line */
if ( ctrl_x_mode == CTRL_X_WHOLE_LINE
|| (continue_status & CONT_SOL))
temp = search_for_exact_line(ins_buf, pos,
dir, complete_pat);
else
temp = searchit(ins_buf, pos, dir, complete_pat, 1L,
SEARCH_KEEP + SEARCH_NFMSG, RE_LAST);
if (!started_completion)
{
/* set started_completion even on fail */
started_completion = TRUE;
first_match_pos = *pos;
last_match_pos = *pos;
}
else if (first_match_pos.lnum == last_match_pos.lnum
&& first_match_pos.col == last_match_pos.col)
temp = FAIL;
if ( temp == FAIL && ins_buf == curbuf
&& (done_info |= p_ws ? 6 : dir + 3) < 6)
/* With nowrapscan, we haven't finished looking in the
* other direction yet -- webb */
temp = -OK;
if (temp != OK)
break;
/* when ADDING, the text before the cursor matches, skip it */
if ( (continue_status & CONT_ADDING) && ins_buf == curbuf
&& ini->lnum == pos->lnum
&& ini->col == pos->col)
continue;
ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
{
if (continue_status & CONT_ADDING)
{
if (pos->lnum >= ins_buf->b_ml.ml_line_count)
continue;
ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
if (!p_paste)
ptr = skipwhite(ptr);
}
temp = STRLEN(ptr);
}
else
{
tmp_ptr = ptr;
if (continue_status & CONT_ADDING)
{
tmp_ptr += completion_length;
if (vim_iswordc(*tmp_ptr))
continue;
while (*tmp_ptr && !vim_iswordc(*tmp_ptr++))
;
}
while (vim_iswordc(*tmp_ptr))
tmp_ptr++;
temp = tmp_ptr - ptr;
if ((continue_status & CONT_ADDING)
&& temp == completion_length)
{
if (pos->lnum < ins_buf->b_ml.ml_line_count)
{
/* Try next line, if any. the new word will be
* "join" as if the normal command "J" was used.
* IOSIZE is always greater than
* completion_length, so the next STRNCPY always
* works -- Acevedo */
STRNCPY(IObuff, ptr, temp);
ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
tmp_ptr = ptr = skipwhite(ptr);
while (*tmp_ptr && !vim_iswordc(*tmp_ptr++))
;
while (vim_iswordc(*tmp_ptr))
tmp_ptr++;
if (tmp_ptr > ptr)
{
if (*ptr != ')' && IObuff[temp-1] != TAB)
{
if (IObuff[temp-1] != ' ')
IObuff[temp++] = ' ';
/* IObuf =~ "\k.* ", thus temp >= 2 */
if (p_js
&& (IObuff[temp-2] == '.'
|| (vim_strchr(p_cpo, CPO_JOINSP)
== NULL
&& (IObuff[temp-2] == '?'
|| IObuff[temp-2] == '!'))))
IObuff[temp++] = ' ';
}
/* copy as much as posible of the new word */
if (tmp_ptr - ptr >= IOSIZE - temp)
tmp_ptr = ptr + IOSIZE - temp - 1;
STRNCPY(IObuff + temp, ptr, tmp_ptr - ptr);
temp += tmp_ptr - ptr;
reuse |= CONT_S_IPOS;
}
IObuff[temp] = NUL;
ptr = IObuff;
}
if (temp == completion_length)
continue;
}
}
if (add_completion_and_infercase(ptr, temp, ins_buf == curbuf ?
NULL : ins_buf->b_sfname, dir, reuse) != FAIL)
{
temp = OK;
break;
}
}
p_scs = save_p_scs;
p_ws = save_p_ws;
}
/* check if curr_match has changed, (e.g. other type of expansion
* added somenthing) */
if (curr_match != old_match)
temp = OK;
/* break the loop for specialized modes (use 'complete' just for the
* generic ctrl_x_mode == 0) and when temp != FAIL */
if (ctrl_x_mode || temp)
break;
if (type == 0 || type == CTRL_X_PATH_PATTERNS)
ins_buf->b_scanned = TRUE;
started_completion = FALSE;
}
started_completion = TRUE;
i = -1; /* total of matches, unknown */
if (temp == FAIL || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE))
i = make_cyclic();
else if (temp == -OK && (curr_match->original & ORIGINAL_TEXT))
{
edit_submode_extra = (continue_status & CONT_ADDING)
&& completion_length > 1
? (dir == FORWARD ? e_hitend_f : e_hitend_b)
: (dir == FORWARD ? e_patnotf_f : e_patnotf_b);
edit_submode_highl = HLF_E;
}
/* If several matches were added (FORWARD) or the search failed and has
* just been made cyclic then we have to move curr_match to the next or
* previous entry (if any, when search failed with 'nows') -- Acevedo */
curr_match = dir == FORWARD ? old_match->next : old_match->prev;
if (curr_match == NULL)
curr_match = old_match;
return i;
}
static int
ins_complete(c)
int c;
{
int complete_direction;
char_u *ptr;
char_u *tmp_ptr = NULL; /* init for gcc */
static colnr_t complete_col = 0; /* init for gcc */
int temp = 0;
int i;
int cc;
static FPOS initial_pos;
if (c == Ctrl('P') || c == Ctrl('L'))
complete_direction = BACKWARD;
else
complete_direction = FORWARD;
if (!started_completion)
{
/* First time we hit ^N or ^P (in a row, I mean) */
/* Turn off 'sm' so we don't show matches with ^X^L */
save_sm = p_sm;
p_sm = FALSE;
did_ai = FALSE;
#ifdef SMARTINDENT
did_si = FALSE;
can_si = FALSE;
can_si_back = FALSE;
#endif
stop_arrow();
ptr = ml_get(curwin->w_cursor.lnum);
complete_col = curwin->w_cursor.col;
/* if this same ctrl_x_mode has been interrupted use the text from
* initial_pos to the cursor as a pattern to add a new word instead of
* expand the one before the cursor, in word-wise if "initial_pos" is
* not in the same line as the cursor then fix it (the line has been
* split because it was longer than 'tw'). if SOL is set then skip
* the previous pattern, a word at the beginning of the line has been
* inserted, we'll look for that -- Acevedo. */
if ((continue_status & CONT_INTRPT) && continue_mode == ctrl_x_mode)
{ /* it is a continued search */
continue_status &= ~CONT_INTRPT; /* remove INTRPT */
if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS
|| ctrl_x_mode == CTRL_X_PATH_DEFINES)
{
if (initial_pos.lnum != curwin->w_cursor.lnum)
{
/* line (probably) wrapped, set initial_pos to the first
* non_blank in the line, if it is not a wordchar include
* it to get a better pattern, but then we don't want the
* "\\<" prefix, check it bellow */
tmp_ptr = skipwhite(ptr);
initial_pos.col = tmp_ptr - ptr;
initial_pos.lnum = curwin->w_cursor.lnum;
continue_status &= ~CONT_SOL; /* clear SOL if present */
}
else
{
/* S_IPOS was set when we inserted a word that was at the
* beginning of the line, which means that we'll go to SOL
* mode but first we need to redefine initial_pos */
if (continue_status & CONT_S_IPOS)
{
continue_status |= CONT_SOL;
initial_pos.col = skipwhite(ptr + completion_length +
initial_pos.col) - ptr;
}
tmp_ptr = ptr + initial_pos.col;
}
temp = curwin->w_cursor.col - (tmp_ptr-ptr);
/* IObuf is used to add a "word from the next line" would we
* have enough space? just being paranoic */
#define MIN_SPACE 75
if (temp > (IOSIZE - MIN_SPACE))
{
continue_status &= ~CONT_SOL;
temp = (IOSIZE - MIN_SPACE);
tmp_ptr = curwin->w_cursor.col - temp + ptr;
}
continue_status |= CONT_ADDING | CONT_N_ADDS;
if (temp < 1)
continue_status &= CONT_LOCAL;
}
else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
continue_status = CONT_ADDING | CONT_N_ADDS;
else
continue_status = 0;
}
else
continue_status &= CONT_LOCAL;
if (!(continue_status & CONT_ADDING)) /* normal expansion */
{
continue_mode = ctrl_x_mode;
if (ctrl_x_mode) /* Remove LOCAL iff ctrl_x_mode != 0 */
continue_status = 0;
continue_status |= CONT_N_ADDS;
initial_pos = curwin->w_cursor;
temp = (int)complete_col;
tmp_ptr = ptr;
}
/* Work out completion pattern and original text -- webb */
if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT))
{
if ( (continue_status & CONT_SOL)
|| ctrl_x_mode == CTRL_X_PATH_DEFINES)
{
if (!(continue_status & CONT_ADDING))
{
while (--temp >= 0 && vim_isIDc(ptr[temp]))
;
tmp_ptr += ++temp;
temp = complete_col - temp;
}
complete_pat = vim_strnsave(tmp_ptr, temp);
if (complete_pat == NULL)
return FALSE;
if (p_ic)
for (i = 0; i < temp; i++)
complete_pat[i] = TO_LOWER(complete_pat[i]);
}
else if (continue_status & CONT_ADDING)
{
char_u *prefix = (char_u *)"\\<";
/* we need 3 extra chars, 1 for the NUL and
* 2 >= strlen(prefix) -- Acevedo */
complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
if (complete_pat == NULL)
return FALSE;
if (!vim_iswordc(*tmp_ptr) ||
(tmp_ptr > ptr && vim_iswordc(*(tmp_ptr-1))))
prefix = (char_u *)"";
STRCPY((char *)complete_pat, prefix);
(void)quote_meta(complete_pat + STRLEN(prefix), tmp_ptr, temp);
}
else if (--temp < 0 || !vim_iswordc(ptr[temp]))
{
/* Match any word of at least two chars */
complete_pat = vim_strsave((char_u *)"\\<\\k\\k");
if (complete_pat == NULL)
return FALSE;
tmp_ptr += complete_col;
temp = 0;
}
else
{
while (--temp >= 0 && vim_iswordc(ptr[temp]))
;
tmp_ptr += ++temp;
if ((temp = (int)complete_col - temp) == 1)
{
/* Only match word with at least two chars -- webb
* there's no need to call quote_meta,
* alloc(7) is enough -- Acevedo
*/
complete_pat = alloc(7);
if (complete_pat == NULL)
return FALSE;
STRCPY((char *)complete_pat, "\\<");
(void)quote_meta(complete_pat + 2, tmp_ptr, 1);
STRCAT((char *)complete_pat, "\\k");
}
else
{
complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
if (complete_pat == NULL)
return FALSE;
STRCPY((char *)complete_pat, "\\<");
(void)quote_meta(complete_pat + 2, tmp_ptr, temp);
}
}
}
else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
{
tmp_ptr = skipwhite(ptr);
temp = (int)complete_col - (tmp_ptr - ptr);
complete_pat = vim_strnsave(tmp_ptr, temp);
if (complete_pat == NULL)
return FALSE;
if (p_ic)
for (i = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -