feat(lua): support table lhs in vim.keymap.set()/del() #39948

Problem:
It is repetitive to map multiple keymaps to do the same thing. Here are some
cases where being able to do this would be useful:

    -- Visual movement for both j/k and down/up:
    vim.keymap.set({ 'n', 'x' }, { 'j', '<Down>' }, 'v:count == 0 ? "gj" : "j"', { expr = true })
    vim.keymap.set({ 'n', 'x' }, { 'k', '<Up>' }, 'v:count == 0 ? "gk" : "k"', { expr = true })
    -- Map multiple keys to `<Nop>` concisely:
    vim.keymap.set({ 'n', 'x' }, { '<Leader>', '<Localleader>', '<CR>' }, '<Nop>')
    -- Remove multiple keymaps at once:
    vim.keymap.del('n', { 'gri', 'grn', 'grr' })

Solution:
Support the `lhs` of `vim.keymap.set()` and `vim.keymap.del()` being a table, in
the same way that `modes` can be.
This commit is contained in:
Olivia Kinnear
2026-05-29 13:45:33 -05:00
committed by GitHub
parent 4b5f026ac9
commit e728c100b5
4 changed files with 45 additions and 25 deletions

View File

@@ -2929,8 +2929,8 @@ describe('vim.keymap', function()
)
matches(
'lhs: expected string, got table',
pcall_err(exec_lua, [[vim.keymap.set('n', {}, print)]])
'lhs: expected string|table, got number',
pcall_err(exec_lua, [[vim.keymap.set('n', 5, print)]])
)
matches(
@@ -2957,13 +2957,16 @@ describe('vim.keymap', function()
exec_lua [[
GlobalCount = 0
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
vim.keymap.set('n', { 'ghjk', 'qwer' }, function() GlobalCount = GlobalCount + 1 end)
return GlobalCount
]]
)
feed('asdf\n')
eq(1, exec_lua [[return GlobalCount]])
feed('ghjk\nqwer\n')
eq(3, exec_lua [[return GlobalCount]])
end)
it('expr mapping', function()
@@ -3004,7 +3007,7 @@ describe('vim.keymap', function()
0,
exec_lua [[
GlobalCount = 0
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
vim.keymap.set('n', { 'asdf', 'ghjk', 'qwer' }, function() GlobalCount = GlobalCount + 1 end)
return GlobalCount
]]
)
@@ -3021,6 +3024,16 @@ describe('vim.keymap', function()
eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', n.exec_capture('nmap asdf'))
exec_lua [[
vim.keymap.del('n', { 'ghjk', 'qwer' })
]]
feed('ghjk\nqwer\n')
eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', n.exec_capture('nmap ghjk'))
eq('\nNo mapping found', n.exec_capture('nmap qwer'))
end)
it('buffer-local mappings', function()