Patch 7.4.2259
Problem: With 'incsearch' can only see the next match.
Solution: Make CTRL-N/CTRL-P move to the previous/next match. (Christian
Brabandt)
Files: runtime/doc/cmdline.txt, src/ex_getln.c, src/testdir/Make_all.mak,
src/testdir/test_search.vim, src/Makefile
*** ../vim-7.4.2258/runtime/doc/cmdline.txt 2015-09-08 18:46:04.337233673
+0200
--- runtime/doc/cmdline.txt 2016-08-26 18:56:26.060363506 +0200
***************
*** 404,414 ****
--- 409,427 ----
*c_CTRL-N*
CTRL-N After using 'wildchar' which got multiple matches, go
to next
match. Otherwise recall more recent command-line from history.
+ */_CTRL-N*
+ When 'incsearch' is set, entering a search pattern for "/" or
+ "?" and the current match is displayed then CTRL-N will move
+ to the next match (does not take |search-offset| into account)
<S-Tab> *c_CTRL-P*
*c_<S-Tab>*
CTRL-P After using 'wildchar' which got multiple matches, go to
previous match. Otherwise recall older command-line from
history. <S-Tab> only works with the GUI, on the Amiga and
with MS-DOS.
+ */_CTRL-P*
+ When 'incsearch' is set, entering a search pattern for "/" or
+ "?" and the current match is displayed then CTRL-P will move
+ to the previous match (does not take |search-offset| into
account).
*c_CTRL-A*
CTRL-A All names that match the pattern in front of the cursor
are
inserted.
*** ../vim-7.4.2258/src/ex_getln.c 2016-07-10 22:11:11.866751401 +0200
--- src/ex_getln.c 2016-08-26 19:03:54.320578262 +0200
***************
*** 137,142 ****
--- 137,145 ----
#endif
sort_func_compare(const void *s1, const void *s2);
#endif
+ #ifdef FEAT_SEARCH_EXTRA
+ static void set_search_match(pos_T *t);
+ #endif
/*
* getcmdline() - accept a command line starting with firstc.
***************
*** 178,183 ****
--- 181,189 ----
colnr_T old_curswant;
colnr_T old_leftcol;
linenr_T old_topline;
+ pos_T cursor_start;
+ pos_T match_start = curwin->w_cursor;
+ pos_T match_end;
# ifdef FEAT_DIFF
int old_topfill;
# endif
***************
*** 223,229 ****
--- 229,237 ----
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;
old_curswant = curwin->w_curswant;
old_leftcol = curwin->w_leftcol;
old_topline = curwin->w_topline;
***************
*** 996,1001 ****
--- 1004,1018 ----
/* Truncate at the end, required for multi-byte chars. */
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);
+ }
+ #endif
redrawcmd();
}
else if (ccline.cmdlen == 0 && c != Ctrl_W
***************
*** 1021,1026 ****
--- 1038,1047 ----
msg_col = 0;
msg_putchar(' '); /* delete ':' */
}
+ #ifdef FEAT_SEARCH_EXTRA
+ if (ccline.cmdlen == 0)
+ old_cursor = cursor_start;
+ #endif
redraw_cmdline = TRUE;
goto returncmd; /* back to cmd mode */
}
***************
*** 1104,1109 ****
--- 1125,1134 ----
ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
/* Truncate at the end, required for multi-byte chars. */
ccline.cmdbuff[ccline.cmdlen] = NUL;
+ #ifdef FEAT_SEARCH_EXTRA
+ if (ccline.cmdlen == 0)
+ old_cursor = cursor_start;
+ #endif
redrawcmd();
goto cmdline_changed;
***************
*** 1440,1465 ****
if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
{
/* Add a character from under the cursor for 'incsearch' */
! if (did_incsearch
! && !equalpos(curwin->w_cursor, old_cursor))
{
! c = gchar_cursor();
! /* If 'ignorecase' and 'smartcase' are set and the
! * command line has no uppercase characters, convert
! * the character to lowercase */
! if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff))
! c = MB_TOLOWER(c);
! if (c != NUL)
{
! if (c == firstc || vim_strchr((char_u *)(
! p_magic ? "\\^$.*[" : "\\^$"), c)
! != NULL)
{
! /* put a backslash before special characters */
! stuffcharReadbuff(c);
! c = '\\';
}
- break;
}
}
goto cmdline_not_changed;
--- 1465,1495 ----
if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
{
/* Add a character from under the cursor for 'incsearch' */
! if (did_incsearch)
{
! curwin->w_cursor = match_end;
! if (!equalpos(curwin->w_cursor, old_cursor))
{
! c = gchar_cursor();
! /* If 'ignorecase' and 'smartcase' are set and the
! * command line has no uppercase characters, convert
! * the character to lowercase */
! if (p_ic && p_scs
! && !pat_has_uppercase(ccline.cmdbuff))
! c = MB_TOLOWER(c);
! if (c != NUL)
{
! if (c == firstc || vim_strchr((char_u *)(
! p_magic ? "\\^$.*[" : "\\^$"), c)
! != NULL)
! {
! /* put a backslash before special
! * characters */
! stuffcharReadbuff(c);
! c = '\\';
! }
! break;
}
}
}
goto cmdline_not_changed;
***************
*** 1473,1479 ****
case Ctrl_N: /* next match */
case Ctrl_P: /* previous match */
! if (xpc.xp_numfiles > 0)
{
if (nextwild(&xpc, (c == Ctrl_P) ? WILD_PREV : WILD_NEXT,
0, firstc != '@') == FAIL)
--- 1503,1577 ----
case Ctrl_N: /* next match */
case Ctrl_P: /* previous match */
! #ifdef FEAT_SEARCH_EXTRA
! if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
! {
! pos_T t;
! int search_flags = SEARCH_KEEP + SEARCH_NOOF
! + SEARCH_PEEK;
!
! if (char_avail())
! continue;
! cursor_off();
! out_flush();
! if (c == Ctrl_N)
! {
! t = match_end;
! search_flags += SEARCH_COL;
! }
! else
! t = match_start;
! ++emsg_off;
! i = searchit(curwin, curbuf, &t,
! c == Ctrl_N ? FORWARD : BACKWARD,
! ccline.cmdbuff, count, search_flags,
! RE_SEARCH, 0, NULL);
! --emsg_off;
! if (i)
! {
! old_cursor = match_start;
! match_end = t;
! match_start = t;
! if (c == Ctrl_P && 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);
! }
! if (lt(t, old_cursor) && c == Ctrl_N)
! {
! /* wrap around */
! old_cursor = t;
! if (firstc == '?')
! (void)incl(&old_cursor);
! else
! (void)decl(&old_cursor);
! }
!
! set_search_match(&match_end);
! curwin->w_cursor = match_start;
! changed_cline_bef_curs();
! update_topline();
! validate_cursor();
! highlight_match = TRUE;
! old_curswant = curwin->w_curswant;
! old_leftcol = curwin->w_leftcol;
! old_topline = curwin->w_topline;
! # ifdef FEAT_DIFF
! old_topfill = curwin->w_topfill;
! # endif
! old_botline = curwin->w_botline;
! update_screen(NOT_VALID);
! redrawcmdline();
! }
! else
! vim_beep(BO_ERROR);
! goto cmdline_not_changed;
! }
! #endif
! else if (xpc.xp_numfiles > 0)
{
if (nextwild(&xpc, (c == Ctrl_P) ? WILD_PREV : WILD_NEXT,
0, firstc != '@') == FAIL)
***************
*** 1821,1839 ****
{
pos_T save_pos = curwin->w_cursor;
! /*
! * First move cursor to end of match, then to the start. This
! * moves the whole match onto the screen when 'nowrap' is set.
! */
! curwin->w_cursor.lnum += search_match_lines;
! curwin->w_cursor.col = search_match_endcol;
! if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
! {
! curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
! coladvance((colnr_T)MAXCOL);
! }
validate_cursor();
end_pos = curwin->w_cursor;
curwin->w_cursor = save_pos;
}
else
--- 1919,1929 ----
{
pos_T save_pos = curwin->w_cursor;
! match_start = curwin->w_cursor;
! set_search_match(&curwin->w_cursor);
validate_cursor();
end_pos = curwin->w_cursor;
+ match_end = end_pos;
curwin->w_cursor = save_pos;
}
else
***************
*** 1894,1899 ****
--- 1984,1991 ----
if (did_incsearch)
{
curwin->w_cursor = old_cursor;
+ if (gotesc)
+ curwin->w_cursor = cursor_start;
curwin->w_curswant = old_curswant;
curwin->w_leftcol = old_leftcol;
curwin->w_topline = old_topline;
***************
*** 6983,6985 ****
--- 7075,7095 ----
return (char_u *)ga.ga_data;
}
+
+ #ifdef FEAT_SEARCH_EXTRA
+ static void
+ set_search_match(pos_T *t)
+ {
+ /*
+ * First move cursor to end of match, then to the start. This
+ * moves the whole match onto the screen when 'nowrap' is set.
+ */
+ t->lnum += search_match_lines;
+ t->col = search_match_endcol;
+ if (t->lnum > curbuf->b_ml.ml_line_count)
+ {
+ t->lnum = curbuf->b_ml.ml_line_count;
+ coladvance((colnr_T)MAXCOL);
+ }
+ }
+ #endif
*** ../vim-7.4.2258/src/testdir/Make_all.mak 2016-08-20 16:56:48.254624304
+0200
--- src/testdir/Make_all.mak 2016-08-26 18:56:26.064363472 +0200
***************
*** 181,186 ****
--- 181,187 ----
test_perl.res \
test_quickfix.res \
test_ruby.res \
+ test_search.res \
test_signs.res \
test_startup.res \
test_startup_utf8.res \
*** ../vim-7.4.2258/src/testdir/test_search.vim 2016-08-26 19:12:15.700304803
+0200
--- src/testdir/test_search.vim 2016-08-26 18:56:26.064363472 +0200
***************
*** 0 ****
--- 1,242 ----
+ " Test for the search command
+
+ func Test_search_cmdline()
+ if !exists('+incsearch')
+ return
+ endif
+ " need to disable char_avail,
+ " so that expansion of commandline works
+ call test_disable_char_avail(1)
+ new
+ call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', '
6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar'])
+ " Test 1
+ " CTRL-N / CTRL-P skips through the previous search history
+ set noincsearch
+ :1
+ call feedkeys("/foobar\<cr>", 'tx')
+ call feedkeys("/the\<cr>",'tx')
+ call assert_equal('the', @/)
+ call feedkeys("/thes\<c-p>\<c-p>\<cr>",'tx')
+ call assert_equal('foobar', @/)
+
+ " Test 2
+ " Ctrl-N goes from one match to the next
+ " until the end of the buffer
+ set incsearch nowrapscan
+ :1
+ " first match
+ call feedkeys("/the\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ :1
+ " second match
+ call feedkeys("/the\<c-n>\<cr>", 'tx')
+ call assert_equal(' 3 the', getline('.'))
+ :1
+ " third match
+ call feedkeys("/the".repeat("\<c-n>", 2)."\<cr>", 'tx')
+ call assert_equal(' 4 their', getline('.'))
+ :1
+ " fourth match
+ call feedkeys("/the".repeat("\<c-n>", 3)."\<cr>", 'tx')
+ call assert_equal(' 5 there', getline('.'))
+ :1
+ " fifth match
+ call feedkeys("/the".repeat("\<c-n>", 4)."\<cr>", 'tx')
+ call assert_equal(' 6 their', getline('.'))
+ :1
+ " sixth match
+ call feedkeys("/the".repeat("\<c-n>", 5)."\<cr>", 'tx')
+ call assert_equal(' 7 the', getline('.'))
+ :1
+ " seventh match
+ call feedkeys("/the".repeat("\<c-n>", 6)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ :1
+ " eigth match
+ call feedkeys("/the".repeat("\<c-n>", 7)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ :1
+ " no further match
+ call feedkeys("/the".repeat("\<c-n>", 8)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+
+ " Test 3
+ " Ctrl-N goes from one match to the next
+ " and continues back at the top
+ set incsearch wrapscan
+ :1
+ " first match
+ call feedkeys("/the\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ :1
+ " second match
+ call feedkeys("/the\<c-n>\<cr>", 'tx')
+ call assert_equal(' 3 the', getline('.'))
+ :1
+ " third match
+ call feedkeys("/the".repeat("\<c-n>", 2)."\<cr>", 'tx')
+ call assert_equal(' 4 their', getline('.'))
+ :1
+ " fourth match
+ call feedkeys("/the".repeat("\<c-n>", 3)."\<cr>", 'tx')
+ call assert_equal(' 5 there', getline('.'))
+ :1
+ " fifth match
+ call feedkeys("/the".repeat("\<c-n>", 4)."\<cr>", 'tx')
+ call assert_equal(' 6 their', getline('.'))
+ :1
+ " sixth match
+ call feedkeys("/the".repeat("\<c-n>", 5)."\<cr>", 'tx')
+ call assert_equal(' 7 the', getline('.'))
+ :1
+ " seventh match
+ call feedkeys("/the".repeat("\<c-n>", 6)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ :1
+ " eigth match
+ call feedkeys("/the".repeat("\<c-n>", 7)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ :1
+ " back at first match
+ call feedkeys("/the".repeat("\<c-n>", 8)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " Test 4
+ " CTRL-P goes to the previous match
+ set incsearch nowrapscan
+ $
+ " first match
+ call feedkeys("?the\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ $
+ " first match
+ call feedkeys("?the\<c-n>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ $
+ " second match
+ call feedkeys("?the".repeat("\<c-p>", 1)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<c-p>", 7)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<c-p>", 8)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " Test 5
+ " CTRL-P goes to the previous match
+ set incsearch wrapscan
+ $
+ " first match
+ call feedkeys("?the\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ $
+ " first match at the top
+ call feedkeys("?the\<c-n>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " second match
+ call feedkeys("?the".repeat("\<c-p>", 1)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<c-p>", 7)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " back at the bottom of the buffer
+ call feedkeys("?the".repeat("\<c-p>", 8)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+
+ " Test 6
+ " CTRL-L adds to the search pattern
+ set incsearch wrapscan
+ 1
+ " first match
+ call feedkeys("/the\<c-l>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " go to next match of 'thes'
+ call feedkeys("/the\<c-l>\<c-n>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ 1
+ " wrap around
+ call feedkeys("/the\<c-l>\<c-n>\<c-n>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " wrap around
+ set nowrapscan
+ call feedkeys("/the\<c-l>\<c-n>\<c-n>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+
+ " Test 7
+ " <bs> remove from match, but stay at current match
+ set incsearch wrapscan
+ 1
+ " first match
+ call feedkeys("/thei\<cr>", 'tx')
+ call assert_equal(' 4 their', getline('.'))
+ 1
+ " delete one char, add another
+ call feedkeys("/thei\<bs>s\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ 1
+ " delete one char, add another, go to previous match, add one char
+ call feedkeys("/thei\<bs>s\<bs>\<c-p>\<c-l>\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ 1
+ " delete all chars, start from the beginning again
+ call feedkeys("/them". repeat("\<bs>",4).'the\>'."\<cr>", 'tx')
+ call assert_equal(' 3 the', getline('.'))
+
+ " clean up
+ call test_disable_char_avail(0)
+ bw!
+ endfunc
+
+ func Test_search_cmdline2()
+ if !exists('+incsearch')
+ return
+ endif
+ " need to disable char_avail,
+ " so that expansion of commandline works
+ call test_disable_char_avail(1)
+ new
+ call setline(1, [' 1', ' 2 these', ' 3 the theother'])
+ " Test 1
+ " Ctrl-P goes correctly back and forth
+ set incsearch
+ 1
+ " first match
+ call feedkeys("/the\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " go to next match (on next line)
+ call feedkeys("/the\<c-n>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to next match (still on line 3)
+ call feedkeys("/the\<c-n>\<c-n>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to next match (still on line 3)
+ call feedkeys("/the\<c-n>\<c-n>\<c-n>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 3)
+ call feedkeys("/the\<c-n>\<c-n>\<c-n>\<c-p>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 3)
+ call feedkeys("/the\<c-n>\<c-n>\<c-n>\<c-p>\<c-p>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 2)
+ call feedkeys("/the\<c-n>\<c-n>\<c-n>\<c-p>\<c-p>\<c-p>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " clean up
+ call test_disable_char_avail(0)
+ bw!
+ endfunc
*** ../vim-7.4.2258/src/Makefile 2016-08-23 23:50:06.872279942 +0200
--- src/Makefile 2016-08-26 18:59:40.214724763 +0200
***************
*** 2110,2115 ****
--- 2120,2126 ----
test_regexp_utf8 \
test_reltime \
test_ruby \
+ test_search \
test_searchpos \
test_set \
test_signs \
*** ../vim-7.4.2258/src/version.c 2016-08-26 17:58:33.590124381 +0200
--- src/version.c 2016-08-26 18:57:46.763682480 +0200
***************
*** 765,766 ****
--- 765,768 ----
{ /* Add new patch number below this line */
+ /**/
+ 2259,
/**/
--
>From "know your smileys":
y:-) Bad toupee
/// Bram Moolenaar -- [email protected] -- 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 ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.