which-key.nvim
which-key.nvim copied to clipboard
[Proposal] A better DSL for keymappings
The current is bad because of the way how lua tables works: duplicate keys aren't supported,
so with { ',' = { "<Leader>", mode = "n" }, ',' = { "<Leader>", mode = "v" } } only the latter would be registered.
This may be quite confusing for users not familiar enough with lua.
Moreover, nested structure encourages registering all mappings at once separately from plugins they depends on.
So, I've implemented a DSL on top of it that gives more freedom:
--- This is how I generate bufferline mappings for each mode
for n = 1, 9 do
local function focus_nth_buffer() require('bufferline').go_to_buffer(n) end
map ['<M-' .. n .. '>'] = { focus_nth_buffer, "Go to (" .. n .. ") buffer", remap = false, silent = true }
end
map ['<M-`>'] = { '<Cmd>BufferLinePick<CR>', "Pick buffer" }
map ['<M-Left>'] = { '<Cmd>BufferLineCyclePrev<CR>', "Previous buffer" }
map ['<M-Right>'] = { '<Cmd>BufferLineCycleNext<CR>', "Next buffer" }
map ['<M-q>'] = { '<Cmd>b # | bd #<CR>', "Close buffer" }
map:register { modes = 'nicxsot' }
--- This is how I register LSP keybindings
map ['<Leader>wl'] = { print_workspace_folders, "Workspace folders" }
map ['<Leader>wa'] = { vim.lsp.buf.add_workspace_folder, "Add workspace folder" }
map ['<Leader>wr'] = { vim.lsp.buf.remove_workspace_folder, "Remove workdspace folder" }
map ['gD'] = { vim.lsp.buf.declaration, "Declaration" }
map ['gd'] = { vim.lsp.buf.definition, "Definition" }
map ['K'] = { vim.lsp.buf.hover, "Hover" }
map ['gi'] = { vim.lsp.buf.implementation, "Implementation" }
map ['<C-k>'] = { vim.lsp.buf.signature_help, "Signature" }
map ['<Leader>D'] = { vim.lsp.buf.type_definition, "Type" }
map ['<Leader>rn'] = { vim.lsp.buf.rename, "Rename" }
map ['gr'] = { vim.lsp.buf.references, "References" }
map ['<Leader>e' ] = { vim.lsp.diagnostic.show_line_diagnostics, "Diagnostics" }
map ['[d'] = { vim.lsp.diagnostic.goto_prev, "Previous diagnostic" }
map [']d'] = { vim.lsp.diagnostic.goto_next, "Next diagnostic" }
map ['<Leader>q'] = { vim.lsp.diagnostic.set_loclist, "Set loclist"
-- Set some keybinds conditional on server capabilities
if client.resolved_capabilities.document_formatting then
map ['<Leader>f'] = { vim.lsp.buf.formatting, "Document formatting" }
elseif client.resolved_capabilities.document_range_formatting then
map ['<Leader>f'] = { vim.lsp.buf.range_formatting, "Range formatting" }
end
map:register { silent = true, remap = false }
--- This is how plugin installation looks like
use {
'phaazon/hop.nvim',
config = function()
local hop = require('hop')
hop.setup {
inclusive_jump = true,
uppercase_labels = true,
}
map ['F'] = { function() vim.cmd 'norm 0<CR>'; hop.hint_lines_skip_whitespace() end, "Jump to a line" }
map ['f'] = { function() hop.hint_char1() end, "Jump to a letter" }
map:split { modes = 'o' }
map ['F'] = { function() hop.hint_lines_skip_whitespace(); vim.cmd 'norm zz' end, "Jump to a line and focus" }
map ['f'] = { function() hop.hint_char1() end, "Jump to a letter" }
map:register { modes = 'n' }
end
}
Let me know if you would like to add something like that to your plugin
This looks amazing!! I second this being added
Upd: now it looks like this:
for n = 1, 9 do
local function focus_nth_buffer() require('bufferline').go_to_buffer(n) end
(map "Go to (" .. n .. ") buffer")
.alt [n] = { focus_nth_buffer, remap = false, silent = true }
end
(map "Pick a buffer")
.alt ['`'] = 'BufferLinePick'
(map "Previous buffer")
.alt ['Left'] = 'BufferLineCyclePrev'
(map "Next buffer")
.alt ['Right'] = 'BufferLineCycleNext'
(map "Close buffer")
.alt ['q'] = 'b # | bd #'
(map "Previous buffer")
['<F13>'] = 'BufferLineCyclePrev'
(map "Next buffer")
['<F14>'] = 'BufferLineCycleNext'
map:register { as = 'cmd', modes = 'nicxsot' }
local function print_workspace_folders()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end
(map "Workspace folders")
['<Leader>wl'] = print_workspace_folders;
(map "Add workspace folder")
['<Leader>wa'] = vim.lsp.buf.add_workspace_folder;
(map "Remove workdspace folder")
['<Leader>wr'] = vim.lsp.buf.remove_workspace_folder;
(map "Declaration")
['gD'] = vim.lsp.buf.declaration;
(map "Definition")
['gd'] = vim.lsp.buf.definition;
(map "Hover")
['K'] = vim.lsp.buf.hover;
(map "Implementation")
['gi'] = vim.lsp.buf.implementation;
(map "Signature")
.ctrl ['k'] = vim.lsp.buf.signature_help;
(map "Type")
['<Leader>D'] = vim.lsp.buf.type_definition;
(map "Rename")
['<Leader>rn'] = vim.lsp.buf.rename;
(map "References")
['gr'] = vim.lsp.buf.references;
(map "Diagnostics")
['<Leader>e' ] = vim.lsp.diagnostic.show_line_diagnostics;
(map "Previous diagnostic")
['[d'] = vim.lsp.diagnostic.goto_prev;
(map "Next diagnostic")
[']d'] = vim.lsp.diagnostic.goto_next;
(map "Set loclist")
['<Leader>q'] = vim.lsp.diagnostic.set_loclist;
-- Set some keybinds conditional on server capabilities
if client.resolved_capabilities.document_formatting then
(map "Document formatting")
['<Leader>f'] = vim.lsp.buf.formatting;
elseif client.resolved_capabilities.document_range_formatting then
(map "Range formatting")
['<Leader>f'] = vim.lsp.buf.range_formatting;
end
map:register { silent = true, remap = false }
use {
'phaazon/hop.nvim',
config = function()
local hop = require('hop')
hop.setup {
inclusive_jump = true,
uppercase_labels = true,
};
(map "Jump to a line")
['F'] = function() vim.cmd 'norm 0<CR>'; hop.hint_lines_skip_whitespace() end
(map "Jump to a letter")
['f'] = function() hop.hint_char1() end
map:split { modes = 'o' };
(map "Jump to a line and focus on it")
['F'] = function() hop.hint_lines_skip_whitespace(); vim.cmd 'norm zz' end
(map "Jump to a letter")
['f'] = function() hop.hint_char1() end
map:register { modes = 'n' }
end
}