meta_key_spec.lua 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local clear, feed, insert = n.clear, n.feed, n.insert
  4. local command = n.command
  5. local exec_lua = n.exec_lua
  6. local eval = n.eval
  7. local expect = n.expect
  8. local fn = n.fn
  9. local eq = t.eq
  10. describe('meta-keys #8226 #13042', function()
  11. before_each(function()
  12. clear()
  13. end)
  14. it('ALT/META, normal-mode', function()
  15. -- Unmapped ALT-chord behaves as ESC+c.
  16. insert('hello')
  17. feed('0<A-x><M-x>')
  18. expect('llo')
  19. -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869
  20. command('nnoremap <ESC> A<lt>ESC><Esc>')
  21. command('nnoremap ; A;<Esc>')
  22. feed('<A-;><M-;>')
  23. expect('llo<ESC>;<ESC>;')
  24. -- Mapped ALT-chord behaves as mapped.
  25. command('nnoremap <M-l> Ameta-l<Esc>')
  26. command('nnoremap <A-j> Aalt-j<Esc>')
  27. feed('<A-j><M-l>')
  28. expect('llo<ESC>;<ESC>;alt-jmeta-l')
  29. -- Unmapped ALT-chord with characters containing K_SPECIAL bytes
  30. command('nnoremap … A…<Esc>')
  31. feed('<A-…><M-…>')
  32. expect('llo<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…')
  33. command("execute 'nnoremap' nr2char(0x40000000) 'AMAX<Esc>'")
  34. command("call nvim_input('<A-'.nr2char(0x40000000).'>')")
  35. command("call nvim_input('<M-'.nr2char(0x40000000).'>')")
  36. expect('llo<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…<ESC>MAX<ESC>MAX')
  37. end)
  38. it('ALT/META, visual-mode', function()
  39. -- Unmapped ALT-chords behave as ESC+c
  40. insert('peaches')
  41. feed('viw<A-x>viw<M-x>')
  42. expect('peach')
  43. -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869
  44. command('vnoremap <ESC> A<lt>ESC>')
  45. feed('viw<A-;><Esc>viw<M-;><Esc>')
  46. expect('peach<ESC>;<ESC>;')
  47. -- Mapped ALT-chord behaves as mapped.
  48. command('vnoremap <M-l> Ameta-l<Esc>')
  49. command('vnoremap <A-j> Aalt-j<Esc>')
  50. feed('viw<A-j>viw<M-l>')
  51. expect('peach<ESC>;<ESC>;alt-jmeta-l')
  52. -- Unmapped ALT-chord with characters containing K_SPECIAL bytes
  53. feed('viw<A-…><Esc>viw<M-…><Esc>')
  54. expect('peach<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…')
  55. command("execute 'inoremap' nr2char(0x40000000) 'MAX'")
  56. command("call nvim_input('viw<A-'.nr2char(0x40000000).'><Esc>')")
  57. command("call nvim_input('viw<M-'.nr2char(0x40000000).'><Esc>')")
  58. expect('peach<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…<ESC>MAX<ESC>MAX')
  59. end)
  60. it('ALT/META insert-mode', function()
  61. -- Mapped ALT-chord behaves as mapped.
  62. command('inoremap <M-l> meta-l')
  63. command('inoremap <A-j> alt-j')
  64. feed('i<M-l> xxx <A-j><M-h>a<A-h>')
  65. expect('meta-l xxx alt-j')
  66. eq({ 0, 1, 14, 0 }, fn.getpos('.'))
  67. -- Unmapped ALT-chord behaves as ESC+c.
  68. command('iunmap <M-l>')
  69. feed('0i<M-l>')
  70. eq({ 0, 1, 2, 0 }, fn.getpos('.'))
  71. -- Unmapped ALT-chord has same `undo` characteristics as ESC+<key>
  72. command('0,$d')
  73. feed('ahello<M-.>')
  74. expect('hellohello')
  75. feed('u')
  76. expect('hello')
  77. end)
  78. it('ALT/META terminal-mode', function()
  79. exec_lua([[
  80. _G.input_data = ''
  81. vim.api.nvim_open_term(0, { on_input = function(_, _, _, data)
  82. _G.input_data = _G.input_data .. vim.fn.strtrans(data)
  83. end })
  84. ]])
  85. -- Mapped ALT-chord behaves as mapped.
  86. command('tnoremap <M-l> meta-l')
  87. command('tnoremap <A-j> alt-j')
  88. feed('i<M-l> xxx <A-j>')
  89. eq('meta-l xxx alt-j', exec_lua([[return _G.input_data]]))
  90. -- Unmapped ALT-chord is sent to terminal as-is. #16202 #16220
  91. exec_lua([[_G.input_data = '']])
  92. command('tunmap <M-l>')
  93. feed('<M-l>')
  94. local meta_l_seq = exec_lua([[return _G.input_data]])
  95. command('tnoremap <Esc> <C-\\><C-N>')
  96. feed('yyy<M-l><A-j>')
  97. eq(meta_l_seq .. 'yyy' .. meta_l_seq .. 'alt-j', exec_lua([[return _G.input_data]]))
  98. eq('t', eval('mode(1)'))
  99. feed('<Esc>j')
  100. eq({ 0, 2, 1, 0 }, fn.getpos('.'))
  101. eq('nt', eval('mode(1)'))
  102. end)
  103. it('ALT/META when recording a macro #13235', function()
  104. command('inoremap <M-Esc> <lt>M-ESC>')
  105. feed('ifoo<CR>bar<CR>baz<Esc>gg0')
  106. -- <M-"> is reinterpreted as <Esc>"
  107. feed('qrviw"ayC// This is some text: <M-">apq')
  108. expect([[
  109. // This is some text: foo
  110. bar
  111. baz]])
  112. -- Should not insert an extra double quote or trigger <M-Esc> when replaying
  113. feed('j0@rj0@@')
  114. expect([[
  115. // This is some text: foo
  116. // This is some text: bar
  117. // This is some text: baz]])
  118. command('%delete')
  119. end)
  120. it('ALT/META with special key when recording a macro', function()
  121. command('inoremap <M-Esc> <lt>M-ESC>')
  122. command('noremap <S-Tab> "')
  123. command('noremap! <S-Tab> "')
  124. feed('ifoo<CR>bar<CR>baz<Esc>gg0')
  125. -- <M-S-Tab> is reinterpreted as <Esc><S-Tab>
  126. feed('qrviw<S-Tab>ayC// This is some text: <M-S-Tab>apq')
  127. expect([[
  128. // This is some text: foo
  129. bar
  130. baz]])
  131. -- Should not insert an extra double quote or trigger <M-Esc> when replaying
  132. feed('j0@rj0@@')
  133. expect([[
  134. // This is some text: foo
  135. // This is some text: bar
  136. // This is some text: baz]])
  137. end)
  138. it('ALT/META with vim.on_key()', function()
  139. feed('ifoo<CR>bar<CR>baz<Esc>gg0viw"ay')
  140. command('nnoremap … "')
  141. exec_lua [[
  142. keys = {}
  143. typed = {}
  144. vim.on_key(function(buf, typed_buf)
  145. table.insert(keys, vim.fn.keytrans(buf))
  146. table.insert(typed, vim.fn.keytrans(typed_buf))
  147. end)
  148. ]]
  149. -- <M-"> and <M-…> are reinterpreted as <Esc>" and <Esc>…
  150. feed('c$FOO.<M-">apA.<M-…>ap')
  151. expect([[
  152. FOO.foo.foo
  153. bar
  154. baz]])
  155. -- vim.on_key() callback should only receive <Esc>" and <Esc>…
  156. eq('c$FOO.<Esc>"apA.<Esc>"ap', exec_lua [[return table.concat(keys, '')]])
  157. eq('c$FOO.<Esc>"apA.<Esc>…ap', exec_lua [[return table.concat(typed, '')]])
  158. end)
  159. end)