Patch 8.1.2207
Problem: "gn" doesn't work quite right. (Jaehwang Jerry Jung)
Solution: Improve and simplify the search logic. (Christian Brabandt,
closes #5103, closes #5075)
Files: src/search.c, src/testdir/test_gn.vim
*** ../vim-8.1.2206/src/search.c 2019-10-19 14:34:58.122164179 +0200
--- src/search.c 2019-10-24 15:18:21.358971106 +0200
***************
*** 4676,4682 ****
#endif /* FEAT_TEXTOBJ */
! static int is_one_char(char_u *pattern, int move, pos_T *cur, int direction);
/*
* Find next search match under cursor, cursor at end.
--- 4676,4748 ----
#endif /* FEAT_TEXTOBJ */
! /*
! * Check if the pattern is one character long or 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_zero_width(char_u *pattern, int move, pos_T *cur, int direction)
! {
! regmmatch_T regmatch;
! int nmatched = 0;
! int result = -1;
! pos_T pos;
! int save_called_emsg = called_emsg;
! int flag = 0;
!
! if (pattern == NULL)
! pattern = spats[last_idx].pat;
!
! if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH,
! SEARCH_KEEP, ®match) == FAIL)
! return -1;
!
! // init startcol correctly
! regmatch.startpos[0].col = -1;
! // move to match
! if (move)
! {
! CLEAR_POS(&pos);
! }
! else
! {
! pos = *cur;
! // accept a match at the cursor position
! flag = SEARCH_START;
! }
!
! if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
! 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;
! do
! {
! regmatch.startpos[0].col++;
! nmatched = vim_regexec_multi(®match, curwin, curbuf,
! pos.lnum, regmatch.startpos[0].col, NULL, NULL);
! if (nmatched != 0)
! break;
! } while (direction == FORWARD ? regmatch.startpos[0].col < pos.col
! : regmatch.startpos[0].col > pos.col);
!
! if (!called_emsg)
! {
! result = (nmatched != 0
! && regmatch.startpos[0].lnum == regmatch.endpos[0].lnum
! && regmatch.startpos[0].col == regmatch.endpos[0].col);
! }
! }
!
! called_emsg |= save_called_emsg;
! vim_regfree(regmatch.regprog);
! return result;
! }
!
/*
* Find next search match under cursor, cursor at end.
***************
*** 4697,4703 ****
char_u old_p_ws = p_ws;
int flags = 0;
pos_T save_VIsual = VIsual;
! int one_char;
/* wrapping should not occur */
p_ws = FALSE;
--- 4763,4769 ----
char_u old_p_ws = p_ws;
int flags = 0;
pos_T save_VIsual = VIsual;
! int zero_width;
/* wrapping should not occur */
p_ws = FALSE;
***************
*** 4706,4734 ****
if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor))
dec_cursor();
if (VIsual_active)
{
! orig_pos = curwin->w_cursor;
!
! pos = curwin->w_cursor;
!
! /* make sure, searching further will extend the match */
! if (VIsual_active)
! {
! 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
*/
! one_char = is_one_char(spats[last_idx].pat, TRUE, &curwin->w_cursor,
FORWARD);
! if (one_char == -1)
{
p_ws = old_p_ws;
return FAIL; /* pattern not found */
--- 4772,4791 ----
if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor))
dec_cursor();
+ orig_pos = pos = curwin->w_cursor;
if (VIsual_active)
{
! if (forward)
! incl(&pos);
! else
! decl(&pos);
}
/* Is the pattern is zero-width?, this time, don't care about the direction
*/
! 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 */
***************
*** 4747,4753 ****
dir = !i;
flags = 0;
! if (!dir && !one_char)
flags = SEARCH_END;
end_pos = pos;
--- 4804,4810 ----
dir = !i;
flags = 0;
! if (!dir && !zero_width)
flags = SEARCH_END;
end_pos = pos;
***************
*** 4784,4790 ****
ml_get(curwin->w_buffer->b_ml.ml_line_count));
}
}
- p_ws = old_p_ws;
}
start_pos = pos;
--- 4841,4846 ----
***************
*** 4797,4806 ****
curwin->w_cursor = end_pos;
if (LT_POS(VIsual, end_pos))
dec_cursor();
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. */
--- 4853,4863 ----
curwin->w_cursor = end_pos;
if (LT_POS(VIsual, end_pos))
dec_cursor();
+ else if (VIsual_active && LT_POS(curwin->w_cursor, VIsual))
+ curwin->w_cursor = pos; // put the cursor on the start of the match
VIsual_active = TRUE;
VIsual_mode = 'v';
if (*p_sel == 'e')
{
/* Correction for exclusive selection depends on the direction. */
***************
*** 4828,4904 ****
return OK;
}
- /*
- * Check if the pattern is one character long or 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, int move, pos_T *cur, int direction)
- {
- regmmatch_T regmatch;
- int nmatched = 0;
- int result = -1;
- pos_T pos;
- int save_called_emsg = called_emsg;
- int flag = 0;
-
- if (pattern == NULL)
- pattern = spats[last_idx].pat;
-
- if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH,
- SEARCH_KEEP, ®match) == FAIL)
- return -1;
-
- /* init startcol correctly */
- regmatch.startpos[0].col = -1;
- /* move to match */
- if (move)
- {
- CLEAR_POS(&pos);
- }
- else
- {
- pos = *cur;
- /* accept a match at the cursor position */
- flag = SEARCH_START;
- }
-
- if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
- 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;
- do
- {
- regmatch.startpos[0].col++;
- nmatched = vim_regexec_multi(®match, curwin, curbuf,
- pos.lnum, regmatch.startpos[0].col, NULL, NULL);
- if (nmatched != 0)
- break;
- } while (direction == FORWARD ? regmatch.startpos[0].col < pos.col
- : regmatch.startpos[0].col > pos.col);
-
- if (!called_emsg)
- {
- 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;
- }
- }
-
- called_emsg |= save_called_emsg;
- vim_regfree(regmatch.regprog);
- return result;
- }
-
#if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(FEAT_TEXTOBJ) \
|| defined(PROTO)
/*
--- 4885,4890 ----
*** ../vim-8.1.2206/src/testdir/test_gn.vim 2019-04-20 23:47:42.518391308 +0200
--- src/testdir/test_gn.vim 2019-10-24 15:17:09.415102003 +0200
***************
*** 128,133 ****
--- 128,154 ----
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 _
+
set wrapscan&vim
endfu
*** ../vim-8.1.2206/src/version.c 2019-10-24 15:12:20.299934958 +0200
--- src/version.c 2019-10-24 15:16:27.895167951 +0200
***************
*** 743,744 ****
--- 743,746 ----
{ /* Add new patch number below this line */
+ /**/
+ 2207,
/**/
--
BEDEVERE: And what do you burn, apart from witches?
FOURTH VILLAGER: ... Wood?
BEDEVERE: So why do witches burn?
SECOND VILLAGER: (pianissimo) ... Because they're made of wood...?
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language --
http://www.Zimbu.org ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///