input_spec.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local clear, feed_command = n.clear, n.feed_command
  5. local feed, next_msg, eq = n.feed, n.next_msg, t.eq
  6. local command = n.command
  7. local expect = n.expect
  8. local curbuf_contents = n.curbuf_contents
  9. local api = n.api
  10. local exec_lua = n.exec_lua
  11. local write_file = t.write_file
  12. local fn = n.fn
  13. local eval = n.eval
  14. before_each(clear)
  15. describe('mappings', function()
  16. local add_mapping = function(mapping, send)
  17. local cmd = 'nnoremap '
  18. .. mapping
  19. .. " :call rpcnotify(1, 'mapped', '"
  20. .. send:gsub('<', '<lt>')
  21. .. "')<cr>"
  22. feed_command(cmd)
  23. end
  24. local check_mapping = function(mapping, expected)
  25. feed(mapping)
  26. eq({ 'notification', 'mapped', { expected } }, next_msg())
  27. end
  28. before_each(function()
  29. add_mapping('<A-l>', '<A-l>')
  30. add_mapping('<A-L>', '<A-L>')
  31. add_mapping('<D-l>', '<D-l>')
  32. add_mapping('<D-L>', '<D-L>')
  33. add_mapping('<C-L>', '<C-L>')
  34. add_mapping('<C-S-L>', '<C-S-L>')
  35. add_mapping('<s-up>', '<s-up>')
  36. add_mapping('<s-up>', '<s-up>')
  37. add_mapping('<c-s-up>', '<c-s-up>')
  38. add_mapping('<c-s-a-up>', '<c-s-a-up>')
  39. add_mapping('<c-s-a-d-up>', '<c-s-a-d-up>')
  40. add_mapping('<c-d-a>', '<c-d-a>')
  41. add_mapping('<d-1>', '<d-1>')
  42. add_mapping('<khome>', '<khome>')
  43. add_mapping('<kup>', '<kup>')
  44. add_mapping('<kpageup>', '<kpageup>')
  45. add_mapping('<kleft>', '<kleft>')
  46. add_mapping('<korigin>', '<korigin>')
  47. add_mapping('<kright>', '<kright>')
  48. add_mapping('<kend>', '<kend>')
  49. add_mapping('<kdown>', '<kdown>')
  50. add_mapping('<kpagedown>', '<kpagedown>')
  51. add_mapping('<kinsert>', '<kinsert>')
  52. add_mapping('<kdel>', '<kdel>')
  53. add_mapping('<kdivide>', '<kdivide>')
  54. add_mapping('<kmultiply>', '<kmultiply>')
  55. add_mapping('<kminus>', '<kminus>')
  56. add_mapping('<kplus>', '<kplus>')
  57. add_mapping('<kenter>', '<kenter>')
  58. add_mapping('<kcomma>', '<kcomma>')
  59. add_mapping('<kequal>', '<kequal>')
  60. add_mapping('<f38>', '<f38>')
  61. add_mapping('<f63>', '<f63>')
  62. end)
  63. it('ok', function()
  64. check_mapping('<A-l>', '<A-l>')
  65. check_mapping('<A-L>', '<A-L>')
  66. check_mapping('<A-S-l>', '<A-L>')
  67. check_mapping('<A-S-L>', '<A-L>')
  68. check_mapping('<D-l>', '<D-l>')
  69. check_mapping('<D-L>', '<D-L>')
  70. check_mapping('<D-S-l>', '<D-L>')
  71. check_mapping('<D-S-L>', '<D-L>')
  72. check_mapping('<C-l>', '<C-L>')
  73. check_mapping('<C-L>', '<C-L>')
  74. check_mapping('<C-S-l>', '<C-S-L>')
  75. check_mapping('<C-S-L>', '<C-S-L>')
  76. check_mapping('<s-up>', '<s-up>')
  77. check_mapping('<c-s-up>', '<c-s-up>')
  78. check_mapping('<s-c-up>', '<c-s-up>')
  79. check_mapping('<c-s-a-up>', '<c-s-a-up>')
  80. check_mapping('<s-c-a-up>', '<c-s-a-up>')
  81. check_mapping('<c-a-s-up>', '<c-s-a-up>')
  82. check_mapping('<s-a-c-up>', '<c-s-a-up>')
  83. check_mapping('<a-c-s-up>', '<c-s-a-up>')
  84. check_mapping('<a-s-c-up>', '<c-s-a-up>')
  85. check_mapping('<c-s-a-d-up>', '<c-s-a-d-up>')
  86. check_mapping('<s-a-d-c-up>', '<c-s-a-d-up>')
  87. check_mapping('<d-s-a-c-up>', '<c-s-a-d-up>')
  88. check_mapping('<c-d-a>', '<c-d-a>')
  89. check_mapping('<d-c-a>', '<c-d-a>')
  90. check_mapping('<d-1>', '<d-1>')
  91. check_mapping('<khome>', '<khome>')
  92. check_mapping('<KP7>', '<khome>')
  93. check_mapping('<kup>', '<kup>')
  94. check_mapping('<KP8>', '<kup>')
  95. check_mapping('<kpageup>', '<kpageup>')
  96. check_mapping('<KP9>', '<kpageup>')
  97. check_mapping('<kleft>', '<kleft>')
  98. check_mapping('<KP4>', '<kleft>')
  99. check_mapping('<korigin>', '<korigin>')
  100. check_mapping('<KP5>', '<korigin>')
  101. check_mapping('<kright>', '<kright>')
  102. check_mapping('<KP6>', '<kright>')
  103. check_mapping('<kend>', '<kend>')
  104. check_mapping('<KP1>', '<kend>')
  105. check_mapping('<kdown>', '<kdown>')
  106. check_mapping('<KP2>', '<kdown>')
  107. check_mapping('<kpagedown>', '<kpagedown>')
  108. check_mapping('<KP3>', '<kpagedown>')
  109. check_mapping('<kinsert>', '<kinsert>')
  110. check_mapping('<KP0>', '<kinsert>')
  111. check_mapping('<kdel>', '<kdel>')
  112. check_mapping('<KPPeriod>', '<kdel>')
  113. check_mapping('<kdivide>', '<kdivide>')
  114. check_mapping('<KPDiv>', '<kdivide>')
  115. check_mapping('<kmultiply>', '<kmultiply>')
  116. check_mapping('<KPMult>', '<kmultiply>')
  117. check_mapping('<kminus>', '<kminus>')
  118. check_mapping('<KPMinus>', '<kminus>')
  119. check_mapping('<kplus>', '<kplus>')
  120. check_mapping('<KPPlus>', '<kplus>')
  121. check_mapping('<kenter>', '<kenter>')
  122. check_mapping('<KPEnter>', '<kenter>')
  123. check_mapping('<kcomma>', '<kcomma>')
  124. check_mapping('<KPComma>', '<kcomma>')
  125. check_mapping('<kequal>', '<kequal>')
  126. check_mapping('<KPEquals>', '<kequal>')
  127. check_mapping('<f38>', '<f38>')
  128. check_mapping('<f63>', '<f63>')
  129. end)
  130. it('support meta + multibyte char mapping', function()
  131. add_mapping('<m-ä>', '<m-ä>')
  132. check_mapping('<m-ä>', '<m-ä>')
  133. end)
  134. end)
  135. describe('input utf sequences that contain K_SPECIAL (0x80)', function()
  136. it('ok', function()
  137. feed('i…<esc>')
  138. expect('…')
  139. end)
  140. it('can be mapped', function()
  141. command('inoremap … E280A6')
  142. feed('i…<esc>')
  143. expect('E280A6')
  144. end)
  145. end)
  146. describe('input utf sequences that contain CSI (0x9B)', function()
  147. it('ok', function()
  148. feed('iě<esc>')
  149. expect('ě')
  150. end)
  151. it('can be mapped', function()
  152. command('inoremap ě C49B')
  153. feed('iě<esc>')
  154. expect('C49B')
  155. end)
  156. end)
  157. describe('input split utf sequences', function()
  158. it('ok', function()
  159. local str = '►'
  160. feed('i' .. str:sub(1, 1))
  161. vim.uv.sleep(10)
  162. feed(str:sub(2, 3))
  163. expect('►')
  164. end)
  165. it('can be mapped', function()
  166. command('inoremap ► E296BA')
  167. local str = '►'
  168. feed('i' .. str:sub(1, 1))
  169. vim.uv.sleep(10)
  170. feed(str:sub(2, 3))
  171. expect('E296BA')
  172. end)
  173. end)
  174. describe('input pairs', function()
  175. describe('<tab> / <c-i>', function()
  176. it('ok', function()
  177. feed('i<tab><c-i><esc>')
  178. eq('\t\t', curbuf_contents())
  179. end)
  180. describe('can be mapped separately', function()
  181. it('if <tab> is mapped after <c-i>', function()
  182. command('inoremap <c-i> CTRL-I!')
  183. command('inoremap <tab> TAB!')
  184. feed('i<tab><c-i><esc>')
  185. eq('TAB!CTRL-I!', curbuf_contents())
  186. end)
  187. it('if <tab> is mapped before <c-i>', function()
  188. command('inoremap <tab> TAB!')
  189. command('inoremap <c-i> CTRL-I!')
  190. feed('i<tab><c-i><esc>')
  191. eq('TAB!CTRL-I!', curbuf_contents())
  192. end)
  193. end)
  194. end)
  195. describe('<cr> / <c-m>', function()
  196. it('ok', function()
  197. feed('iunos<c-m>dos<cr>tres<esc>')
  198. eq('unos\ndos\ntres', curbuf_contents())
  199. end)
  200. describe('can be mapped separately', function()
  201. it('if <cr> is mapped after <c-m>', function()
  202. command('inoremap <c-m> SNIPPET!')
  203. command('inoremap <cr> , and then<cr>')
  204. feed('iunos<c-m>dos<cr>tres<esc>')
  205. eq('unosSNIPPET!dos, and then\ntres', curbuf_contents())
  206. end)
  207. it('if <cr> is mapped before <c-m>', function()
  208. command('inoremap <cr> , and then<cr>')
  209. command('inoremap <c-m> SNIPPET!')
  210. feed('iunos<c-m>dos<cr>tres<esc>')
  211. eq('unosSNIPPET!dos, and then\ntres', curbuf_contents())
  212. end)
  213. end)
  214. end)
  215. describe('<esc> / <c-[>', function()
  216. it('ok', function()
  217. feed('2adouble<c-[>asingle<esc>')
  218. eq('doubledoublesingle', curbuf_contents())
  219. end)
  220. describe('can be mapped separately', function()
  221. it('if <esc> is mapped after <c-[>', function()
  222. command('inoremap <c-[> HALLOJ!')
  223. command('inoremap <esc> ,<esc>')
  224. feed('2adubbel<c-[>upp<esc>')
  225. eq('dubbelHALLOJ!upp,dubbelHALLOJ!upp,', curbuf_contents())
  226. end)
  227. it('if <esc> is mapped before <c-[>', function()
  228. command('inoremap <esc> ,<esc>')
  229. command('inoremap <c-[> HALLOJ!')
  230. feed('2adubbel<c-[>upp<esc>')
  231. eq('dubbelHALLOJ!upp,dubbelHALLOJ!upp,', curbuf_contents())
  232. end)
  233. end)
  234. end)
  235. end)
  236. it('Ctrl-6 is Ctrl-^ vim-patch:8.1.2333', function()
  237. command('split aaa')
  238. command('edit bbb')
  239. feed('<C-6>')
  240. eq('aaa', fn.bufname())
  241. end)
  242. it('c_CTRL-R_CTRL-R, i_CTRL-R_CTRL-R, i_CTRL-G_CTRL-K work properly vim-patch:8.1.2346', function()
  243. command('set timeoutlen=10')
  244. command([[let @a = 'aaa']])
  245. feed([[:let x = '<C-R><C-R>a'<CR>]])
  246. eq([[let x = 'aaa']], eval('@:'))
  247. feed('a<C-R><C-R>a<Esc>')
  248. expect('aaa')
  249. command('bwipe!')
  250. feed('axx<CR>yy<C-G><C-K>a<Esc>')
  251. expect([[
  252. axx
  253. yy]])
  254. end)
  255. it('typing a simplifiable key at hit-enter prompt triggers mapping vim-patch:8.2.0839', function()
  256. local screen = Screen.new(60, 8)
  257. command([[nnoremap <C-6> <Cmd>echo 'hit ctrl-6'<CR>]])
  258. feed_command('ls')
  259. screen:expect([[
  260. |
  261. {1:~ }|*3
  262. {3: }|
  263. :ls |
  264. 1 %a "[No Name]" line 1 |
  265. {6:Press ENTER or type command to continue}^ |
  266. ]])
  267. feed('<C-6>')
  268. screen:expect([[
  269. ^ |
  270. {1:~ }|*6
  271. hit ctrl-6 |
  272. ]])
  273. end)
  274. it('mixing simplified and unsimplified keys can trigger mapping vim-patch:8.2.0916', function()
  275. command('set timeoutlen=10')
  276. command([[imap ' <C-W>]])
  277. command('imap <C-W><C-A> c-a')
  278. feed([[a'<C-A>]])
  279. expect('c-a')
  280. end)
  281. it('unsimplified mapping works when there was a partial match vim-patch:8.2.4504', function()
  282. command('set timeoutlen=10')
  283. command('nnoremap <C-J> a')
  284. command('nnoremap <NL> x')
  285. command('nnoremap <C-J>x <Nop>')
  286. fn.setline(1, 'x')
  287. -- CTRL-J b should have trigger the <C-J> mapping and then insert "b"
  288. feed('<C-J>b<Esc>')
  289. expect('xb')
  290. end)
  291. describe('input non-printable chars', function()
  292. after_each(function()
  293. os.remove('Xtest-overwrite')
  294. end)
  295. it("doesn't crash when echoing them back", function()
  296. write_file('Xtest-overwrite', [[foobar]])
  297. local screen = Screen.new(60, 8)
  298. command('set shortmess-=F')
  299. feed_command('e Xtest-overwrite')
  300. screen:expect([[
  301. ^foobar |
  302. {1:~ }|*6
  303. "Xtest-overwrite" [noeol] 1L, 6B |
  304. ]])
  305. -- Wait for some time so that the timestamp changes.
  306. vim.uv.sleep(10)
  307. write_file('Xtest-overwrite', [[smurf]])
  308. feed_command('w')
  309. screen:expect([[
  310. foobar |
  311. {1:~ }|*3
  312. {3: }|
  313. "Xtest-overwrite" |
  314. {9:WARNING: The file has been changed since reading it!!!} |
  315. {6:Do you really want to write to it (y/n)?}^ |
  316. ]])
  317. feed('u')
  318. screen:expect([[
  319. foobar |
  320. {1:~ }|*2
  321. {3: }|
  322. "Xtest-overwrite" |
  323. {9:WARNING: The file has been changed since reading it!!!} |
  324. {6:Do you really want to write to it (y/n)?}u |
  325. {6:Do you really want to write to it (y/n)?}^ |
  326. ]])
  327. feed('\005')
  328. screen:expect([[
  329. foobar |
  330. {1:~ }|
  331. {3: }|
  332. "Xtest-overwrite" |
  333. {9:WARNING: The file has been changed since reading it!!!} |
  334. {6:Do you really want to write to it (y/n)?}u |
  335. {6:Do you really want to write to it (y/n)?}{18:^E} |
  336. {6:Do you really want to write to it (y/n)?}^ |
  337. ]])
  338. feed('n')
  339. screen:expect([[
  340. foobar |
  341. {3: }|
  342. "Xtest-overwrite" |
  343. {9:WARNING: The file has been changed since reading it!!!} |
  344. {6:Do you really want to write to it (y/n)?}u |
  345. {6:Do you really want to write to it (y/n)?}{18:^E} |
  346. {6:Do you really want to write to it (y/n)?}n |
  347. {6:Press ENTER or type command to continue}^ |
  348. ]])
  349. feed('<cr>')
  350. screen:expect([[
  351. ^foobar |
  352. {1:~ }|*6
  353. |
  354. ]])
  355. end)
  356. end)
  357. describe('event processing and input', function()
  358. it('not blocked by event bursts', function()
  359. api.nvim_set_keymap(
  360. '',
  361. '<f2>',
  362. "<cmd>lua vim.rpcnotify(1, 'stop') winning = true <cr>",
  363. { noremap = true }
  364. )
  365. exec_lua [[
  366. winning = false
  367. burst = vim.schedule_wrap(function(tell)
  368. if tell then
  369. vim.rpcnotify(1, 'start')
  370. end
  371. -- Are we winning, son?
  372. if not winning then
  373. burst(false)
  374. end
  375. end)
  376. burst(true)
  377. ]]
  378. eq({ 'notification', 'start', {} }, next_msg())
  379. feed '<f2>'
  380. eq({ 'notification', 'stop', {} }, next_msg())
  381. end)
  382. end)
  383. describe('display is updated', function()
  384. local screen
  385. before_each(function()
  386. screen = Screen.new(60, 8)
  387. end)
  388. it('in Insert mode after <Nop> mapping #17911', function()
  389. command('imap <Plug>test <Nop>')
  390. command('imap <F2> abc<CR><Plug>test')
  391. feed('i<F2>')
  392. screen:expect([[
  393. abc |
  394. ^ |
  395. {1:~ }|*5
  396. {5:-- INSERT --} |
  397. ]])
  398. end)
  399. it('in Insert mode after empty string <expr> mapping #17911', function()
  400. command('imap <expr> <Plug>test ""')
  401. command('imap <F2> abc<CR><Plug>test')
  402. feed('i<F2>')
  403. screen:expect([[
  404. abc |
  405. ^ |
  406. {1:~ }|*5
  407. {5:-- INSERT --} |
  408. ]])
  409. end)
  410. end)