mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #16591 from shadmansaleh/feat/lua_keymaps2
feat(lua): add support for lua keymaps
This commit is contained in:
commit
2f779e3361
@ -1847,4 +1847,81 @@ add({filetypes}) *vim.filetype.add()*
|
|||||||
{filetypes} table A table containing new filetype maps
|
{filetypes} table A table containing new filetype maps
|
||||||
(see example).
|
(see example).
|
||||||
|
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
Lua module: keymap *lua-keymap*
|
||||||
|
|
||||||
|
del({modes}, {lhs}, {opts}) *vim.keymap.del()*
|
||||||
|
Remove an existing mapping. Examples: >
|
||||||
|
|
||||||
|
vim.keymap.del('n', 'lhs')
|
||||||
|
|
||||||
|
vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
|
||||||
|
<
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{opts} table A table of optional arguments:
|
||||||
|
• buffer: (number or boolean) Remove a mapping
|
||||||
|
from the given buffer. When "true" or 0, use the
|
||||||
|
current buffer.
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
|vim.keymap.set()|
|
||||||
|
|
||||||
|
set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
|
||||||
|
Add a new |mapping|. Examples: >
|
||||||
|
|
||||||
|
-- Can add mapping to Lua functions
|
||||||
|
vim.keymap.set('n', 'lhs', function() print("real lua function") end)
|
||||||
|
|
||||||
|
-- Can use it to map multiple modes
|
||||||
|
vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true })
|
||||||
|
|
||||||
|
-- Can add mapping for specific buffer
|
||||||
|
vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 })
|
||||||
|
|
||||||
|
-- Expr mappings
|
||||||
|
vim.keymap.set('i', '<Tab>', function()
|
||||||
|
return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
|
||||||
|
end, { expr = true })
|
||||||
|
-- <Plug> mappings
|
||||||
|
vim.keymap.set('n', '[%', '<Plug>(MatchitNormalMultiBackward)')
|
||||||
|
<
|
||||||
|
|
||||||
|
Note that in a mapping like: >
|
||||||
|
|
||||||
|
vim.keymap.set('n', 'asdf', require('jkl').my_fun)
|
||||||
|
<
|
||||||
|
|
||||||
|
the require('jkl') gets evaluated during this call in order to
|
||||||
|
access the function. If you want to avoid this cost at startup
|
||||||
|
you can wrap it in a function, for example: >
|
||||||
|
|
||||||
|
vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
|
||||||
|
<
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{mode} string|table Same mode short names as
|
||||||
|
|nvim_set_keymap()|. Can also be list of modes to
|
||||||
|
create mapping on multiple modes.
|
||||||
|
{lhs} string Left-hand side |{lhs}| of the mapping.
|
||||||
|
{rhs} string|function Right-hand side |{rhs}| of the
|
||||||
|
mapping. Can also be a Lua function.
|
||||||
|
{opts} table A table of |:map-arguments| such as
|
||||||
|
"silent". In addition to the options listed in
|
||||||
|
|nvim_set_keymap()|, this table also accepts the
|
||||||
|
following keys:
|
||||||
|
• replace_keycodes: (boolean, default true) When
|
||||||
|
both this and expr is "true",
|
||||||
|
|nvim_replace_termcodes()| is applied to the
|
||||||
|
result of Lua expr maps.
|
||||||
|
• remap: (boolean) Make the mapping recursive.
|
||||||
|
This is the inverse of the "noremap" option from
|
||||||
|
|nvim_set_keymap()|. Default `true` if `lhs` is
|
||||||
|
a string starting with `<plug>`
|
||||||
|
(case-insensitive), `false` otherwise.
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
|nvim_set_keymap()|
|
||||||
|
|
||||||
vim:tw=78:ts=8:ft=help:norl:
|
vim:tw=78:ts=8:ft=help:norl:
|
||||||
|
135
runtime/lua/vim/keymap.lua
Normal file
135
runtime/lua/vim/keymap.lua
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
local keymap = {}
|
||||||
|
|
||||||
|
--- Add a new |mapping|.
|
||||||
|
--- Examples:
|
||||||
|
--- <pre>
|
||||||
|
--- -- Can add mapping to Lua functions
|
||||||
|
--- vim.keymap.set('n', 'lhs', function() print("real lua function") end)
|
||||||
|
---
|
||||||
|
--- -- Can use it to map multiple modes
|
||||||
|
--- vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true })
|
||||||
|
---
|
||||||
|
--- -- Can add mapping for specific buffer
|
||||||
|
--- vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 })
|
||||||
|
---
|
||||||
|
--- -- Expr mappings
|
||||||
|
--- vim.keymap.set('i', '<Tab>', function()
|
||||||
|
--- return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
|
||||||
|
--- end, { expr = true })
|
||||||
|
--- -- <Plug> mappings
|
||||||
|
--- vim.keymap.set('n', '[%%', '<Plug>(MatchitNormalMultiBackward)')
|
||||||
|
--- </pre>
|
||||||
|
---
|
||||||
|
--- Note that in a mapping like:
|
||||||
|
--- <pre>
|
||||||
|
--- vim.keymap.set('n', 'asdf', require('jkl').my_fun)
|
||||||
|
--- </pre>
|
||||||
|
---
|
||||||
|
--- the require('jkl') gets evaluated during this call in order to access the function. If you want to
|
||||||
|
--- avoid this cost at startup you can wrap it in a function, for example:
|
||||||
|
--- <pre>
|
||||||
|
--- vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
|
||||||
|
--- </pre>
|
||||||
|
---
|
||||||
|
---@param mode string|table Same mode short names as |nvim_set_keymap()|.
|
||||||
|
--- Can also be list of modes to create mapping on multiple modes.
|
||||||
|
---@param lhs string Left-hand side |{lhs}| of the mapping.
|
||||||
|
---@param rhs string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function.
|
||||||
|
--
|
||||||
|
---@param opts table A table of |:map-arguments| such as "silent". In addition to the options
|
||||||
|
--- listed in |nvim_set_keymap()|, this table also accepts the following keys:
|
||||||
|
--- - replace_keycodes: (boolean, default true) When both this and expr is "true",
|
||||||
|
--- |nvim_replace_termcodes()| is applied to the result of Lua expr maps.
|
||||||
|
--- - remap: (boolean) Make the mapping recursive. This is the
|
||||||
|
--- inverse of the "noremap" option from |nvim_set_keymap()|.
|
||||||
|
--- Default `true` if `lhs` is a string starting with `<plug>` (case-insensitive), `false` otherwise.
|
||||||
|
---@see |nvim_set_keymap()|
|
||||||
|
function keymap.set(mode, lhs, rhs, opts)
|
||||||
|
vim.validate {
|
||||||
|
mode = {mode, {'s', 't'}},
|
||||||
|
lhs = {lhs, 's'},
|
||||||
|
rhs = {rhs, {'s', 'f'}},
|
||||||
|
opts = {opts, 't', true}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = vim.deepcopy(opts) or {}
|
||||||
|
local is_rhs_luaref = type(rhs) == "function"
|
||||||
|
mode = type(mode) == 'string' and {mode} or mode
|
||||||
|
|
||||||
|
if is_rhs_luaref and opts.expr and opts.replace_keycodes ~= false then
|
||||||
|
local user_rhs = rhs
|
||||||
|
rhs = function ()
|
||||||
|
return vim.api.nvim_replace_termcodes(user_rhs(), true, true, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- clear replace_keycodes from opts table
|
||||||
|
opts.replace_keycodes = nil
|
||||||
|
|
||||||
|
if opts.remap == nil then
|
||||||
|
-- remap by default on <plug> mappings and don't otherwise.
|
||||||
|
opts.noremap = is_rhs_luaref or rhs:lower():match("^<plug>") == nil
|
||||||
|
else
|
||||||
|
-- remaps behavior is opposite of noremap option.
|
||||||
|
opts.noremap = not opts.remap
|
||||||
|
opts.remap = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if is_rhs_luaref then
|
||||||
|
opts.callback = rhs
|
||||||
|
rhs = ''
|
||||||
|
end
|
||||||
|
|
||||||
|
if opts.buffer then
|
||||||
|
local bufnr = opts.buffer == true and 0 or opts.buffer
|
||||||
|
opts.buffer = nil
|
||||||
|
for _, m in ipairs(mode) do
|
||||||
|
vim.api.nvim_buf_set_keymap(bufnr, m, lhs, rhs, opts)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
opts.buffer = nil
|
||||||
|
for _, m in ipairs(mode) do
|
||||||
|
vim.api.nvim_set_keymap(m, lhs, rhs, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove an existing mapping.
|
||||||
|
--- Examples:
|
||||||
|
--- <pre>
|
||||||
|
--- vim.keymap.del('n', 'lhs')
|
||||||
|
---
|
||||||
|
--- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
|
||||||
|
--- </pre>
|
||||||
|
---@param opts table A table of optional arguments:
|
||||||
|
--- - buffer: (number or boolean) Remove a mapping from the given buffer.
|
||||||
|
--- When "true" or 0, use the current buffer.
|
||||||
|
---@see |vim.keymap.set()|
|
||||||
|
---
|
||||||
|
function keymap.del(modes, lhs, opts)
|
||||||
|
vim.validate {
|
||||||
|
mode = {modes, {'s', 't'}},
|
||||||
|
lhs = {lhs, 's'},
|
||||||
|
opts = {opts, 't', true}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = opts or {}
|
||||||
|
modes = type(modes) == 'string' and {modes} or modes
|
||||||
|
|
||||||
|
local buffer = false
|
||||||
|
if opts.buffer ~= nil then
|
||||||
|
buffer = opts.buffer == true and 0 or opts.buffer
|
||||||
|
opts.buffer = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if buffer == false then
|
||||||
|
for _, mode in ipairs(modes) do
|
||||||
|
vim.api.nvim_del_keymap(mode, lhs)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, mode in ipairs(modes) do
|
||||||
|
vim.api.nvim_buf_del_keymap(buffer, mode, lhs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return keymap
|
@ -129,6 +129,7 @@ CONFIG = {
|
|||||||
'uri.lua',
|
'uri.lua',
|
||||||
'ui.lua',
|
'ui.lua',
|
||||||
'filetype.lua',
|
'filetype.lua',
|
||||||
|
'keymap.lua',
|
||||||
],
|
],
|
||||||
'files': ' '.join([
|
'files': ' '.join([
|
||||||
os.path.join(base_dir, 'src/nvim/lua/vim.lua'),
|
os.path.join(base_dir, 'src/nvim/lua/vim.lua'),
|
||||||
@ -136,6 +137,7 @@ CONFIG = {
|
|||||||
os.path.join(base_dir, 'runtime/lua/vim/uri.lua'),
|
os.path.join(base_dir, 'runtime/lua/vim/uri.lua'),
|
||||||
os.path.join(base_dir, 'runtime/lua/vim/ui.lua'),
|
os.path.join(base_dir, 'runtime/lua/vim/ui.lua'),
|
||||||
os.path.join(base_dir, 'runtime/lua/vim/filetype.lua'),
|
os.path.join(base_dir, 'runtime/lua/vim/filetype.lua'),
|
||||||
|
os.path.join(base_dir, 'runtime/lua/vim/keymap.lua'),
|
||||||
]),
|
]),
|
||||||
'file_patterns': '*.lua',
|
'file_patterns': '*.lua',
|
||||||
'fn_name_prefix': '',
|
'fn_name_prefix': '',
|
||||||
@ -151,6 +153,7 @@ CONFIG = {
|
|||||||
'uri': 'vim',
|
'uri': 'vim',
|
||||||
'ui': 'vim.ui',
|
'ui': 'vim.ui',
|
||||||
'filetype': 'vim.filetype',
|
'filetype': 'vim.filetype',
|
||||||
|
'keymap': 'vim.keymap',
|
||||||
},
|
},
|
||||||
'append_only': [
|
'append_only': [
|
||||||
'shared.lua',
|
'shared.lua',
|
||||||
|
@ -115,6 +115,9 @@ setmetatable(vim, {
|
|||||||
elseif key == 'ui' then
|
elseif key == 'ui' then
|
||||||
t.ui = require('vim.ui')
|
t.ui = require('vim.ui')
|
||||||
return t.ui
|
return t.ui
|
||||||
|
elseif key == 'keymap' then
|
||||||
|
t.keymap = require('vim.keymap')
|
||||||
|
return t.keymap
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
@ -2298,3 +2298,82 @@ describe('lua: require("mod") from packages', function()
|
|||||||
eq('I am fancy_z.lua', exec_lua [[ return require'fancy_z' ]])
|
eq('I am fancy_z.lua', exec_lua [[ return require'fancy_z' ]])
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('vim.keymap', function()
|
||||||
|
it('can make a mapping', function()
|
||||||
|
eq(0, exec_lua [[
|
||||||
|
GlobalCount = 0
|
||||||
|
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
|
||||||
|
return GlobalCount
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('asdf\n')
|
||||||
|
|
||||||
|
eq(1, exec_lua[[return GlobalCount]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can make an expr mapping', function()
|
||||||
|
exec_lua [[
|
||||||
|
vim.keymap.set('n', 'aa', function() return ':lua SomeValue = 99<cr>' end, {expr = true})
|
||||||
|
]]
|
||||||
|
|
||||||
|
feed('aa')
|
||||||
|
|
||||||
|
eq(99, exec_lua[[return SomeValue]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can overwrite a mapping', function()
|
||||||
|
eq(0, exec_lua [[
|
||||||
|
GlobalCount = 0
|
||||||
|
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
|
||||||
|
return GlobalCount
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('asdf\n')
|
||||||
|
|
||||||
|
eq(1, exec_lua[[return GlobalCount]])
|
||||||
|
|
||||||
|
exec_lua [[
|
||||||
|
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount - 1 end)
|
||||||
|
]]
|
||||||
|
|
||||||
|
feed('asdf\n')
|
||||||
|
|
||||||
|
eq(0, exec_lua[[return GlobalCount]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can unmap a mapping', function()
|
||||||
|
eq(0, exec_lua [[
|
||||||
|
GlobalCount = 0
|
||||||
|
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
|
||||||
|
return GlobalCount
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('asdf\n')
|
||||||
|
|
||||||
|
eq(1, exec_lua[[return GlobalCount]])
|
||||||
|
|
||||||
|
exec_lua [[
|
||||||
|
vim.keymap.del('n', 'asdf')
|
||||||
|
]]
|
||||||
|
|
||||||
|
feed('asdf\n')
|
||||||
|
|
||||||
|
eq(1, exec_lua[[return GlobalCount]])
|
||||||
|
eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can do <Plug> mappings', function()
|
||||||
|
eq(0, exec_lua [[
|
||||||
|
GlobalCount = 0
|
||||||
|
vim.keymap.set('n', '<plug>(asdf)', function() GlobalCount = GlobalCount + 1 end)
|
||||||
|
vim.keymap.set('n', 'ww', '<plug>(asdf)')
|
||||||
|
return GlobalCount
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('ww\n')
|
||||||
|
|
||||||
|
eq(1, exec_lua[[return GlobalCount]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user