completion_spec.lua 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local assert_alive = n.assert_alive
  5. local clear, feed = n.clear, n.feed
  6. local eval, eq, neq, ok = n.eval, t.eq, t.neq, t.ok
  7. local feed_command, source, expect = n.feed_command, n.source, n.expect
  8. local fn = n.fn
  9. local command = n.command
  10. local api = n.api
  11. local poke_eventloop = n.poke_eventloop
  12. describe('completion', function()
  13. local screen
  14. before_each(function()
  15. clear()
  16. screen = Screen.new(60, 8)
  17. screen:add_extra_attr_ids {
  18. [100] = { foreground = Screen.colors.Gray0, background = Screen.colors.Yellow },
  19. [101] = { background = Screen.colors.Gray0 },
  20. }
  21. end)
  22. describe('v:completed_item', function()
  23. it('is empty dict until completion', function()
  24. eq({}, eval('v:completed_item'))
  25. end)
  26. it('is empty dict if the candidate is not inserted', function()
  27. feed('ifoo<ESC>o<C-x><C-n>')
  28. screen:expect([[
  29. foo |
  30. foo^ |
  31. {1:~ }|*5
  32. {5:-- Keyword Local completion (^N^P) The only match} |
  33. ]])
  34. feed('<C-e>')
  35. screen:expect([[
  36. foo |
  37. ^ |
  38. {1:~ }|*5
  39. {5:-- INSERT --} |
  40. ]])
  41. feed('<ESC>')
  42. eq({}, eval('v:completed_item'))
  43. end)
  44. it('returns expected dict in normal completion', function()
  45. feed('ifoo<ESC>o<C-x><C-n>')
  46. eq('foo', eval('getline(2)'))
  47. eq(
  48. { word = 'foo', abbr = '', menu = '', info = '', kind = '', user_data = '' },
  49. eval('v:completed_item')
  50. )
  51. end)
  52. it('is readonly', function()
  53. screen:try_resize(80, 8)
  54. feed('ifoo<ESC>o<C-x><C-n><ESC>')
  55. feed_command('let v:completed_item.word = "bar"')
  56. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  57. feed_command('let v:errmsg = ""')
  58. feed_command('let v:completed_item.abbr = "bar"')
  59. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  60. feed_command('let v:errmsg = ""')
  61. feed_command('let v:completed_item.menu = "bar"')
  62. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  63. feed_command('let v:errmsg = ""')
  64. feed_command('let v:completed_item.info = "bar"')
  65. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  66. feed_command('let v:errmsg = ""')
  67. feed_command('let v:completed_item.kind = "bar"')
  68. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  69. feed_command('let v:errmsg = ""')
  70. feed_command('let v:completed_item.user_data = "bar"')
  71. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  72. feed_command('let v:errmsg = ""')
  73. end)
  74. it('returns expected dict in omni completion', function()
  75. source([[
  76. function! TestOmni(findstart, base) abort
  77. return a:findstart ? 0 : [{'word': 'foo', 'abbr': 'bar',
  78. \ 'menu': 'baz', 'info': 'foobar', 'kind': 'foobaz'},
  79. \ {'word': 'word', 'abbr': 'abbr', 'menu': 'menu',
  80. \ 'info': 'info', 'kind': 'kind'}]
  81. endfunction
  82. setlocal omnifunc=TestOmni
  83. ]])
  84. feed('i<C-x><C-o>')
  85. eq('foo', eval('getline(1)'))
  86. screen:expect([[
  87. foo^ |
  88. {12:bar foobaz baz }{1: }|
  89. {4:abbr kind menu }{1: }|
  90. {1:~ }|*4
  91. {5:-- Omni completion (^O^N^P) }{6:match 1 of 2} |
  92. ]])
  93. eq({
  94. word = 'foo',
  95. abbr = 'bar',
  96. menu = 'baz',
  97. info = 'foobar',
  98. kind = 'foobaz',
  99. user_data = '',
  100. }, eval('v:completed_item'))
  101. end)
  102. end)
  103. describe('completeopt', function()
  104. before_each(function()
  105. source([[
  106. function! TestComplete() abort
  107. call complete(1, ['foo'])
  108. return ''
  109. endfunction
  110. ]])
  111. end)
  112. it('inserts the first candidate if default', function()
  113. feed_command('set completeopt+=menuone')
  114. feed('ifoo<ESC>o')
  115. screen:expect([[
  116. foo |
  117. ^ |
  118. {1:~ }|*5
  119. {5:-- INSERT --} |
  120. ]])
  121. feed('<C-x>')
  122. -- the ^X prompt, only test this once
  123. screen:expect([[
  124. foo |
  125. ^ |
  126. {1:~ }|*5
  127. {5:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} |
  128. ]])
  129. feed('<C-n>')
  130. screen:expect([[
  131. foo |
  132. foo^ |
  133. {12:foo }{1: }|
  134. {1:~ }|*4
  135. {5:-- Keyword Local completion (^N^P) The only match} |
  136. ]])
  137. feed('bar<ESC>')
  138. eq('foobar', eval('getline(2)'))
  139. feed('o<C-r>=TestComplete()<CR>')
  140. screen:expect([[
  141. foo |
  142. foobar |
  143. foo^ |
  144. {12:foo }{1: }|
  145. {1:~ }|*3
  146. {5:-- INSERT --} |
  147. ]])
  148. eq('foo', eval('getline(3)'))
  149. end)
  150. it('selects the first candidate if noinsert', function()
  151. feed_command('set completeopt+=menuone,noinsert')
  152. feed('ifoo<ESC>o<C-x><C-n>')
  153. screen:expect([[
  154. foo |
  155. ^ |
  156. {12:foo }{1: }|
  157. {1:~ }|*4
  158. {5:-- Keyword Local completion (^N^P) The only match} |
  159. ]])
  160. feed('<C-y>')
  161. screen:expect([[
  162. foo |
  163. foo^ |
  164. {1:~ }|*5
  165. {5:-- INSERT --} |
  166. ]])
  167. feed('<ESC>')
  168. eq('foo', eval('getline(2)'))
  169. feed('o<C-r>=TestComplete()<CR>')
  170. screen:expect([[
  171. foo |*2
  172. ^ |
  173. {12:foo }{1: }|
  174. {1:~ }|*3
  175. {5:-- INSERT --} |
  176. ]])
  177. feed('<C-y><ESC>')
  178. eq('foo', eval('getline(3)'))
  179. end)
  180. it('does not insert the first candidate if noselect', function()
  181. feed_command('set completeopt+=menuone,noselect')
  182. feed('ifoo<ESC>o<C-x><C-n>')
  183. screen:expect([[
  184. foo |
  185. ^ |
  186. {4:foo }{1: }|
  187. {1:~ }|*4
  188. {5:-- Keyword Local completion (^N^P) }{19:Back at original} |
  189. ]])
  190. feed('b')
  191. screen:expect([[
  192. foo |
  193. b^ |
  194. {1:~ }|*5
  195. {5:-- Keyword Local completion (^N^P) }{19:Back at original} |
  196. ]])
  197. feed('ar<ESC>')
  198. eq('bar', eval('getline(2)'))
  199. feed('o<C-r>=TestComplete()<CR>')
  200. screen:expect([[
  201. foo |
  202. bar |
  203. ^ |
  204. {4:foo }{1: }|
  205. {1:~ }|*3
  206. {5:-- INSERT --} |
  207. ]])
  208. feed('bar<ESC>')
  209. eq('bar', eval('getline(3)'))
  210. end)
  211. it('does not select/insert the first candidate if noselect and noinsert', function()
  212. feed_command('set completeopt+=menuone,noselect,noinsert')
  213. feed('ifoo<ESC>o<C-x><C-n>')
  214. screen:expect([[
  215. foo |
  216. ^ |
  217. {4:foo }{1: }|
  218. {1:~ }|*4
  219. {5:-- Keyword Local completion (^N^P) }{19:Back at original} |
  220. ]])
  221. feed('<ESC>')
  222. screen:expect([[
  223. foo |
  224. ^ |
  225. {1:~ }|*5
  226. |
  227. ]])
  228. eq('', eval('getline(2)'))
  229. feed('o<C-r>=TestComplete()<CR>')
  230. screen:expect([[
  231. foo |
  232. |
  233. ^ |
  234. {4:foo }{1: }|
  235. {1:~ }|*3
  236. {5:-- INSERT --} |
  237. ]])
  238. feed('<ESC>')
  239. screen:expect([[
  240. foo |
  241. |
  242. ^ |
  243. {1:~ }|*4
  244. |
  245. ]])
  246. eq('', eval('getline(3)'))
  247. end)
  248. it('does not change modified state if noinsert', function()
  249. feed_command('set completeopt+=menuone,noinsert')
  250. feed_command('setlocal nomodified')
  251. feed('i<C-r>=TestComplete()<CR><ESC>')
  252. eq(0, eval('&l:modified'))
  253. end)
  254. it('does not change modified state if noselect', function()
  255. feed_command('set completeopt+=menuone,noselect')
  256. feed_command('setlocal nomodified')
  257. feed('i<C-r>=TestComplete()<CR><ESC>')
  258. eq(0, eval('&l:modified'))
  259. end)
  260. end)
  261. describe('completeopt+=noinsert does not add blank undo items', function()
  262. before_each(function()
  263. source([[
  264. function! TestComplete() abort
  265. call complete(1, ['foo', 'bar'])
  266. return ''
  267. endfunction
  268. ]])
  269. feed_command('set completeopt+=noselect,noinsert')
  270. feed_command('inoremap <right> <c-r>=TestComplete()<cr>')
  271. end)
  272. local tests = {
  273. ['<up>, <down>, <cr>'] = { '<down><cr>', '<up><cr>' },
  274. ['<c-n>, <c-p>, <c-y>'] = { '<c-n><c-y>', '<c-p><c-y>' },
  275. }
  276. for name, seq in pairs(tests) do
  277. it('using ' .. name, function()
  278. feed('iaaa<esc>')
  279. feed('A<right>' .. seq[1] .. '<esc>')
  280. feed('A<right><esc>A<right><esc>')
  281. feed('A<cr>bbb<esc>')
  282. feed('A<right>' .. seq[2] .. '<esc>')
  283. feed('A<right><esc>A<right><esc>')
  284. feed('A<cr>ccc<esc>')
  285. feed('A<right>' .. seq[1] .. '<esc>')
  286. feed('A<right><esc>A<right><esc>')
  287. local expected = {
  288. { 'foo', 'bar', 'foo' },
  289. { 'foo', 'bar', 'ccc' },
  290. { 'foo', 'bar' },
  291. { 'foo', 'bbb' },
  292. { 'foo' },
  293. { 'aaa' },
  294. { '' },
  295. }
  296. for i = 1, #expected do
  297. if i > 1 then
  298. feed('u')
  299. end
  300. eq(expected[i], eval('getline(1, "$")'))
  301. end
  302. for i = #expected, 1, -1 do
  303. if i < #expected then
  304. feed('<c-r>')
  305. end
  306. eq(expected[i], eval('getline(1, "$")'))
  307. end
  308. end)
  309. end
  310. end)
  311. describe('with refresh:always and noselect', function()
  312. before_each(function()
  313. source([[
  314. function! TestCompletion(findstart, base) abort
  315. if a:findstart
  316. let line = getline('.')
  317. let start = col('.') - 1
  318. while start > 0 && line[start - 1] =~ '\a'
  319. let start -= 1
  320. endwhile
  321. return start
  322. else
  323. let ret = []
  324. for m in split("January February March April May June July August September October November December")
  325. if m =~ a:base " match by regex
  326. call add(ret, m)
  327. endif
  328. endfor
  329. return {'words':ret, 'refresh':'always'}
  330. endif
  331. endfunction
  332. set completeopt=menuone,noselect
  333. set completefunc=TestCompletion
  334. ]])
  335. end)
  336. it('completes on each input char', function()
  337. feed('i<C-x><C-u>')
  338. screen:expect([[
  339. ^ |
  340. {4:January }{101: }{1: }|
  341. {4:February }{101: }{1: }|
  342. {4:March }{101: }{1: }|
  343. {4:April }{12: }{1: }|
  344. {4:May }{12: }{1: }|
  345. {4:June }{12: }{1: }|
  346. {5:-- User defined completion (^U^N^P) }{19:Back at original} |
  347. ]])
  348. feed('u')
  349. screen:expect([[
  350. u^ |
  351. {4:January }{1: }|
  352. {4:February }{1: }|
  353. {4:June }{1: }|
  354. {4:July }{1: }|
  355. {4:August }{1: }|
  356. {1:~ }|
  357. {5:-- User defined completion (^U^N^P) }{19:Back at original} |
  358. ]])
  359. feed('g')
  360. screen:expect([[
  361. ug^ |
  362. {4:August }{1: }|
  363. {1:~ }|*5
  364. {5:-- User defined completion (^U^N^P) }{19:Back at original} |
  365. ]])
  366. feed('<Down>')
  367. screen:expect([[
  368. ug^ |
  369. {12:August }{1: }|
  370. {1:~ }|*5
  371. {5:-- User defined completion (^U^N^P) The only match} |
  372. ]])
  373. feed('<C-y>')
  374. screen:expect([[
  375. August^ |
  376. {1:~ }|*6
  377. {5:-- INSERT --} |
  378. ]])
  379. expect('August')
  380. end)
  381. it('repeats correctly after backspace #2674', function()
  382. feed('o<C-x><C-u>Ja')
  383. screen:expect([[
  384. |
  385. Ja^ |
  386. {4:January }{1: }|
  387. {1:~ }|*4
  388. {5:-- User defined completion (^U^N^P) }{19:Back at original} |
  389. ]])
  390. feed('<BS>')
  391. screen:expect([[
  392. |
  393. J^ |
  394. {4:January }{1: }|
  395. {4:June }{1: }|
  396. {4:July }{1: }|
  397. {1:~ }|*2
  398. {5:-- User defined completion (^U^N^P) }{19:Back at original} |
  399. ]])
  400. feed('<C-n>')
  401. screen:expect([[
  402. |
  403. January^ |
  404. {12:January }{1: }|
  405. {4:June }{1: }|
  406. {4:July }{1: }|
  407. {1:~ }|*2
  408. {5:-- User defined completion (^U^N^P) }{6:match 1 of 3} |
  409. ]])
  410. feed('<C-n>')
  411. screen:expect([[
  412. |
  413. June^ |
  414. {4:January }{1: }|
  415. {12:June }{1: }|
  416. {4:July }{1: }|
  417. {1:~ }|*2
  418. {5:-- User defined completion (^U^N^P) }{6:match 2 of 3} |
  419. ]])
  420. feed('<Esc>')
  421. screen:expect([[
  422. |
  423. Jun^e |
  424. {1:~ }|*5
  425. |
  426. ]])
  427. feed('.')
  428. screen:expect([[
  429. |
  430. June |
  431. Jun^e |
  432. {1:~ }|*4
  433. |
  434. ]])
  435. expect([[
  436. June
  437. June]])
  438. end)
  439. it('Enter does not select original text', function()
  440. feed('iJ<C-x><C-u>')
  441. poke_eventloop()
  442. feed('u')
  443. poke_eventloop()
  444. feed('<CR>')
  445. expect([[
  446. Ju
  447. ]])
  448. feed('J<C-x><C-u>')
  449. poke_eventloop()
  450. feed('<CR>')
  451. expect([[
  452. Ju
  453. J
  454. ]])
  455. end)
  456. end)
  457. describe('with noselect but not refresh:always', function()
  458. before_each(function()
  459. source([[
  460. function! TestCompletion(findstart, base) abort
  461. if a:findstart
  462. let line = getline('.')
  463. let start = col('.') - 1
  464. while start > 0 && line[start - 1] =~ '\a'
  465. let start -= 1
  466. endwhile
  467. return start
  468. else
  469. let ret = []
  470. for m in split("January February March April May June July August September October November December")
  471. if m =~ a:base " match by regex
  472. call add(ret, m)
  473. endif
  474. endfor
  475. return {'words':ret}
  476. endif
  477. endfunction
  478. set completeopt=menuone,noselect
  479. set completefunc=TestCompletion
  480. ]])
  481. end)
  482. it('Enter selects original text after adding leader', function()
  483. feed('iJ<C-x><C-u>')
  484. poke_eventloop()
  485. feed('u')
  486. poke_eventloop()
  487. feed('<CR>')
  488. expect('Ju')
  489. feed('<Esc>')
  490. poke_eventloop()
  491. -- The behavior should be the same when completion has been interrupted,
  492. -- which can happen interactively if the completion function is slow.
  493. feed('SJ<C-x><C-u>u<CR>')
  494. expect('Ju')
  495. end)
  496. end)
  497. describe('with a lot of items', function()
  498. before_each(function()
  499. source([[
  500. function! TestComplete() abort
  501. call complete(1, map(range(0,100), "string(v:val)"))
  502. return ''
  503. endfunction
  504. ]])
  505. feed_command('set completeopt=menuone,noselect')
  506. end)
  507. it('works', function()
  508. feed('i<C-r>=TestComplete()<CR>')
  509. screen:expect([[
  510. ^ |
  511. {4:0 }{101: }{1: }|
  512. {4:1 }{12: }{1: }|
  513. {4:2 }{12: }{1: }|
  514. {4:3 }{12: }{1: }|
  515. {4:4 }{12: }{1: }|
  516. {4:5 }{12: }{1: }|
  517. {5:-- INSERT --} |
  518. ]])
  519. feed('7')
  520. screen:expect([[
  521. 7^ |
  522. {4:7 }{101: }{1: }|
  523. {4:70 }{101: }{1: }|
  524. {4:71 }{101: }{1: }|
  525. {4:72 }{12: }{1: }|
  526. {4:73 }{12: }{1: }|
  527. {4:74 }{12: }{1: }|
  528. {5:-- INSERT --} |
  529. ]])
  530. feed('<c-n>')
  531. screen:expect([[
  532. 7^ |
  533. {12:7 }{101: }{1: }|
  534. {4:70 }{101: }{1: }|
  535. {4:71 }{101: }{1: }|
  536. {4:72 }{12: }{1: }|
  537. {4:73 }{12: }{1: }|
  538. {4:74 }{12: }{1: }|
  539. {5:-- INSERT --} |
  540. ]])
  541. feed('<c-n>')
  542. screen:expect([[
  543. 70^ |
  544. {4:7 }{101: }{1: }|
  545. {12:70 }{101: }{1: }|
  546. {4:71 }{101: }{1: }|
  547. {4:72 }{12: }{1: }|
  548. {4:73 }{12: }{1: }|
  549. {4:74 }{12: }{1: }|
  550. {5:-- INSERT --} |
  551. ]])
  552. end)
  553. it('can be navigated with <PageDown>, <PageUp>', function()
  554. feed('i<C-r>=TestComplete()<CR>')
  555. screen:expect([[
  556. ^ |
  557. {4:0 }{101: }{1: }|
  558. {4:1 }{12: }{1: }|
  559. {4:2 }{12: }{1: }|
  560. {4:3 }{12: }{1: }|
  561. {4:4 }{12: }{1: }|
  562. {4:5 }{12: }{1: }|
  563. {5:-- INSERT --} |
  564. ]])
  565. feed('<PageDown>')
  566. screen:expect([[
  567. ^ |
  568. {4:0 }{101: }{1: }|
  569. {4:1 }{12: }{1: }|
  570. {4:2 }{12: }{1: }|
  571. {12:3 }{1: }|
  572. {4:4 }{12: }{1: }|
  573. {4:5 }{12: }{1: }|
  574. {5:-- INSERT --} |
  575. ]])
  576. feed('<PageDown>')
  577. screen:expect([[
  578. ^ |
  579. {4:5 }{101: }{1: }|
  580. {4:6 }{12: }{1: }|
  581. {12:7 }{1: }|
  582. {4:8 }{12: }{1: }|
  583. {4:9 }{12: }{1: }|
  584. {4:10 }{12: }{1: }|
  585. {5:-- INSERT --} |
  586. ]])
  587. feed('<Down>')
  588. screen:expect([[
  589. ^ |
  590. {4:5 }{101: }{1: }|
  591. {4:6 }{12: }{1: }|
  592. {4:7 }{12: }{1: }|
  593. {12:8 }{1: }|
  594. {4:9 }{12: }{1: }|
  595. {4:10 }{12: }{1: }|
  596. {5:-- INSERT --} |
  597. ]])
  598. feed('<PageUp>')
  599. screen:expect([[
  600. ^ |
  601. {4:2 }{101: }{1: }|
  602. {4:3 }{12: }{1: }|
  603. {12:4 }{1: }|
  604. {4:5 }{12: }{1: }|
  605. {4:6 }{12: }{1: }|
  606. {4:7 }{12: }{1: }|
  607. {5:-- INSERT --} |
  608. ]])
  609. feed('<PageUp>') -- stop on first item
  610. screen:expect([[
  611. ^ |
  612. {12:0 }{101: }{1: }|
  613. {4:1 }{12: }{1: }|
  614. {4:2 }{12: }{1: }|
  615. {4:3 }{12: }{1: }|
  616. {4:4 }{12: }{1: }|
  617. {4:5 }{12: }{1: }|
  618. {5:-- INSERT --} |
  619. ]])
  620. feed('<PageUp>') -- when on first item, unselect
  621. screen:expect([[
  622. ^ |
  623. {4:0 }{101: }{1: }|
  624. {4:1 }{12: }{1: }|
  625. {4:2 }{12: }{1: }|
  626. {4:3 }{12: }{1: }|
  627. {4:4 }{12: }{1: }|
  628. {4:5 }{12: }{1: }|
  629. {5:-- INSERT --} |
  630. ]])
  631. feed('<PageUp>') -- when unselected, select last item
  632. screen:expect([[
  633. ^ |
  634. {4:95 }{12: }{1: }|
  635. {4:96 }{12: }{1: }|
  636. {4:97 }{12: }{1: }|
  637. {4:98 }{12: }{1: }|
  638. {4:99 }{12: }{1: }|
  639. {12:100 }{101: }{1: }|
  640. {5:-- INSERT --} |
  641. ]])
  642. feed('<PageUp>')
  643. screen:expect([[
  644. ^ |
  645. {4:94 }{12: }{1: }|
  646. {4:95 }{12: }{1: }|
  647. {12:96 }{1: }|
  648. {4:97 }{12: }{1: }|
  649. {4:98 }{12: }{1: }|
  650. {4:99 }{101: }{1: }|
  651. {5:-- INSERT --} |
  652. ]])
  653. feed('<cr>')
  654. screen:expect([[
  655. 96^ |
  656. {1:~ }|*6
  657. {5:-- INSERT --} |
  658. ]])
  659. end)
  660. end)
  661. it('does not indent until an item is selected #8345', function()
  662. -- Indents on "ind", unindents on "unind".
  663. source([[
  664. function! TestIndent()
  665. let line = getline(v:lnum)
  666. if (line =~ '^\s*ind')
  667. return indent(v:lnum-1) + shiftwidth()
  668. elseif (line =~ '^\s*unind')
  669. return indent(v:lnum-1) - shiftwidth()
  670. else
  671. return indent(v:lnum-1)
  672. endif
  673. endfunction
  674. set indentexpr=TestIndent()
  675. set indentkeys=o,O,!^F,=ind,=unind
  676. set completeopt+=menuone
  677. ]])
  678. -- Give some words to complete.
  679. feed('iinc uninc indent unindent<CR>')
  680. -- Does not indent when "ind" is typed.
  681. feed('in<C-X><C-N>')
  682. -- Completion list is generated incorrectly if we send everything at once
  683. -- via nvim_input(). So poke_eventloop() before sending <BS>. #8480
  684. poke_eventloop()
  685. feed('<BS>d')
  686. screen:expect([[
  687. inc uninc indent unindent |
  688. ind^ |
  689. {12:indent }{1: }|
  690. {1:~ }|*4
  691. {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} |
  692. ]])
  693. -- Indents when the item is selected
  694. feed('<C-Y>')
  695. screen:expect([[
  696. inc uninc indent unindent |
  697. indent^ |
  698. {1:~ }|*5
  699. {5:-- INSERT --} |
  700. ]])
  701. -- Indents when completion is exited using ESC.
  702. feed('<CR>in<C-N><BS>d<Esc>')
  703. screen:expect([[
  704. inc uninc indent unindent |
  705. indent |
  706. in^d |
  707. {1:~ }|*4
  708. |
  709. ]])
  710. -- Works for unindenting too.
  711. feed('ounin<C-X><C-N>')
  712. poke_eventloop()
  713. feed('<BS>d')
  714. screen:expect([[
  715. inc uninc indent unindent |
  716. indent |
  717. ind |
  718. unind^ |
  719. {1:~ }{12: unindent }{1: }|
  720. {1:~ }|*2
  721. {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} |
  722. ]])
  723. -- Works when going back and forth.
  724. feed('<BS>c')
  725. screen:expect([[
  726. inc uninc indent unindent |
  727. indent |
  728. ind |
  729. uninc^ |
  730. {1:~ }{12: uninc }{1: }|
  731. {1:~ }|*2
  732. {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} |
  733. ]])
  734. feed('<BS>d')
  735. screen:expect([[
  736. inc uninc indent unindent |
  737. indent |
  738. ind |
  739. unind^ |
  740. {1:~ }{12: unindent }{1: }|
  741. {1:~ }|*2
  742. {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} |
  743. ]])
  744. feed('<C-N><C-N><C-Y><Esc>')
  745. screen:expect([[
  746. inc uninc indent unindent |
  747. indent |
  748. ind |
  749. uninden^t |
  750. {1:~ }|*3
  751. |
  752. ]])
  753. end)
  754. it('disables folding during completion', function()
  755. feed_command('set foldmethod=indent')
  756. feed('i<Tab>foo<CR><Tab>bar<Esc>gg')
  757. screen:expect([[
  758. ^foo |
  759. bar |
  760. {1:~ }|*5
  761. |
  762. ]])
  763. feed('A<C-x><C-l>')
  764. screen:expect([[
  765. foo^ |
  766. bar |
  767. {1:~ }|*5
  768. {5:-- Whole line completion (^L^N^P) }{9:Pattern not found} |
  769. ]])
  770. eq(-1, eval('foldclosed(1)'))
  771. end)
  772. it('popupmenu is not interrupted by events', function()
  773. feed_command('set complete=.')
  774. feed('ifoobar fooegg<cr>f<c-p>')
  775. screen:expect([[
  776. foobar fooegg |
  777. fooegg^ |
  778. {4:foobar }{1: }|
  779. {12:fooegg }{1: }|
  780. {1:~ }|*3
  781. {5:-- Keyword completion (^N^P) }{6:match 1 of 2} |
  782. ]])
  783. assert_alive()
  784. -- popupmenu still visible
  785. screen:expect {
  786. grid = [[
  787. foobar fooegg |
  788. fooegg^ |
  789. {4:foobar }{1: }|
  790. {12:fooegg }{1: }|
  791. {1:~ }|*3
  792. {5:-- Keyword completion (^N^P) }{6:match 1 of 2} |
  793. ]],
  794. unchanged = true,
  795. }
  796. feed('<c-p>')
  797. -- Didn't restart completion: old matches still used
  798. screen:expect([[
  799. foobar fooegg |
  800. foobar^ |
  801. {12:foobar }{1: }|
  802. {4:fooegg }{1: }|
  803. {1:~ }|*3
  804. {5:-- Keyword completion (^N^P) }{6:match 2 of 2} |
  805. ]])
  806. end)
  807. describe('lua completion', function()
  808. it('expands when there is only one match', function()
  809. feed(':lua CURRENT_TESTING_VAR = 1<CR>')
  810. feed(':lua CURRENT_TESTING_<TAB>')
  811. screen:expect {
  812. grid = [[
  813. |
  814. {1:~ }|*6
  815. :lua CURRENT_TESTING_VAR^ |
  816. ]],
  817. }
  818. end)
  819. it('expands when there is only one match', function()
  820. feed(':lua CURRENT_TESTING_FOO = 1<CR>')
  821. feed(':lua CURRENT_TESTING_BAR = 1<CR>')
  822. feed(':lua CURRENT_TESTING_<TAB>')
  823. screen:expect {
  824. grid = [[
  825. |
  826. {1:~ }|*5
  827. {100:CURRENT_TESTING_BAR}{3: CURRENT_TESTING_FOO }|
  828. :lua CURRENT_TESTING_BAR^ |
  829. ]],
  830. unchanged = true,
  831. }
  832. end)
  833. it('prefix is not included in completion for cmdline mode', function()
  834. feed(':lua math.a<Tab>')
  835. screen:expect([[
  836. |
  837. {1:~ }|*5
  838. {100:abs}{3: acos asin atan atan2 }|
  839. :lua math.abs^ |
  840. ]])
  841. feed('<Tab>')
  842. screen:expect([[
  843. |
  844. {1:~ }|*5
  845. {3:abs }{100:acos}{3: asin atan atan2 }|
  846. :lua math.acos^ |
  847. ]])
  848. end)
  849. it('prefix is not included in completion for i_CTRL-X_CTRL-V #19623', function()
  850. feed('ilua math.a<C-X><C-V>')
  851. screen:expect([[
  852. lua math.abs^ |
  853. {1:~ }{12: abs }{1: }|
  854. {1:~ }{4: acos }{1: }|
  855. {1:~ }{4: asin }{1: }|
  856. {1:~ }{4: atan }{1: }|
  857. {1:~ }{4: atan2 }{1: }|
  858. {1:~ }|
  859. {5:-- Command-line completion (^V^N^P) }{6:match 1 of 5} |
  860. ]])
  861. feed('<C-V>')
  862. screen:expect([[
  863. lua math.acos^ |
  864. {1:~ }{4: abs }{1: }|
  865. {1:~ }{12: acos }{1: }|
  866. {1:~ }{4: asin }{1: }|
  867. {1:~ }{4: atan }{1: }|
  868. {1:~ }{4: atan2 }{1: }|
  869. {1:~ }|
  870. {5:-- Command-line completion (^V^N^P) }{6:match 2 of 5} |
  871. ]])
  872. end)
  873. it('works when cursor is in the middle of cmdline #29586', function()
  874. feed(':lua math.a(); 1<Left><Left><Left><Left><Left><Tab>')
  875. screen:expect([[
  876. |
  877. {1:~ }|*5
  878. {100:abs}{3: acos asin atan atan2 }|
  879. :lua math.abs^(); 1 |
  880. ]])
  881. end)
  882. it('provides completion from `getcompletion()`', function()
  883. eq({ 'vim' }, fn.getcompletion('vi', 'lua'))
  884. eq({ 'api' }, fn.getcompletion('vim.ap', 'lua'))
  885. eq({ 'tbl_filter' }, fn.getcompletion('vim.tbl_fil', 'lua'))
  886. eq({ 'vim' }, fn.getcompletion('print(vi', 'lua'))
  887. eq({ 'abs', 'acos', 'asin', 'atan', 'atan2' }, fn.getcompletion('math.a', 'lua'))
  888. eq({ 'abs', 'acos', 'asin', 'atan', 'atan2' }, fn.getcompletion('lua math.a', 'cmdline'))
  889. -- fuzzy completion is not supported, so the result should be the same
  890. command('set wildoptions+=fuzzy')
  891. eq({ 'vim' }, fn.getcompletion('vi', 'lua'))
  892. end)
  893. end)
  894. it('cmdline completion supports various string options', function()
  895. eq('auto', fn.getcompletion('set foldcolumn=', 'cmdline')[2])
  896. eq({ 'nosplit', 'split' }, fn.getcompletion('set inccommand=', 'cmdline'))
  897. eq({ 'ver:3,hor:6', 'hor:', 'ver:' }, fn.getcompletion('set mousescroll=', 'cmdline'))
  898. eq('BS', fn.getcompletion('set termpastefilter=', 'cmdline')[2])
  899. eq('SpecialKey', fn.getcompletion('set winhighlight=', 'cmdline')[1])
  900. eq('SpecialKey', fn.getcompletion('set winhighlight=NonText:', 'cmdline')[1])
  901. end)
  902. it('cmdline completion for -complete does not contain spaces', function()
  903. for _, str in ipairs(fn.getcompletion('command -complete=', 'cmdline')) do
  904. ok(not str:find(' '), 'string without spaces', str)
  905. end
  906. end)
  907. describe('from the commandline window', function()
  908. it('is cleared after CTRL-C', function()
  909. feed('q:')
  910. feed('ifoo faa fee f')
  911. screen:expect([[
  912. |
  913. {2:[No Name] }|
  914. {1::}foo faa fee f^ |
  915. {1:~ }|*3
  916. {3:[Command Line] }|
  917. {5:-- INSERT --} |
  918. ]])
  919. feed('<c-x><c-n>')
  920. screen:expect([[
  921. |
  922. {2:[No Name] }|
  923. {1::}foo faa fee foo^ |
  924. {1:~ }{12: foo }{1: }|
  925. {1:~ }{4: faa }{1: }|
  926. {1:~ }{4: fee }{1: }|
  927. {3:[Command Line] }|
  928. {5:-- Keyword Local completion (^N^P) }{6:match 1 of 3} |
  929. ]])
  930. feed('<c-c>')
  931. screen:expect([[
  932. |
  933. {2:[No Name] }|
  934. {1::}foo faa fee foo |
  935. {1:~ }|*3
  936. {3:[Command Line] }|
  937. :foo faa fee foo^ |
  938. ]])
  939. end)
  940. end)
  941. describe('with numeric items', function()
  942. before_each(function()
  943. source([[
  944. function! TestComplete() abort
  945. call complete(1, g:_complist)
  946. return ''
  947. endfunction
  948. ]])
  949. api.nvim_set_option_value('completeopt', 'menuone,noselect', {})
  950. api.nvim_set_var('_complist', {
  951. {
  952. word = 0,
  953. abbr = 1,
  954. menu = 2,
  955. kind = 3,
  956. info = 4,
  957. icase = 5,
  958. dup = 6,
  959. empty = 7,
  960. },
  961. })
  962. end)
  963. it('shows correct variant as word', function()
  964. feed('i<C-r>=TestComplete()<CR>')
  965. screen:expect([[
  966. ^ |
  967. {4:1 3 2 }{1: }|
  968. {1:~ }|*5
  969. {5:-- INSERT --} |
  970. ]])
  971. end)
  972. end)
  973. it("'ignorecase' 'infercase' CTRL-X CTRL-N #6451", function()
  974. feed_command('set ignorecase infercase')
  975. feed_command('edit runtime/doc/backers.txt')
  976. feed('oX<C-X><C-N>')
  977. screen:expect {
  978. grid = [[
  979. *backers.txt* Nvim |
  980. Xnull^ |
  981. {12:Xnull }{101: } |
  982. {4:Xoxomoon }{101: } |
  983. {4:Xu }{101: } NVIM REFERENCE MANUAL |
  984. {4:Xpayn }{12: } |
  985. {4:Xinity }{12: } |
  986. {5:-- Keyword Local completion (^N^P) }{6:match 1 of 7} |
  987. ]],
  988. }
  989. end)
  990. it('CompleteChanged autocommand', function()
  991. api.nvim_buf_set_lines(0, 0, 1, false, { 'foo', 'bar', 'foobar', '' })
  992. source([[
  993. set complete=. completeopt=noinsert,noselect,menuone
  994. function! OnPumChange()
  995. let g:event = copy(v:event)
  996. let g:item = get(v:event, 'completed_item', {})
  997. let g:word = get(g:item, 'word', v:null)
  998. endfunction
  999. autocmd! CompleteChanged * :call OnPumChange()
  1000. call cursor(4, 1)
  1001. ]])
  1002. -- v:event.size should be set with ext_popupmenu #20646
  1003. screen:set_option('ext_popupmenu', true)
  1004. feed('Sf<C-N>')
  1005. screen:expect({
  1006. grid = [[
  1007. foo |
  1008. bar |
  1009. foobar |
  1010. f^ |
  1011. {1:~ }|*3
  1012. {5:-- Keyword completion (^N^P) }{19:Back at original} |
  1013. ]],
  1014. popupmenu = {
  1015. anchor = { 1, 3, 0 },
  1016. items = { { 'foo', '', '', '' }, { 'foobar', '', '', '' } },
  1017. pos = -1,
  1018. },
  1019. })
  1020. eq(
  1021. { completed_item = {}, width = 0, height = 2, size = 2, col = 0, row = 4, scrollbar = false },
  1022. eval('g:event')
  1023. )
  1024. feed('oob')
  1025. screen:expect({
  1026. grid = [[
  1027. foo |
  1028. bar |
  1029. foobar |
  1030. foob^ |
  1031. {1:~ }|*3
  1032. {5:-- Keyword completion (^N^P) }{19:Back at original} |
  1033. ]],
  1034. popupmenu = {
  1035. anchor = { 1, 3, 0 },
  1036. items = { { 'foobar', '', '', '' } },
  1037. pos = -1,
  1038. },
  1039. })
  1040. eq(
  1041. { completed_item = {}, width = 0, height = 1, size = 1, col = 0, row = 4, scrollbar = false },
  1042. eval('g:event')
  1043. )
  1044. feed('<Esc>')
  1045. screen:set_option('ext_popupmenu', false)
  1046. feed('Sf<C-N>')
  1047. screen:expect([[
  1048. foo |
  1049. bar |
  1050. foobar |
  1051. f^ |
  1052. {4:foo }{1: }|
  1053. {4:foobar }{1: }|
  1054. {1:~ }|
  1055. {5:-- Keyword completion (^N^P) }{19:Back at original} |
  1056. ]])
  1057. eq(
  1058. { completed_item = {}, width = 15, height = 2, size = 2, col = 0, row = 4, scrollbar = false },
  1059. eval('g:event')
  1060. )
  1061. feed('<C-N>')
  1062. screen:expect([[
  1063. foo |
  1064. bar |
  1065. foobar |
  1066. foo^ |
  1067. {12:foo }{1: }|
  1068. {4:foobar }{1: }|
  1069. {1:~ }|
  1070. {5:-- Keyword completion (^N^P) }{6:match 1 of 2} |
  1071. ]])
  1072. eq('foo', eval('g:word'))
  1073. feed('<C-N>')
  1074. screen:expect([[
  1075. foo |
  1076. bar |
  1077. foobar |
  1078. foobar^ |
  1079. {4:foo }{1: }|
  1080. {12:foobar }{1: }|
  1081. {1:~ }|
  1082. {5:-- Keyword completion (^N^P) }{6:match 2 of 2} |
  1083. ]])
  1084. eq('foobar', eval('g:word'))
  1085. feed('<up>')
  1086. screen:expect([[
  1087. foo |
  1088. bar |
  1089. foobar |
  1090. foobar^ |
  1091. {12:foo }{1: }|
  1092. {4:foobar }{1: }|
  1093. {1:~ }|
  1094. {5:-- Keyword completion (^N^P) }{6:match 1 of 2} |
  1095. ]])
  1096. eq('foo', eval('g:word'))
  1097. feed('<down>')
  1098. screen:expect([[
  1099. foo |
  1100. bar |
  1101. foobar |
  1102. foobar^ |
  1103. {4:foo }{1: }|
  1104. {12:foobar }{1: }|
  1105. {1:~ }|
  1106. {5:-- Keyword completion (^N^P) }{6:match 2 of 2} |
  1107. ]])
  1108. eq('foobar', eval('g:word'))
  1109. feed('<esc>')
  1110. end)
  1111. it('is stopped by :stopinsert from timer #12976', function()
  1112. screen:try_resize(32, 14)
  1113. command([[call setline(1, ['hello', 'hullo', 'heeee', ''])]])
  1114. feed('Gah<c-x><c-n>')
  1115. screen:expect([[
  1116. hello |
  1117. hullo |
  1118. heeee |
  1119. hello^ |
  1120. {12:hello }{1: }|
  1121. {4:hullo }{1: }|
  1122. {4:heeee }{1: }|
  1123. {1:~ }|*6
  1124. {5:-- }{6:match 1 of 3} |
  1125. ]])
  1126. command([[call timer_start(100, { -> execute('stopinsert') })]])
  1127. vim.uv.sleep(200)
  1128. feed('k') -- cursor should move up in Normal mode
  1129. screen:expect([[
  1130. hello |
  1131. hullo |
  1132. heee^e |
  1133. hello |
  1134. {1:~ }|*9
  1135. |
  1136. ]])
  1137. end)
  1138. -- oldtest: Test_complete_changed_complete_info()
  1139. it('no crash calling complete_info() in CompleteChanged', function()
  1140. source([[
  1141. set completeopt=menuone
  1142. autocmd CompleteChanged * call complete_info(['items'])
  1143. call feedkeys("iii\<cr>\<c-p>")
  1144. ]])
  1145. screen:expect([[
  1146. ii |
  1147. ii^ |
  1148. {12:ii }{1: }|
  1149. {1:~ }|*4
  1150. {5:-- Keyword completion (^N^P) The only match} |
  1151. ]])
  1152. assert_alive()
  1153. end)
  1154. it('no crash if text changed by first call to complete function #17489', function()
  1155. source([[
  1156. func Complete(findstart, base) abort
  1157. if a:findstart
  1158. let col = col('.')
  1159. call complete_add('#')
  1160. return col - 1
  1161. else
  1162. return []
  1163. endif
  1164. endfunc
  1165. set completeopt=longest
  1166. set completefunc=Complete
  1167. ]])
  1168. feed('ifoo#<C-X><C-U>')
  1169. assert_alive()
  1170. end)
  1171. it('no crash using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function()
  1172. feed('icolorscheme NOSUCHCOLORSCHEME<C-X><C-V>')
  1173. expect('colorscheme NOSUCHCOLORSCHEME')
  1174. assert_alive()
  1175. end)
  1176. it('complete with f flag #25598', function()
  1177. screen:try_resize(20, 9)
  1178. command('set complete+=f | edit foo | edit bar |edit foa |edit .hidden')
  1179. feed('i<C-n>')
  1180. screen:expect {
  1181. grid = [[
  1182. foo^ |
  1183. {12:foo }{1: }|
  1184. {4:bar }{1: }|
  1185. {4:foa }{1: }|
  1186. {4:.hidden }{1: }|
  1187. {1:~ }|*3
  1188. {5:-- }{6:match 1 of 4} |
  1189. ]],
  1190. }
  1191. feed('<Esc>ccf<C-n>')
  1192. screen:expect {
  1193. grid = [[
  1194. foo^ |
  1195. {12:foo }{1: }|
  1196. {4:foa }{1: }|
  1197. {1:~ }|*5
  1198. {5:-- }{6:match 1 of 2} |
  1199. ]],
  1200. }
  1201. end)
  1202. it('restores extmarks if original text is restored #23653', function()
  1203. screen:try_resize(screen._width, 4)
  1204. command([[
  1205. call setline(1, ['aaaa'])
  1206. let ns_id = nvim_create_namespace('extmark')
  1207. let mark_id = nvim_buf_set_extmark(0, ns_id, 0, 0, { 'end_col':2, 'hl_group':'Error'})
  1208. let mark = nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })
  1209. inoremap <C-x> <C-r>=Complete()<CR>
  1210. function Complete() abort
  1211. call complete(1, [{ 'word': 'aaaaa' }])
  1212. return ''
  1213. endfunction
  1214. ]])
  1215. feed('A<C-X><C-E><Esc>')
  1216. eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
  1217. feed('A<C-N>')
  1218. eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
  1219. feed('<Esc>0Yppia<Esc>ggI<C-N>')
  1220. screen:expect([[
  1221. aaaa{9:^aa}aa |
  1222. {12:aaaa } |
  1223. {4:aaaaa } |
  1224. {5:-- Keyword completion (^N^P) }{6:match 1 of 2} |
  1225. ]])
  1226. feed('<C-N><C-N><Esc>')
  1227. eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
  1228. feed('A<C-N>')
  1229. eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
  1230. feed('<C-N>')
  1231. screen:expect([[
  1232. aaaaa^ |
  1233. {4:aaaa } |
  1234. {12:aaaaa } |
  1235. {5:-- Keyword completion (^N^P) }{6:match 2 of 2} |
  1236. ]])
  1237. feed('<C-E>')
  1238. screen:expect([[
  1239. {9:aa}aa^ |
  1240. aaaa |
  1241. aaaaa |
  1242. {5:-- INSERT --} |
  1243. ]])
  1244. end)
  1245. end)