vim-patch:7.4.2100

Problem:    "cgn" and "dgn" do not work correctly with a single character
            match and the replacement includes the searched pattern. (John
            Beckett)
Solution:   If the match is found in the wrong column try in the next column.
            Turn the test into new style. (Christian Brabandt)

6835dc61ae

Closes #5796
This commit is contained in:
James McCoy 2017-01-10 10:21:48 -05:00
parent 6095c5df45
commit 4c3204097c
6 changed files with 117 additions and 94 deletions

View File

@ -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, * If move is true, check from the beginning of the buffer,
* else from the current cursor position. * else from the current cursor position.
* Returns TRUE, FALSE or -1 for failure. * 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 save_called_emsg = called_emsg;
int flag = 0; int flag = 0;
if (pattern == NULL) {
pattern = spats[last_idx].pat;
}
if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH, if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH,
SEARCH_KEEP, &regmatch) == FAIL) SEARCH_KEEP, &regmatch) == FAIL)
return -1; return -1;
// init startcol correctly
regmatch.startpos[0].col = -1;
/* move to match */ /* move to match */
if (move) { if (move) {
clearpos(&pos); clearpos(&pos);
@ -4003,21 +4009,29 @@ static int is_one_char(char_u *pattern, bool move)
/* accept a match at the cursor position */ /* accept a match at the cursor position */
flag = SEARCH_START; 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) { SEARCH_KEEP + flag, RE_SEARCH, 0, NULL) != FAIL) {
/* Zero-width pattern should match somewhere, then we can check if /* Zero-width pattern should match somewhere, then we can check if
* start and end are in the same position. */ * start and end are in the same position. */
called_emsg = FALSE; called_emsg = FALSE;
nmatched = vim_regexec_multi(&regmatch, curwin, curbuf, do {
pos.lnum, (colnr_T)0, NULL); regmatch.startpos[0].col++;
nmatched = vim_regexec_multi(&regmatch, 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 result = (nmatched != 0
&& regmatch.startpos[0].lnum == regmatch.endpos[0].lnum && regmatch.startpos[0].lnum == regmatch.endpos[0].lnum
&& regmatch.startpos[0].col == regmatch.endpos[0].col); && regmatch.startpos[0].col == regmatch.endpos[0].col);
// one char width
if (!result && inc(&pos) >= 0 && pos.col == regmatch.endpos[0].col) if (!result && inc(&pos) >= 0 && pos.col == regmatch.endpos[0].col) {
result = TRUE; result = true;
}
}
} }
called_emsg |= save_called_emsg; called_emsg |= save_called_emsg;

View File

@ -34,6 +34,7 @@ NEW_TESTS = \
test_cmdline.res \ test_cmdline.res \
test_cscope.res \ test_cscope.res \
test_diffmode.res \ test_diffmode.res \
test_gn.res \
test_hardcopy.res \ test_hardcopy.res \
test_help_tagjump.res \ test_help_tagjump.res \
test_history.res \ test_history.res \

View File

@ -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 match() and matchstr()
Also test the gn command and repeating it.
STARTTEST STARTTEST
/^start:/ /^start:/
da" da"
@ -52,35 +50,6 @@ dit
:put =match('abc', '\zs', 2, 1) " 2 :put =match('abc', '\zs', 2, 1) " 2
:put =match('abc', '\zs', 3, 1) " 3 :put =match('abc', '\zs', 3, 1) " 3
:put =match('abc', '\zs', 4, 1) " -1 :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 :/^start:/,/^end:/wq! test.out
ENDTEST ENDTEST
@ -102,32 +71,4 @@ innertext object
</b> </b>
</begin> </begin>
SEARCH: 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: end:

View File

@ -42,30 +42,4 @@ a
3 3
-1 -1
SEARCH: 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: end:

View File

@ -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'\<esc>.."
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\<CR>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\<cr>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\<esc>p"
call assert_equal(['a:10', '', 'a:1', '1', '', 'a:20'], getline(1,'$'))
sil! %d _
endfu
" vim: tabstop=2 shiftwidth=0 expandtab

View File

@ -340,7 +340,7 @@ static int included_patches[] = {
2103, 2103,
// 2102 NA // 2102 NA
// 2101, // 2101,
// 2100, 2100,
// 2099, // 2099,
// 2098, // 2098,
// 2097, // 2097,