aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames McCoy <jamessan@jamessan.com>2017-06-27 03:19:01 +0000
committerGitHub <noreply@github.com>2017-06-27 03:19:01 +0000
commit91749c06dcc7e5119be097238a6e20fe829c8cc8 (patch)
tree11ff5884cd35e9dfd6d37044fb277fb1a428d15e /src
parentf34befe74c5a7b18a802f6f3c79607cb2124004c (diff)
parent6a842132bcecb0d255fabf937694d1abfde1c86d (diff)
downloadrneovim-91749c06dcc7e5119be097238a6e20fe829c8cc8.tar.gz
rneovim-91749c06dcc7e5119be097238a6e20fe829c8cc8.tar.bz2
rneovim-91749c06dcc7e5119be097238a6e20fe829c8cc8.zip
Merge pull request #6927 from jamessan/vim-7.4.2259
vim-patch:7.4.2259,7.4.2268,7.4.2318,7.4.2320
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_getln.c286
-rw-r--r--src/nvim/normal.c6
-rw-r--r--src/nvim/testdir/test_search.vim273
-rw-r--r--src/nvim/version.c8
4 files changed, 488 insertions, 85 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 858374c68e..7793081957 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -100,12 +100,20 @@ 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;
+ linenr_T init_botline;
+ pos_T match_start;
+ pos_T match_end;
int did_incsearch;
int incsearch_postponed;
int did_wild_list; // did wild_list() recently
@@ -167,6 +175,12 @@ 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;
+ 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;
@@ -179,7 +193,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
}
ccline.overstrike = false; // always start in insert mode
- s->old_cursor = curwin->w_cursor; // needs to be restored later
+ clearpos(&s->match_end);
+ 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;
@@ -282,7 +298,16 @@ 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->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;
curwin->w_topline = s->old_topline;
@@ -857,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.
@@ -929,6 +1066,16 @@ 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->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
&& ccline.cmdprompt == NULL && s->indent == 0) {
@@ -947,6 +1094,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
}
@@ -1001,6 +1149,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->search_start = s->save_cursor;
+ }
redrawcmd();
return command_line_changed(s);
@@ -1230,24 +1381,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->search_start)) {
+ 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);
@@ -1266,7 +1420,7 @@ static int command_line_handle_key(CommandLineState *s)
0, s->firstc != '@') == FAIL) {
break;
}
- return command_line_changed(s);
+ return command_line_not_changed(s);
}
// fallthrough
@@ -1291,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
@@ -1407,6 +1515,17 @@ 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 == '?')) {
+ if (char_avail()) {
+ return 1;
+ }
+ command_line_next_incsearch(s, s->c == Ctrl_G);
+ return command_line_not_changed(s);
+ }
+ break;
+
case Ctrl_V:
case Ctrl_Q:
s->ignore_drag_release = true;
@@ -1521,7 +1640,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) {
@@ -1566,16 +1685,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
@@ -1617,7 +1731,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;
@@ -5519,3 +5633,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/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 e85525e663..2106fc2dec 100644
--- a/src/nvim/testdir/test_search.vim
+++ b/src/nvim/testdir/test_search.vim
@@ -1,5 +1,278 @@
" 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
+ 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-G 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-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')
+ call assert_equal(' 4 their', getline('.'))
+ :1
+ " fourth match
+ call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
+ call assert_equal(' 5 there', getline('.'))
+ :1
+ " fifth match
+ call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
+ call assert_equal(' 6 their', getline('.'))
+ :1
+ " sixth match
+ call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
+ call assert_equal(' 7 the', getline('.'))
+ :1
+ " seventh match
+ call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ :1
+ " eigth match
+ call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ :1
+ " 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
+ " 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-G>\<cr>", 'tx')
+ call assert_equal(' 3 the', getline('.'))
+ :1
+ " third match
+ call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
+ call assert_equal(' 4 their', getline('.'))
+ :1
+ " fourth match
+ call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
+ call assert_equal(' 5 there', getline('.'))
+ :1
+ " fifth match
+ call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
+ call assert_equal(' 6 their', getline('.'))
+ :1
+ " sixth match
+ call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
+ call assert_equal(' 7 the', getline('.'))
+ :1
+ " seventh match
+ call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ :1
+ " eigth match
+ call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ :1
+ " back at first match
+ call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " Test 4
+ " CTRL-T 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-G>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ $
+ " second match
+ call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " Test 5
+ " CTRL-T 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-G>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " second match
+ call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " back at the bottom of the buffer
+ call feedkeys("?the".repeat("\<C-T>", 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-G>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ 1
+ " wrap around
+ call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " wrap around
+ set nowrapscan
+ call feedkeys("/the\<c-l>\<C-G>\<C-G>\<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(' 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(' 9 these', 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()
+ " See test/functional/legacy/search_spec.lua
+ 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-T 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-G>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to next match (still on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to next match (still on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 2)
+ 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
+
func Test_use_sub_pat()
split
let @/ = ''
diff --git a/src/nvim/version.c b/src/nvim/version.c
index a28dbcf061..094ca29b01 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -124,9 +124,9 @@ static const int included_patches[] = {
2323,
2322,
2321,
- // 2320,
+ 2320,
// 2319 NA
- // 2318,
+ 2318,
2317,
// 2316 NA
2315,
@@ -176,7 +176,7 @@ static const int included_patches[] = {
// 2271 NA
// 2270 NA
2269,
- // 2268,
+ 2268,
// 2267 NA
2266,
2265,
@@ -185,7 +185,7 @@ static const int included_patches[] = {
// 2262 NA
// 2261 NA
// 2260 NA
- // 2259,
+ 2259,
// 2258 NA
// 2257 NA
2256,