local t = require('test.testutil') local n = require('test.functional.testnvim')() local clear = n.clear local command = n.command local eq, neq = t.eq, t.neq local exec_lua = n.exec_lua local exec = n.exec local feed = n.feed local fn = n.fn local api = n.api local matches = t.matches local source = n.source local pcall_err = t.pcall_err local shallowcopy = t.shallowcopy local sleep = vim.uv.sleep local sid_api_client = -9 local sid_lua = -8 local mode_bits_map = { ['n'] = 0x01, ['x'] = 0x02, ['o'] = 0x04, ['c'] = 0x08, ['i'] = 0x10, ['l'] = 0x20, ['s'] = 0x40, ['t'] = 0x80, [' '] = 0x47, ['v'] = 0x42, ['!'] = 0x18, } describe('nvim_get_keymap', function() before_each(clear) -- Basic mapping and table to be used to describe results local foo_bar_string = 'nnoremap foo bar' local foo_bar_map_table = { lhs = 'foo', lhsraw = 'foo', script = 0, silent = 0, rhs = 'bar', expr = 0, sid = 0, scriptversion = 1, buffer = 0, nowait = 0, mode = 'n', mode_bits = 0x01, abbr = 0, noremap = 1, lnum = 0, } it('returns empty list when no map', function() eq({}, api.nvim_get_keymap('n')) end) it('returns list of all applicable mappings', function() command(foo_bar_string) -- Only one mapping available -- Should be the same as the dictionary we supplied earlier -- and the dictionary you would get from maparg -- since this is a global map, and not script local eq({ foo_bar_map_table }, api.nvim_get_keymap('n')) eq({ fn.maparg('foo', 'n', false, true) }, api.nvim_get_keymap('n')) -- Add another mapping command('nnoremap foo_longer bar_longer') local foolong_bar_map_table = shallowcopy(foo_bar_map_table) foolong_bar_map_table['lhs'] = 'foo_longer' foolong_bar_map_table['lhsraw'] = 'foo_longer' foolong_bar_map_table['rhs'] = 'bar_longer' eq({ foolong_bar_map_table, foo_bar_map_table }, api.nvim_get_keymap('n')) -- Remove a mapping command('unmap foo_longer') eq({ foo_bar_map_table }, api.nvim_get_keymap('n')) end) it('works for other modes', function() -- Add two mappings, one in insert and one normal -- We'll only check the insert mode one command('nnoremap not_going to_check') command('inoremap foo bar') -- The table will be the same except for the mode local insert_table = shallowcopy(foo_bar_map_table) insert_table['mode'] = 'i' insert_table['mode_bits'] = 0x10 eq({ insert_table }, api.nvim_get_keymap('i')) end) it('considers scope', function() -- change the map slightly command('nnoremap foo_longer bar_longer') local foolong_bar_map_table = shallowcopy(foo_bar_map_table) foolong_bar_map_table['lhs'] = 'foo_longer' foolong_bar_map_table['lhsraw'] = 'foo_longer' foolong_bar_map_table['rhs'] = 'bar_longer' local buffer_table = shallowcopy(foo_bar_map_table) buffer_table['buffer'] = 1 command('nnoremap foo bar') -- The buffer mapping should not show up eq({ foolong_bar_map_table }, api.nvim_get_keymap('n')) eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n')) end) it('considers scope for overlapping maps', function() command('nnoremap foo bar') local buffer_table = shallowcopy(foo_bar_map_table) buffer_table['buffer'] = 1 command('nnoremap foo bar') eq({ foo_bar_map_table }, api.nvim_get_keymap('n')) eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n')) end) it('can retrieve mapping for different buffers', function() local original_buffer = api.nvim_buf_get_number(0) -- Place something in each of the buffers to make sure they stick around -- and set hidden so we can leave them command('set hidden') command('new') command('normal! ihello 2') command('new') command('normal! ihello 3') local final_buffer = api.nvim_buf_get_number(0) command('nnoremap foo bar') -- Final buffer will have buffer mappings local buffer_table = shallowcopy(foo_bar_map_table) buffer_table['buffer'] = final_buffer eq({ buffer_table }, api.nvim_buf_get_keymap(final_buffer, 'n')) eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n')) command('buffer ' .. original_buffer) eq(original_buffer, api.nvim_buf_get_number(0)) -- Original buffer won't have any mappings eq({}, api.nvim_get_keymap('n')) eq({}, api.nvim_buf_get_keymap(0, 'n')) eq({ buffer_table }, api.nvim_buf_get_keymap(final_buffer, 'n')) end) -- Test toggle switches for basic options -- @param option The key represented in the `maparg()` result dict local function global_and_buffer_test( map, option, option_token, global_on_result, buffer_on_result, global_off_result, buffer_off_result, new_windows ) local function make_new_windows(number_of_windows) if new_windows == nil then return nil end for _ = 1, number_of_windows do command('new') end end local mode = string.sub(map, 1, 1) -- Don't run this for the mapping, since it doesn't make sense if option_token ~= '' then it( string.format( 'returns %d for the key "%s" when %s is used globally with %s (%s)', global_on_result, option, option_token, map, mode ), function() make_new_windows(new_windows) command(map .. ' ' .. option_token .. ' foo bar') local result = api.nvim_get_keymap(mode)[1][option] eq(global_on_result, result) end ) end it( string.format( 'returns %d for the key "%s" when %s is used for buffers with %s (%s)', buffer_on_result, option, option_token, map, mode ), function() make_new_windows(new_windows) command(map .. ' ' .. option_token .. ' foo bar') local result = api.nvim_buf_get_keymap(0, mode)[1][option] eq(buffer_on_result, result) end ) -- Don't run these for the mapping, since it doesn't make sense if option_token ~= '' then it( string.format( 'returns %d for the key "%s" when %s is not used globally with %s (%s)', global_off_result, option, option_token, map, mode ), function() make_new_windows(new_windows) command(map .. ' baz bat') local result = api.nvim_get_keymap(mode)[1][option] eq(global_off_result, result) end ) it( string.format( 'returns %d for the key "%s" when %s is not used for buffers with %s (%s)', buffer_off_result, option, option_token, map, mode ), function() make_new_windows(new_windows) command(map .. ' foo bar') local result = api.nvim_buf_get_keymap(0, mode)[1][option] eq(buffer_off_result, result) end ) end end -- Standard modes and returns the same values in the dictionary as maparg() local mode_list = { 'nnoremap', 'nmap', 'imap', 'inoremap', 'cnoremap' } for mode in pairs(mode_list) do global_and_buffer_test(mode_list[mode], 'silent', '', 1, 1, 0, 0) global_and_buffer_test(mode_list[mode], 'nowait', '', 1, 1, 0, 0) global_and_buffer_test(mode_list[mode], 'expr', '', 1, 1, 0, 0) end -- noremap will now be 2 if script was used, which is not the same as maparg() global_and_buffer_test('nmap', 'noremap', '