Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions lib/keymap-helpers.nix
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ rec {

mapOptionSubmodule = mkMapOptionSubmodule { };

# NOTE: options that have the deprecated `lua` sub-option must use `removeDeprecatedMapAttrs`
# to ensure `lua` isn't evaluated when (e.g.) generating lua code.
# Failure to do so will result in "option used but not defined" errors!
deprecatedMapOptionSubmodule = mkMapOptionSubmodule { lua = true; };
removeDeprecatedMapAttrs = v: builtins.removeAttrs v [ "lua" ];

mkModeOption =
default:
mkOption {
Expand All @@ -81,13 +87,12 @@ rec {
# or an attrset to enable the option and add/override mkOption args.
key ? true,
action ? true,
lua ? false, # WARNING: for historic use only - do not use in new options!
}:
# TODO remove assert once `lua` option is gone
# This is here to ensure no uses of `mkMapOptionSubmodule` set a `lua` default
assert !(defaults ? lua);
(
with types;
submodule {
with types;
submodule (
{ config, options, ... }:
{
options =
(optionalAttrs (isAttrs key || key) {
key = mkOption (
Expand All @@ -105,27 +110,31 @@ rec {
{
type = helpers.nixvimTypes.maybeRaw str;
description = "The action to execute.";
apply = v: if options.lua.isDefined or false && config.lua then helpers.mkRaw v else v;
}
// (optionalAttrs (isAttrs action) action)
// (optionalAttrs (defaults ? action) { default = defaults.action; })
);
})
// optionalAttrs (isAttrs lua || lua) {
lua = mkOption (
{
type = bool;
description = ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.

This option is deprecated and will be removed in 24.11.
You should use a "raw" action instead, e.g. `action.__raw = ""`.
'';
visible = false;
}
// optionalAttrs (isAttrs lua) lua
);
}
// {
mode = mkModeOption defaults.mode or "";
options = mapConfigOptions;

lua = mkOption {
type = nullOr bool;
description = ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.

This option is deprecated and will be removed in 24.11.
You should use a "raw" action instead, e.g. `action.__raw = ""`.
'';
default = null;
visible = false;
};
};
}
);
Expand Down
131 changes: 60 additions & 71 deletions modules/keymaps.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ with lib;
{
options = {
keymaps = mkOption {
type = types.listOf helpers.keymaps.mapOptionSubmodule;
type = types.listOf helpers.keymaps.deprecatedMapOptionSubmodule;
default = [ ];
description = "Nixvim keymaps.";
example = [
Expand All @@ -22,7 +22,7 @@ with lib;
};

keymapsOnEvents = mkOption {
type = types.attrsOf (types.listOf helpers.keymaps.mapOptionSubmodule);
type = types.attrsOf (types.listOf helpers.keymaps.deprecatedMapOptionSubmodule);
default = { };
example = {
"InsertEnter" = [
Expand All @@ -43,82 +43,71 @@ with lib;
};
};

config =
let
# TODO remove `normalizeMapping` once `lua` option is gone
normalizeMapping = keyMapping: {
inherit (keyMapping) mode key options;
config = {
# Deprecate `lua` keymap option
# TODO upgrade to an assertion (removal notice) in 24.11
# TODO remove entirely in 25.05?
warnings =
let
# All keymap options that have historically supported the `lua` sub-option
keymapOptions =
[
options.keymaps
options.keymapsOnEvents
options.plugins.wtf.keymaps.ai
options.plugins.wtf.keymaps.search
# NOTE: lsp `diagnostic` and `lspBuf` don't use `mapOptionSubmodule` yet
# So we only need `lua` deprecation in lsp's `extra` option
options.plugins.lsp.keymaps.extra
# NOTE: tmux-navigator added `mapOptionSubmodule` support _after_ branching off 24.05
options.plugins.tmux-navigator.keymaps
]
# NOTE: barbar added `mapOptionSubmodule` support shortly _before_ branching off 24.05
++ builtins.attrValues (builtins.removeAttrs options.plugins.barbar.keymaps [ "silent" ]);
in
lib.pipe keymapOptions [
(map (opt: (opt.type.getSubOptions opt.loc).lua))
(filter (opt: opt.isDefined))
(map (opt: ''
${"\n"}
The `${lib.showOption opt.loc}' option is deprecated and will be removed in 24.11.

action =
if keyMapping.lua != null && keyMapping.lua then
helpers.mkRaw keyMapping.action
else
keyMapping.action;
};
in
{
# Deprecate `lua` keymap option
# TODO upgrade to an assertion (removal notice) in 24.11
# TODO remove entirely in 25.05?
warnings =
let
luaDefs = pipe options.keymaps.definitionsWithLocations [
(map (def: {
inherit (def) file;
value = filter (v: (v.lua or null) != null) def.value;
}))
(filter (def: def.value != [ ]))
(map (
def:
let
count = length def.value;
plural = count > 1;
in
''
Found ${toString count} use${optionalString plural "s"} in ${def.file}:
${generators.toPretty { } def.value}
''
))
];
in
optional (luaDefs != [ ]) ''
Nixvim (keymaps): the `lua` keymap option is deprecated.

This option will be removed in 24.11. You should use a "raw" `action` instead;
You should use a "raw" `action` instead;
e.g. `action.__raw = "<lua code>"` or `action = helpers.mkRaw "<lua code>"`.

${concatStringsSep "\n" luaDefs}
'';
${lib.options.showDefs opt.definitionsWithLocations}
''))
];

extraConfigLua = mkIf (config.keymaps != [ ]) ''
-- Set up keybinds {{{
do
local __nixvim_binds = ${helpers.toLuaObject (map normalizeMapping config.keymaps)}
for i, map in ipairs(__nixvim_binds) do
vim.keymap.set(map.mode, map.key, map.action, map.options)
end
extraConfigLua = mkIf (config.keymaps != [ ]) ''
-- Set up keybinds {{{
do
local __nixvim_binds = ${helpers.toLuaObject (map helpers.keymaps.removeDeprecatedMapAttrs config.keymaps)}
for i, map in ipairs(__nixvim_binds) do
vim.keymap.set(map.mode, map.key, map.action, map.options)
end
-- }}}
'';
end
-- }}}
'';

autoGroups = mapAttrs' (
event: mappings: nameValuePair "nixvim_binds_${event}" { clear = true; }
) config.keymapsOnEvents;
autoGroups = mapAttrs' (
event: mappings: nameValuePair "nixvim_binds_${event}" { clear = true; }
) config.keymapsOnEvents;

autoCmd = mapAttrsToList (event: mappings: {
inherit event;
group = "nixvim_binds_${event}";
callback = helpers.mkRaw ''
function()
do
local __nixvim_binds = ${helpers.toLuaObject (map normalizeMapping mappings)}
for i, map in ipairs(__nixvim_binds) do
vim.keymap.set(map.mode, map.key, map.action, map.options)
end
autoCmd = mapAttrsToList (event: mappings: {
inherit event;
group = "nixvim_binds_${event}";
callback = helpers.mkRaw ''
function()
do
local __nixvim_binds = ${helpers.toLuaObject (map helpers.keymaps.removeDeprecatedMapAttrs mappings)}
for i, map in ipairs(__nixvim_binds) do
vim.keymap.set(map.mode, map.key, map.action, map.options)
end
end
'';
desc = "Load keymaps for ${event}";
}) config.keymapsOnEvents;
};
end
'';
desc = "Load keymaps for ${event}";
}) config.keymapsOnEvents;
};
}
15 changes: 10 additions & 5 deletions plugins/bufferlines/barbar.nix
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,17 @@ helpers.neovim-plugin.mkNeovimPlugin config {
extraOptions = {
keymaps = mapAttrs (
optionName: funcName:
helpers.mkNullOrOption (helpers.keymaps.mkMapOptionSubmodule {
defaults = {
mode = "n";
action = "<Cmd>Buffer${funcName}<CR>";
helpers.mkNullOrOption' {
type = helpers.keymaps.mkMapOptionSubmodule {
defaults = {
mode = "n";
action = "<Cmd>Buffer${funcName}<CR>";
};
lua = true;
};
}) "Keymap for function Buffer${funcName}"
apply = v: if v == null then null else helpers.keymaps.removeDeprecatedMapAttrs v;
description = "Keymap for function Buffer${funcName}";
}
) keymapsActions;
};

Expand Down
3 changes: 2 additions & 1 deletion plugins/lsp/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ in
};

extra = mkOption {
type = with types; listOf helpers.keymaps.mapOptionSubmodule;
type = with types; listOf helpers.keymaps.deprecatedMapOptionSubmodule;
apply = map helpers.keymaps.removeDeprecatedMapAttrs;
description = ''
Extra keymaps to register when an LSP is attached.
This can be used to customise LSP behaviour, for example with "telescope" or the "Lspsaga" plugin, as seen in the examples.
Expand Down
21 changes: 13 additions & 8 deletions plugins/lsp/wtf.nix
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,18 @@ in

keymaps = mapAttrs (
action: defaults:
helpers.mkNullOrOption (
with types; either str (helpers.keymaps.mkMapOptionSubmodule { inherit defaults; })
) "Keymap for the ${action} action."
helpers.mkNullOrOption' {
type =
with types;
coercedTo str (key: defaultKeymaps.${action} // { inherit key; }) (
helpers.keymaps.mkMapOptionSubmodule {
inherit defaults;
lua = true;
}
);
apply = v: if v == null then null else helpers.keymaps.removeDeprecatedMapAttrs v;
description = "Keymap for the ${action} action.";
}
) defaultKeymaps;

popupType =
Expand Down Expand Up @@ -106,11 +115,7 @@ in
mkIf cfg.enable {
extraPlugins = [ cfg.package ];

keymaps = filter (keymap: keymap != null) (
mapAttrsToList (
action: value: if isString value then defaultKeymaps.${action} // { key = value; } else value
) cfg.keymaps
);
keymaps = filter (keymap: keymap != null) (attrValues cfg.keymaps);

extraConfigLua = ''
require("wtf").setup(${helpers.toLuaObject setupOptions})
Expand Down
2 changes: 2 additions & 0 deletions plugins/utils/tmux-navigator.nix
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@ helpers.vim-plugin.mkVimPlugin config {
];
example = "left";
};
lua = true;
}
);
apply = map helpers.keymaps.removeDeprecatedMapAttrs;
};
};

Expand Down