plugins: better compatability with nullable keybinds

Mostly involves filtering keybinds that are null in cases where the
keybind is the attrname, and optionalString for manual lua keybind
registration.
This commit is contained in:
alfarel 2026-03-14 22:18:05 -04:00
commit f040b4a943
No known key found for this signature in database
8 changed files with 185 additions and 155 deletions

View file

@ -21,11 +21,11 @@
''; '';
mkLuaKeymap = mode: key: action: desc: opts: mkLuaKeymap = mode: key: action: desc: opts:
opts mkIf (key != null) (opts
// { // {
inherit mode key action desc; inherit mode key action desc;
lua = true; lua = true;
}; });
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim = { vim = {

View file

@ -5,7 +5,7 @@
}: let }: let
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.attrsets) optionalAttrs; inherit (lib.attrsets) mapAttrs' optionalAttrs;
inherit (lib.generators) mkLuaInline; inherit (lib.generators) mkLuaInline;
inherit (lib.attrsets) attrValues filterAttrs mapAttrsToList; inherit (lib.attrsets) attrValues filterAttrs mapAttrsToList;
inherit (lib.lists) map optional optionals elem; inherit (lib.lists) map optional optionals elem;
@ -98,51 +98,57 @@ in {
preset = "luasnip"; preset = "luasnip";
}; };
keymap = { keymap =
${mappings.complete} = ["show" "fallback"]; mapAttrs' (mapping-name: action: {
${mappings.close} = ["hide" "fallback"]; name = mappings.${mapping-name};
${mappings.scrollDocsUp} = ["scroll_documentation_up" "fallback"]; value = action;
${mappings.scrollDocsDown} = ["scroll_documentation_down" "fallback"]; }) (filterAttrs (mapping-name: _action: mappings.${mapping-name} != null) {
${mappings.confirm} = ["accept" "fallback"]; complete = ["show" "fallback"];
close = ["hide" "fallback"];
scrollDocsUp = ["scroll_documentation_up" "fallback"];
scrollDocsDown = ["scroll_documentation_down" "fallback"];
confirm = ["accept" "fallback"];
next = [
"select_next"
"snippet_forward"
(mkLuaInline
# lua
''
function(cmp)
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
has_words_before = col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
${mappings.next} = [ if has_words_before then
"select_next" return cmp.show()
"snippet_forward" end
(mkLuaInline
# lua
''
function(cmp)
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
has_words_before = col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
if has_words_before then
return cmp.show()
end end
end '')
'') "fallback"
"fallback" ];
]; previous = [
${mappings.previous} = [ "select_prev"
"select_prev" "snippet_backward"
"snippet_backward" "fallback"
"fallback" ];
]; });
};
# cmdline is not enabled by default, we're just providing keymaps in # cmdline is not enabled by default, we're just providing keymaps in
# case the user enables them # case the user enables them
cmdline.keymap = { cmdline.keymap =
${mappings.complete} = ["show" "fallback"]; mapAttrs' (mapping-name: action: {
${mappings.close} = ["hide" "fallback"]; name = mappings.${mapping-name};
${mappings.scrollDocsUp} = ["scroll_documentation_up" "fallback"]; value = action;
${mappings.scrollDocsDown} = ["scroll_documentation_down" "fallback"]; }) (filterAttrs (mapping-name: _action: mappings.${mapping-name} != null) {
# NOTE: mappings.confirm is skipped because our default, <CR> would complete = ["show" "fallback"];
# lead to accidental triggers of blink.accept instead of executing close = ["hide" "fallback"];
# the cmd scrollDocsUp = ["scroll_documentation_up" "fallback"];
scrollDocsDown = ["scroll_documentation_down" "fallback"];
${mappings.next} = ["select_next" "show" "fallback"]; # NOTE: mappings.confirm is skipped because our default, <CR> would
${mappings.previous} = ["select_prev" "fallback"]; # lead to accidental triggers of blink.accept instead of executing
}; # the cmd
next = ["select_next" "show" "fallback"];
previous = ["select_prev" "fallback"];
});
}; };
}; };
}; };

View file

@ -3,6 +3,7 @@
config, config,
... ...
}: let }: let
inherit (lib.attrsets) filterAttrs mapAttrs';
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.generators) mkLuaInline; inherit (lib.generators) mkLuaInline;
@ -72,48 +73,53 @@ in {
formatting.format = cfg.format; formatting.format = cfg.format;
# `cmp` and `luasnip` are defined above, in the `nvim-cmp` section # `cmp` and `luasnip` are defined above, in the `nvim-cmp` section
mapping = { mapping =
${mappings.complete} = mkLuaInline "cmp.mapping.complete()"; mapAttrs' (mapping-name: action: {
${mappings.close} = mkLuaInline "cmp.mapping.abort()"; name = mappings.${mapping-name};
${mappings.scrollDocsUp} = mkLuaInline "cmp.mapping.scroll_docs(-4)"; value = action;
${mappings.scrollDocsDown} = mkLuaInline "cmp.mapping.scroll_docs(4)"; }) (filterAttrs (mapping-name: _action: mappings.${mapping-name} != null)
${mappings.confirm} = mkLuaInline "cmp.mapping.confirm({ select = true })"; {
complete = mkLuaInline "cmp.mapping.complete()";
close = mkLuaInline "cmp.mapping.abort()";
scrollDocsUp = mkLuaInline "cmp.mapping.scroll_docs(-4)";
scrollDocsDown = mkLuaInline "cmp.mapping.scroll_docs(4)";
confirm = mkLuaInline "cmp.mapping.confirm({ select = true })";
${mappings.next} = mkLuaInline '' next = mkLuaInline ''
cmp.mapping(function(fallback) cmp.mapping(function(fallback)
local has_words_before = function() local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0)) local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end end
if cmp.visible() then if cmp.visible() then
cmp.select_next_item() cmp.select_next_item()
${optionalString luasnipEnable '' ${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(1) then elseif luasnip.locally_jumpable(1) then
luasnip.jump(1) luasnip.jump(1)
''} ''}
elseif has_words_before() then elseif has_words_before() then
cmp.complete() cmp.complete()
else else
fallback() fallback()
end end
end) end)
''; '';
${mappings.previous} = mkLuaInline '' previous = mkLuaInline ''
cmp.mapping(function(fallback) cmp.mapping(function(fallback)
if cmp.visible() then if cmp.visible() then
cmp.select_prev_item() cmp.select_prev_item()
${optionalString luasnipEnable '' ${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(-1) then elseif luasnip.locally_jumpable(-1) then
luasnip.jump(-1) luasnip.jump(-1)
''} ''}
else else
fallback() fallback()
end end
end) end)
''; '';
}; });
}; };
}; };
}; };

View file

@ -214,24 +214,31 @@ in {
on_attach = function(client, bufnr) on_attach = function(client, bufnr)
default_on_attach(client, bufnr) default_on_attach(client, bufnr)
local opts = { noremap=true, silent=true, buffer = bufnr } local opts = { noremap=true, silent=true, buffer = bufnr }
vim.keymap.set("n", "<localleader>rr", ":RustLsp runnables<CR>", opts)
vim.keymap.set("n", "<localleader>rp", ":RustLsp parentModule<CR>", opts) ${optionalString config.vim.vendoredKeymaps ''
vim.keymap.set("n", "<localleader>rm", ":RustLsp expandMacro<CR>", opts) vim.keymap.set("n", "<localleader>rr", ":RustLsp runnables<CR>", opts)
vim.keymap.set("n", "<localleader>rc", ":RustLsp openCargo", opts) vim.keymap.set("n", "<localleader>rp", ":RustLsp parentModule<CR>", opts)
vim.keymap.set("n", "<localleader>rg", ":RustLsp crateGraph x11", opts) vim.keymap.set("n", "<localleader>rm", ":RustLsp expandMacro<CR>", opts)
${optionalString cfg.dap.enable '' vim.keymap.set("n", "<localleader>rc", ":RustLsp openCargo", opts)
vim.keymap.set("n", "<localleader>rg", ":RustLsp crateGraph x11", opts)
''}
${optionalString (cfg.dap.enable && config.vim.vendoredKeymaps) ''
vim.keymap.set("n", "<localleader>rd", ":RustLsp debuggables<cr>", opts) vim.keymap.set("n", "<localleader>rd", ":RustLsp debuggables<cr>", opts)
''}
${optionalString (cfg.dap.enable && config.vim.debugger.nvim-dap.mappings.continue != null) ''
vim.keymap.set( vim.keymap.set(
"n", "${config.vim.debugger.nvim-dap.mappings.continue}", "n", "${config.vim.debugger.nvim-dap.mappings.continue}",
function() function()
local dap = require("dap") local dap = require("dap")
if dap.status() == "" then if dap.status() == "" then
vim.cmd "RustLsp debuggables" vim.cmd "RustLsp debuggables"
else else
dap.continue() dap.continue()
end end
end, end,
opts opts
) )
''} ''}
end end

View file

@ -117,7 +117,9 @@ in {
local attach_metals_keymaps = function(client, bufnr) local attach_metals_keymaps = function(client, bufnr)
attach_keymaps(client, bufnr) -- from lsp-setup attach_keymaps(client, bufnr) -- from lsp-setup
${optionalString (cfg.lsp.extraMappings.listCommands != null) ''
vim.api.nvim_buf_set_keymap(bufnr, 'n', '${cfg.lsp.extraMappings.listCommands}', '<cmd>lua ${listCommandsAction}<CR>', {noremap=true, silent=true, desc='Show all Metals commands'}) vim.api.nvim_buf_set_keymap(bufnr, 'n', '${cfg.lsp.extraMappings.listCommands}', '<cmd>lua ${listCommandsAction}<CR>', {noremap=true, silent=true, desc='Show all Metals commands'})
''}
end end
metals_config = require('metals').bare_config() metals_config = require('metals').bare_config()

View file

@ -54,7 +54,9 @@ in {
end end
}) })
vim.keymap.set('n', ${toLuaObject cfg.lazygit.mappings.open}, function() lazygit:toggle() end, {silent = true, noremap = true, desc = '${lazygitMapDesc}'}) ${optionalString (cfg.lazygit.mappings.open != null) ''
vim.keymap.set('n', ${toLuaObject cfg.lazygit.mappings.open}, function() lazygit:toggle() end, {silent = true, noremap = true, desc = '${lazygitMapDesc}'})
''}
''; '';
}; };
}; };

View file

@ -3,6 +3,7 @@
lib, lib,
... ...
}: let }: let
inherit (lib.attrsets) filterAttrs mapAttrs';
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.lists) optionals; inherit (lib.lists) optionals;
@ -30,57 +31,62 @@ in {
]; ];
vim.ui.breadcrumbs.navbuddy.setupOpts = { vim.ui.breadcrumbs.navbuddy.setupOpts = {
mappings = { mappings =
${cfg.navbuddy.mappings.close} = mkLuaInline "actions.close()"; mapAttrs' (mapping-name: action: {
${cfg.navbuddy.mappings.nextSibling} = mkLuaInline "actions.next_sibling()"; name = cfg.navbuddy.mappings.${mapping-name};
${cfg.navbuddy.mappings.previousSibling} = mkLuaInline "actions.previous_sibling()"; value = action;
${cfg.navbuddy.mappings.parent} = mkLuaInline "actions.parent()"; }) (filterAttrs (mapping-name: _action: cfg.navbuddy.mappings.${mapping-name} != null)
${cfg.navbuddy.mappings.children} = mkLuaInline "actions.children()"; {
${cfg.navbuddy.mappings.root} = mkLuaInline "actions.root()"; close = mkLuaInline "actions.close()";
nextSibling = mkLuaInline "actions.next_sibling()";
previousSibling = mkLuaInline "actions.previous_sibling()";
parent = mkLuaInline "actions.parent()";
children = mkLuaInline "actions.children()";
root = mkLuaInline "actions.root()";
${cfg.navbuddy.mappings.visualName} = mkLuaInline "actions.visual_name()"; visualName = mkLuaInline "actions.visual_name()";
${cfg.navbuddy.mappings.visualScope} = mkLuaInline "actions.visual_scope()"; visualScope = mkLuaInline "actions.visual_scope()";
${cfg.navbuddy.mappings.yankName} = mkLuaInline "actions.yank_name()"; yankName = mkLuaInline "actions.yank_name()";
${cfg.navbuddy.mappings.yankScope} = mkLuaInline "actions.yank_scope()"; yankScope = mkLuaInline "actions.yank_scope()";
${cfg.navbuddy.mappings.insertName} = mkLuaInline "actions.insert_name()"; insertName = mkLuaInline "actions.insert_name()";
${cfg.navbuddy.mappings.insertScope} = mkLuaInline "actions.insert_scope()"; insertScope = mkLuaInline "actions.insert_scope()";
${cfg.navbuddy.mappings.appendName} = mkLuaInline "actions.append_name()"; appendName = mkLuaInline "actions.append_name()";
${cfg.navbuddy.mappings.appendScope} = mkLuaInline "actions.append_scope()"; appendScope = mkLuaInline "actions.append_scope()";
${cfg.navbuddy.mappings.rename} = mkLuaInline "actions.rename()"; rename = mkLuaInline "actions.rename()";
${cfg.navbuddy.mappings.delete} = mkLuaInline "actions.delete()"; delete = mkLuaInline "actions.delete()";
${cfg.navbuddy.mappings.foldCreate} = mkLuaInline "actions.fold_create()"; foldCreate = mkLuaInline "actions.fold_create()";
${cfg.navbuddy.mappings.foldDelete} = mkLuaInline "actions.fold_delete()"; foldDelete = mkLuaInline "actions.fold_delete()";
${cfg.navbuddy.mappings.comment} = mkLuaInline "actions.comment()"; comment = mkLuaInline "actions.comment()";
${cfg.navbuddy.mappings.select} = mkLuaInline "actions.select()"; select = mkLuaInline "actions.select()";
${cfg.navbuddy.mappings.moveDown} = mkLuaInline "actions.move_down()"; moveDown = mkLuaInline "actions.move_down()";
${cfg.navbuddy.mappings.moveUp} = mkLuaInline "actions.move_up()"; moveUp = mkLuaInline "actions.move_up()";
${cfg.navbuddy.mappings.togglePreview} = mkLuaInline "actions.toggle_preview()"; togglePreview = mkLuaInline "actions.toggle_preview()";
${cfg.navbuddy.mappings.vsplit} = mkLuaInline "actions.vsplit()"; vsplit = mkLuaInline "actions.vsplit()";
${cfg.navbuddy.mappings.hsplit} = mkLuaInline "actions.hsplit()"; hsplit = mkLuaInline "actions.hsplit()";
${cfg.navbuddy.mappings.telescope} = mkLuaInline '' telescope = mkLuaInline ''
actions.telescope({ actions.telescope({
layout_strategy = "horizontal", layout_strategy = "horizontal",
layout_config = { layout_config = {
height = 0.60, height = 0.60,
width = 0.75, width = 0.75,
prompt_position = "top", prompt_position = "top",
preview_width = 0.50 preview_width = 0.50
}, },
})''; })'';
${cfg.navbuddy.mappings.help} = mkLuaInline "actions.help()"; help = mkLuaInline "actions.help()";
}; });
}; };
vim.pluginRC.breadcrumbs = entryAfter ["lspconfig"] '' vim.pluginRC.breadcrumbs = entryAfter ["lspconfig"] ''

View file

@ -3,7 +3,7 @@
config, config,
... ...
}: let }: let
inherit (lib.options) mkOption; inherit (lib.options) literalExpression mkOption;
inherit (lib.types) bool str; inherit (lib.types) bool str;
inherit (lib.nvim.types) mkPluginSetupOption; inherit (lib.nvim.types) mkPluginSetupOption;
@ -64,7 +64,8 @@ in {
useVendoredKeybindings = mkOption { useVendoredKeybindings = mkOption {
type = bool; type = bool;
default = true; default = config.vim.vendoredKeymaps;
defaultText = literalExpression "config.vim.vendoredKeymaps";
description = '' description = ''
Use alternative set of keybindings that avoids conflicts with other popular plugins, e.g. nvim-leap Use alternative set of keybindings that avoids conflicts with other popular plugins, e.g. nvim-leap
''; '';