wildmode_spec.lua 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. local helpers = require('test.functional.helpers')(after_each)
  2. local Screen = require('test.functional.ui.screen')
  3. local clear, feed, command = helpers.clear, helpers.feed, helpers.command
  4. local iswin = helpers.iswin
  5. local funcs = helpers.funcs
  6. local meths = helpers.meths
  7. local eq = helpers.eq
  8. local eval = helpers.eval
  9. local retry = helpers.retry
  10. local nvim_dir = helpers.nvim_dir
  11. describe("'wildmenu'", function()
  12. local screen
  13. before_each(function()
  14. clear()
  15. screen = Screen.new(25, 5)
  16. screen:attach()
  17. end)
  18. it('C-E to cancel wildmenu completion restore original input', function()
  19. feed(':sign <tab>')
  20. screen:expect([[
  21. |
  22. ~ |
  23. ~ |
  24. define jump list > |
  25. :sign define^ |
  26. ]])
  27. feed('<C-E>')
  28. screen:expect([[
  29. |
  30. ~ |
  31. ~ |
  32. ~ |
  33. :sign ^ |
  34. ]])
  35. end)
  36. it('C-Y to apply selection and end wildmenu completion', function()
  37. feed(':sign <tab>')
  38. screen:expect([[
  39. |
  40. ~ |
  41. ~ |
  42. define jump list > |
  43. :sign define^ |
  44. ]])
  45. feed('<tab><C-Y>')
  46. screen:expect([[
  47. |
  48. ~ |
  49. ~ |
  50. ~ |
  51. :sign jump^ |
  52. ]])
  53. end)
  54. it(':sign <tab> shows wildmenu completions', function()
  55. command('set wildmenu wildmode=full')
  56. feed(':sign <tab>')
  57. screen:expect([[
  58. |
  59. ~ |
  60. ~ |
  61. define jump list > |
  62. :sign define^ |
  63. ]])
  64. end)
  65. it(':sign <tab> <space> hides wildmenu #8453', function()
  66. command('set wildmode=full')
  67. -- only a regression if status-line open
  68. command('set laststatus=2')
  69. command('set wildmenu')
  70. feed(':sign <tab>')
  71. screen:expect([[
  72. |
  73. ~ |
  74. ~ |
  75. define jump list > |
  76. :sign define^ |
  77. ]])
  78. feed('<space>')
  79. screen:expect([[
  80. |
  81. ~ |
  82. ~ |
  83. [No Name] |
  84. :sign define ^ |
  85. ]])
  86. end)
  87. it('does not crash after cycling back to original text', function()
  88. command('set wildmode=full')
  89. feed(':j<Tab><Tab><Tab>')
  90. screen:expect([[
  91. |
  92. ~ |
  93. ~ |
  94. join jumps |
  95. :j^ |
  96. ]])
  97. -- This would cause nvim to crash before #6650
  98. feed('<BS><Tab>')
  99. screen:expect([[
  100. |
  101. ~ |
  102. ~ |
  103. ! # & < = > @ > |
  104. :!^ |
  105. ]])
  106. end)
  107. it('is preserved during :terminal activity', function()
  108. command('set wildmenu wildmode=full')
  109. command('set scrollback=4')
  110. feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 5000 !terminal_output!<cr>]])
  111. feed('G') -- Follow :terminal output.
  112. feed([[:sign <Tab>]]) -- Invoke wildmenu.
  113. -- NB: in earlier versions terminal output was redrawn during cmdline mode.
  114. -- For now just assert that the screen remains unchanged.
  115. screen:expect{any='define jump list > |\n:sign define^ |'}
  116. screen:expect_unchanged()
  117. -- cmdline CTRL-D display should also be preserved.
  118. feed([[<C-U>]])
  119. feed([[sign <C-D>]]) -- Invoke cmdline CTRL-D.
  120. screen:expect{grid=[[
  121. :sign |
  122. define place |
  123. jump undefine |
  124. list unplace |
  125. :sign ^ |
  126. ]]}
  127. screen:expect_unchanged()
  128. -- Exiting cmdline should show the buffer.
  129. feed([[<C-\><C-N>]])
  130. screen:expect{any=[[!terminal_output!]]}
  131. end)
  132. it('ignores :redrawstatus called from a timer #7108', function()
  133. command('set wildmenu wildmode=full')
  134. command([[call timer_start(10, {->execute('redrawstatus')}, {'repeat':-1})]])
  135. feed([[<C-\><C-N>]])
  136. feed([[:sign <Tab>]]) -- Invoke wildmenu.
  137. screen:expect{grid=[[
  138. |
  139. ~ |
  140. ~ |
  141. define jump list > |
  142. :sign define^ |
  143. ]]}
  144. screen:expect_unchanged()
  145. end)
  146. it('with laststatus=0, :vsplit, :term #2255', function()
  147. -- Because this test verifies a _lack_ of activity after screen:sleep(), we
  148. -- must wait the full timeout. So make it reasonable.
  149. screen.timeout = 1000
  150. if not iswin() then
  151. command('set shell=sh') -- Need a predictable "$" prompt.
  152. command('let $PS1 = "$"')
  153. end
  154. command('set laststatus=0')
  155. command('vsplit')
  156. command('term')
  157. -- Check for a shell prompt to verify that the terminal loaded.
  158. retry(nil, nil, function()
  159. if iswin() then
  160. eq('Microsoft', eval("matchstr(join(getline(1, '$')), 'Microsoft')"))
  161. else
  162. eq('$', eval([[matchstr(getline(1), '\$')]]))
  163. end
  164. end)
  165. feed([[<C-\><C-N>]])
  166. feed([[:<Tab>]]) -- Invoke wildmenu.
  167. -- Check only the last 2 lines, because the shell output is
  168. -- system-dependent.
  169. screen:expect{any='! # & < = > @ > |\n:!^'}
  170. screen:expect_unchanged()
  171. end)
  172. it('wildmode=list,full and display+=msgsep interaction #10092', function()
  173. -- Need more than 5 rows, else tabline is covered and will be redrawn.
  174. screen:try_resize(25, 7)
  175. command('set display+=msgsep')
  176. command('set wildmenu wildmode=list,full')
  177. command('set showtabline=2')
  178. feed(':set wildm<tab>')
  179. screen:expect([[
  180. [No Name] |
  181. |
  182. ~ |
  183. |
  184. :set wildm |
  185. wildmenu wildmode |
  186. :set wildm^ |
  187. ]])
  188. feed('<tab>') -- trigger wildmode full
  189. screen:expect([[
  190. [No Name] |
  191. |
  192. |
  193. :set wildm |
  194. wildmenu wildmode |
  195. wildmenu wildmode |
  196. :set wildmenu^ |
  197. ]])
  198. feed('<Esc>')
  199. screen:expect([[
  200. [No Name] |
  201. ^ |
  202. ~ |
  203. ~ |
  204. ~ |
  205. ~ |
  206. |
  207. ]])
  208. end)
  209. it('wildmode=list,full and display-=msgsep interaction', function()
  210. -- Need more than 5 rows, else tabline is covered and will be redrawn.
  211. screen:try_resize(25, 7)
  212. command('set display-=msgsep')
  213. command('set wildmenu wildmode=list,full')
  214. feed(':set wildm<tab>')
  215. screen:expect([[
  216. ~ |
  217. ~ |
  218. ~ |
  219. ~ |
  220. :set wildm |
  221. wildmenu wildmode |
  222. :set wildm^ |
  223. ]])
  224. feed('<tab>') -- trigger wildmode full
  225. screen:expect([[
  226. ~ |
  227. ~ |
  228. ~ |
  229. :set wildm |
  230. wildmenu wildmode |
  231. wildmenu wildmode |
  232. :set wildmenu^ |
  233. ]])
  234. feed('<Esc>')
  235. screen:expect([[
  236. ^ |
  237. ~ |
  238. ~ |
  239. ~ |
  240. ~ |
  241. ~ |
  242. |
  243. ]])
  244. end)
  245. it('wildmode=longest,list', function()
  246. -- Need more than 5 rows, else tabline is covered and will be redrawn.
  247. screen:try_resize(25, 7)
  248. command('set wildmenu wildmode=longest,list')
  249. -- give wildmode-longest something to expand to
  250. feed(':sign u<tab>')
  251. screen:expect([[
  252. |
  253. ~ |
  254. ~ |
  255. ~ |
  256. ~ |
  257. ~ |
  258. :sign un^ |
  259. ]])
  260. feed('<tab>') -- trigger wildmode list
  261. screen:expect([[
  262. |
  263. ~ |
  264. ~ |
  265. |
  266. :sign un |
  267. undefine unplace |
  268. :sign un^ |
  269. ]])
  270. feed('<Esc>')
  271. screen:expect([[
  272. ^ |
  273. ~ |
  274. ~ |
  275. ~ |
  276. ~ |
  277. ~ |
  278. |
  279. ]])
  280. -- give wildmode-longest something it cannot expand, use list
  281. feed(':sign un<tab>')
  282. screen:expect([[
  283. |
  284. ~ |
  285. ~ |
  286. |
  287. :sign un |
  288. undefine unplace |
  289. :sign un^ |
  290. ]])
  291. feed('<tab>')
  292. screen:expect_unchanged()
  293. feed('<Esc>')
  294. screen:expect([[
  295. ^ |
  296. ~ |
  297. ~ |
  298. ~ |
  299. ~ |
  300. ~ |
  301. |
  302. ]])
  303. end)
  304. it('wildmode=list,longest', function()
  305. -- Need more than 5 rows, else tabline is covered and will be redrawn.
  306. screen:try_resize(25, 7)
  307. command('set wildmenu wildmode=list,longest')
  308. feed(':sign u<tab>')
  309. screen:expect([[
  310. |
  311. ~ |
  312. ~ |
  313. |
  314. :sign u |
  315. undefine unplace |
  316. :sign u^ |
  317. ]])
  318. feed('<tab>') -- trigger wildmode longest
  319. screen:expect([[
  320. |
  321. ~ |
  322. ~ |
  323. |
  324. :sign u |
  325. undefine unplace |
  326. :sign un^ |
  327. ]])
  328. feed('<Esc>')
  329. screen:expect([[
  330. ^ |
  331. ~ |
  332. ~ |
  333. ~ |
  334. ~ |
  335. ~ |
  336. |
  337. ]])
  338. end)
  339. it('multiple <C-D> renders correctly', function()
  340. screen:try_resize(25, 7)
  341. command('set laststatus=2')
  342. command('set display+=msgsep')
  343. feed(':set wildm')
  344. feed('<c-d>')
  345. screen:expect([[
  346. |
  347. ~ |
  348. ~ |
  349. |
  350. :set wildm |
  351. wildmenu wildmode |
  352. :set wildm^ |
  353. ]])
  354. feed('<c-d>')
  355. screen:expect([[
  356. |
  357. |
  358. :set wildm |
  359. wildmenu wildmode |
  360. :set wildm |
  361. wildmenu wildmode |
  362. :set wildm^ |
  363. ]])
  364. feed('<Esc>')
  365. screen:expect([[
  366. ^ |
  367. ~ |
  368. ~ |
  369. ~ |
  370. ~ |
  371. [No Name] |
  372. |
  373. ]])
  374. end)
  375. it('works with c_CTRL_Z standard mapping', function()
  376. screen:set_default_attr_ids {
  377. [1] = {bold = true, foreground = Screen.colors.Blue1};
  378. [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow};
  379. [3] = {bold = true, reverse = true};
  380. }
  381. -- Wildcharm? where we are going we aint't no need no wildcharm.
  382. eq(0, meths.get_option'wildcharm')
  383. -- Don't mess the defaults yet (neovim is about backwards compatibility)
  384. eq(9, meths.get_option'wildchar')
  385. -- Lol what is cnoremap? Some say it can define mappings.
  386. command 'set wildchar=0'
  387. eq(0, meths.get_option'wildchar')
  388. command 'cnoremap <f2> <c-z>'
  389. feed(':syntax <f2>')
  390. screen:expect{grid=[[
  391. |
  392. {1:~ }|
  393. {1:~ }|
  394. {2:case}{3: clear cluster > }|
  395. :syntax case^ |
  396. ]]}
  397. feed '<esc>'
  398. command 'set wildmode=longest:full,full'
  399. -- this will get cleaner once we have native lua expr mappings:
  400. command [[cnoremap <expr> <tab> luaeval("not rawset(_G, 'coin', not coin).coin") ? "<c-z>" : "c"]]
  401. feed ':syntax <tab>'
  402. screen:expect{grid=[[
  403. |
  404. {1:~ }|
  405. {1:~ }|
  406. {1:~ }|
  407. :syntax c^ |
  408. ]]}
  409. feed '<tab>'
  410. screen:expect{grid=[[
  411. |
  412. {1:~ }|
  413. {1:~ }|
  414. {3:case clear cluster > }|
  415. :syntax c^ |
  416. ]]}
  417. feed '<tab>'
  418. screen:expect{grid=[[
  419. |
  420. {1:~ }|
  421. {1:~ }|
  422. {1:~ }|
  423. :syntax cc^ |
  424. ]]}
  425. end)
  426. end)
  427. describe('command line completion', function()
  428. local screen
  429. before_each(function()
  430. screen = Screen.new(40, 5)
  431. screen:set_default_attr_ids({
  432. [1] = {bold = true, foreground = Screen.colors.Blue1},
  433. [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow},
  434. [3] = {bold = true, reverse = true},
  435. })
  436. end)
  437. after_each(function()
  438. os.remove('Xtest-functional-viml-compl-dir')
  439. end)
  440. it('lists directories with empty PATH', function()
  441. clear()
  442. screen:attach()
  443. local tmp = funcs.tempname()
  444. command('e '.. tmp)
  445. command('cd %:h')
  446. command("call mkdir('Xtest-functional-viml-compl-dir')")
  447. command('let $PATH=""')
  448. feed(':!<tab><bs>')
  449. screen:expect([[
  450. |
  451. {1:~ }|
  452. {1:~ }|
  453. {1:~ }|
  454. :!Xtest-functional-viml-compl-dir^ |
  455. ]])
  456. end)
  457. it('completes env var names #9681', function()
  458. clear()
  459. screen:attach()
  460. command('let $XTEST_1 = "foo" | let $XTEST_2 = "bar"')
  461. command('set wildmenu wildmode=full')
  462. feed(':!echo $XTEST_<tab>')
  463. screen:expect([[
  464. |
  465. {1:~ }|
  466. {1:~ }|
  467. {2:XTEST_1}{3: XTEST_2 }|
  468. :!echo $XTEST_1^ |
  469. ]])
  470. end)
  471. it('completes (multibyte) env var names #9655', function()
  472. clear({env={
  473. ['XTEST_1AaあB']='foo',
  474. ['XTEST_2']='bar',
  475. }})
  476. screen:attach()
  477. command('set wildmenu wildmode=full')
  478. feed(':!echo $XTEST_<tab>')
  479. screen:expect([[
  480. |
  481. {1:~ }|
  482. {1:~ }|
  483. {2:XTEST_1AaあB}{3: XTEST_2 }|
  484. :!echo $XTEST_1AaあB^ |
  485. ]])
  486. end)
  487. end)
  488. describe('ui/ext_wildmenu', function()
  489. local screen
  490. before_each(function()
  491. clear()
  492. screen = Screen.new(25, 5)
  493. screen:attach({rgb=true, ext_wildmenu=true})
  494. end)
  495. it('works with :sign <tab>', function()
  496. local expected = {
  497. 'define',
  498. 'jump',
  499. 'list',
  500. 'place',
  501. 'undefine',
  502. 'unplace',
  503. }
  504. command('set wildmode=full')
  505. command('set wildmenu')
  506. feed(':sign <tab>')
  507. screen:expect{grid=[[
  508. |
  509. ~ |
  510. ~ |
  511. ~ |
  512. :sign define^ |
  513. ]], wildmenu_items=expected, wildmenu_pos=0}
  514. feed('<tab>')
  515. screen:expect{grid=[[
  516. |
  517. ~ |
  518. ~ |
  519. ~ |
  520. :sign jump^ |
  521. ]], wildmenu_items=expected, wildmenu_pos=1}
  522. feed('<left><left>')
  523. screen:expect{grid=[[
  524. |
  525. ~ |
  526. ~ |
  527. ~ |
  528. :sign ^ |
  529. ]], wildmenu_items=expected, wildmenu_pos=-1}
  530. feed('<right>')
  531. screen:expect{grid=[[
  532. |
  533. ~ |
  534. ~ |
  535. ~ |
  536. :sign define^ |
  537. ]], wildmenu_items=expected, wildmenu_pos=0}
  538. feed('a')
  539. screen:expect{grid=[[
  540. |
  541. ~ |
  542. ~ |
  543. ~ |
  544. :sign definea^ |
  545. ]]}
  546. end)
  547. end)