modules/keymaps: factor out helper functions for use in plugins

This commit is contained in:
Gaetan Lepage 2023-10-02 15:44:06 +02:00 committed by Gaétan Lepage
parent 7eb1a85ccb
commit 418bf5da17
6 changed files with 416 additions and 407 deletions

View file

@ -1,7 +1,7 @@
{lib, ...}:
with lib;
(import ./keymap-helpers.nix {inherit lib;})
// rec {
with lib; rec {
keymaps = import ./keymap-helpers.nix {inherit lib;};
# vim dictionaries are, in theory, compatible with JSON
toVimDict = args:
toJSON

View file

@ -1,5 +1,145 @@
{lib, ...}:
with lib; rec {
with lib; let
helpers = import ../lib/helpers.nix {inherit lib;};
in rec {
# These are the configuration options that change the behavior of each mapping.
mapConfigOptions = {
silent =
helpers.defaultNullOpts.mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait =
helpers.defaultNullOpts.mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script =
helpers.defaultNullOpts.mkBool false
"Equivalent to adding <script> to a map.";
expr =
helpers.defaultNullOpts.mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique =
helpers.defaultNullOpts.mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap =
helpers.defaultNullOpts.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.";
remap =
helpers.defaultNullOpts.mkBool false
"Make the mapping recursive. Inverses \"noremap\"";
desc =
helpers.mkNullOrOption types.str
"A textual description of this keybind, to be shown in which-key, if you have it.";
};
modes = {
normal.short = "n";
insert.short = "i";
visual = {
desc = "visual and select";
short = "v";
};
visualOnly = {
desc = "visual only";
short = "x";
};
select.short = "s";
terminal.short = "t";
normalVisualOp = {
desc = "normal, visual, select and operator-pending (same as plain 'map')";
short = "";
};
operator.short = "o";
lang = {
desc = "normal, visual, select and operator-pending (same as plain 'map')";
short = "l";
};
insertCommand = {
desc = "insert and command-line";
short = "!";
};
command.short = "c";
};
modeEnum =
types.enum
# ["" "n" "v" ...]
(
map
(
{short, ...}: short
)
(attrValues modes)
);
# TODO: When `maps` will have to be deprecated (early December 2023), change this.
# mapOptionSubmodule = {...} (no need for options... except for 'optionalAction')
mkMapOptionSubmodule = {
defaultMode ? "",
withKeyOpt ? true,
flatConfig ? false,
actionIsOptional ? false,
}:
with types;
either
str
(submodule {
options =
(
if withKeyOpt
then {
key = mkOption {
type = str;
description = "The key to map.";
example = "<C-m>";
};
}
else {}
)
// {
mode = mkOption {
type = either modeEnum (listOf modeEnum);
description = ''
One or several modes.
Use the short-names (`"n"`, `"v"`, ...).
See `:h map-modes` to learn more.
'';
default = defaultMode;
example = ["n" "v"];
};
action =
if actionIsOptional
then helpers.mkNullOrOption str "The action to execute"
else
mkOption {
type = str;
description = "The action to execute.";
};
lua = mkOption {
type = bool;
description = ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';
default = false;
};
}
// (
if flatConfig
then mapConfigOptions
else {
options = mapConfigOptions;
}
);
});
# Correctly merge two attrs (partially) representing a mapping.
mergeKeymap = defaults: keymap: let
# First, merge the `options` attrs of both options.

View file

@ -5,142 +5,6 @@
}:
with lib; let
helpers = import ../lib/helpers.nix {inherit lib;};
# These are the configuration options that change the behavior of each mapping.
mapConfigOptions = {
silent =
helpers.defaultNullOpts.mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait =
helpers.defaultNullOpts.mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script =
helpers.defaultNullOpts.mkBool false
"Equivalent to adding <script> to a map.";
expr =
helpers.defaultNullOpts.mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique =
helpers.defaultNullOpts.mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap =
helpers.defaultNullOpts.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.";
remap =
helpers.defaultNullOpts.mkBool false
"Make the mapping recursive. Inverses \"noremap\"";
desc =
helpers.mkNullOrOption types.str
"A textual description of this keybind, to be shown in which-key, if you have it.";
};
modes = {
normal.short = "n";
insert.short = "i";
visual = {
desc = "visual and select";
short = "v";
};
visualOnly = {
desc = "visual only";
short = "x";
};
select.short = "s";
terminal.short = "t";
normalVisualOp = {
desc = "normal, visual, select and operator-pending (same as plain 'map')";
short = "";
};
operator.short = "o";
lang = {
desc = "normal, visual, select and operator-pending (same as plain 'map')";
short = "l";
};
insertCommand = {
desc = "insert and command-line";
short = "!";
};
command.short = "c";
};
mkMapOptionSubmodule = {
defaultMode ? "",
withKeyOpt ? true,
flatConfig ? false,
}:
with types;
either
str
(types.submodule {
options =
(
if withKeyOpt
then {
key = mkOption {
type = types.str;
description = "The key to map.";
example = "<C-m>";
};
}
else {}
)
// {
mode = mkOption {
type = let
modeEnum =
enum
# ["" "n" "v" ...]
(
map
(
{short, ...}: short
)
(attrValues modes)
);
in
either modeEnum (listOf modeEnum);
description = ''
One or several modes.
Use the short-names (`"n"`, `"v"`, ...).
See `:h map-modes` to learn more.
'';
default = defaultMode;
example = ["n" "v"];
};
action =
if config.plugins.which-key.enable
then helpers.mkNullOrOption types.str "The action to execute"
else
mkOption {
type = types.str;
description = "The action to execute.";
};
lua = mkOption {
type = types.bool;
description = ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';
default = false;
};
}
// (
if flatConfig
then mapConfigOptions
else {
options = mapConfigOptions;
}
);
});
in {
options = {
maps =
@ -157,21 +21,26 @@ in {
either
str
(
mkMapOptionSubmodule
helpers.keymaps.mkMapOptionSubmodule
{
defaultMode = modeProps.short;
withKeyOpt = false;
flatConfig = true;
actionIsOptional = config.plugins.which-key.enable;
}
)
);
default = {};
}
)
modes;
helpers.keymaps.modes;
keymaps = mkOption {
type = types.listOf (mkMapOptionSubmodule {});
type =
types.listOf
(helpers.keymaps.mkMapOptionSubmodule {
actionIsOptional = config.plugins.which-key.enable;
});
default = [];
example = [
{
@ -246,7 +115,7 @@ in {
// {
options =
getAttrs
(attrNames mapConfigOptions)
(attrNames helpers.keymaps.mapConfigOptions)
action;
}
)
@ -254,7 +123,7 @@ in {
)
config.maps.${modeOptionName}
)
modes
helpers.keymaps.modes
);
mappings = let

View file

@ -35,7 +35,7 @@ in {
extraPackages = with pkgs; [typst];
keymaps = with cfg.keymaps;
helpers.mkKeymaps
helpers.keymaps.mkKeymaps
{
mode = "n";
options.silent = silent;

View file

@ -34,7 +34,7 @@ in {
extraPlugins = [cfg.package];
keymaps = with cfg.keymaps;
helpers.mkKeymaps
helpers.keymaps.mkKeymaps
{
mode = "n";
options.silent = cfg.keymapsSilent;

View file

@ -4,7 +4,7 @@
};
legacy-mkMaps = {
maps = helpers.mkMaps {silent = true;} {
maps = helpers.keymaps.mkMaps {silent = true;} {
normal."," = "<cmd>echo \"test\"<cr>";
visual = {
"<C-a>" = {
@ -20,7 +20,7 @@
};
legacy-mkModeMaps = {
maps.normal = helpers.mkModeMaps {silent = true;} {
maps.normal = helpers.keymaps.mkModeMaps {silent = true;} {
"," = "<cmd>echo \"test\"<cr>";
"<C-a>" = {
action = "function() print('toto') end";
@ -49,7 +49,7 @@
mkMaps = {
keymaps =
helpers.mkKeymaps
helpers.keymaps.mkKeymaps
{
mode = "x";
options.silent = true;