A Neovim Lua plugin to make mapping and commands more manageable.
Mapx.nvim is a Lua library that mimics Vim's :map
and :command
family of
commands.
Its aim is to make configuring key mappings and commands from within Lua more
ergonomic.
Without Mapx:
vim.api.nvim_set_keymap("n", "j", "v:count ? 'j' : 'gj'", { noremap = true, expr = true })
vim.api.nvim_set_keymap("n", "k", "v:count ? 'k' : 'gk'", { noremap = true, expr = true })
vim.api.nvim_set_keymap("n", "J", "5j", {})
vim.api.nvim_set_keymap("n", "K", "5k", {})
vim.api.nvim_set_keymap("i", "<Tab>", [[pumvisible() ? "\<C-n>" : "\<Tab>"]], { noremap = true, silent = true, expr = true })
vim.api.nvim_set_keymap("i", "<S-Tab>", [[pumvisible() ? "\<C-p>" : "\<S-Tab>"]], { noremap = true, silent = true, expr = true })
vim.api.nvim_set_keymap("", "<M-/>", ":Commentary<Cr>", { silent = true })
vim.cmd [[command -nargs=0 LspDiag lua vim.lsp.diagnostic.set_loclist()]]
With Mapx:
require'mapx'.setup{ global = true }
nnoremap("j", "v:count ? 'j' : 'gj'", "expr")
nnoremap("k", "v:count ? 'k' : 'gk'", "expr")
nmap("J", "5j")
nmap("K", "5k")
inoremap("<Tab>", [[pumvisible() ? "\<C-n>" : "\<Tab>"]], "silent", "expr")
inoremap("<S-Tab>", [[pumvisible() ? "\<C-p>" : "\<S-Tab>"]], "silent", "expr")
map("<M-/>", ":Commentary<Cr>", "silent")
cmd("LspDiag", function() vim.lsp.diagnostic.set_loclist() end, {nargs = 0})
Create multiple mappings to the same action in one shot:
nnoremap({"<C-f><C-f>", "<C-f>f"}, ":lua require('telescope.builtin').find_files()<Cr>", "silent")
Integrate with which-key.nvim by passing a label as the final argument:
local m = require'mapx'.setup{ global = true, whichkey = true }
nnoremap("gD", "<cmd>lua vim.lsp.buf.declaration()<Cr>", "silent", "LSP: Goto declaration")
-- Also supports setting WhichKey group names
m.nname("<leader>l", "LSP")
nnoremap("<leader>li", ":LspInfo<Cr>", "LSP: Show LSP information")
nnoremap("<leader>lr", ":LspRestart<Cr>", "LSP: Restart LSP")
nnoremap("<leader>ls", ":LspStart<Cr>", "LSP: Start LSP")
nnoremap("<leader>lS", ":LspStop<Cr>", "LSP: Stop LSP")
FileType mappings will be applied only to buffers with a matching filetype.
nnoremap("<tab>", [[:call search('\(\w\+(\w\+)\)', 's')<Cr>]], "silent", { ft = "man" })
nnoremap("<S-tab>", [[:call search('\(\w\+(\w\+)\)', 'sb')<Cr>]], "silent", { ft = "man" })
Mappings with common options can be grouped to reduce repetition.
mapx.group("silent", { ft = "man" }, function()
nnoremap("<tab>", [[:call search('\(\w\+(\w\+)\)', 's')<Cr>]])
nnoremap("<S-tab>", [[:call search('\(\w\+(\w\+)\)', 'sb')<Cr>]])
end)
The {rhs}
of a mapping can be a Lua function.
map("<leader>hi", function() print("Hello!") end, "silent")
-- Expression maps work too:
nnoremap("j", function() return vim.v.count > 0 and "j" or "gj" end, "silent", "expr")
nnoremap("k", function() return vim.v.count > 0 and "k" or "gk" end, "silent", "expr")
Mappings can be applied to the current buffer, or to a specific buffer.
-- Use the current buffer
nnoremap("<C-]>", ":call man#get_page_from_cword('horizontal', v:count)<CR>", "silent", "buffer")
-- Use a specific buffer
nnoremap("<C-]>", ":call man#get_page_from_cword('horizontal', v:count)<CR>", "silent", {
buffer = vim.api.nvim_win_get_buf(myWindowVariable)
})
There are various ways to specify map options:
-- Lua tables
nnoremap ("j", "v:count ? 'j' : 'gj'", { silent = true, expr = true })
-- Multiple Lua tables
nnoremap ("j", "v:count ? 'j' : 'gj'", { silent = true }, { expr = true })
-- Mapx's exported convenience variables
nnoremap ("j", "v:count ? 'j' : 'gj'", mapx.silent, mapx.expr)
-- Strings
nnoremap ("j", "v:count ? 'j' : 'gj'", "silent", "expr")
-- Vim-style strings
nnoremap ("j", "v:count ? 'j' : 'gj'", "<silent>", "<expr>")
Adding the Mapx map functions to the global scope is opt-in.
local mapx = require'mapx'
mapx.nmap("J", "5j")
mapx.nmap("K", "5k")
Create commands easily with the cmd
and cmdbang
functions. The
cmdbang
function only differs from the cmd
function in that it creates
a function with a bang which overwrites a previously defined function with
the same name.
cmd("LspDiag",
function() vim.lsp.diagnostic.set_loclist() end,
{nargs = 0})
cmdbang("LspAddFolder",
function(opt) vim.lsp.buf.add_workspace_folder(opt.arguments[1]) end,
{nargs = 1, complete = 'file'})
cmdbang("LspRemFolder",
function(opt) vim.lsp.buf.remove_workspace_folder(opt.arguments[1]) end,
{nargs = 1, complete = 'file'})
Mapx is fully documented. See :help mapx
.
Mapx provides the ability to convert mappings that use Neovim's
vim.api.nvim_set_keymap()
/vim.api.nvim_buf_set_keymap()
functions to the
Mapx API.
See the conversion documentation for instructions.
use "b0o/mapx.nvim"
Mapx aims to be the most powerful way to configure key mappings. To that end, we'd like to include the following features in future versions:
-
Autocommand mappings (a generalization of FileType mappings).
-
VimL conversion tool.
-
Telescope.nvim integration.
-
API for creating user commands.
-
API for creating user autocommands.
-
Support passing mapping mode in opts.
-
Support specifying multiple modes as a string like 'nvt'.
-
Support specifying labels on groups which become which-key group names.
-
Support progressively building up maps with groups, like:
mapx.group({ prefix = "<leader>t" }, "LSP", function() mapx.group({ prefix = "g" }, "Goto", function() nnoremap("d", "<cmd>lua vim.lsp.buf.definition()<Cr>", "Definition") nnoremap("D", "<cmd>lua vim.lsp.buf.declaration()<Cr>", "Declaration") nnoremap("i", "<cmd>lua vim.lsp.buf.implementation()<Cr>", "Implementation") nnoremap("t", "<cmd>lua vim.lsp.buf.type_definition()<Cr>", "Type definition") nnoremap("r", "<cmd>lua vim.lsp.buf.references()<Cr>", "References") end) mapx.group({ prefix = "w" }, "Workspace", function() nnoremap("a", "<cmd>lua vim.lsp.buf.add_workspace_folder()<Cr>", "Add folder") nnoremap("r", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<Cr>", "Rm folder") nnoremap("l", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<Cr>", "List folders") end) end) -- Would be equivalent to: mapx.nname("<leader>l", "LSP") mapx.nname("<leader>lg", "LSP-Goto") nnoremap ("<leader>lgd", "<cmd>lua vim.lsp.buf.definition()<Cr>", "LSP-Goto: Definition") nnoremap ("<leader>lgD", "<cmd>lua vim.lsp.buf.declaration()<Cr>", "LSP-Goto: Declaration") nnoremap ("<leader>lgi", "<cmd>lua vim.lsp.buf.implementation()<Cr>", "LSP-Goto: Implementation") nnoremap ("<leader>lgt", "<cmd>lua vim.lsp.buf.type_definition()<Cr>", "LSP-Goto: Type definition") nnoremap ("<leader>lgr", "<cmd>lua vim.lsp.buf.references()<Cr>", "LSP-Goto: References") mapx.nname("<leader>lw", "LSP-Workspace") nnoremap ("<leader>lwa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<Cr>", "LSP-Workspace: Add folder") nnoremap ("<leader>lwr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<Cr>", "LSP-Workspace: Rm folder") nnoremap ("<leader>lwl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<Cr>", "LSP-Workspace: List folders")
-
Better test coverage
-
Support setting default opts in
.setup{}
-
Benchmarks
-
Performance optimization (especially WhichKey integration)
01 Nov 2021 v0.2.2
Added user command support
10 Sep 2021 v0.2.1
Renamed project to Mapx.nvim
Added tests
Added config auto-conversion tool
Fixed bugs
08 Sep 2021 v0.2.0
Breaking: Deprecated config.quiet in favor of `setup({global = "force"})`
or `setup({global = "skip"})`
08 Sep 2021 v0.1.2
Added support for assigning WhichKey group names
Allow wrapping string opts in <angle brackets>
Refactored code
Bug fixes
04 Sep 2021 v0.1.1
Added `mapx.group()`
Added debug logging with `mapx-config-debug`
Added support for `mapx-opt-filetype` maps
Added support for Lua functions as a map's `{rhs}`
Added `mapx-config-quiet`
Fixed bugs
01 Sep 2021 v0.1.0
Added `mapx.setup()`
Added `mapx-whichkey-support`
Breaking: Deprecated `mapx.globalize()` in favor of `setup({global = true})`
28 Aug 2021 v0.0.2
Added `mapx.globalize()`
27 Aug 2021 v0.0.1
Initial Release
ยฉ 2021 Maddison Hellstrom
Released under the MIT License.