Permalink
Browse files

patch 7.4.2320

Problem:    Redraw problem when using 'incsearch'.
Solution:   Save the current view when deleting characters. (Christian
            Brabandt) Fix that the '" mark is set in the wrong position. Don't
            change the search start when using BS.
  • Loading branch information...
1 parent b07a82b commit dda933d06c06c2792bd686d059f6ad19191ad30b @brammool brammool committed Sep 3, 2016
Showing with 78 additions and 24 deletions.
  1. +41 −21 src/ex_getln.c
  2. +5 −1 src/normal.c
  3. +30 −2 src/testdir/test_search.vim
  4. +2 −0 src/version.c
View
@@ -177,17 +177,22 @@ getcmdline(
int histype; /* history type to be used */
#endif
#ifdef FEAT_SEARCH_EXTRA
- pos_T old_cursor;
+ pos_T search_start; /* where 'incsearch' starts searching */
+ pos_T save_cursor;
colnr_T old_curswant;
+ colnr_T init_curswant = curwin->w_curswant;
colnr_T old_leftcol;
+ colnr_T init_leftcol = curwin->w_leftcol;
linenr_T old_topline;
- pos_T cursor_start;
+ linenr_T init_topline = curwin->w_topline;
pos_T match_start = curwin->w_cursor;
pos_T match_end;
# ifdef FEAT_DIFF
int old_topfill;
+ int init_topfill = curwin->w_topfill;
# endif
linenr_T old_botline;
+ linenr_T init_botline = curwin->w_botline;
int did_incsearch = FALSE;
int incsearch_postponed = FALSE;
#endif
@@ -230,8 +235,8 @@ getcmdline(
ccline.overstrike = FALSE; /* always start in insert mode */
#ifdef FEAT_SEARCH_EXTRA
clearpos(&match_end);
- old_cursor = curwin->w_cursor; /* needs to be restored later */
- cursor_start = old_cursor;
+ save_cursor = curwin->w_cursor; /* may be restored later */
+ search_start = curwin->w_cursor;
old_curswant = curwin->w_curswant;
old_leftcol = curwin->w_leftcol;
old_topline = curwin->w_topline;
@@ -1006,11 +1011,17 @@ getcmdline(
ccline.cmdbuff[ccline.cmdlen] = NUL;
#ifdef FEAT_SEARCH_EXTRA
if (ccline.cmdlen == 0)
- old_cursor = cursor_start;
- else
{
- old_cursor = match_start;
- decl(&old_cursor);
+ search_start = save_cursor;
+ /* save view settings, so that the screen
+ * won't be restored at the wrong position */
+ old_curswant = init_curswant;
+ old_leftcol = init_leftcol;
+ old_topline = init_topline;
+# ifdef FEAT_DIFF
+ old_topfill = init_topfill;
+# endif
+ old_botline = init_botline;
}
#endif
redrawcmd();
@@ -1040,7 +1051,7 @@ getcmdline(
}
#ifdef FEAT_SEARCH_EXTRA
if (ccline.cmdlen == 0)
- old_cursor = cursor_start;
+ search_start = save_cursor;
#endif
redraw_cmdline = TRUE;
goto returncmd; /* back to cmd mode */
@@ -1127,7 +1138,7 @@ getcmdline(
ccline.cmdbuff[ccline.cmdlen] = NUL;
#ifdef FEAT_SEARCH_EXTRA
if (ccline.cmdlen == 0)
- old_cursor = cursor_start;
+ search_start = save_cursor;
#endif
redrawcmd();
goto cmdline_changed;
@@ -1468,7 +1479,7 @@ getcmdline(
if (did_incsearch)
{
curwin->w_cursor = match_end;
- if (!equalpos(curwin->w_cursor, old_cursor))
+ if (!equalpos(curwin->w_cursor, search_start))
{
c = gchar_cursor();
/* If 'ignorecase' and 'smartcase' are set and the
@@ -1685,25 +1696,25 @@ getcmdline(
--emsg_off;
if (i)
{
- old_cursor = match_start;
+ search_start = match_start;
match_end = t;
match_start = t;
if (c == Ctrl_T && firstc == '/')
{
/* move just before the current match, so that
* when nv_search finishes the cursor will be
* put back on the match */
- old_cursor = t;
- (void)decl(&old_cursor);
+ search_start = t;
+ (void)decl(&search_start);
}
- if (lt(t, old_cursor) && c == Ctrl_G)
+ if (lt(t, search_start) && c == Ctrl_G)
{
/* wrap around */
- old_cursor = t;
+ search_start = t;
if (firstc == '?')
- (void)incl(&old_cursor);
+ (void)incl(&search_start);
else
- (void)decl(&old_cursor);
+ (void)decl(&search_start);
}
set_search_match(&match_end);
@@ -1870,7 +1881,7 @@ getcmdline(
continue;
}
incsearch_postponed = FALSE;
- curwin->w_cursor = old_cursor; /* start at old position */
+ curwin->w_cursor = search_start; /* start at old position */
/* If there is no command line, don't do anything */
if (ccline.cmdlen == 0)
@@ -1988,9 +1999,18 @@ getcmdline(
#ifdef FEAT_SEARCH_EXTRA
if (did_incsearch)
{
- curwin->w_cursor = old_cursor;
if (gotesc)
- curwin->w_cursor = cursor_start;
+ curwin->w_cursor = save_cursor;
+ else
+ {
+ if (!equalpos(save_cursor, search_start))
+ {
+ /* put the '" mark at the original position */
+ curwin->w_cursor = save_cursor;
+ setpcmark();
+ }
+ curwin->w_cursor = search_start;
+ }
curwin->w_curswant = old_curswant;
curwin->w_leftcol = old_leftcol;
curwin->w_topline = old_topline;
View
@@ -6228,6 +6228,7 @@ nv_dollar(cmdarg_T *cap)
nv_search(cmdarg_T *cap)
{
oparg_T *oap = cap->oap;
+ pos_T save_cursor = curwin->w_cursor;
if (cap->cmdchar == '?' && cap->oap->op_type == OP_ROT13)
{
@@ -6238,6 +6239,8 @@ nv_search(cmdarg_T *cap)
return;
}
+ /* When using 'incsearch' the cursor may be moved to set a different search
+ * start position. */
cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0);
if (cap->searchbuf == NULL)
@@ -6247,7 +6250,8 @@ nv_search(cmdarg_T *cap)
}
(void)normal_search(cap, cap->cmdchar, cap->searchbuf,
- (cap->arg ? 0 : SEARCH_MARK));
+ (cap->arg || !equalpos(save_cursor, curwin->w_cursor))
+ ? 0 : SEARCH_MARK);
}
/*
@@ -31,6 +31,7 @@ func Test_search_cmdline()
" second match
call feedkeys("/the\<C-G>\<cr>", 'tx')
call assert_equal(' 3 the', getline('.'))
+ call assert_equal([0, 0, 0, 0], getpos('"'))
:1
" third match
call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
@@ -59,6 +60,7 @@ func Test_search_cmdline()
" no further match
call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
call assert_equal(' 9 these', getline('.'))
+ call assert_equal([0, 0, 0, 0], getpos('"'))
" Test 3
" Ctrl-G goes from one match to the next
@@ -180,11 +182,11 @@ func Test_search_cmdline()
1
" delete one char, add another
call feedkeys("/thei\<bs>s\<cr>", 'tx')
- call assert_equal(' 9 these', getline('.'))
+ call assert_equal(' 2 these', getline('.'))
1
" delete one char, add another, go to previous match, add one char
call feedkeys("/thei\<bs>s\<bs>\<C-T>\<c-l>\<cr>", 'tx')
- call assert_equal(' 8 them', getline('.'))
+ call assert_equal(' 9 these', getline('.'))
1
" delete all chars, start from the beginning again
call feedkeys("/them". repeat("\<bs>",4).'the\>'."\<cr>", 'tx')
@@ -236,7 +238,33 @@ func Test_search_cmdline2()
call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<C-T>\<cr>", 'tx')
call assert_equal(' 2 these', getline('.'))
+ " Test 2: keep the view,
+ " after deleting a character from the search cmd
+ call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar'])
+ resize 5
+ 1
+ call feedkeys("/foo\<bs>\<cr>", 'tx')
+ redraw
+ call assert_equal({'lnum': 10, 'leftcol': 0, 'col': 4, 'topfill': 0, 'topline': 6, 'coladd': 0, 'skipcol': 0, 'curswant': 4}, winsaveview())
+
+ " remove all history entries
+ for i in range(10)
+ call histdel('/')
+ endfor
+
+ " Test 3: reset the view,
+ " after deleting all characters from the search cmd
+ norm! 1gg0
+ " unfortunately, neither "/foo\<c-w>\<cr>", nor "/foo\<bs>\<bs>\<bs>\<cr>",
+ " nor "/foo\<c-u>\<cr>" works to delete the commandline.
+ " In that case Vim should return "E35 no previous regular expression",
+ " but it looks like Vim still sees /foo and therefore the test fails.
+ " Therefore, disableing this test
+ "call assert_fails(feedkeys("/foo\<c-w>\<cr>", 'tx'), 'E35')
+ "call assert_equal({'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0}, winsaveview())
+
" clean up
+ set noincsearch
call test_disable_char_avail(0)
bw!
endfunc
View
@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2320,
+/**/
2319,
/**/
2318,

0 comments on commit dda933d

Please sign in to comment.