feat: rewrite vim.maps

This commit is contained in:
diniamo 2024-08-05 12:45:48 +02:00
parent 773186d93d
commit e134acb3bd
3 changed files with 64 additions and 213 deletions

View file

@ -8,46 +8,27 @@
cfg = config.vim;
in {
config = {
vim.maps = {
normal = mkIf cfg.disableArrows {
"<up>" = {
action = "<nop>";
noremap = false;
};
"<down>" = {
action = "<nop>";
noremap = false;
};
"<left>" = {
action = "<nop>";
noremap = false;
};
"<right>" = {
action = "<nop>";
noremap = false;
};
};
insert = mkIf cfg.disableArrows {
vim.maps = mkIf cfg.disableArrows {
"<up>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};
"<down>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};
"<left>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};
"<right>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};
};
};
};
}

View file

@ -1,96 +1,49 @@
{lib, ...}: let
inherit (lib.options) mkOption;
inherit (lib.types) bool str attrsOf nullOr submodule;
inherit (lib.types) either str listOf attrsOf nullOr submodule;
inherit (lib.nvim.config) mkBool;
# Most of the keybindings code is highly inspired by pta2002/nixvim.
# Thank you!
mapConfigOptions = {
silent =
mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait =
mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script =
mkBool false
"Equivalent to adding <script> to a map.";
expr =
mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique =
mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap =
mkBool true
"Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
mapType = submodule {
mode = mkOption {
type = either str (listOf str);
description = ''
The short-name of the mode to set the keymapping for. Passing an empty string is the equivalent of `:map`.
See `:help map-modes` for a list of modes.
'';
};
desc = mkOption {
type = nullOr str;
default = null;
description = "A description of this keybind, to be shown in which-key, if you have it enabled.";
};
};
mapOption = submodule {
options =
mapConfigOptions
// {
action = mkOption {
type = str;
description = "The action to execute.";
description = "The command to execute.";
};
lua = mkOption {
type = bool;
description = ''
lua = mkBool false ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';
default = false;
};
};
};
mapOptions = mode:
mkOption {
description = "Mappings for ${mode} mode";
type = attrsOf mapOption;
default = {};
silent = mkBool false "Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait = mkBool false "Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script = mkBool false "Equivalent to adding <script> to a map.";
expr = mkBool false "Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique = mkBool false "Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap = mkBool true "Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
};
in {
options.vim = {
maps = mkOption {
type = submodule {
options = {
normal = mapOptions "normal";
insert = mapOptions "insert";
select = mapOptions "select";
visual = mapOptions "visual and select";
terminal = mapOptions "terminal";
normalVisualOp = mapOptions "normal, visual, select and operator-pending (same as plain 'map')";
visualOnly = mapOptions "visual only";
operator = mapOptions "operator-pending";
insertCommand = mapOptions "insert and command-line";
lang = mapOptions "insert, command-line and lang-arg";
command = mapOptions "command-line";
};
};
type = attrsOf mapType;
default = {};
description = ''
Custom keybindings for any mode.
For plain maps (e.g. just 'map' or 'remap') use `maps.normalVisualOp`.
'';
description = "Custom keybindings.";
example = ''
maps = {
normal."<leader>m" = {
"<leader>m" = {
mode = "n";
silent = true;
action = "<cmd>make<CR>";
}; # Same as nnoremap <leader>m <silent> <cmd>make<CR>

View file

@ -3,85 +3,19 @@
lib,
...
}: let
inherit (builtins) map mapAttrs filter;
inherit (lib.options) mkOption;
inherit (lib.attrsets) filterAttrs getAttrs attrValues attrNames;
inherit (builtins) map mapAttrs filter attrsToList;
inherit (lib.attrsets) filterAttrs;
inherit (lib.strings) concatLines concatMapStringsSep;
inherit (lib.misc) mapAttrsFlatten;
inherit (lib.trivial) showWarnings;
inherit (lib.types) str nullOr;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.dag) entryAfter mkLuarcSection resolveDag entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.config) mkBool;
cfg = config.vim;
# Most of the keybindings code is highly inspired by pta2002/nixvim.
# Thank you!
mapConfigOptions = {
silent =
mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait =
mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script =
mkBool false
"Equivalent to adding <script> to a map.";
expr =
mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique =
mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap =
mkBool true
"Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
desc = mkOption {
type = nullOr str;
default = null;
description = "A description of this keybind, to be shown in which-key, if you have it enabled.";
};
};
genMaps = mode: maps: let
/*
Take a user-defined action (string or attrs) and return the following attribute set:
{
action = (string) the actual action to map to this key
config = (attrs) the configuration options for this mapping (noremap, silent...)
}
*/
normalizeAction = action: {
# Extract the values of the config options that have been explicitly set by the user
config =
filterAttrs (_: v: v != null)
(getAttrs (attrNames mapConfigOptions) action);
action =
if action.lua
then mkLuaInline action.action
else action.action;
};
in
attrValues (mapAttrs
(key: action: let
normalizedAction = normalizeAction action;
in {
inherit (normalizedAction) action config;
inherit key;
inherit mode;
})
maps);
in {
config = let
filterNonNull = attrs: filterAttrs (_: value: value != null) attrs;
filterNonNull = filterAttrs (_: value: value != null);
globalsScript =
mapAttrsFlatten (name: value: "vim.g.${name} = ${toLuaObject value}")
(filterNonNull cfg.globals);
@ -98,38 +32,21 @@ in {
mapResult = result: concatLines (map mkLuarcSection result);
};
toLuaBindings = mode: maps:
map (value: ''
vim.keymap.set(${toLuaObject mode}, ${toLuaObject value.key}, ${toLuaObject value.action}, ${toLuaObject value.config})
'') (genMaps mode maps);
getAction = keymap:
if keymap.lua
then mkLuaInline keymap.action
else keymap.action;
# I'm not sure if every one of these will work.
allmap = toLuaBindings "" config.vim.maps.normalVisualOp;
nmap = toLuaBindings "n" config.vim.maps.normal;
vmap = toLuaBindings "v" config.vim.maps.visual;
xmap = toLuaBindings "x" config.vim.maps.visualOnly;
smap = toLuaBindings "s" config.vim.maps.select;
imap = toLuaBindings "i" config.vim.maps.insert;
cmap = toLuaBindings "c" config.vim.maps.command;
tmap = toLuaBindings "t" config.vim.maps.terminal;
lmap = toLuaBindings "l" config.vim.maps.lang;
omap = toLuaBindings "o" config.vim.maps.operator;
icmap = toLuaBindings "ic" config.vim.maps.insertCommand;
getOpts = keymap: {
inherit (keymap) silent nowait script expr unique noremap;
};
maps = [
nmap
imap
vmap
xmap
smap
cmap
omap
tmap
lmap
icmap
allmap
];
mappings = concatLines (map concatLines maps);
toLuaKeymap = {
name,
value,
}: "vim.keymap.set(${toLuaObject value.mode}, ${toLuaObject name}, ${toLuaObject (getAction value)}, ${toLuaObject (getOpts value)})";
keymaps = concatLines (map toLuaKeymap (attrsToList (filterNonNull config.maps)));
in {
vim = {
luaConfigRC = {
@ -137,7 +54,7 @@ in {
# basic, theme
pluginConfigs = entryAfter ["theme"] pluginConfigs;
extraPluginConfigs = entryAfter ["pluginConfigs"] extraPluginConfigs;
mappings = entryAfter ["extraPluginConfigs"] mappings;
mappings = entryAfter ["extraPluginConfigs"] keymaps;
};
builtLuaConfigRC = let