1" Tests for search_stats, when "S" is not in 'shortmess' 2 3source screendump.vim 4source check.vim 5 6func Test_search_stat() 7 new 8 set shortmess-=S 9 " Append 50 lines with text to search for, "foobar" appears 20 times 10 call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 10)) 11 call nvim_win_set_cursor(0, [1, 0]) 12 13 " searchcount() returns an empty dictionary when previous pattern was not set 14 call assert_equal({}, searchcount(#{pattern: ''})) 15 " but setting @/ should also work (even 'n' nor 'N' was executed) 16 " recompute the count when the last position is different. 17 call assert_equal( 18 \ #{current: 1, exact_match: 1, total: 40, incomplete: 0, maxcount: 99}, 19 \ searchcount(#{pattern: 'foo'})) 20 call assert_equal( 21 \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 99}, 22 \ searchcount(#{pattern: 'fooooobar'})) 23 call assert_equal( 24 \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 99}, 25 \ searchcount(#{pattern: 'fooooobar', pos: [2, 1, 0]})) 26 call assert_equal( 27 \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 99}, 28 \ searchcount(#{pattern: 'fooooobar', pos: [3, 1, 0]})) 29 " on last char of match 30 call assert_equal( 31 \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 99}, 32 \ searchcount(#{pattern: 'fooooobar', pos: [3, 9, 0]})) 33 " on char after match 34 call assert_equal( 35 \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 99}, 36 \ searchcount(#{pattern: 'fooooobar', pos: [3, 10, 0]})) 37 call assert_equal( 38 \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 99}, 39 \ searchcount(#{pattern: 'fooooobar', pos: [4, 1, 0]})) 40 call assert_equal( 41 \ #{current: 1, exact_match: 0, total: 2, incomplete: 2, maxcount: 1}, 42 \ searchcount(#{pattern: 'fooooobar', pos: [4, 1, 0], maxcount: 1})) 43 call assert_equal( 44 \ #{current: 0, exact_match: 0, total: 2, incomplete: 2, maxcount: 1}, 45 \ searchcount(#{pattern: 'fooooobar', maxcount: 1})) 46 47 " match at second line 48 call cursor(1, 1) 49 let messages_before = execute('messages') 50 let @/ = 'fo*\(bar\?\)\?' 51 let g:a = execute(':unsilent :norm! n') 52 let stat = '\[2/50\]' 53 let pat = escape(@/, '()*?'). '\s\+' 54 call assert_match(pat .. stat, g:a) 55 call assert_equal( 56 \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 99}, 57 \ searchcount(#{recompute: 0})) 58 " didn't get added to message history 59 call assert_equal(messages_before, execute('messages')) 60 61 " Match at last line 62 call cursor(line('$')-2, 1) 63 let g:a = execute(':unsilent :norm! n') 64 let stat = '\[50/50\]' 65 call assert_match(pat .. stat, g:a) 66 call assert_equal( 67 \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99}, 68 \ searchcount(#{recompute: 0})) 69 70 " No search stat 71 set shortmess+=S 72 call cursor(1, 1) 73 let stat = '\[2/50\]' 74 let g:a = execute(':unsilent :norm! n') 75 call assert_notmatch(pat .. stat, g:a) 76 call writefile(getline(1, '$'), 'sample.txt') 77 " n does not update search stat 78 call assert_equal( 79 \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99}, 80 \ searchcount(#{recompute: 0})) 81 call assert_equal( 82 \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 99}, 83 \ searchcount(#{recompute: v:true})) 84 set shortmess-=S 85 86 " Many matches 87 call cursor(line('$')-2, 1) 88 let @/ = '.' 89 let pat = escape(@/, '()*?'). '\s\+' 90 let g:a = execute(':unsilent :norm! n') 91 let stat = '\[>99/>99\]' 92 call assert_match(pat .. stat, g:a) 93 call assert_equal( 94 \ #{current: 100, exact_match: 0, total: 100, incomplete: 2, maxcount: 99}, 95 \ searchcount(#{recompute: 0})) 96 call assert_equal( 97 \ #{current: 272, exact_match: 1, total: 280, incomplete: 0, maxcount: 0}, 98 \ searchcount(#{recompute: v:true, maxcount: 0, timeout: 200})) 99 call assert_equal( 100 \ #{current: 1, exact_match: 1, total: 280, incomplete: 0, maxcount: 0}, 101 \ searchcount(#{recompute: 1, maxcount: 0, pos: [1, 1, 0], timeout: 200})) 102 call cursor(line('$'), 1) 103 let g:a = execute(':unsilent :norm! n') 104 let stat = 'W \[1/>99\]' 105 call assert_match(pat .. stat, g:a) 106 call assert_equal( 107 \ #{current: 1, exact_match: 1, total: 100, incomplete: 2, maxcount: 99}, 108 \ searchcount(#{recompute: 0})) 109 call assert_equal( 110 \ #{current: 1, exact_match: 1, total: 280, incomplete: 0, maxcount: 0}, 111 \ searchcount(#{recompute: 1, maxcount: 0, timeout: 200})) 112 call assert_equal( 113 \ #{current: 271, exact_match: 1, total: 280, incomplete: 0, maxcount: 0}, 114 \ searchcount(#{recompute: 1, maxcount: 0, pos: [line('$')-2, 1, 0], timeout: 200})) 115 116 " Many matches 117 call cursor(1, 1) 118 let g:a = execute(':unsilent :norm! n') 119 let stat = '\[2/>99\]' 120 call assert_match(pat .. stat, g:a) 121 call cursor(1, 1) 122 let g:a = execute(':unsilent :norm! N') 123 let stat = 'W \[>99/>99\]' 124 call assert_match(pat .. stat, g:a) 125 126 " right-left 127 if exists("+rightleft") 128 set rl 129 call cursor(1,1) 130 let @/ = 'foobar' 131 let pat = 'raboof/\s\+' 132 let g:a = execute(':unsilent :norm! n') 133 let stat = '\[20/2\]' 134 call assert_match(pat .. stat, g:a) 135 set norl 136 endif 137 138 " right-left bottom 139 if exists("+rightleft") 140 set rl 141 call cursor('$',1) 142 let pat = 'raboof?\s\+' 143 let g:a = execute(':unsilent :norm! N') 144 let stat = '\[20/20\]' 145 call assert_match(pat .. stat, g:a) 146 set norl 147 endif 148 149 " right-left back at top 150 if exists("+rightleft") 151 set rl 152 call cursor('$',1) 153 let pat = 'raboof/\s\+' 154 let g:a = execute(':unsilent :norm! n') 155 let stat = 'W \[20/1\]' 156 call assert_match(pat .. stat, g:a) 157 call assert_match('search hit BOTTOM, continuing at TOP', g:a) 158 set norl 159 endif 160 161 " normal, back at bottom 162 call cursor(1,1) 163 let @/ = 'foobar' 164 let pat = '?foobar\s\+' 165 let g:a = execute(':unsilent :norm! N') 166 let stat = 'W \[20/20\]' 167 call assert_match(pat .. stat, g:a) 168 call assert_match('search hit TOP, continuing at BOTTOM', g:a) 169 call assert_match('W \[20/20\]', Screenline(&lines)) 170 171 " normal, no match 172 call cursor(1,1) 173 let @/ = 'zzzzzz' 174 let g:a = '' 175 try 176 let g:a = execute(':unsilent :norm! n') 177 catch /^Vim\%((\a\+)\)\=:E486/ 178 let stat = '' 179 " error message is not redir'ed to g:a, it is empty 180 call assert_true(empty(g:a)) 181 catch 182 call assert_false(1) 183 endtry 184 185 " with count 186 call cursor(1, 1) 187 let @/ = 'fo*\(bar\?\)\?' 188 let g:a = execute(':unsilent :norm! 2n') 189 let stat = '\[3/50\]' 190 let pat = escape(@/, '()*?'). '\s\+' 191 call assert_match(pat .. stat, g:a) 192 let g:a = execute(':unsilent :norm! 2n') 193 let stat = '\[5/50\]' 194 call assert_match(pat .. stat, g:a) 195 196 " with offset 197 call cursor(1, 1) 198 call feedkeys("/fo*\\(bar\\?\\)\\?/+1\<cr>", 'tx') 199 let g:a = execute(':unsilent :norm! n') 200 let stat = '\[5/50\]' 201 let pat = escape(@/ .. '/+1', '()*?'). '\s\+' 202 call assert_match(pat .. stat, g:a) 203 204 " normal, n comes from a mapping 205 " Need to move over more than 64 lines to trigger char_avail(. 206 nnoremap n nzv 207 call cursor(1,1) 208 call append(50, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 10)) 209 call setline(2, 'find this') 210 call setline(70, 'find this') 211 let @/ = 'find this' 212 let pat = '/find this\s\+' 213 let g:a = execute(':unsilent :norm n') 214 " g:a will contain several lines 215 let g:b = split(g:a, "\n")[-1] 216 let stat = '\[1/2\]' 217 call assert_match(pat .. stat, g:b) 218 unmap n 219 220 " normal, but silent 221 call cursor(1,1) 222 let @/ = 'find this' 223 let pat = '/find this\s\+' 224 let g:a = execute(':norm! n') 225 let stat = '\[1/2\]' 226 call assert_notmatch(pat .. stat, g:a) 227 228 " normal, n comes from a silent mapping 229 " First test a normal mapping, then a silent mapping 230 call cursor(1,1) 231 nnoremap n n 232 let @/ = 'find this' 233 let pat = '/find this\s\+' 234 let g:a = execute(':unsilent :norm n') 235 let g:b = split(g:a, "\n")[-1] 236 let stat = '\[1/2\]' 237 call assert_match(pat .. stat, g:b) 238 nnoremap <silent> n n 239 call cursor(1,1) 240 let g:a = execute(':unsilent :norm n') 241 let g:b = split(g:a, "\n")[-1] 242 let stat = '\[1/2\]' 243 call assert_notmatch(pat .. stat, g:b) 244 call assert_match(stat, g:b) 245 " Test that the message is not truncated 246 " it would insert '...' into the output. 247 call assert_match('^\s\+' .. stat, g:b) 248 unmap n 249 250 " Time out 251 %delete _ 252 call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 100000)) 253 call cursor(1, 1) 254 call assert_equal(1, searchcount(#{pattern: 'foo', maxcount: 0, timeout: 1}).incomplete) 255 256 " Clean up 257 set shortmess+=S 258 " close the window 259 bwipe! 260endfunc 261 262func Test_searchcount_fails() 263 call assert_fails('echo searchcount("boo!")', 'E715:') 264endfunc 265 266func Test_search_stat_foldopen() 267 CheckScreendump 268 269 let lines =<< trim END 270 set shortmess-=S 271 setl foldenable foldmethod=indent foldopen-=search 272 call append(0, ['if', "\tfoo", "\tfoo", 'endif']) 273 let @/ = 'foo' 274 call cursor(1,1) 275 norm n 276 END 277 call writefile(lines, 'Xsearchstat1') 278 279 let buf = RunVimInTerminal('-S Xsearchstat1', #{rows: 10}) 280 call TermWait(buf) 281 call VerifyScreenDump(buf, 'Test_searchstat_3', {}) 282 283 call term_sendkeys(buf, "n") 284 call TermWait(buf) 285 call VerifyScreenDump(buf, 'Test_searchstat_3', {}) 286 287 call term_sendkeys(buf, "n") 288 call TermWait(buf) 289 call VerifyScreenDump(buf, 'Test_searchstat_3', {}) 290 291 call StopVimInTerminal(buf) 292 call delete('Xsearchstat1') 293endfunc 294 295func! Test_search_stat_screendump() 296 CheckScreendump 297 298 let lines =<< trim END 299 set shortmess-=S 300 " Append 50 lines with text to search for, "foobar" appears 20 times 301 call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 20)) 302 call setline(2, 'find this') 303 call setline(70, 'find this') 304 nnoremap n n 305 let @/ = 'find this' 306 call cursor(1,1) 307 norm n 308 END 309 call writefile(lines, 'Xsearchstat') 310 let buf = RunVimInTerminal('-S Xsearchstat', #{rows: 10}) 311 call term_wait(buf) 312 call VerifyScreenDump(buf, 'Test_searchstat_1', {}) 313 314 call term_sendkeys(buf, ":nnoremap <silent> n n\<cr>") 315 call term_sendkeys(buf, "gg0n") 316 call term_wait(buf) 317 call VerifyScreenDump(buf, 'Test_searchstat_2', {}) 318 319 call StopVimInTerminal(buf) 320 call delete('Xsearchstat') 321endfunc 322 323func Test_searchcount_in_statusline() 324 CheckScreendump 325 326 let lines =<< trim END 327 set shortmess-=S 328 call append(0, 'this is something') 329 function TestSearchCount() abort 330 let search_count = searchcount() 331 if !empty(search_count) 332 return '[' . search_count.current . '/' . search_count.total . ']' 333 else 334 return '' 335 endif 336 endfunction 337 set hlsearch 338 set laststatus=2 statusline+=%{TestSearchCount()} 339 END 340 call writefile(lines, 'Xsearchstatusline') 341 let buf = RunVimInTerminal('-S Xsearchstatusline', #{rows: 10}) 342 call TermWait(buf) 343 call term_sendkeys(buf, "/something") 344 call VerifyScreenDump(buf, 'Test_searchstat_4', {}) 345 346 call term_sendkeys(buf, "\<Esc>") 347 call StopVimInTerminal(buf) 348 call delete('Xsearchstatusline') 349endfunc 350