diff --git a/src/nvim/search.c b/src/nvim/search.c index 1029190db4..8cfac8c362 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -3977,7 +3977,7 @@ current_search ( } /* - * Check if the pattern is one character or zero-width. + * Check if the pattern is one character long or zero-width. * If move is true, check from the beginning of the buffer, * else from the current cursor position. * Returns TRUE, FALSE or -1 for failure. @@ -3991,10 +3991,16 @@ static int is_one_char(char_u *pattern, bool move) int save_called_emsg = called_emsg; int flag = 0; + if (pattern == NULL) { + pattern = spats[last_idx].pat; + } + if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH, SEARCH_KEEP, ®match) == FAIL) return -1; + // init startcol correctly + regmatch.startpos[0].col = -1; /* move to match */ if (move) { clearpos(&pos); @@ -4003,21 +4009,29 @@ static int is_one_char(char_u *pattern, bool move) /* accept a match at the cursor position */ flag = SEARCH_START; } - if (searchit(curwin, curbuf, &pos, FORWARD, spats[last_idx].pat, 1, + if (searchit(curwin, curbuf, &pos, FORWARD, pattern, 1, SEARCH_KEEP + flag, RE_SEARCH, 0, NULL) != FAIL) { /* Zero-width pattern should match somewhere, then we can check if * start and end are in the same position. */ called_emsg = FALSE; - nmatched = vim_regexec_multi(®match, curwin, curbuf, - pos.lnum, (colnr_T)0, NULL); + do { + regmatch.startpos[0].col++; + nmatched = vim_regexec_multi(®match, curwin, curbuf, + pos.lnum, regmatch.startpos[0].col, NULL); + if (!nmatched) { + break; + } + } while (regmatch.startpos[0].col < pos.col); - if (!called_emsg) + if (!called_emsg) { result = (nmatched != 0 && regmatch.startpos[0].lnum == regmatch.endpos[0].lnum && regmatch.startpos[0].col == regmatch.endpos[0].col); - - if (!result && inc(&pos) >= 0 && pos.col == regmatch.endpos[0].col) - result = TRUE; + // one char width + if (!result && inc(&pos) >= 0 && pos.col == regmatch.endpos[0].col) { + result = true; + } + } } called_emsg |= save_called_emsg; diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 612071e2e2..814c0bc3cb 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -34,6 +34,7 @@ NEW_TESTS = \ test_cmdline.res \ test_cscope.res \ test_diffmode.res \ + test_gn.res \ test_hardcopy.res \ test_help_tagjump.res \ test_history.res \ diff --git a/src/nvim/testdir/test53.in b/src/nvim/testdir/test53.in index f3778c5192..20b5d019af 100644 --- a/src/nvim/testdir/test53.in +++ b/src/nvim/testdir/test53.in @@ -4,8 +4,6 @@ Note that the end-of-line moves the cursor to the next test line. Also test match() and matchstr() -Also test the gn command and repeating it. - STARTTEST /^start:/ da" @@ -52,35 +50,6 @@ dit :put =match('abc', '\zs', 2, 1) " 2 :put =match('abc', '\zs', 3, 1) " 3 :put =match('abc', '\zs', 4, 1) " -1 -/^foobar -gncsearchmatch/one\_s*two\_s -:1 -gnd -/[a]bcdx -:1 -2gnd/join -/$ -0gnd -/\>\zs -0gnd/^ -gnd$h/\zs -gnd/[u]niquepattern/s -vlgnd -/mother -:set selection=exclusive -$cgNmongoose/i -cgnj -:" Make sure there is no other match y uppercase. -/x59 -gggnd -:" test repeating dgn -/^Johnny -ggdgn. -:" test repeating gUgn -/^Depp -gggUgn. -gg/a:0\@!\zs\d\+ -nygnop :/^start:/,/^end:/wq! test.out ENDTEST @@ -102,32 +71,4 @@ innertext object SEARCH: -foobar -one -two -abcdx | abcdx | abcdx -join -lines -zero width pattern -delete first and last chars -uniquepattern uniquepattern -my very excellent mother just served us nachos -for (i=0; i<=10; i++) -a:10 - -a:1 - -a:20 -Y -text -Y ---1 -Johnny ---2 -Johnny ---3 -Depp ---4 -Depp ---5 end: diff --git a/src/nvim/testdir/test53.ok b/src/nvim/testdir/test53.ok index 05206972a4..d57d86bbb0 100644 --- a/src/nvim/testdir/test53.ok +++ b/src/nvim/testdir/test53.ok @@ -42,30 +42,4 @@ a 3 -1 SEARCH: -searchmatch -abcdx | | abcdx -join lines -zerowidth pattern -elete first and last char - uniquepattern -my very excellent mongoose just served us nachos -for (j=0; i<=10; i++) -a:10 - -a:1 -1 - -a:20 - -text -Y ---1 - ---2 - ---3 -DEPP ---4 -DEPP ---5 end: diff --git a/src/nvim/testdir/test_gn.vim b/src/nvim/testdir/test_gn.vim new file mode 100644 index 0000000000..3eca99bd99 --- /dev/null +++ b/src/nvim/testdir/test_gn.vim @@ -0,0 +1,93 @@ +" Test for gn command + +func Test_gn_command() + noa new + " replace a single char by itsself quoted: + call setline('.', 'abc x def x ghi x jkl') + let @/='x' + exe "norm! cgn'x'\.." + call assert_equal("abc 'x' def 'x' ghi 'x' jkl", getline('.')) + sil! %d_ + " simple search match + call setline('.', 'foobar') + let @/='foobar' + exe "norm! gncsearchmatch" + call assert_equal('searchmatch', getline('.')) + sil! %d _ + " replace a multi-line match + call setline('.', ['', 'one', 'two']) + let @/='one\_s*two\_s' + exe "norm! gnceins\zwei" + call assert_equal(['','eins','zwei'], getline(1,'$')) + sil! %d _ + " test count argument + call setline('.', ['', 'abcdx | abcdx | abcdx']) + let @/='[a]bcdx' + exe "norm! 2gnd" + call assert_equal(['','abcdx | | abcdx'], getline(1,'$')) + sil! %d _ + " join lines + call setline('.', ['join ', 'lines']) + let @/='$' + exe "norm! 0gnd" + call assert_equal(['join lines'], getline(1,'$')) + sil! %d _ + " zero-width match + call setline('.', ['', 'zero width pattern']) + let @/='\>\zs' + exe "norm! 0gnd" + call assert_equal(['', 'zerowidth pattern'], getline(1,'$')) + sil! %d _ + " delete first and last chars + call setline('.', ['delete first and last chars']) + let @/='^' + exe "norm! 0gnd$" + let @/='\zs' + exe "norm! gnd" + call assert_equal(['elete first and last char'], getline(1,'$')) + sil! %d _ + " using visual mode + call setline('.', ['', 'uniquepattern uniquepattern']) + exe "norm! /[u]niquepattern/s\vlgnd" + call assert_equal(['', ' uniquepattern'], getline(1,'$')) + sil! %d _ + " backwards search + call setline('.', ['my very excellent mother just served us nachos']) + let @/='mother' + exe "norm! $cgNmongoose" + call assert_equal(['my very excellent mongoose just served us nachos'], getline(1,'$')) + sil! %d _ + " search for single char + call setline('.', ['','for (i=0; i<=10; i++)']) + let @/='i' + exe "norm! cgnj" + call assert_equal(['','for (j=0; i<=10; i++)'], getline(1,'$')) + sil! %d _ + " search hex char + call setline('.', ['','Y']) + set noignorecase + let @/='\%x59' + exe "norm! gnd" + call assert_equal(['',''], getline(1,'$')) + sil! %d _ + " test repeating gdn + call setline('.', ['', '1', 'Johnny', '2', 'Johnny', '3']) + let @/='Johnny' + exe "norm! dgn." + call assert_equal(['','1', '', '2', '', '3'], getline(1,'$')) + sil! %d _ + " test repeating gUgn + call setline('.', ['', '1', 'Depp', '2', 'Depp', '3']) + let @/='Depp' + exe "norm! gUgn." + call assert_equal(['', '1', 'DEPP', '2', 'DEPP', '3'], getline(1,'$')) + sil! %d _ + " test using look-ahead assertions + call setline('.', ['a:10', '', 'a:1', '', 'a:20']) + let @/='a:0\@!\zs\d\+' + exe "norm! 2nygno\p" + call assert_equal(['a:10', '', 'a:1', '1', '', 'a:20'], getline(1,'$')) + sil! %d _ +endfu + +" vim: tabstop=2 shiftwidth=0 expandtab diff --git a/src/nvim/version.c b/src/nvim/version.c index b8f0acb96b..3e9cccda20 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -340,7 +340,7 @@ static int included_patches[] = { 2103, // 2102 NA // 2101, - // 2100, + 2100, // 2099, // 2098, // 2097,