mirror of
https://github.com/neovim/neovim
synced 2025-07-16 09:11:51 +00:00
Merge #11294 from tomtomjhj/vim-8.1.2173
vim-patch:8.1.{2173,2207,2218}
This commit is contained in:
@ -4118,7 +4118,7 @@ static int ins_compl_get_exp(pos_T *ini)
|
||||
compl_direction,
|
||||
compl_pattern, 1L,
|
||||
SEARCH_KEEP + SEARCH_NFMSG,
|
||||
RE_LAST, (linenr_T)0, NULL, NULL);
|
||||
RE_LAST, NULL);
|
||||
}
|
||||
msg_silent--;
|
||||
if (!compl_started || set_match_pos) {
|
||||
|
@ -14617,6 +14617,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
||||
long time_limit = 0;
|
||||
int options = SEARCH_KEEP;
|
||||
int subpatnum;
|
||||
searchit_arg_T sia;
|
||||
|
||||
const char *const pat = tv_get_string(&argvars[0]);
|
||||
dir = get_search_arg(&argvars[1], flagsp); // May set p_ws.
|
||||
@ -14664,8 +14665,11 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
||||
}
|
||||
|
||||
pos = save_cursor = curwin->w_cursor;
|
||||
memset(&sia, 0, sizeof(sia));
|
||||
sia.sa_stop_lnum = (linenr_T)lnum_stop;
|
||||
sia.sa_tm = &tm;
|
||||
subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1,
|
||||
options, RE_SEARCH, (linenr_T)lnum_stop, &tm, NULL);
|
||||
options, RE_SEARCH, &sia);
|
||||
if (subpatnum != FAIL) {
|
||||
if (flags & SP_SUBPAT)
|
||||
retval = subpatnum;
|
||||
@ -15237,8 +15241,13 @@ do_searchpair(
|
||||
clearpos(&foundpos);
|
||||
pat = pat3;
|
||||
for (;; ) {
|
||||
searchit_arg_T sia;
|
||||
memset(&sia, 0, sizeof(sia));
|
||||
sia.sa_stop_lnum = lnum_stop;
|
||||
sia.sa_tm = &tm;
|
||||
|
||||
n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
|
||||
options, RE_SEARCH, lnum_stop, &tm, NULL);
|
||||
options, RE_SEARCH, &sia);
|
||||
if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) {
|
||||
// didn't find it or found the first match again: FAIL
|
||||
break;
|
||||
|
@ -3750,8 +3750,7 @@ static linenr_T get_address(exarg_T *eap,
|
||||
curwin->w_cursor.col = 0;
|
||||
}
|
||||
searchcmdlen = 0;
|
||||
if (!do_search(NULL, c, cmd, 1L,
|
||||
SEARCH_HIS | SEARCH_MSG, NULL, NULL)) {
|
||||
if (!do_search(NULL, c, cmd, 1L, SEARCH_HIS | SEARCH_MSG, NULL)) {
|
||||
curwin->w_cursor = pos;
|
||||
cmd = NULL;
|
||||
goto error;
|
||||
@ -3788,8 +3787,7 @@ static linenr_T get_address(exarg_T *eap,
|
||||
pos.coladd = 0;
|
||||
if (searchit(curwin, curbuf, &pos, NULL,
|
||||
*cmd == '?' ? BACKWARD : FORWARD,
|
||||
(char_u *)"", 1L, SEARCH_MSG,
|
||||
i, (linenr_T)0, NULL, NULL) != FAIL) {
|
||||
(char_u *)"", 1L, SEARCH_MSG, i, NULL) != FAIL) {
|
||||
lnum = pos.lnum;
|
||||
} else {
|
||||
cmd = NULL;
|
||||
|
@ -1075,7 +1075,7 @@ static void command_line_next_incsearch(CommandLineState *s, bool next_match)
|
||||
int found = searchit(curwin, curbuf, &t, NULL,
|
||||
next_match ? FORWARD : BACKWARD,
|
||||
pat, s->count, search_flags,
|
||||
RE_SEARCH, 0, NULL, NULL);
|
||||
RE_SEARCH, NULL);
|
||||
emsg_off--;
|
||||
ui_busy_stop();
|
||||
if (found) {
|
||||
@ -1818,6 +1818,7 @@ static int command_line_changed(CommandLineState *s)
|
||||
if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) {
|
||||
pos_T end_pos;
|
||||
proftime_T tm;
|
||||
searchit_arg_T sia;
|
||||
|
||||
// if there is a character waiting, search and redraw later
|
||||
if (char_avail()) {
|
||||
@ -1844,8 +1845,10 @@ static int command_line_changed(CommandLineState *s)
|
||||
if (!p_hls) {
|
||||
search_flags += SEARCH_KEEP;
|
||||
}
|
||||
memset(&sia, 0, sizeof(sia));
|
||||
sia.sa_tm = &tm;
|
||||
i = do_search(NULL, s->firstc, ccline.cmdbuff, s->count,
|
||||
search_flags, &tm, NULL);
|
||||
search_flags, &sia);
|
||||
emsg_off--;
|
||||
// if interrupted while searching, behave like it failed
|
||||
if (got_int) {
|
||||
|
@ -3794,7 +3794,7 @@ find_decl (
|
||||
valid = false;
|
||||
(void)valid; // Avoid "dead assignment" warning.
|
||||
t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD,
|
||||
pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL, NULL);
|
||||
pat, 1L, searchflags, RE_LAST, NULL);
|
||||
if (curwin->w_cursor.lnum >= old_pos.lnum) {
|
||||
t = false; // match after start is failure too
|
||||
}
|
||||
@ -4936,7 +4936,8 @@ static void nv_ident(cmdarg_T *cap)
|
||||
/* put pattern in search history */
|
||||
init_history();
|
||||
add_to_history(HIST_SEARCH, (char_u *)buf, true, NUL);
|
||||
(void)normal_search(cap, cmdchar == '*' ? '/' : '?', (char_u *)buf, 0);
|
||||
(void)normal_search(cap, cmdchar == '*' ? '/' : '?', (char_u *)buf, 0,
|
||||
NULL);
|
||||
} else {
|
||||
g_tag_at_cursor = true;
|
||||
do_cmdline_cmd(buf);
|
||||
@ -5363,7 +5364,7 @@ static void nv_search(cmdarg_T *cap)
|
||||
|
||||
(void)normal_search(cap, cap->cmdchar, cap->searchbuf,
|
||||
(cap->arg || !equalpos(save_cursor, curwin->w_cursor))
|
||||
? 0 : SEARCH_MARK);
|
||||
? 0 : SEARCH_MARK, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5373,14 +5374,15 @@ static void nv_search(cmdarg_T *cap)
|
||||
static void nv_next(cmdarg_T *cap)
|
||||
{
|
||||
pos_T old = curwin->w_cursor;
|
||||
int i = normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg);
|
||||
int wrapped = false;
|
||||
int i = normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg, &wrapped);
|
||||
|
||||
if (i == 1 && equalpos(old, curwin->w_cursor)) {
|
||||
if (i == 1 && !wrapped && equalpos(old, curwin->w_cursor)) {
|
||||
// Avoid getting stuck on the current cursor position, which can happen when
|
||||
// an offset is given and the cursor is on the last char in the buffer:
|
||||
// Repeat with count + 1.
|
||||
cap->count1 += 1;
|
||||
(void)normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg);
|
||||
(void)normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg, NULL);
|
||||
cap->count1 -= 1;
|
||||
}
|
||||
}
|
||||
@ -5394,18 +5396,24 @@ static int normal_search(
|
||||
cmdarg_T *cap,
|
||||
int dir,
|
||||
char_u *pat,
|
||||
int opt /* extra flags for do_search() */
|
||||
int opt, // extra flags for do_search()
|
||||
int *wrapped
|
||||
)
|
||||
{
|
||||
int i;
|
||||
searchit_arg_T sia;
|
||||
|
||||
cap->oap->motion_type = kMTCharWise;
|
||||
cap->oap->inclusive = false;
|
||||
cap->oap->use_reg_one = true;
|
||||
curwin->w_set_curswant = true;
|
||||
|
||||
memset(&sia, 0, sizeof(sia));
|
||||
i = do_search(cap->oap, dir, pat, cap->count1,
|
||||
opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL, NULL);
|
||||
opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia);
|
||||
if (wrapped != NULL) {
|
||||
*wrapped = sia.sa_wrapped;
|
||||
}
|
||||
if (i == 0) {
|
||||
clearop(cap->oap);
|
||||
} else {
|
||||
|
@ -2463,7 +2463,7 @@ static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char_u qf_viscol,
|
||||
// Move the cursor to the first line in the buffer
|
||||
pos_T save_cursor = curwin->w_cursor;
|
||||
curwin->w_cursor.lnum = 0;
|
||||
if (!do_search(NULL, '/', qf_pattern, (long)1, SEARCH_KEEP, NULL, NULL)) {
|
||||
if (!do_search(NULL, '/', qf_pattern, (long)1, SEARCH_KEEP, NULL)) {
|
||||
curwin->w_cursor = save_cursor;
|
||||
}
|
||||
}
|
||||
|
@ -516,19 +516,17 @@ void last_pat_prog(regmmatch_T *regmatch)
|
||||
/// the index of the first matching
|
||||
/// subpattern plus one; one if there was none.
|
||||
int searchit(
|
||||
win_T *win, /* window to search in, can be NULL for a
|
||||
buffer without a window! */
|
||||
win_T *win, // window to search in; can be NULL for a
|
||||
// buffer without a window!
|
||||
buf_T *buf,
|
||||
pos_T *pos,
|
||||
pos_T *end_pos, // set to end of the match, unless NULL
|
||||
pos_T *end_pos, // set to end of the match, unless NULL
|
||||
Direction dir,
|
||||
char_u *pat,
|
||||
long count,
|
||||
int options,
|
||||
int pat_use, // which pattern to use when "pat" is empty
|
||||
linenr_T stop_lnum, // stop after this line number when != 0
|
||||
proftime_T *tm, // timeout limit or NULL
|
||||
int *timed_out // set when timed out or NULL
|
||||
int pat_use, // which pattern to use when "pat" is empty
|
||||
searchit_arg_T *extra_arg // optional extra arguments, can be NULL
|
||||
)
|
||||
{
|
||||
int found;
|
||||
@ -548,7 +546,16 @@ int searchit(
|
||||
int submatch = 0;
|
||||
bool first_match = true;
|
||||
int save_called_emsg = called_emsg;
|
||||
int break_loop = FALSE;
|
||||
int break_loop = false;
|
||||
linenr_T stop_lnum = 0; // stop after this line number when != 0
|
||||
proftime_T *tm = NULL; // timeout limit or NULL
|
||||
int *timed_out = NULL; // set when timed out or NULL
|
||||
|
||||
if (extra_arg != NULL) {
|
||||
stop_lnum = extra_arg->sa_stop_lnum;
|
||||
tm = extra_arg->sa_tm;
|
||||
timed_out = &extra_arg->sa_timed_out;
|
||||
}
|
||||
|
||||
if (search_regcomp(pat, RE_SEARCH, pat_use,
|
||||
(options & (SEARCH_HIS + SEARCH_KEEP)), ®match) == FAIL) {
|
||||
@ -889,6 +896,9 @@ int searchit(
|
||||
give_warning((char_u *)_(dir == BACKWARD
|
||||
? top_bot_msg : bot_top_msg), true);
|
||||
}
|
||||
if (extra_arg != NULL) {
|
||||
extra_arg->sa_wrapped = true;
|
||||
}
|
||||
}
|
||||
if (got_int || called_emsg
|
||||
|| (timed_out != NULL && *timed_out)
|
||||
@ -983,8 +993,7 @@ int do_search(
|
||||
char_u *pat,
|
||||
long count,
|
||||
int options,
|
||||
proftime_T *tm, // timeout limit or NULL
|
||||
int *timed_out // flag set on timeout or NULL
|
||||
searchit_arg_T *sia // optional arguments or NULL
|
||||
)
|
||||
{
|
||||
pos_T pos; /* position of the last match */
|
||||
@ -1271,7 +1280,7 @@ int do_search(
|
||||
& (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG
|
||||
+ SEARCH_START
|
||||
+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF)))),
|
||||
RE_LAST, (linenr_T)0, tm, timed_out);
|
||||
RE_LAST, sia);
|
||||
|
||||
if (dircp != NULL) {
|
||||
*dircp = dirc; // restore second '/' or '?' for normal_cmd()
|
||||
@ -4040,23 +4049,20 @@ current_search(
|
||||
pos_T pos; // position after the pattern
|
||||
int result; // result of various function calls
|
||||
|
||||
orig_pos = pos = curwin->w_cursor;
|
||||
if (VIsual_active) {
|
||||
orig_pos = pos = curwin->w_cursor;
|
||||
|
||||
// Searching further will extend the match.
|
||||
if (forward) {
|
||||
incl(&pos);
|
||||
} else {
|
||||
decl(&pos);
|
||||
}
|
||||
} else {
|
||||
orig_pos = pos = curwin->w_cursor;
|
||||
}
|
||||
|
||||
// Is the pattern is zero-width?, this time, don't care about the direction
|
||||
int one_char = is_one_char(spats[last_idx].pat, true, &curwin->w_cursor,
|
||||
FORWARD);
|
||||
if (one_char == -1) {
|
||||
int zero_width = is_zero_width(spats[last_idx].pat, true, &curwin->w_cursor,
|
||||
FORWARD);
|
||||
if (zero_width == -1) {
|
||||
p_ws = old_p_ws;
|
||||
return FAIL; /* pattern not found */
|
||||
}
|
||||
@ -4070,7 +4076,7 @@ current_search(
|
||||
int dir = forward ? i : !i;
|
||||
int flags = 0;
|
||||
|
||||
if (!dir && !one_char) {
|
||||
if (!dir && !zero_width) {
|
||||
flags = SEARCH_END;
|
||||
}
|
||||
end_pos = pos;
|
||||
@ -4078,7 +4084,7 @@ current_search(
|
||||
result = searchit(curwin, curbuf, &pos, &end_pos,
|
||||
(dir ? FORWARD : BACKWARD),
|
||||
spats[last_idx].pat, i ? count : 1,
|
||||
SEARCH_KEEP | flags, RE_SEARCH, 0, NULL, NULL);
|
||||
SEARCH_KEEP | flags, RE_SEARCH, NULL);
|
||||
|
||||
// First search may fail, but then start searching from the
|
||||
// beginning of the file (cursor might be on the search match)
|
||||
@ -4100,7 +4106,6 @@ current_search(
|
||||
ml_get(curwin->w_buffer->b_ml.ml_line_count));
|
||||
}
|
||||
}
|
||||
p_ws = old_p_ws;
|
||||
}
|
||||
|
||||
pos_T start_pos = pos;
|
||||
@ -4113,13 +4118,14 @@ current_search(
|
||||
|
||||
// put cursor on last character of match
|
||||
curwin->w_cursor = end_pos;
|
||||
if (lt(VIsual, end_pos)) {
|
||||
if (lt(VIsual, end_pos) && forward) {
|
||||
dec_cursor();
|
||||
} else if (VIsual_active && lt(curwin->w_cursor, VIsual)) {
|
||||
curwin->w_cursor = pos; // put the cursor on the start of the match
|
||||
}
|
||||
VIsual_active = true;
|
||||
VIsual_mode = 'v';
|
||||
|
||||
redraw_curbuf_later(INVERTED); // Update the inversion.
|
||||
if (*p_sel == 'e') {
|
||||
// Correction for exclusive selection depends on the direction.
|
||||
if (forward && ltoreq(VIsual, curwin->w_cursor)) {
|
||||
@ -4141,13 +4147,13 @@ current_search(
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Check if the pattern is one character long or zero-width.
|
||||
/// Check if the pattern is zero-width.
|
||||
/// If move is true, check from the beginning of the buffer,
|
||||
/// else from position "cur".
|
||||
/// "direction" is FORWARD or BACKWARD.
|
||||
/// Returns TRUE, FALSE or -1 for failure.
|
||||
static int is_one_char(char_u *pattern, bool move, pos_T *cur,
|
||||
Direction direction)
|
||||
static int
|
||||
is_zero_width(char_u *pattern, int move, pos_T *cur, Direction direction)
|
||||
{
|
||||
regmmatch_T regmatch;
|
||||
int nmatched = 0;
|
||||
@ -4175,7 +4181,7 @@ static int is_one_char(char_u *pattern, bool move, pos_T *cur,
|
||||
flag = SEARCH_START;
|
||||
}
|
||||
if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
|
||||
SEARCH_KEEP + flag, RE_SEARCH, 0, NULL, NULL) != FAIL) {
|
||||
SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL) {
|
||||
// Zero-width pattern should match somewhere, then we can check if
|
||||
// start and end are in the same position.
|
||||
called_emsg = false;
|
||||
@ -4195,13 +4201,6 @@ static int is_one_char(char_u *pattern, bool move, pos_T *cur,
|
||||
result = (nmatched != 0
|
||||
&& regmatch.startpos[0].lnum == regmatch.endpos[0].lnum
|
||||
&& regmatch.startpos[0].col == regmatch.endpos[0].col);
|
||||
// one char width
|
||||
if (!result
|
||||
&& nmatched != 0
|
||||
&& inc(&pos) >= 0
|
||||
&& pos.col == regmatch.endpos[0].col) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4265,7 +4264,7 @@ static void search_stat(int dirc, pos_T *pos,
|
||||
start = profile_setlimit(20L);
|
||||
while (!got_int && searchit(curwin, curbuf, &lastpos, NULL,
|
||||
FORWARD, NULL, 1, SEARCH_KEEP, RE_LAST,
|
||||
(linenr_T)0, NULL, NULL) != FAIL) {
|
||||
NULL) != FAIL) {
|
||||
// Stop after passing the time limit.
|
||||
if (profile_passed_limit(start)) {
|
||||
cnt = OUT_OF_TIME;
|
||||
|
@ -70,6 +70,15 @@ typedef struct spat {
|
||||
dict_T *additional_data; ///< Additional data from ShaDa file.
|
||||
} SearchPattern;
|
||||
|
||||
/// Optional extra arguments for searchit().
|
||||
typedef struct {
|
||||
linenr_T sa_stop_lnum; ///< stop after this line number when != 0
|
||||
proftime_T *sa_tm; ///< timeout limit or NULL
|
||||
int sa_timed_out; ///< set when timed out
|
||||
int sa_wrapped; ///< search wrapped around
|
||||
} searchit_arg_T;
|
||||
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "search.h.generated.h"
|
||||
#endif
|
||||
|
@ -3031,7 +3031,7 @@ void ex_spellrepall(exarg_T *eap)
|
||||
sub_nlines = 0;
|
||||
curwin->w_cursor.lnum = 0;
|
||||
while (!got_int) {
|
||||
if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL, NULL) == 0
|
||||
if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
|
||||
|| u_save_cursor() == FAIL) {
|
||||
break;
|
||||
}
|
||||
|
@ -2813,7 +2813,7 @@ static int jumpto_tag(
|
||||
save_lnum = curwin->w_cursor.lnum;
|
||||
curwin->w_cursor.lnum = 0; /* start search before first line */
|
||||
if (do_search(NULL, pbuf[0], pbuf + 1, (long)1,
|
||||
search_options, NULL, NULL)) {
|
||||
search_options, NULL)) {
|
||||
retval = OK;
|
||||
} else {
|
||||
int found = 1;
|
||||
@ -2824,20 +2824,18 @@ static int jumpto_tag(
|
||||
*/
|
||||
p_ic = TRUE;
|
||||
if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
|
||||
search_options, NULL, NULL)) {
|
||||
search_options, NULL)) {
|
||||
// Failed to find pattern, take a guess: "^func ("
|
||||
found = 2;
|
||||
(void)test_for_static(&tagp);
|
||||
cc = *tagp.tagname_end;
|
||||
*tagp.tagname_end = NUL;
|
||||
snprintf((char *)pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
|
||||
if (!do_search(NULL, '/', pbuf, (long)1,
|
||||
search_options, NULL, NULL)) {
|
||||
if (!do_search(NULL, '/', pbuf, (long)1, search_options, NULL)) {
|
||||
// Guess again: "^char * \<func ("
|
||||
snprintf((char *)pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
|
||||
tagp.tagname);
|
||||
if (!do_search(NULL, '/', pbuf, (long)1,
|
||||
search_options, NULL, NULL)) {
|
||||
if (!do_search(NULL, '/', pbuf, (long)1, search_options, NULL)) {
|
||||
found = 0;
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +129,32 @@ func Test_gn_command()
|
||||
call assert_equal([' nnoremap', '', 'match'], getline(1,'$'))
|
||||
sil! %d_
|
||||
|
||||
" make sure it works correctly for one-char wide search items
|
||||
call setline('.', ['abcdefghi'])
|
||||
let @/ = 'a'
|
||||
exe "norm! 0fhvhhgNgU"
|
||||
call assert_equal(['ABCDEFGHi'], getline(1,'$'))
|
||||
call setline('.', ['abcdefghi'])
|
||||
let @/ = 'b'
|
||||
exe "norm! 0fhvhhgngU"
|
||||
call assert_equal(['abcdefghi'], getline(1,'$'))
|
||||
sil! %d _
|
||||
call setline('.', ['abcdefghi'])
|
||||
let @/ = 'f'
|
||||
exe "norm! 0vllgngU"
|
||||
call assert_equal(['ABCDEFghi'], getline(1,'$'))
|
||||
sil! %d _
|
||||
call setline('.', ['12345678'])
|
||||
let @/ = '5'
|
||||
norm! gg0f7vhhhhgnd
|
||||
call assert_equal(['12348'], getline(1,'$'))
|
||||
sil! %d _
|
||||
call setline('.', ['12345678'])
|
||||
let @/ = '5'
|
||||
norm! gg0f2vf7gNd
|
||||
call assert_equal(['1678'], getline(1,'$'))
|
||||
sil! %d _
|
||||
|
||||
set wrapscan&vim
|
||||
set belloff&vim
|
||||
endfu
|
||||
|
@ -68,6 +68,9 @@ NULL
|
||||
|
||||
// clang-format off
|
||||
static const int included_patches[] = {
|
||||
2218,
|
||||
2207,
|
||||
2173,
|
||||
1850,
|
||||
1849,
|
||||
1848,
|
||||
|
Reference in New Issue
Block a user