From 7955cf35158f56a207ece32127adece23fd0fba1 Mon Sep 17 00:00:00 2001 From: raichoo Date: Sat, 25 Mar 2017 14:09:31 +0100 Subject: vim-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) https://github.com/vim/vim/commit/4d6f32cbfbaf324ac4a25c0206a5db0e9f7a48f7 --- src/nvim/ex_getln.c | 140 +++++++++++++++++----- src/nvim/testdir/test_search.vim | 243 +++++++++++++++++++++++++++++++++++++++ src/nvim/version.c | 2 +- 3 files changed, 358 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 858374c68e..efa8cd24bc 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -106,6 +106,9 @@ typedef struct command_line_state { linenr_T old_topline; int old_topfill; linenr_T old_botline; + pos_T cursor_start; + pos_T match_start; + pos_T match_end; int did_incsearch; int incsearch_postponed; int did_wild_list; // did wild_list() recently @@ -167,6 +170,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) s->save_State = State; s->save_p_icm = vim_strsave(p_icm); s->ignore_drag_release = true; + s->match_start = curwin->w_cursor; if (s->firstc == -1) { s->firstc = NUL; @@ -179,7 +183,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) } ccline.overstrike = false; // always start in insert mode + clearpos(&s->match_end); s->old_cursor = curwin->w_cursor; // needs to be restored later + s->cursor_start = s->old_cursor; s->old_curswant = curwin->w_curswant; s->old_leftcol = curwin->w_leftcol; s->old_topline = curwin->w_topline; @@ -283,6 +289,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) if (s->did_incsearch) { curwin->w_cursor = s->old_cursor; + if (s->gotesc) { + curwin->w_cursor = s->cursor_start; + } curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; @@ -929,6 +938,12 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->old_cursor = s->cursor_start; + } else { + s->old_cursor = s->match_start; + decl(&s->old_cursor); + } redrawcmd(); } else if (ccline.cmdlen == 0 && s->c != Ctrl_W && ccline.cmdprompt == NULL && s->indent == 0) { @@ -1001,6 +1016,9 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->old_cursor = s->cursor_start; + } redrawcmd(); return command_line_changed(s); @@ -1230,24 +1248,27 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_L: if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { // Add a character from under the cursor for 'incsearch' - if (s->did_incsearch && !equalpos(curwin->w_cursor, s->old_cursor)) { - s->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)) { - s->c = mb_tolower(s->c); - } - - if (s->c != NUL) { - if (s->c == s->firstc - || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) - != NULL) { - // put a backslash before special characters - stuffcharReadbuff(s->c); - s->c = '\\'; + if (s->did_incsearch) { + curwin->w_cursor = s->match_end; + if (!equalpos(curwin->w_cursor, s->old_cursor)) { + s->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)) { + s->c = mb_tolower(s->c); + } + if (s->c != NUL) { + if (s->c == s->firstc + || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) + != NULL) { + // put a backslash before special characters + stuffcharReadbuff(s->c); + s->c = '\\'; + } + break; } - break; } } return command_line_not_changed(s); @@ -1261,7 +1282,67 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_N: // next match case Ctrl_P: // previous match - if (s->xpc.xp_numfiles > 0) { + if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + + if (char_avail()) { + return 1; + } + ui_busy_start(); + ui_flush(); + if (s->c == Ctrl_N) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + s->c == Ctrl_N ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->old_cursor = s->match_start; + s->match_end = t; + s->match_start = t; + if (s->c == Ctrl_P && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->old_cursor = t; + (void)decl(&s->old_cursor); + } + if (lt(t, s->old_cursor) && s->c == Ctrl_N) { + // wrap around + s->old_cursor = t; + if (s->firstc == '?') { + (void)incl(&s->old_cursor); + } else { + (void)decl(&s->old_cursor); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + return command_line_not_changed(s); + } else if (s->xpc.xp_numfiles > 0) { if (nextwild(&s->xpc, (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT, 0, s->firstc != '@') == FAIL) { break; @@ -1566,16 +1647,11 @@ static int command_line_changed(CommandLineState *s) if (s->i != 0) { 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); - } + s->match_start = curwin->w_cursor; + set_search_match(&curwin->w_cursor); validate_cursor(); end_pos = curwin->w_cursor; + s->match_end = end_pos; curwin->w_cursor = save_pos; } else { end_pos = curwin->w_cursor; // shutup gcc 4 @@ -5519,3 +5595,15 @@ histentry_T *hist_get_array(const uint8_t history_type, int **const new_hisidx, *new_hisnum = &(hisnum[history_type]); return history[history_type]; } + +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); + } +} diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index e85525e663..9c29236ac9 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -1,5 +1,248 @@ " Test for the search command +func Test_search_cmdline() + throw 'skipped: Nvim does not support test_disable_char_avail()' + 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\", 'tx') + call feedkeys("/the\",'tx') + call assert_equal('the', @/) + call feedkeys("/thes\\\",'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\", 'tx') + call assert_equal(' 2 these', getline('.')) + :1 + " second match + call feedkeys("/the\\", 'tx') + call assert_equal(' 3 the', getline('.')) + :1 + " third match + call feedkeys("/the".repeat("\", 2)."\", 'tx') + call assert_equal(' 4 their', getline('.')) + :1 + " fourth match + call feedkeys("/the".repeat("\", 3)."\", 'tx') + call assert_equal(' 5 there', getline('.')) + :1 + " fifth match + call feedkeys("/the".repeat("\", 4)."\", 'tx') + call assert_equal(' 6 their', getline('.')) + :1 + " sixth match + call feedkeys("/the".repeat("\", 5)."\", 'tx') + call assert_equal(' 7 the', getline('.')) + :1 + " seventh match + call feedkeys("/the".repeat("\", 6)."\", 'tx') + call assert_equal(' 8 them', getline('.')) + :1 + " eigth match + call feedkeys("/the".repeat("\", 7)."\", 'tx') + call assert_equal(' 9 these', getline('.')) + :1 + " no further match + call feedkeys("/the".repeat("\", 8)."\", '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\", 'tx') + call assert_equal(' 2 these', getline('.')) + :1 + " second match + call feedkeys("/the\\", 'tx') + call assert_equal(' 3 the', getline('.')) + :1 + " third match + call feedkeys("/the".repeat("\", 2)."\", 'tx') + call assert_equal(' 4 their', getline('.')) + :1 + " fourth match + call feedkeys("/the".repeat("\", 3)."\", 'tx') + call assert_equal(' 5 there', getline('.')) + :1 + " fifth match + call feedkeys("/the".repeat("\", 4)."\", 'tx') + call assert_equal(' 6 their', getline('.')) + :1 + " sixth match + call feedkeys("/the".repeat("\", 5)."\", 'tx') + call assert_equal(' 7 the', getline('.')) + :1 + " seventh match + call feedkeys("/the".repeat("\", 6)."\", 'tx') + call assert_equal(' 8 them', getline('.')) + :1 + " eigth match + call feedkeys("/the".repeat("\", 7)."\", 'tx') + call assert_equal(' 9 these', getline('.')) + :1 + " back at first match + call feedkeys("/the".repeat("\", 8)."\", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 4 + " CTRL-P goes to the previous match + set incsearch nowrapscan + $ + " first match + call feedkeys("?the\", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " first match + call feedkeys("?the\\", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " second match + call feedkeys("?the".repeat("\", 1)."\", 'tx') + call assert_equal(' 8 them', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\", 7)."\", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\", 8)."\", 'tx') + call assert_equal(' 2 these', getline('.')) + + " Test 5 + " CTRL-P goes to the previous match + set incsearch wrapscan + $ + " first match + call feedkeys("?the\", 'tx') + call assert_equal(' 9 these', getline('.')) + $ + " first match at the top + call feedkeys("?the\\", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " second match + call feedkeys("?the".repeat("\", 1)."\", 'tx') + call assert_equal(' 8 them', getline('.')) + $ + " last match + call feedkeys("?the".repeat("\", 7)."\", 'tx') + call assert_equal(' 2 these', getline('.')) + $ + " back at the bottom of the buffer + call feedkeys("?the".repeat("\", 8)."\", '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\\", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " go to next match of 'thes' + call feedkeys("/the\\\", 'tx') + call assert_equal(' 9 these', getline('.')) + 1 + " wrap around + call feedkeys("/the\\\\", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " wrap around + set nowrapscan + call feedkeys("/the\\\\", 'tx') + call assert_equal(' 9 these', getline('.')) + + " Test 7 + " remove from match, but stay at current match + set incsearch wrapscan + 1 + " first match + call feedkeys("/thei\", 'tx') + call assert_equal(' 4 their', getline('.')) + 1 + " delete one char, add another + call feedkeys("/thei\s\", 'tx') + call assert_equal(' 9 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('.')) + 1 + " delete all chars, start from the beginning again + call feedkeys("/them". repeat("\",4).'the\>'."\", 'tx') + call assert_equal(' 3 the', getline('.')) + + " clean up + call test_disable_char_avail(0) + bw! +endfunc + +func Test_search_cmdline2() + throw 'skipped: Nvim does not support test_disable_char_avail()' + 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\", 'tx') + call assert_equal(' 2 these', getline('.')) + 1 + " go to next match (on next line) + call feedkeys("/the\\", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to next match (still on line 3) + call feedkeys("/the\\\", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to next match (still on line 3) + call feedkeys("/the\\\\", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 3) + call feedkeys("/the\\\\\", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 3) + call feedkeys("/the\\\\\\", 'tx') + call assert_equal(' 3 the theother', getline('.')) + 1 + " go to previous match (on line 2) + call feedkeys("/the\\\\\\\", 'tx') + call assert_equal(' 2 these', getline('.')) + + " clean up + call test_disable_char_avail(0) + bw! +endfunc + func Test_use_sub_pat() split let @/ = '' diff --git a/src/nvim/version.c b/src/nvim/version.c index a28dbcf061..dceceb46ad 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -185,7 +185,7 @@ static const int included_patches[] = { // 2262 NA // 2261 NA // 2260 NA - // 2259, + 2259, // 2258 NA // 2257 NA 2256, -- cgit From 518b42db916ccbb9057ca9361b48e83ea65bc3b9 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 14 Jun 2017 22:51:50 -0400 Subject: functests/legacy: Add lua version of test_search.vim --- src/nvim/testdir/test_search.vim | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 9c29236ac9..1398cc4d4e 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -1,6 +1,7 @@ " Test for the search command func Test_search_cmdline() + " See test/functional/legacy/search_spec.lua throw 'skipped: Nvim does not support test_disable_char_avail()' if !exists('+incsearch') return @@ -197,6 +198,7 @@ func Test_search_cmdline() endfunc func Test_search_cmdline2() + " See test/functional/legacy/search_spec.lua throw 'skipped: Nvim does not support test_disable_char_avail()' if !exists('+incsearch') return -- cgit From 0dd64556590633b2cab7cd846b28bbf5f7ef35d4 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 25 Jun 2017 11:01:16 -0400 Subject: vim-patch:7.4.2268 Problem: Using CTRL-N and CTRL-P for incsearch shadows completion keys. Solution: Use CTRL-T and CTRL-G instead. https://github.com/vim/vim/commit/1195669f9e434fa9ab8b57ee9470bf951e4990b8 --- src/nvim/ex_getln.c | 128 ++++++++++++++++++++------------------- src/nvim/testdir/test_search.vim | 80 ++++++++++++------------ src/nvim/version.c | 2 +- 3 files changed, 107 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index efa8cd24bc..62f802fb8f 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1282,72 +1282,12 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_N: // next match case Ctrl_P: // previous match - if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { - pos_T t; - int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; - - if (char_avail()) { - return 1; - } - ui_busy_start(); - ui_flush(); - if (s->c == Ctrl_N) { - t = s->match_end; - search_flags += SEARCH_COL; - } else { - t = s->match_start; - } - emsg_off++; - s->i = searchit(curwin, curbuf, &t, - s->c == Ctrl_N ? FORWARD : BACKWARD, - ccline.cmdbuff, s->count, search_flags, - RE_SEARCH, 0, NULL); - emsg_off--; - ui_busy_stop(); - if (s->i) { - s->old_cursor = s->match_start; - s->match_end = t; - s->match_start = t; - if (s->c == Ctrl_P && s->firstc == '/') { - // move just before the current match, so that - // when nv_search finishes the cursor will be - // put back on the match - s->old_cursor = t; - (void)decl(&s->old_cursor); - } - if (lt(t, s->old_cursor) && s->c == Ctrl_N) { - // wrap around - s->old_cursor = t; - if (s->firstc == '?') { - (void)incl(&s->old_cursor); - } else { - (void)decl(&s->old_cursor); - } - } - - set_search_match(&s->match_end); - curwin->w_cursor = s->match_start; - changed_cline_bef_curs(); - update_topline(); - validate_cursor(); - highlight_match = true; - s->old_curswant = curwin->w_curswant; - s->old_leftcol = curwin->w_leftcol; - s->old_topline = curwin->w_topline; - s->old_topfill = curwin->w_topfill; - s->old_botline = curwin->w_botline; - update_screen(NOT_VALID); - redrawcmdline(); - } else { - vim_beep(BO_ERROR); - } - return command_line_not_changed(s); - } else if (s->xpc.xp_numfiles > 0) { + if (s->xpc.xp_numfiles > 0) { if (nextwild(&s->xpc, (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT, 0, s->firstc != '@') == FAIL) { break; } - return command_line_changed(s); + return command_line_not_changed(s); } // fallthrough @@ -1488,6 +1428,70 @@ static int command_line_handle_key(CommandLineState *s) beep_flush(); return command_line_not_changed(s); + case Ctrl_G: // next match + case Ctrl_T: // previous match + if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + + if (char_avail()) { + return 1; + } + ui_busy_start(); + ui_flush(); + if (s->c == Ctrl_G) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + s->c == Ctrl_G ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->old_cursor = s->match_start; + s->match_end = t; + s->match_start = t; + if (s->c == Ctrl_T && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->old_cursor = t; + (void)decl(&s->old_cursor); + } + if (lt(t, s->old_cursor) && s->c == Ctrl_G) { + // wrap around + s->old_cursor = t; + if (s->firstc == '?') { + (void)incl(&s->old_cursor); + } else { + (void)decl(&s->old_cursor); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + } + return command_line_not_changed(s); + case Ctrl_V: case Ctrl_Q: s->ignore_drag_release = true; diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 1398cc4d4e..28e504a883 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -18,11 +18,11 @@ func Test_search_cmdline() call feedkeys("/foobar\", 'tx') call feedkeys("/the\",'tx') call assert_equal('the', @/) - call feedkeys("/thes\\\",'tx') + call feedkeys("/thes\\\",'tx') call assert_equal('foobar', @/) " Test 2 - " Ctrl-N goes from one match to the next + " Ctrl-G goes from one match to the next " until the end of the buffer set incsearch nowrapscan :1 @@ -31,39 +31,39 @@ func Test_search_cmdline() call assert_equal(' 2 these', getline('.')) :1 " second match - call feedkeys("/the\\", 'tx') + call feedkeys("/the\\", 'tx') call assert_equal(' 3 the', getline('.')) :1 " third match - call feedkeys("/the".repeat("\", 2)."\", 'tx') + call feedkeys("/the".repeat("\", 2)."\", 'tx') call assert_equal(' 4 their', getline('.')) :1 " fourth match - call feedkeys("/the".repeat("\", 3)."\", 'tx') + call feedkeys("/the".repeat("\", 3)."\", 'tx') call assert_equal(' 5 there', getline('.')) :1 " fifth match - call feedkeys("/the".repeat("\", 4)."\", 'tx') + call feedkeys("/the".repeat("\", 4)."\", 'tx') call assert_equal(' 6 their', getline('.')) :1 " sixth match - call feedkeys("/the".repeat("\", 5)."\", 'tx') + call feedkeys("/the".repeat("\", 5)."\", 'tx') call assert_equal(' 7 the', getline('.')) :1 " seventh match - call feedkeys("/the".repeat("\", 6)."\", 'tx') + call feedkeys("/the".repeat("\", 6)."\", 'tx') call assert_equal(' 8 them', getline('.')) :1 " eigth match - call feedkeys("/the".repeat("\", 7)."\", 'tx') + call feedkeys("/the".repeat("\", 7)."\", 'tx') call assert_equal(' 9 these', getline('.')) :1 " no further match - call feedkeys("/the".repeat("\", 8)."\", 'tx') + call feedkeys("/the".repeat("\", 8)."\", 'tx') call assert_equal(' 9 these', getline('.')) " Test 3 - " Ctrl-N goes from one match to the next + " Ctrl-G goes from one match to the next " and continues back at the top set incsearch wrapscan :1 @@ -72,39 +72,39 @@ func Test_search_cmdline() call assert_equal(' 2 these', getline('.')) :1 " second match - call feedkeys("/the\\", 'tx') + call feedkeys("/the\\", 'tx') call assert_equal(' 3 the', getline('.')) :1 " third match - call feedkeys("/the".repeat("\", 2)."\", 'tx') + call feedkeys("/the".repeat("\", 2)."\", 'tx') call assert_equal(' 4 their', getline('.')) :1 " fourth match - call feedkeys("/the".repeat("\", 3)."\", 'tx') + call feedkeys("/the".repeat("\", 3)."\", 'tx') call assert_equal(' 5 there', getline('.')) :1 " fifth match - call feedkeys("/the".repeat("\", 4)."\", 'tx') + call feedkeys("/the".repeat("\", 4)."\", 'tx') call assert_equal(' 6 their', getline('.')) :1 " sixth match - call feedkeys("/the".repeat("\", 5)."\", 'tx') + call feedkeys("/the".repeat("\", 5)."\", 'tx') call assert_equal(' 7 the', getline('.')) :1 " seventh match - call feedkeys("/the".repeat("\", 6)."\", 'tx') + call feedkeys("/the".repeat("\", 6)."\", 'tx') call assert_equal(' 8 them', getline('.')) :1 " eigth match - call feedkeys("/the".repeat("\", 7)."\", 'tx') + call feedkeys("/the".repeat("\", 7)."\", 'tx') call assert_equal(' 9 these', getline('.')) :1 " back at first match - call feedkeys("/the".repeat("\", 8)."\", 'tx') + call feedkeys("/the".repeat("\", 8)."\", 'tx') call assert_equal(' 2 these', getline('.')) " Test 4 - " CTRL-P goes to the previous match + " CTRL-T goes to the previous match set incsearch nowrapscan $ " first match @@ -112,23 +112,23 @@ func Test_search_cmdline() call assert_equal(' 9 these', getline('.')) $ " first match - call feedkeys("?the\\", 'tx') + call feedkeys("?the\\", 'tx') call assert_equal(' 9 these', getline('.')) $ " second match - call feedkeys("?the".repeat("\", 1)."\", 'tx') + call feedkeys("?the".repeat("\", 1)."\", 'tx') call assert_equal(' 8 them', getline('.')) $ " last match - call feedkeys("?the".repeat("\", 7)."\", 'tx') + call feedkeys("?the".repeat("\", 7)."\", 'tx') call assert_equal(' 2 these', getline('.')) $ " last match - call feedkeys("?the".repeat("\", 8)."\", 'tx') + call feedkeys("?the".repeat("\", 8)."\", 'tx') call assert_equal(' 2 these', getline('.')) " Test 5 - " CTRL-P goes to the previous match + " CTRL-T goes to the previous match set incsearch wrapscan $ " first match @@ -136,19 +136,19 @@ func Test_search_cmdline() call assert_equal(' 9 these', getline('.')) $ " first match at the top - call feedkeys("?the\\", 'tx') + call feedkeys("?the\\", 'tx') call assert_equal(' 2 these', getline('.')) $ " second match - call feedkeys("?the".repeat("\", 1)."\", 'tx') + call feedkeys("?the".repeat("\", 1)."\", 'tx') call assert_equal(' 8 them', getline('.')) $ " last match - call feedkeys("?the".repeat("\", 7)."\", 'tx') + call feedkeys("?the".repeat("\", 7)."\", 'tx') call assert_equal(' 2 these', getline('.')) $ " back at the bottom of the buffer - call feedkeys("?the".repeat("\", 8)."\", 'tx') + call feedkeys("?the".repeat("\", 8)."\", 'tx') call assert_equal(' 9 these', getline('.')) " Test 6 @@ -160,16 +160,16 @@ func Test_search_cmdline() call assert_equal(' 2 these', getline('.')) 1 " go to next match of 'thes' - call feedkeys("/the\\\", 'tx') + call feedkeys("/the\\\", 'tx') call assert_equal(' 9 these', getline('.')) 1 " wrap around - call feedkeys("/the\\\\", 'tx') + call feedkeys("/the\\\\", 'tx') call assert_equal(' 2 these', getline('.')) 1 " wrap around set nowrapscan - call feedkeys("/the\\\\", 'tx') + call feedkeys("/the\\\\", 'tx') call assert_equal(' 9 these', getline('.')) " Test 7 @@ -185,7 +185,7 @@ func Test_search_cmdline() call assert_equal(' 9 these', getline('.')) 1 " delete one char, add another, go to previous match, add one char - call feedkeys("/thei\s\\\\", 'tx') + call feedkeys("/thei\s\\\\", 'tx') call assert_equal(' 8 them', getline('.')) 1 " delete all chars, start from the beginning again @@ -209,7 +209,7 @@ func Test_search_cmdline2() new call setline(1, [' 1', ' 2 these', ' 3 the theother']) " Test 1 - " Ctrl-P goes correctly back and forth + " Ctrl-T goes correctly back and forth set incsearch 1 " first match @@ -217,27 +217,27 @@ func Test_search_cmdline2() call assert_equal(' 2 these', getline('.')) 1 " go to next match (on next line) - call feedkeys("/the\\", 'tx') + call feedkeys("/the\\", 'tx') call assert_equal(' 3 the theother', getline('.')) 1 " go to next match (still on line 3) - call feedkeys("/the\\\", 'tx') + call feedkeys("/the\\\", 'tx') call assert_equal(' 3 the theother', getline('.')) 1 " go to next match (still on line 3) - call feedkeys("/the\\\\", 'tx') + call feedkeys("/the\\\\", 'tx') call assert_equal(' 3 the theother', getline('.')) 1 " go to previous match (on line 3) - call feedkeys("/the\\\\\", 'tx') + call feedkeys("/the\\\\\", 'tx') call assert_equal(' 3 the theother', getline('.')) 1 " go to previous match (on line 3) - call feedkeys("/the\\\\\\", 'tx') + call feedkeys("/the\\\\\\", 'tx') call assert_equal(' 3 the theother', getline('.')) 1 " go to previous match (on line 2) - call feedkeys("/the\\\\\\\", 'tx') + call feedkeys("/the\\\\\\\", 'tx') call assert_equal(' 2 these', getline('.')) " clean up diff --git a/src/nvim/version.c b/src/nvim/version.c index dceceb46ad..23c2fac28a 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -176,7 +176,7 @@ static const int included_patches[] = { // 2271 NA // 2270 NA 2269, - // 2268, + 2268, // 2267 NA 2266, 2265, -- cgit From 3679752dbd9191f4067a43143da637478cc389f1 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 25 Jun 2017 12:11:22 -0400 Subject: vim-patch:7.4.2318 Problem: When 'incsearch' is not set CTRL-T and CTRL-G are not inserted as before. Solution: Move vim/vim#ifdef and don't use goto. https://github.com/vim/vim/commit/349e7d94e6bbb253bb87adad9039f095128ab543 --- src/nvim/ex_getln.c | 3 ++- src/nvim/version.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 62f802fb8f..45fff4f9d7 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1489,8 +1489,9 @@ static int command_line_handle_key(CommandLineState *s) } else { vim_beep(BO_ERROR); } + return command_line_not_changed(s); } - return command_line_not_changed(s); + break; case Ctrl_V: case Ctrl_Q: diff --git a/src/nvim/version.c b/src/nvim/version.c index 23c2fac28a..5a107f0023 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -126,7 +126,7 @@ static const int included_patches[] = { 2321, // 2320, // 2319 NA - // 2318, + 2318, 2317, // 2316 NA 2315, -- cgit From 54d5e90a2b87736a3248300ed423374e88ce8e79 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 25 Jun 2017 12:15:58 -0400 Subject: vim-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. https://github.com/vim/vim/commit/dda933d06c06c2792bd686d059f6ad19191ad30b --- src/nvim/ex_getln.c | 63 ++++++++++++++++++++++++++-------------- src/nvim/normal.c | 6 +++- src/nvim/testdir/test_search.vim | 32 ++++++++++++++++++-- src/nvim/version.c | 2 +- 4 files changed, 78 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 45fff4f9d7..e8f9d9bf47 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -100,13 +100,18 @@ typedef struct command_line_state { char_u *lookfor; // string to match int hiscnt; // current history line in use int histype; // history type to be used - pos_T old_cursor; + pos_T search_start; // where 'incsearch' starts searching + pos_T save_cursor; colnr_T old_curswant; + colnr_T init_curswant; colnr_T old_leftcol; + colnr_T init_leftcol; linenr_T old_topline; + linenr_T init_topline; int old_topfill; + int init_topfill; linenr_T old_botline; - pos_T cursor_start; + linenr_T init_botline; pos_T match_start; pos_T match_end; int did_incsearch; @@ -171,6 +176,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) s->save_p_icm = vim_strsave(p_icm); s->ignore_drag_release = true; s->match_start = curwin->w_cursor; + s->init_curswant = curwin->w_curswant; + s->init_leftcol = curwin->w_leftcol; + s->init_topline = curwin->w_topline; + s->init_topfill = curwin->w_topfill; + s->init_botline = curwin->w_botline; if (s->firstc == -1) { s->firstc = NUL; @@ -184,8 +194,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.overstrike = false; // always start in insert mode clearpos(&s->match_end); - s->old_cursor = curwin->w_cursor; // needs to be restored later - s->cursor_start = s->old_cursor; + s->save_cursor = curwin->w_cursor; // may be restored later + s->search_start = curwin->w_cursor; s->old_curswant = curwin->w_curswant; s->old_leftcol = curwin->w_leftcol; s->old_topline = curwin->w_topline; @@ -288,9 +298,15 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.xpc = NULL; if (s->did_incsearch) { - curwin->w_cursor = s->old_cursor; if (s->gotesc) { - curwin->w_cursor = s->cursor_start; + curwin->w_cursor = s->save_cursor; + } else { + if (!equalpos(s->save_cursor, s->search_start)) { + // put the '" mark at the original position + curwin->w_cursor = s->save_cursor; + setpcmark(); + } + curwin->w_cursor = s->search_start; } curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; @@ -939,10 +955,14 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; if (ccline.cmdlen == 0) { - s->old_cursor = s->cursor_start; - } else { - s->old_cursor = s->match_start; - decl(&s->old_cursor); + s->search_start = s->save_cursor; + // save view settings, so that the screen won't be restored at the + // wrong position + s->old_curswant = s->init_curswant; + s->old_leftcol = s->init_leftcol; + s->old_topline = s->init_topline; + s->old_topfill = s->init_topfill; + s->old_botline = s->init_botline; } redrawcmd(); } else if (ccline.cmdlen == 0 && s->c != Ctrl_W @@ -962,6 +982,7 @@ static int command_line_handle_key(CommandLineState *s) } msg_putchar(' '); // delete ':' } + s->search_start = s->save_cursor; redraw_cmdline = true; return 0; // back to cmd mode } @@ -1017,7 +1038,7 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; if (ccline.cmdlen == 0) { - s->old_cursor = s->cursor_start; + s->search_start = s->save_cursor; } redrawcmd(); return command_line_changed(s); @@ -1250,7 +1271,7 @@ static int command_line_handle_key(CommandLineState *s) // Add a character from under the cursor for 'incsearch' if (s->did_incsearch) { curwin->w_cursor = s->match_end; - if (!equalpos(curwin->w_cursor, s->old_cursor)) { + if (!equalpos(curwin->w_cursor, s->search_start)) { s->c = gchar_cursor(); // If 'ignorecase' and 'smartcase' are set and the // command line has no uppercase characters, convert @@ -1453,23 +1474,23 @@ static int command_line_handle_key(CommandLineState *s) emsg_off--; ui_busy_stop(); if (s->i) { - s->old_cursor = s->match_start; + s->search_start = s->match_start; s->match_end = t; s->match_start = t; if (s->c == Ctrl_T && s->firstc == '/') { // move just before the current match, so that // when nv_search finishes the cursor will be // put back on the match - s->old_cursor = t; - (void)decl(&s->old_cursor); + s->search_start = t; + (void)decl(&s->search_start); } - if (lt(t, s->old_cursor) && s->c == Ctrl_G) { + if (lt(t, s->search_start) && s->c == Ctrl_G) { // wrap around - s->old_cursor = t; + s->search_start = t; if (s->firstc == '?') { - (void)incl(&s->old_cursor); + (void)incl(&s->search_start); } else { - (void)decl(&s->old_cursor); + (void)decl(&s->search_start); } } @@ -1607,7 +1628,7 @@ static int command_line_changed(CommandLineState *s) return 1; } s->incsearch_postponed = false; - curwin->w_cursor = s->old_cursor; // start at old position + curwin->w_cursor = s->search_start; // start at old position // If there is no command line, don't do anything if (ccline.cmdlen == 0) { @@ -1698,7 +1719,7 @@ static int command_line_changed(CommandLineState *s) emsg_silent--; // Unblock error reporting // Restore the window "view". - curwin->w_cursor = s->old_cursor; + curwin->w_cursor = s->save_cursor; curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 050020d79d..39cd2c6631 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -5231,6 +5231,7 @@ static void nv_dollar(cmdarg_T *cap) static void 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) { /* Translate "g??" to "g?g?" */ @@ -5240,6 +5241,8 @@ static void 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) { @@ -5248,7 +5251,8 @@ static void 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/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 28e504a883..2106fc2dec 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -33,6 +33,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') @@ -61,6 +62,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 @@ -182,11 +184,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') @@ -240,7 +242,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/nvim/version.c b/src/nvim/version.c index 5a107f0023..094ca29b01 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -124,7 +124,7 @@ static const int included_patches[] = { 2323, 2322, 2321, - // 2320, + 2320, // 2319 NA 2318, 2317, -- cgit From 6a842132bcecb0d255fabf937694d1abfde1c86d Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 26 Jun 2017 19:12:06 -0400 Subject: ex_getln: Lint command_line_handle_key readability/fn_size Create new functions to handle moving to the next incsearch match or matching history index. --- src/nvim/ex_getln.c | 220 +++++++++++++++++++++++++++------------------------- 1 file changed, 116 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e8f9d9bf47..7793081957 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -882,6 +882,118 @@ static int command_line_execute(VimState *state, int key) return command_line_handle_key(s); } +static void command_line_next_incsearch(CommandLineState *s, bool next_match) +{ + ui_busy_start(); + ui_flush(); + + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + if (next_match) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + next_match ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->search_start = s->match_start; + s->match_end = t; + s->match_start = t; + if (!next_match && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->search_start = t; + (void)decl(&s->search_start); + } + if (lt(t, s->search_start) && next_match) { + // wrap around + s->search_start = t; + if (s->firstc == '?') { + (void)incl(&s->search_start); + } else { + (void)decl(&s->search_start); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + return; +} + +static void command_line_next_histidx(CommandLineState *s, bool next_match) +{ + s->j = (int)STRLEN(s->lookfor); + for (;; ) { + // one step backwards + if (!next_match) { + if (s->hiscnt == hislen) { + // first time + s->hiscnt = hisidx[s->histype]; + } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { + s->hiscnt = hislen - 1; + } else if (s->hiscnt != hisidx[s->histype] + 1) { + s->hiscnt--; + } else { + // at top of list + s->hiscnt = s->i; + break; + } + } else { // one step forwards + // on last entry, clear the line + if (s->hiscnt == hisidx[s->histype]) { + s->hiscnt = hislen; + break; + } + + // not on a history line, nothing to do + if (s->hiscnt == hislen) { + break; + } + + if (s->hiscnt == hislen - 1) { + // wrap around + s->hiscnt = 0; + } else { + s->hiscnt++; + } + } + + if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { + s->hiscnt = s->i; + break; + } + + if ((s->c != K_UP && s->c != K_DOWN) + || s->hiscnt == s->i + || STRNCMP(history[s->histype][s->hiscnt].hisstr, + s->lookfor, (size_t)s->j) == 0) { + break; + } + } +} + static int command_line_handle_key(CommandLineState *s) { // Big switch for a typed command line character. @@ -1333,55 +1445,9 @@ static int command_line_handle_key(CommandLineState *s) s->lookfor[ccline.cmdpos] = NUL; } - s->j = (int)STRLEN(s->lookfor); - for (;; ) { - // one step backwards - if (s->c == K_UP|| s->c == K_S_UP || s->c == Ctrl_P - || s->c == K_PAGEUP || s->c == K_KPAGEUP) { - if (s->hiscnt == hislen) { - // first time - s->hiscnt = hisidx[s->histype]; - } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { - s->hiscnt = hislen - 1; - } else if (s->hiscnt != hisidx[s->histype] + 1) { - --s->hiscnt; - } else { - // at top of list - s->hiscnt = s->i; - break; - } - } else { // one step forwards - // on last entry, clear the line - if (s->hiscnt == hisidx[s->histype]) { - s->hiscnt = hislen; - break; - } - - // not on a history line, nothing to do - if (s->hiscnt == hislen) { - break; - } - - if (s->hiscnt == hislen - 1) { - // wrap around - s->hiscnt = 0; - } else { - ++s->hiscnt; - } - } - - if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { - s->hiscnt = s->i; - break; - } - - if ((s->c != K_UP && s->c != K_DOWN) - || s->hiscnt == s->i - || STRNCMP(history[s->histype][s->hiscnt].hisstr, - s->lookfor, (size_t)s->j) == 0) { - break; - } - } + bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N + || s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN); + command_line_next_histidx(s, next_match); if (s->hiscnt != s->i) { // jumped to other entry @@ -1452,64 +1518,10 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_G: // next match case Ctrl_T: // previous match if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { - pos_T t; - int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; - if (char_avail()) { return 1; } - ui_busy_start(); - ui_flush(); - if (s->c == Ctrl_G) { - t = s->match_end; - search_flags += SEARCH_COL; - } else { - t = s->match_start; - } - emsg_off++; - s->i = searchit(curwin, curbuf, &t, - s->c == Ctrl_G ? FORWARD : BACKWARD, - ccline.cmdbuff, s->count, search_flags, - RE_SEARCH, 0, NULL); - emsg_off--; - ui_busy_stop(); - if (s->i) { - s->search_start = s->match_start; - s->match_end = t; - s->match_start = t; - if (s->c == Ctrl_T && s->firstc == '/') { - // move just before the current match, so that - // when nv_search finishes the cursor will be - // put back on the match - s->search_start = t; - (void)decl(&s->search_start); - } - if (lt(t, s->search_start) && s->c == Ctrl_G) { - // wrap around - s->search_start = t; - if (s->firstc == '?') { - (void)incl(&s->search_start); - } else { - (void)decl(&s->search_start); - } - } - - set_search_match(&s->match_end); - curwin->w_cursor = s->match_start; - changed_cline_bef_curs(); - update_topline(); - validate_cursor(); - highlight_match = true; - s->old_curswant = curwin->w_curswant; - s->old_leftcol = curwin->w_leftcol; - s->old_topline = curwin->w_topline; - s->old_topfill = curwin->w_topfill; - s->old_botline = curwin->w_botline; - update_screen(NOT_VALID); - redrawcmdline(); - } else { - vim_beep(BO_ERROR); - } + command_line_next_incsearch(s, s->c == Ctrl_G); return command_line_not_changed(s); } break; -- cgit