local t = require('test.testutil') local n = require('test.functional.testnvim')() local clear, feed, insert = n.clear, n.feed, n.insert local command = n.command local exec_lua = n.exec_lua local eval = n.eval local expect = n.expect local fn = n.fn local eq = t.eq describe('meta-keys #8226 #13042', function() before_each(function() clear() end) it('ALT/META, normal-mode', function() -- Unmapped ALT-chord behaves as ESC+c. insert('hello') feed('0') expect('llo') -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869 command('nnoremap AESC>') command('nnoremap ; A;') feed('') expect('llo;;') -- Mapped ALT-chord behaves as mapped. command('nnoremap Ameta-l') command('nnoremap Aalt-j') feed('') expect('llo;;alt-jmeta-l') -- Unmapped ALT-chord with characters containing K_SPECIAL bytes command('nnoremap … A…') feed('') expect('llo;;alt-jmeta-l…') command("execute 'nnoremap' nr2char(0x40000000) 'AMAX'") command("call nvim_input('')") command("call nvim_input('')") expect('llo;;alt-jmeta-lMAXMAX') end) it('ALT/META, visual-mode', function() -- Unmapped ALT-chords behave as ESC+c insert('peaches') feed('viwviw') expect('peach') -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869 command('vnoremap AESC>') feed('viwviw') expect('peach;;') -- Mapped ALT-chord behaves as mapped. command('vnoremap Ameta-l') command('vnoremap Aalt-j') feed('viwviw') expect('peach;;alt-jmeta-l') -- Unmapped ALT-chord with characters containing K_SPECIAL bytes feed('viwviw') expect('peach;;alt-jmeta-l…') command("execute 'inoremap' nr2char(0x40000000) 'MAX'") command("call nvim_input('viw')") command("call nvim_input('viw')") expect('peach;;alt-jmeta-lMAXMAX') end) it('ALT/META insert-mode', function() -- Mapped ALT-chord behaves as mapped. command('inoremap meta-l') command('inoremap alt-j') feed('i xxx a') expect('meta-l xxx alt-j') eq({ 0, 1, 14, 0 }, fn.getpos('.')) -- Unmapped ALT-chord behaves as ESC+c. command('iunmap ') feed('0i') eq({ 0, 1, 2, 0 }, fn.getpos('.')) -- Unmapped ALT-chord has same `undo` characteristics as ESC+ command('0,$d') feed('ahello') expect('hellohello') feed('u') expect('hello') end) it('ALT/META terminal-mode', function() exec_lua([[ _G.input_data = '' vim.api.nvim_open_term(0, { on_input = function(_, _, _, data) _G.input_data = _G.input_data .. vim.fn.strtrans(data) end }) ]]) -- Mapped ALT-chord behaves as mapped. command('tnoremap meta-l') command('tnoremap alt-j') feed('i xxx ') eq('meta-l xxx alt-j', exec_lua([[return _G.input_data]])) -- Unmapped ALT-chord is sent to terminal as-is. #16202 #16220 exec_lua([[_G.input_data = '']]) command('tunmap ') feed('') local meta_l_seq = exec_lua([[return _G.input_data]]) command('tnoremap ') feed('yyy') eq(meta_l_seq .. 'yyy' .. meta_l_seq .. 'alt-j', exec_lua([[return _G.input_data]])) eq('t', eval('mode(1)')) feed('j') eq({ 0, 2, 1, 0 }, fn.getpos('.')) eq('nt', eval('mode(1)')) end) it('ALT/META when recording a macro #13235', function() command('inoremap M-ESC>') feed('ifoobarbazgg0') -- is reinterpreted as " feed('qrviw"ayC// This is some text: apq') expect([[ // This is some text: foo bar baz]]) -- Should not insert an extra double quote or trigger when replaying feed('j0@rj0@@') expect([[ // This is some text: foo // This is some text: bar // This is some text: baz]]) command('%delete') end) it('ALT/META with special key when recording a macro', function() command('inoremap M-ESC>') command('noremap "') command('noremap! "') feed('ifoobarbazgg0') -- is reinterpreted as feed('qrviwayC// This is some text: apq') expect([[ // This is some text: foo bar baz]]) -- Should not insert an extra double quote or trigger when replaying feed('j0@rj0@@') expect([[ // This is some text: foo // This is some text: bar // This is some text: baz]]) end) it('ALT/META with vim.on_key()', function() feed('ifoobarbazgg0viw"ay') command('nnoremap … "') exec_lua [[ keys = {} typed = {} vim.on_key(function(buf, typed_buf) table.insert(keys, vim.fn.keytrans(buf)) table.insert(typed, vim.fn.keytrans(typed_buf)) end) ]] -- and are reinterpreted as " and … feed('c$FOO.apA.ap') expect([[ FOO.foo.foo bar baz]]) -- vim.on_key() callback should only receive " and … eq('c$FOO."apA."ap', exec_lua [[return table.concat(keys, '')]]) eq('c$FOO."apA.…ap', exec_lua [[return table.concat(typed, '')]]) end) end)