Skip to content

Commit bdb6579

Browse files
committed
patch 8.1.0018: using "gn" may select wrong text when wrapping
Problem: Using "gn" may select wrong text when wrapping. Solution: Avoid wrapping when searching forward. (Christian Brabandt)
1 parent 62fe66f commit bdb6579

3 files changed

Lines changed: 46 additions & 16 deletions

File tree

src/search.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4665,6 +4665,7 @@ current_search(
46654665
{
46664666
pos_T start_pos; /* position before the pattern */
46674667
pos_T orig_pos; /* position of the cursor at beginning */
4668+
pos_T first_match; /* position of first match */
46684669
pos_T pos; /* position after the pattern */
46694670
int i;
46704671
int dir;
@@ -4758,6 +4759,8 @@ current_search(
47584759
ml_get(curwin->w_buffer->b_ml.ml_line_count));
47594760
}
47604761
}
4762+
if (i == 0)
4763+
first_match = pos;
47614764
p_ws = old_p_ws;
47624765
}
47634766

@@ -4774,9 +4777,25 @@ current_search(
47744777
/* move to match, except for zero-width matches, in which case, we are
47754778
* already on the next match */
47764779
if (!one_char)
4777-
result = searchit(curwin, curbuf, &pos, direction,
4780+
{
4781+
p_ws = FALSE;
4782+
for (i = 0; i < 2; i++)
4783+
{
4784+
result = searchit(curwin, curbuf, &pos, direction,
47784785
spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0,
47794786
NULL, NULL);
4787+
/* Search successfull, break out from the loop */
4788+
if (result)
4789+
break;
4790+
/* search failed, try again from the last search position match */
4791+
pos = first_match;
4792+
}
4793+
}
4794+
4795+
p_ws = old_p_ws;
4796+
/* not found */
4797+
if (!result)
4798+
return FAIL;
47804799

47814800
if (!VIsual_active)
47824801
VIsual = start_pos;

src/testdir/test_gn.vim

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,51 @@ func Test_gn_command()
44
noautocmd new
55
" replace a single char by itsself quoted:
66
call setline('.', 'abc x def x ghi x jkl')
7-
let @/='x'
7+
let @/ = 'x'
88
exe "norm! cgn'x'\<esc>.."
99
call assert_equal("abc 'x' def 'x' ghi 'x' jkl", getline('.'))
1010
sil! %d_
1111

1212
" simple search match
1313
call setline('.', 'foobar')
14-
let @/='foobar'
14+
let @/ = 'foobar'
1515
exe "norm! gncsearchmatch"
1616
call assert_equal('searchmatch', getline('.'))
1717
sil! %d _
1818

1919
" replace a multi-line match
2020
call setline('.', ['', 'one', 'two'])
21-
let @/='one\_s*two\_s'
21+
let @/ = 'one\_s*two\_s'
2222
exe "norm! gnceins\<CR>zwei"
2323
call assert_equal(['','eins','zwei'], getline(1,'$'))
2424
sil! %d _
2525

2626
" test count argument
2727
call setline('.', ['', 'abcdx | abcdx | abcdx'])
28-
let @/='[a]bcdx'
28+
let @/ = '[a]bcdx'
2929
exe "norm! 2gnd"
3030
call assert_equal(['','abcdx | | abcdx'], getline(1,'$'))
3131
sil! %d _
3232

3333
" join lines
3434
call setline('.', ['join ', 'lines'])
35-
let @/='$'
35+
let @/ = '$'
3636
exe "norm! 0gnd"
3737
call assert_equal(['join lines'], getline(1,'$'))
3838
sil! %d _
3939

4040
" zero-width match
4141
call setline('.', ['', 'zero width pattern'])
42-
let @/='\>\zs'
42+
let @/ = '\>\zs'
4343
exe "norm! 0gnd"
4444
call assert_equal(['', 'zerowidth pattern'], getline(1,'$'))
4545
sil! %d _
4646

4747
" delete first and last chars
4848
call setline('.', ['delete first and last chars'])
49-
let @/='^'
49+
let @/ = '^'
5050
exe "norm! 0gnd$"
51-
let @/='\zs'
51+
let @/ = '\zs'
5252
exe "norm! gnd"
5353
call assert_equal(['elete first and last char'], getline(1,'$'))
5454
sil! %d _
@@ -61,43 +61,43 @@ func Test_gn_command()
6161

6262
" backwards search
6363
call setline('.', ['my very excellent mother just served us nachos'])
64-
let @/='mother'
64+
let @/ = 'mother'
6565
exe "norm! $cgNmongoose"
6666
call assert_equal(['my very excellent mongoose just served us nachos'], getline(1,'$'))
6767
sil! %d _
6868

6969
" search for single char
7070
call setline('.', ['','for (i=0; i<=10; i++)'])
71-
let @/='i'
71+
let @/ = 'i'
7272
exe "norm! cgnj"
7373
call assert_equal(['','for (j=0; i<=10; i++)'], getline(1,'$'))
7474
sil! %d _
7575

7676
" search hex char
7777
call setline('.', ['','Y'])
7878
set noignorecase
79-
let @/='\%x59'
79+
let @/ = '\%x59'
8080
exe "norm! gnd"
8181
call assert_equal(['',''], getline(1,'$'))
8282
sil! %d _
8383

8484
" test repeating gdn
8585
call setline('.', ['', '1', 'Johnny', '2', 'Johnny', '3'])
86-
let @/='Johnny'
86+
let @/ = 'Johnny'
8787
exe "norm! dgn."
8888
call assert_equal(['','1', '', '2', '', '3'], getline(1,'$'))
8989
sil! %d _
9090

9191
" test repeating gUgn
9292
call setline('.', ['', '1', 'Depp', '2', 'Depp', '3'])
93-
let @/='Depp'
93+
let @/ = 'Depp'
9494
exe "norm! gUgn."
9595
call assert_equal(['', '1', 'DEPP', '2', 'DEPP', '3'], getline(1,'$'))
9696
sil! %d _
9797

9898
" test using look-ahead assertions
9999
call setline('.', ['a:10', '', 'a:1', '', 'a:20'])
100-
let @/='a:0\@!\zs\d\+'
100+
let @/ = 'a:0\@!\zs\d\+'
101101
exe "norm! 2nygno\<esc>p"
102102
call assert_equal(['a:10', '', 'a:1', '1', '', 'a:20'], getline(1,'$'))
103103
sil! %d _
@@ -113,12 +113,21 @@ func Test_gn_command()
113113
" search upwards with nowrapscan set
114114
call setline('.', ['foo', 'bar', 'foo', 'baz'])
115115
set nowrapscan
116-
let @/='foo'
116+
let @/ = 'foo'
117117
$
118118
norm! dgN
119119
call assert_equal(['foo', 'bar', '', 'baz'], getline(1,'$'))
120120
sil! %d_
121121

122+
" search using the \zs atom
123+
call setline(1, [' nnoremap', '' , 'nnoremap'])
124+
set wrapscan&vim
125+
let @/ = '\_s\zsnnoremap'
126+
$
127+
norm! cgnmatch
128+
call assert_equal([' nnoremap', '', 'match'], getline(1,'$'))
129+
sil! %d_
130+
122131
set wrapscan&vim
123132
endfu
124133

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,8 @@ static char *(features[]) =
761761

762762
static int included_patches[] =
763763
{ /* Add new patch number below this line */
764+
/**/
765+
18,
764766
/**/
765767
17,
766768
/**/

0 commit comments

Comments
 (0)