test_search_stat.vim 14 KB

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