5.9 KiB
Keybinds
As of 0.4, there exists an API for writing your own keybinds and a couple of useful utility functions are available in the extended standard library. The following section contains a general overview to how you may utilize said functions.
Custom Key Mappings Support for a Plugin
To set a mapping, you should define it in vim.maps.<<mode>>
.
The available modes are:
- normal
- insert
- select
- visual
- terminal
- normalVisualOp
- visualOnly
- operator
- insertCommand
- lang
- command
An example, simple keybinding, can look like this:
{
vim.maps.normal = {
"<leader>wq" = {
action = ":wq<CR>";
silent = true;
desc = "Save file and quit";
};
};
}
There are many settings available in the options. Please refer to the documentation to see a list of them.
nvf provides a list of helper commands, so that you don't have to write the mapping attribute sets every time:
mkBinding = key: action: desc:
- makes a basic binding, withsilent
set to true.mkExprBinding = key: action: desc:
- makes an expression binding, withlua
,silent
, andexpr
set to true.mkLuaBinding = key: action: desc:
- makes an expression binding, withlua
, andsilent
set to true.
Do note that the Lua in these bindings is actual Lua, and not pasted into a
:lua
command. Therefore, you should either pass in a function like
require('someplugin').some_function
, without actually calling it, or you
should define your own functions, for example
function()
require('someplugin').some_function()
end
Additionally, to not have to repeat the descriptions, there's another utility function with its own set of functions: Utility function that takes two attribute sets:
{ someKey = "some_value" }
{ someKey = { description = "Some Description"; }; }
and merges them into { someKey = { value = "some_value"; description = "Some Description"; }; }
addDescriptionsToMappings = actualMappings: mappingDefinitions:
This function can be used in combination with the same mkBinding
functions as
above, except they only take two arguments - binding
and action
, and have
different names:
mkSetBinding = binding: action:
- makes a basic binding, withsilent
set to true.mkSetExprBinding = binding: action:
- makes an expression binding, withlua
,silent
, andexpr
set to true.mkSetLuaBinding = binding: action:
- makes an expression binding, withlua
, andsilent
set to true.
You can read the source code of some modules to see them in action, but their usage should look something like this:
# plugindefinition.nix
{lib, ...}: with lib; {
options.vim.plugin = {
enable = mkEnableOption "Enable plugin";
# Mappings should always be inside an attrset called mappings
mappings = {
# mkMappingOption is a helper function from lib,
# that takes a description (which will also appear in which-key),
# and a default mapping (which can be null)
toggleCurrentLine = mkMappingOption "Toggle current line comment" "gcc";
toggleCurrentBlock = mkMappingOption "Toggle current block comment" "gbc";
toggleOpLeaderLine = mkMappingOption "Toggle line comment" "gc";
toggleOpLeaderBlock = mkMappingOption "Toggle block comment" "gb";
toggleSelectedLine = mkMappingOption "Toggle selected comment" "gc";
toggleSelectedBlock = mkMappingOption "Toggle selected block" "gb";
};
};
}
# config.nix
{
config,
pkgs,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.plugin;
self = import ./plugindefinition.nix {inherit lib;};
mappingDefinitions = self.options.vim.plugin;
# addDescriptionsToMappings is a helper function from lib,
# that merges mapping values and their descriptions
# into one nice attribute set
mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions;
in {
config = mkIf (cfg.enable) {
# ...
vim.maps.normal = mkMerge [
# mkSetBinding is another helper function from lib,
# that actually adds the mapping with a description.
(mkSetBinding mappings.findFiles "<cmd> Telescope find_files<CR>")
(mkSetBinding mappings.liveGrep "<cmd> Telescope live_grep<CR>")
(mkSetBinding mappings.buffers "<cmd> Telescope buffers<CR>")
(mkSetBinding mappings.helpTags "<cmd> Telescope help_tags<CR>")
(mkSetBinding mappings.open "<cmd> Telescope<CR>")
(mkSetBinding mappings.gitCommits "<cmd> Telescope git_commits<CR>")
(mkSetBinding mappings.gitBufferCommits "<cmd> Telescope git_bcommits<CR>")
(mkSetBinding mappings.gitBranches "<cmd> Telescope git_branches<CR>")
(mkSetBinding mappings.gitStatus "<cmd> Telescope git_status<CR>")
(mkSetBinding mappings.gitStash "<cmd> Telescope git_stash<CR>")
(mkIf config.vim.lsp.enable (mkMerge [
(mkSetBinding mappings.lspDocumentSymbols "<cmd> Telescope lsp_document_symbols<CR>")
(mkSetBinding mappings.lspWorkspaceSymbols "<cmd> Telescope lsp_workspace_symbols<CR>")
(mkSetBinding mappings.lspReferences "<cmd> Telescope lsp_references<CR>")
(mkSetBinding mappings.lspImplementations "<cmd> Telescope lsp_implementations<CR>")
(mkSetBinding mappings.lspDefinitions "<cmd> Telescope lsp_definitions<CR>")
(mkSetBinding mappings.lspTypeDefinitions "<cmd> Telescope lsp_type_definitions<CR>")
(mkSetBinding mappings.diagnostics "<cmd> Telescope diagnostics<CR>")
]))
(
mkIf config.vim.treesitter.enable
(mkSetBinding mappings.treesitter "<cmd> Telescope treesitter<CR>")
)
];
# ...
};
}
::: {.note} If you have come across a plugin that has an API that doesn't seem to easily allow custom keybindings, don't be scared to implement a draft PR. We'll help you get it done. :::