# HG changeset patch # User Christian Brabandt # Date 1472930106 -7200 # Node ID 72e4b7f904650787eb5fab4b3ee39de5ac2b3d8d # Parent 26ade1c95bd940b296eb81a07f47b1407bb0162c commit https://github.com/vim/vim/commit/dda933d06c06c2792bd686d059f6ad19191ad30b Author: Bram Moolenaar Date: Sat Sep 3 21:04:58 2016 +0200 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. diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -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,7 +1696,7 @@ getcmdline( --emsg_off; if (i) { - old_cursor = match_start; + search_start = match_start; match_end = t; match_start = t; if (c == Ctrl_T && firstc == '/') @@ -1693,17 +1704,17 @@ getcmdline( /* 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 @@ cmdline_changed: 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 @@ returncmd: #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; diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -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); } /* diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -31,6 +31,7 @@ func Test_search_cmdline() " second match call feedkeys("/the\\", 'tx') call assert_equal(' 3 the', getline('.')) + call assert_equal([0, 0, 0, 0], getpos('"')) :1 " third match call feedkeys("/the".repeat("\", 2)."\", 'tx') @@ -59,6 +60,7 @@ func Test_search_cmdline() " no further match call feedkeys("/the".repeat("\", 8)."\", '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\s\", '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\s\\\\", '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("\",4).'the\>'."\", 'tx') @@ -236,7 +238,33 @@ func Test_search_cmdline2() call feedkeys("/the\\\\\\\", '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\\", '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\\", nor "/foo\\\\", + " nor "/foo\\" 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\\", '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 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2320, +/**/ 2319, /**/ 2318,