completion_spec.lua 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. local helpers = require('test.functional.helpers')(after_each)
  2. local Screen = require('test.functional.ui.screen')
  3. local clear, feed = helpers.clear, helpers.feed
  4. local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
  5. local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect
  6. local curbufmeths = helpers.curbufmeths
  7. local command = helpers.command
  8. local meths = helpers.meths
  9. local wait = helpers.wait
  10. describe('completion', function()
  11. local screen
  12. before_each(function()
  13. clear()
  14. screen = Screen.new(60, 8)
  15. screen:attach()
  16. screen:set_default_attr_ids({
  17. [0] = {bold=true, foreground=Screen.colors.Blue},
  18. [1] = {background = Screen.colors.LightMagenta},
  19. [2] = {background = Screen.colors.Grey},
  20. [3] = {bold = true},
  21. [4] = {bold = true, foreground = Screen.colors.SeaGreen},
  22. [5] = {foreground = Screen.colors.Red},
  23. [6] = {background = Screen.colors.Black},
  24. [7] = {foreground = Screen.colors.White, background = Screen.colors.Red},
  25. [8] = {reverse = true},
  26. [9] = {bold = true, reverse = true},
  27. })
  28. end)
  29. describe('v:completed_item', function()
  30. it('is empty dict until completion', function()
  31. eq({}, eval('v:completed_item'))
  32. end)
  33. it('is empty dict if the candidate is not inserted', function()
  34. feed('ifoo<ESC>o<C-x><C-n>')
  35. screen:expect([[
  36. foo |
  37. foo^ |
  38. {0:~ }|
  39. {0:~ }|
  40. {0:~ }|
  41. {0:~ }|
  42. {0:~ }|
  43. {3:-- Keyword Local completion (^N^P) The only match} |
  44. ]])
  45. feed('<C-e>')
  46. screen:expect([[
  47. foo |
  48. ^ |
  49. {0:~ }|
  50. {0:~ }|
  51. {0:~ }|
  52. {0:~ }|
  53. {0:~ }|
  54. {3:-- INSERT --} |
  55. ]])
  56. feed('<ESC>')
  57. eq({}, eval('v:completed_item'))
  58. end)
  59. it('returns expected dict in normal completion', function()
  60. feed('ifoo<ESC>o<C-x><C-n>')
  61. eq('foo', eval('getline(2)'))
  62. eq({word = 'foo', abbr = '', menu = '',
  63. info = '', kind = '', user_data = ''},
  64. eval('v:completed_item'))
  65. end)
  66. it('is readonly', function()
  67. screen:try_resize(80, 8)
  68. feed('ifoo<ESC>o<C-x><C-n><ESC>')
  69. feed_command('let v:completed_item.word = "bar"')
  70. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  71. feed_command('let v:errmsg = ""')
  72. feed_command('let v:completed_item.abbr = "bar"')
  73. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  74. feed_command('let v:errmsg = ""')
  75. feed_command('let v:completed_item.menu = "bar"')
  76. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  77. feed_command('let v:errmsg = ""')
  78. feed_command('let v:completed_item.info = "bar"')
  79. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  80. feed_command('let v:errmsg = ""')
  81. feed_command('let v:completed_item.kind = "bar"')
  82. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  83. feed_command('let v:errmsg = ""')
  84. feed_command('let v:completed_item.user_data = "bar"')
  85. neq(nil, string.find(eval('v:errmsg'), '^E46: '))
  86. feed_command('let v:errmsg = ""')
  87. end)
  88. it('returns expected dict in omni completion', function()
  89. source([[
  90. function! TestOmni(findstart, base) abort
  91. return a:findstart ? 0 : [{'word': 'foo', 'abbr': 'bar',
  92. \ 'menu': 'baz', 'info': 'foobar', 'kind': 'foobaz'},
  93. \ {'word': 'word', 'abbr': 'abbr', 'menu': 'menu',
  94. \ 'info': 'info', 'kind': 'kind'}]
  95. endfunction
  96. setlocal omnifunc=TestOmni
  97. ]])
  98. feed('i<C-x><C-o>')
  99. eq('foo', eval('getline(1)'))
  100. screen:expect([[
  101. foo^ |
  102. {2:bar foobaz baz }{0: }|
  103. {1:abbr kind menu }{0: }|
  104. {0:~ }|
  105. {0:~ }|
  106. {0:~ }|
  107. {0:~ }|
  108. {3:-- Omni completion (^O^N^P) }{4:match 1 of 2} |
  109. ]])
  110. eq({word = 'foo', abbr = 'bar', menu = 'baz',
  111. info = 'foobar', kind = 'foobaz', user_data = ''},
  112. eval('v:completed_item'))
  113. end)
  114. end)
  115. describe('completeopt', function()
  116. before_each(function()
  117. source([[
  118. function! TestComplete() abort
  119. call complete(1, ['foo'])
  120. return ''
  121. endfunction
  122. ]])
  123. end)
  124. it('inserts the first candidate if default', function()
  125. feed_command('set completeopt+=menuone')
  126. feed('ifoo<ESC>o')
  127. screen:expect([[
  128. foo |
  129. ^ |
  130. {0:~ }|
  131. {0:~ }|
  132. {0:~ }|
  133. {0:~ }|
  134. {0:~ }|
  135. {3:-- INSERT --} |
  136. ]])
  137. feed('<C-x>')
  138. -- the ^X prompt, only test this once
  139. screen:expect([[
  140. foo |
  141. ^ |
  142. {0:~ }|
  143. {0:~ }|
  144. {0:~ }|
  145. {0:~ }|
  146. {0:~ }|
  147. {3:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} |
  148. ]])
  149. feed('<C-n>')
  150. screen:expect([[
  151. foo |
  152. foo^ |
  153. {2:foo }{0: }|
  154. {0:~ }|
  155. {0:~ }|
  156. {0:~ }|
  157. {0:~ }|
  158. {3:-- Keyword Local completion (^N^P) The only match} |
  159. ]])
  160. feed('bar<ESC>')
  161. eq('foobar', eval('getline(2)'))
  162. feed('o<C-r>=TestComplete()<CR>')
  163. screen:expect([[
  164. foo |
  165. foobar |
  166. foo^ |
  167. {2:foo }{0: }|
  168. {0:~ }|
  169. {0:~ }|
  170. {0:~ }|
  171. {3:-- INSERT --} |
  172. ]])
  173. eq('foo', eval('getline(3)'))
  174. end)
  175. it('selects the first candidate if noinsert', function()
  176. feed_command('set completeopt+=menuone,noinsert')
  177. feed('ifoo<ESC>o<C-x><C-n>')
  178. screen:expect([[
  179. foo |
  180. ^ |
  181. {2:foo }{0: }|
  182. {0:~ }|
  183. {0:~ }|
  184. {0:~ }|
  185. {0:~ }|
  186. {3:-- Keyword Local completion (^N^P) The only match} |
  187. ]])
  188. feed('<C-y>')
  189. screen:expect([[
  190. foo |
  191. foo^ |
  192. {0:~ }|
  193. {0:~ }|
  194. {0:~ }|
  195. {0:~ }|
  196. {0:~ }|
  197. {3:-- INSERT --} |
  198. ]])
  199. feed('<ESC>')
  200. eq('foo', eval('getline(2)'))
  201. feed('o<C-r>=TestComplete()<CR>')
  202. screen:expect([[
  203. foo |
  204. foo |
  205. ^ |
  206. {2:foo }{0: }|
  207. {0:~ }|
  208. {0:~ }|
  209. {0:~ }|
  210. {3:-- INSERT --} |
  211. ]])
  212. feed('<C-y><ESC>')
  213. eq('foo', eval('getline(3)'))
  214. end)
  215. it('does not insert the first candidate if noselect', function()
  216. feed_command('set completeopt+=menuone,noselect')
  217. feed('ifoo<ESC>o<C-x><C-n>')
  218. screen:expect([[
  219. foo |
  220. ^ |
  221. {1:foo }{0: }|
  222. {0:~ }|
  223. {0:~ }|
  224. {0:~ }|
  225. {0:~ }|
  226. {3:-- Keyword Local completion (^N^P) }{5:Back at original} |
  227. ]])
  228. feed('b')
  229. screen:expect([[
  230. foo |
  231. b^ |
  232. {0:~ }|
  233. {0:~ }|
  234. {0:~ }|
  235. {0:~ }|
  236. {0:~ }|
  237. {3:-- Keyword Local completion (^N^P) }{5:Back at original} |
  238. ]])
  239. feed('ar<ESC>')
  240. eq('bar', eval('getline(2)'))
  241. feed('o<C-r>=TestComplete()<CR>')
  242. screen:expect([[
  243. foo |
  244. bar |
  245. ^ |
  246. {1:foo }{0: }|
  247. {0:~ }|
  248. {0:~ }|
  249. {0:~ }|
  250. {3:-- INSERT --} |
  251. ]])
  252. feed('bar<ESC>')
  253. eq('bar', eval('getline(3)'))
  254. end)
  255. it('does not select/insert the first candidate if noselect and noinsert', function()
  256. feed_command('set completeopt+=menuone,noselect,noinsert')
  257. feed('ifoo<ESC>o<C-x><C-n>')
  258. screen:expect([[
  259. foo |
  260. ^ |
  261. {1:foo }{0: }|
  262. {0:~ }|
  263. {0:~ }|
  264. {0:~ }|
  265. {0:~ }|
  266. {3:-- Keyword Local completion (^N^P) }{5:Back at original} |
  267. ]])
  268. feed('<ESC>')
  269. screen:expect([[
  270. foo |
  271. ^ |
  272. {0:~ }|
  273. {0:~ }|
  274. {0:~ }|
  275. {0:~ }|
  276. {0:~ }|
  277. |
  278. ]])
  279. eq('', eval('getline(2)'))
  280. feed('o<C-r>=TestComplete()<CR>')
  281. screen:expect([[
  282. foo |
  283. |
  284. ^ |
  285. {1:foo }{0: }|
  286. {0:~ }|
  287. {0:~ }|
  288. {0:~ }|
  289. {3:-- INSERT --} |
  290. ]])
  291. feed('<ESC>')
  292. screen:expect([[
  293. foo |
  294. |
  295. ^ |
  296. {0:~ }|
  297. {0:~ }|
  298. {0:~ }|
  299. {0:~ }|
  300. |
  301. ]])
  302. eq('', eval('getline(3)'))
  303. end)
  304. it('does not change modified state if noinsert', function()
  305. feed_command('set completeopt+=menuone,noinsert')
  306. feed_command('setlocal nomodified')
  307. feed('i<C-r>=TestComplete()<CR><ESC>')
  308. eq(0, eval('&l:modified'))
  309. end)
  310. it('does not change modified state if noselect', function()
  311. feed_command('set completeopt+=menuone,noselect')
  312. feed_command('setlocal nomodified')
  313. feed('i<C-r>=TestComplete()<CR><ESC>')
  314. eq(0, eval('&l:modified'))
  315. end)
  316. end)
  317. describe('completeopt+=noinsert does not add blank undo items', function()
  318. before_each(function()
  319. source([[
  320. function! TestComplete() abort
  321. call complete(1, ['foo', 'bar'])
  322. return ''
  323. endfunction
  324. ]])
  325. feed_command('set completeopt+=noselect,noinsert')
  326. feed_command('inoremap <right> <c-r>=TestComplete()<cr>')
  327. end)
  328. local tests = {
  329. ['<up>, <down>, <cr>'] = {'<down><cr>', '<up><cr>'},
  330. ['<c-n>, <c-p>, <c-y>'] = {'<c-n><c-y>', '<c-p><c-y>'},
  331. }
  332. for name, seq in pairs(tests) do
  333. it('using ' .. name, function()
  334. feed('iaaa<esc>')
  335. feed('A<right>' .. seq[1] .. '<esc>')
  336. feed('A<right><esc>A<right><esc>')
  337. feed('A<cr>bbb<esc>')
  338. feed('A<right>' .. seq[2] .. '<esc>')
  339. feed('A<right><esc>A<right><esc>')
  340. feed('A<cr>ccc<esc>')
  341. feed('A<right>' .. seq[1] .. '<esc>')
  342. feed('A<right><esc>A<right><esc>')
  343. local expected = {
  344. {'foo', 'bar', 'foo'},
  345. {'foo', 'bar', 'ccc'},
  346. {'foo', 'bar'},
  347. {'foo', 'bbb'},
  348. {'foo'},
  349. {'aaa'},
  350. {''},
  351. }
  352. for i = 1, #expected do
  353. if i > 1 then
  354. feed('u')
  355. end
  356. eq(expected[i], eval('getline(1, "$")'))
  357. end
  358. for i = #expected, 1, -1 do
  359. if i < #expected then
  360. feed('<c-r>')
  361. end
  362. eq(expected[i], eval('getline(1, "$")'))
  363. end
  364. end)
  365. end
  366. end)
  367. describe("refresh:always", function()
  368. before_each(function()
  369. source([[
  370. function! TestCompletion(findstart, base) abort
  371. if a:findstart
  372. let line = getline('.')
  373. let start = col('.') - 1
  374. while start > 0 && line[start - 1] =~ '\a'
  375. let start -= 1
  376. endwhile
  377. return start
  378. else
  379. let ret = []
  380. for m in split("January February March April May June July August September October November December")
  381. if m =~ a:base " match by regex
  382. call add(ret, m)
  383. endif
  384. endfor
  385. return {'words':ret, 'refresh':'always'}
  386. endif
  387. endfunction
  388. set completeopt=menuone,noselect
  389. set completefunc=TestCompletion
  390. ]])
  391. end )
  392. it('completes on each input char', function ()
  393. feed('i<C-x><C-u>')
  394. screen:expect([[
  395. ^ |
  396. {1:January }{6: }{0: }|
  397. {1:February }{6: }{0: }|
  398. {1:March }{6: }{0: }|
  399. {1:April }{2: }{0: }|
  400. {1:May }{2: }{0: }|
  401. {1:June }{2: }{0: }|
  402. {3:-- User defined completion (^U^N^P) }{5:Back at original} |
  403. ]])
  404. feed('u')
  405. screen:expect([[
  406. u^ |
  407. {1:January }{0: }|
  408. {1:February }{0: }|
  409. {1:June }{0: }|
  410. {1:July }{0: }|
  411. {1:August }{0: }|
  412. {0:~ }|
  413. {3:-- User defined completion (^U^N^P) }{5:Back at original} |
  414. ]])
  415. feed('g')
  416. screen:expect([[
  417. ug^ |
  418. {1:August }{0: }|
  419. {0:~ }|
  420. {0:~ }|
  421. {0:~ }|
  422. {0:~ }|
  423. {0:~ }|
  424. {3:-- User defined completion (^U^N^P) }{5:Back at original} |
  425. ]])
  426. feed('<Down>')
  427. screen:expect([[
  428. ug^ |
  429. {2:August }{0: }|
  430. {0:~ }|
  431. {0:~ }|
  432. {0:~ }|
  433. {0:~ }|
  434. {0:~ }|
  435. {3:-- User defined completion (^U^N^P) The only match} |
  436. ]])
  437. feed('<C-y>')
  438. screen:expect([[
  439. August^ |
  440. {0:~ }|
  441. {0:~ }|
  442. {0:~ }|
  443. {0:~ }|
  444. {0:~ }|
  445. {0:~ }|
  446. {3:-- INSERT --} |
  447. ]])
  448. expect('August')
  449. end)
  450. it("repeats correctly after backspace #2674", function ()
  451. feed('o<C-x><C-u>Ja')
  452. screen:expect([[
  453. |
  454. Ja^ |
  455. {1:January }{0: }|
  456. {0:~ }|
  457. {0:~ }|
  458. {0:~ }|
  459. {0:~ }|
  460. {3:-- User defined completion (^U^N^P) }{5:Back at original} |
  461. ]])
  462. feed('<BS>')
  463. screen:expect([[
  464. |
  465. J^ |
  466. {1:January }{0: }|
  467. {1:June }{0: }|
  468. {1:July }{0: }|
  469. {0:~ }|
  470. {0:~ }|
  471. {3:-- User defined completion (^U^N^P) }{5:Back at original} |
  472. ]])
  473. feed('<C-n>')
  474. screen:expect([[
  475. |
  476. January^ |
  477. {2:January }{0: }|
  478. {1:June }{0: }|
  479. {1:July }{0: }|
  480. {0:~ }|
  481. {0:~ }|
  482. {3:-- User defined completion (^U^N^P) }{4:match 1 of 3} |
  483. ]])
  484. feed('<C-n>')
  485. screen:expect([[
  486. |
  487. June^ |
  488. {1:January }{0: }|
  489. {2:June }{0: }|
  490. {1:July }{0: }|
  491. {0:~ }|
  492. {0:~ }|
  493. {3:-- User defined completion (^U^N^P) }{4:match 2 of 3} |
  494. ]])
  495. feed('<Esc>')
  496. screen:expect([[
  497. |
  498. Jun^e |
  499. {0:~ }|
  500. {0:~ }|
  501. {0:~ }|
  502. {0:~ }|
  503. {0:~ }|
  504. |
  505. ]])
  506. feed('.')
  507. screen:expect([[
  508. |
  509. June |
  510. Jun^e |
  511. {0:~ }|
  512. {0:~ }|
  513. {0:~ }|
  514. {0:~ }|
  515. |
  516. ]])
  517. expect([[
  518. June
  519. June]])
  520. end)
  521. end)
  522. describe('with a lot of items', function()
  523. before_each(function()
  524. source([[
  525. function! TestComplete() abort
  526. call complete(1, map(range(0,100), "string(v:val)"))
  527. return ''
  528. endfunction
  529. ]])
  530. feed_command("set completeopt=menuone,noselect")
  531. end)
  532. it("works", function()
  533. feed('i<C-r>=TestComplete()<CR>')
  534. screen:expect([[
  535. ^ |
  536. {1:0 }{6: }{0: }|
  537. {1:1 }{2: }{0: }|
  538. {1:2 }{2: }{0: }|
  539. {1:3 }{2: }{0: }|
  540. {1:4 }{2: }{0: }|
  541. {1:5 }{2: }{0: }|
  542. {3:-- INSERT --} |
  543. ]])
  544. feed('7')
  545. screen:expect([[
  546. 7^ |
  547. {1:7 }{6: }{0: }|
  548. {1:70 }{6: }{0: }|
  549. {1:71 }{6: }{0: }|
  550. {1:72 }{2: }{0: }|
  551. {1:73 }{2: }{0: }|
  552. {1:74 }{2: }{0: }|
  553. {3:-- INSERT --} |
  554. ]])
  555. feed('<c-n>')
  556. screen:expect([[
  557. 7^ |
  558. {2:7 }{6: }{0: }|
  559. {1:70 }{6: }{0: }|
  560. {1:71 }{6: }{0: }|
  561. {1:72 }{2: }{0: }|
  562. {1:73 }{2: }{0: }|
  563. {1:74 }{2: }{0: }|
  564. {3:-- INSERT --} |
  565. ]])
  566. feed('<c-n>')
  567. screen:expect([[
  568. 70^ |
  569. {1:7 }{6: }{0: }|
  570. {2:70 }{6: }{0: }|
  571. {1:71 }{6: }{0: }|
  572. {1:72 }{2: }{0: }|
  573. {1:73 }{2: }{0: }|
  574. {1:74 }{2: }{0: }|
  575. {3:-- INSERT --} |
  576. ]])
  577. end)
  578. it('can be navigated with <PageDown>, <PageUp>', function()
  579. feed('i<C-r>=TestComplete()<CR>')
  580. screen:expect([[
  581. ^ |
  582. {1:0 }{6: }{0: }|
  583. {1:1 }{2: }{0: }|
  584. {1:2 }{2: }{0: }|
  585. {1:3 }{2: }{0: }|
  586. {1:4 }{2: }{0: }|
  587. {1:5 }{2: }{0: }|
  588. {3:-- INSERT --} |
  589. ]])
  590. feed('<PageDown>')
  591. screen:expect([[
  592. ^ |
  593. {1:0 }{6: }{0: }|
  594. {1:1 }{2: }{0: }|
  595. {1:2 }{2: }{0: }|
  596. {2:3 }{0: }|
  597. {1:4 }{2: }{0: }|
  598. {1:5 }{2: }{0: }|
  599. {3:-- INSERT --} |
  600. ]])
  601. feed('<PageDown>')
  602. screen:expect([[
  603. ^ |
  604. {1:5 }{6: }{0: }|
  605. {1:6 }{2: }{0: }|
  606. {2:7 }{0: }|
  607. {1:8 }{2: }{0: }|
  608. {1:9 }{2: }{0: }|
  609. {1:10 }{2: }{0: }|
  610. {3:-- INSERT --} |
  611. ]])
  612. feed('<Down>')
  613. screen:expect([[
  614. ^ |
  615. {1:5 }{6: }{0: }|
  616. {1:6 }{2: }{0: }|
  617. {1:7 }{2: }{0: }|
  618. {2:8 }{0: }|
  619. {1:9 }{2: }{0: }|
  620. {1:10 }{2: }{0: }|
  621. {3:-- INSERT --} |
  622. ]])
  623. feed('<PageUp>')
  624. screen:expect([[
  625. ^ |
  626. {1:2 }{6: }{0: }|
  627. {1:3 }{2: }{0: }|
  628. {2:4 }{0: }|
  629. {1:5 }{2: }{0: }|
  630. {1:6 }{2: }{0: }|
  631. {1:7 }{2: }{0: }|
  632. {3:-- INSERT --} |
  633. ]])
  634. feed('<PageUp>') -- stop on first item
  635. screen:expect([[
  636. ^ |
  637. {2:0 }{6: }{0: }|
  638. {1:1 }{2: }{0: }|
  639. {1:2 }{2: }{0: }|
  640. {1:3 }{2: }{0: }|
  641. {1:4 }{2: }{0: }|
  642. {1:5 }{2: }{0: }|
  643. {3:-- INSERT --} |
  644. ]])
  645. feed('<PageUp>') -- when on first item, unselect
  646. screen:expect([[
  647. ^ |
  648. {1:0 }{6: }{0: }|
  649. {1:1 }{2: }{0: }|
  650. {1:2 }{2: }{0: }|
  651. {1:3 }{2: }{0: }|
  652. {1:4 }{2: }{0: }|
  653. {1:5 }{2: }{0: }|
  654. {3:-- INSERT --} |
  655. ]])
  656. feed('<PageUp>') -- when unselected, select last item
  657. screen:expect([[
  658. ^ |
  659. {1:95 }{2: }{0: }|
  660. {1:96 }{2: }{0: }|
  661. {1:97 }{2: }{0: }|
  662. {1:98 }{2: }{0: }|
  663. {1:99 }{2: }{0: }|
  664. {2:100 }{6: }{0: }|
  665. {3:-- INSERT --} |
  666. ]])
  667. feed('<PageUp>')
  668. screen:expect([[
  669. ^ |
  670. {1:94 }{2: }{0: }|
  671. {1:95 }{2: }{0: }|
  672. {2:96 }{0: }|
  673. {1:97 }{2: }{0: }|
  674. {1:98 }{2: }{0: }|
  675. {1:99 }{6: }{0: }|
  676. {3:-- INSERT --} |
  677. ]])
  678. feed('<cr>')
  679. screen:expect([[
  680. 96^ |
  681. {0:~ }|
  682. {0:~ }|
  683. {0:~ }|
  684. {0:~ }|
  685. {0:~ }|
  686. {0:~ }|
  687. {3:-- INSERT --} |
  688. ]])
  689. end)
  690. end)
  691. it('disables folding during completion', function ()
  692. feed_command("set foldmethod=indent")
  693. feed('i<Tab>foo<CR><Tab>bar<Esc>gg')
  694. screen:expect([[
  695. ^foo |
  696. bar |
  697. {0:~ }|
  698. {0:~ }|
  699. {0:~ }|
  700. {0:~ }|
  701. {0:~ }|
  702. |
  703. ]])
  704. feed('A<C-x><C-l>')
  705. screen:expect([[
  706. foo^ |
  707. bar |
  708. {0:~ }|
  709. {0:~ }|
  710. {0:~ }|
  711. {0:~ }|
  712. {0:~ }|
  713. {3:-- Whole line completion (^L^N^P) }{7:Pattern not found} |
  714. ]])
  715. eq(-1, eval('foldclosed(1)'))
  716. end)
  717. it('popupmenu is not interrupted by events', function ()
  718. feed_command("set complete=.")
  719. feed('ifoobar fooegg<cr>f<c-p>')
  720. screen:expect([[
  721. foobar fooegg |
  722. fooegg^ |
  723. {1:foobar }{0: }|
  724. {2:fooegg }{0: }|
  725. {0:~ }|
  726. {0:~ }|
  727. {0:~ }|
  728. {3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
  729. ]])
  730. eval('1 + 1')
  731. -- popupmenu still visible
  732. screen:expect{grid=[[
  733. foobar fooegg |
  734. fooegg^ |
  735. {1:foobar }{0: }|
  736. {2:fooegg }{0: }|
  737. {0:~ }|
  738. {0:~ }|
  739. {0:~ }|
  740. {3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
  741. ]], unchanged=true}
  742. feed('<c-p>')
  743. -- Didn't restart completion: old matches still used
  744. screen:expect([[
  745. foobar fooegg |
  746. foobar^ |
  747. {2:foobar }{0: }|
  748. {1:fooegg }{0: }|
  749. {0:~ }|
  750. {0:~ }|
  751. {0:~ }|
  752. {3:-- Keyword completion (^N^P) }{4:match 2 of 2} |
  753. ]])
  754. end)
  755. describe('from the commandline window', function()
  756. it('is cleared after CTRL-C', function ()
  757. feed('q:')
  758. feed('ifoo faa fee f')
  759. screen:expect([[
  760. |
  761. {8:[No Name] }|
  762. {0::}foo faa fee f^ |
  763. {0::~ }|
  764. {0::~ }|
  765. {0::~ }|
  766. {9:[Command Line] }|
  767. {3:-- INSERT --} |
  768. ]] )
  769. feed('<c-x><c-n>')
  770. screen:expect([[
  771. |
  772. {8:[No Name] }|
  773. {0::}foo faa fee foo^ |
  774. {0::~ }{2: foo }{0: }|
  775. {0::~ }{1: faa }{0: }|
  776. {0::~ }{1: fee }{0: }|
  777. {9:[Command Line] }|
  778. {3:-- Keyword Local completion (^N^P) }{4:match 1 of 3} |
  779. ]])
  780. feed('<c-c>')
  781. screen:expect([[
  782. |
  783. {8:[No Name] }|
  784. {0::}foo faa fee foo |
  785. {0::~ }|
  786. {0::~ }|
  787. {0::~ }|
  788. {9:[Command Line] }|
  789. :foo faa fee foo^ |
  790. ]])
  791. end)
  792. end)
  793. describe('with numeric items', function()
  794. before_each(function()
  795. source([[
  796. function! TestComplete() abort
  797. call complete(1, g:_complist)
  798. return ''
  799. endfunction
  800. ]])
  801. meths.set_option('completeopt', 'menuone,noselect')
  802. meths.set_var('_complist', {{
  803. word=0,
  804. abbr=1,
  805. menu=2,
  806. kind=3,
  807. info=4,
  808. icase=5,
  809. dup=6,
  810. empty=7,
  811. }})
  812. end)
  813. it('shows correct variant as word', function()
  814. feed('i<C-r>=TestComplete()<CR>')
  815. screen:expect([[
  816. ^ |
  817. {1:1 3 2 }{0: }|
  818. {0:~ }|
  819. {0:~ }|
  820. {0:~ }|
  821. {0:~ }|
  822. {0:~ }|
  823. {3:-- INSERT --} |
  824. ]])
  825. end)
  826. end)
  827. it("'ignorecase' 'infercase' CTRL-X CTRL-N #6451", function()
  828. feed_command('set ignorecase infercase')
  829. feed_command('edit BACKERS.md')
  830. feed('oX<C-X><C-N>')
  831. screen:expect([[
  832. # Bountysource Backers |
  833. Xnull^ |
  834. {2:Xnull }{6: } |
  835. {1:Xoxomoon }{6: }ryone who backed our [Bountysource fundraise|
  836. {1:Xu }{6: }ountysource.com/teams/neovim/fundraiser)! |
  837. {1:Xpayn }{2: } |
  838. {1:Xinity }{2: }d URL in BACKERS.md. |
  839. {3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} |
  840. ]])
  841. end)
  842. it('TextChangedP autocommand', function()
  843. curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar'})
  844. source([[
  845. set complete=. completeopt=menuone
  846. let g:foo = []
  847. autocmd! TextChanged * :call add(g:foo, "N")
  848. autocmd! TextChangedI * :call add(g:foo, "I")
  849. autocmd! TextChangedP * :call add(g:foo, "P")
  850. call cursor(3, 1)
  851. ]])
  852. command('let g:foo = []')
  853. feed('o')
  854. wait()
  855. feed('<esc>')
  856. eq({'I'}, eval('g:foo'))
  857. command('let g:foo = []')
  858. feed('S')
  859. wait()
  860. feed('f')
  861. wait()
  862. eq({'I', 'I'}, eval('g:foo'))
  863. feed('<esc>')
  864. command('let g:foo = []')
  865. feed('S')
  866. wait()
  867. feed('f')
  868. wait()
  869. feed('<C-N>')
  870. wait()
  871. eq({'I', 'I', 'P'}, eval('g:foo'))
  872. feed('<esc>')
  873. command('let g:foo = []')
  874. feed('S')
  875. wait()
  876. feed('f')
  877. wait()
  878. feed('<C-N>')
  879. wait()
  880. feed('<C-N>')
  881. wait()
  882. eq({'I', 'I', 'P', 'P'}, eval('g:foo'))
  883. feed('<esc>')
  884. command('let g:foo = []')
  885. feed('S')
  886. wait()
  887. feed('f')
  888. wait()
  889. feed('<C-N>')
  890. wait()
  891. feed('<C-N>')
  892. wait()
  893. feed('<C-N>')
  894. wait()
  895. eq({'I', 'I', 'P', 'P', 'P'}, eval('g:foo'))
  896. feed('<esc>')
  897. command('let g:foo = []')
  898. feed('S')
  899. wait()
  900. feed('f')
  901. wait()
  902. feed('<C-N>')
  903. wait()
  904. feed('<C-N>')
  905. wait()
  906. feed('<C-N>')
  907. wait()
  908. feed('<C-N>')
  909. eq({'I', 'I', 'P', 'P', 'P', 'P'}, eval('g:foo'))
  910. feed('<esc>')
  911. eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")'))
  912. source([[
  913. au! TextChanged
  914. au! TextChangedI
  915. au! TextChangedP
  916. set complete&vim completeopt&vim
  917. ]])
  918. end)
  919. end)