From f040b4a943869b545c303bff60351e6e73903468 Mon Sep 17 00:00:00 2001 From: alfarel Date: Sat, 14 Mar 2026 22:18:05 -0400 Subject: [PATCH] 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. --- modules/plugins/assistant/copilot/config.nix | 10 +-- .../plugins/completion/blink-cmp/config.nix | 88 ++++++++++--------- .../plugins/completion/nvim-cmp/config.nix | 84 ++++++++++-------- modules/plugins/languages/rust.nix | 39 ++++---- modules/plugins/languages/scala.nix | 2 + .../plugins/terminal/toggleterm/config.nix | 4 +- modules/plugins/ui/breadcrumbs/config.nix | 82 +++++++++-------- modules/plugins/utility/surround/surround.nix | 5 +- 8 files changed, 172 insertions(+), 142 deletions(-) diff --git a/modules/plugins/assistant/copilot/config.nix b/modules/plugins/assistant/copilot/config.nix index 39b0d0ff..9d717a9e 100644 --- a/modules/plugins/assistant/copilot/config.nix +++ b/modules/plugins/assistant/copilot/config.nix @@ -21,11 +21,11 @@ ''; mkLuaKeymap = mode: key: action: desc: opts: - opts - // { - inherit mode key action desc; - lua = true; - }; + mkIf (key != null) (opts + // { + inherit mode key action desc; + lua = true; + }); in { config = mkIf cfg.enable { vim = { diff --git a/modules/plugins/completion/blink-cmp/config.nix b/modules/plugins/completion/blink-cmp/config.nix index 5789c514..7b29b380 100644 --- a/modules/plugins/completion/blink-cmp/config.nix +++ b/modules/plugins/completion/blink-cmp/config.nix @@ -5,7 +5,7 @@ }: let inherit (lib.modules) mkIf; inherit (lib.strings) optionalString; - inherit (lib.attrsets) optionalAttrs; + inherit (lib.attrsets) mapAttrs' optionalAttrs; inherit (lib.generators) mkLuaInline; inherit (lib.attrsets) attrValues filterAttrs mapAttrsToList; inherit (lib.lists) map optional optionals elem; @@ -98,51 +98,57 @@ in { preset = "luasnip"; }; - keymap = { - ${mappings.complete} = ["show" "fallback"]; - ${mappings.close} = ["hide" "fallback"]; - ${mappings.scrollDocsUp} = ["scroll_documentation_up" "fallback"]; - ${mappings.scrollDocsDown} = ["scroll_documentation_down" "fallback"]; - ${mappings.confirm} = ["accept" "fallback"]; + keymap = + mapAttrs' (mapping-name: action: { + name = mappings.${mapping-name}; + value = action; + }) (filterAttrs (mapping-name: _action: mappings.${mapping-name} != null) { + 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} = [ - "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 - - if has_words_before then - return cmp.show() + if has_words_before then + return cmp.show() + end end - end - '') - "fallback" - ]; - ${mappings.previous} = [ - "select_prev" - "snippet_backward" - "fallback" - ]; - }; + '') + "fallback" + ]; + previous = [ + "select_prev" + "snippet_backward" + "fallback" + ]; + }); # cmdline is not enabled by default, we're just providing keymaps in # case the user enables them - cmdline.keymap = { - ${mappings.complete} = ["show" "fallback"]; - ${mappings.close} = ["hide" "fallback"]; - ${mappings.scrollDocsUp} = ["scroll_documentation_up" "fallback"]; - ${mappings.scrollDocsDown} = ["scroll_documentation_down" "fallback"]; - # NOTE: mappings.confirm is skipped because our default, would - # lead to accidental triggers of blink.accept instead of executing - # the cmd - - ${mappings.next} = ["select_next" "show" "fallback"]; - ${mappings.previous} = ["select_prev" "fallback"]; - }; + cmdline.keymap = + mapAttrs' (mapping-name: action: { + name = mappings.${mapping-name}; + value = action; + }) (filterAttrs (mapping-name: _action: mappings.${mapping-name} != null) { + complete = ["show" "fallback"]; + close = ["hide" "fallback"]; + scrollDocsUp = ["scroll_documentation_up" "fallback"]; + scrollDocsDown = ["scroll_documentation_down" "fallback"]; + # NOTE: mappings.confirm is skipped because our default, would + # lead to accidental triggers of blink.accept instead of executing + # the cmd + next = ["select_next" "show" "fallback"]; + previous = ["select_prev" "fallback"]; + }); }; }; }; diff --git a/modules/plugins/completion/nvim-cmp/config.nix b/modules/plugins/completion/nvim-cmp/config.nix index 9cceb0b7..8a0d19b4 100644 --- a/modules/plugins/completion/nvim-cmp/config.nix +++ b/modules/plugins/completion/nvim-cmp/config.nix @@ -3,6 +3,7 @@ config, ... }: let + inherit (lib.attrsets) filterAttrs mapAttrs'; inherit (lib.modules) mkIf; inherit (lib.strings) optionalString; inherit (lib.generators) mkLuaInline; @@ -72,48 +73,53 @@ in { formatting.format = cfg.format; # `cmp` and `luasnip` are defined above, in the `nvim-cmp` section - mapping = { - ${mappings.complete} = mkLuaInline "cmp.mapping.complete()"; - ${mappings.close} = mkLuaInline "cmp.mapping.abort()"; - ${mappings.scrollDocsUp} = mkLuaInline "cmp.mapping.scroll_docs(-4)"; - ${mappings.scrollDocsDown} = mkLuaInline "cmp.mapping.scroll_docs(4)"; - ${mappings.confirm} = mkLuaInline "cmp.mapping.confirm({ select = true })"; + mapping = + mapAttrs' (mapping-name: action: { + name = mappings.${mapping-name}; + value = action; + }) (filterAttrs (mapping-name: _action: mappings.${mapping-name} != null) + { + 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 '' - cmp.mapping(function(fallback) - local has_words_before = function() - 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 - end + next = mkLuaInline '' + cmp.mapping(function(fallback) + local has_words_before = function() + 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 + end - if cmp.visible() then - cmp.select_next_item() - ${optionalString luasnipEnable '' - elseif luasnip.locally_jumpable(1) then - luasnip.jump(1) - ''} - elseif has_words_before() then - cmp.complete() - else - fallback() - end - end) - ''; + if cmp.visible() then + cmp.select_next_item() + ${optionalString luasnipEnable '' + elseif luasnip.locally_jumpable(1) then + luasnip.jump(1) + ''} + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end) + ''; - ${mappings.previous} = mkLuaInline '' - cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - ${optionalString luasnipEnable '' - elseif luasnip.locally_jumpable(-1) then - luasnip.jump(-1) - ''} - else - fallback() - end - end) - ''; - }; + previous = mkLuaInline '' + cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + ${optionalString luasnipEnable '' + elseif luasnip.locally_jumpable(-1) then + luasnip.jump(-1) + ''} + else + fallback() + end + end) + ''; + }); }; }; }; diff --git a/modules/plugins/languages/rust.nix b/modules/plugins/languages/rust.nix index 3a3e4d1f..d5e8699c 100644 --- a/modules/plugins/languages/rust.nix +++ b/modules/plugins/languages/rust.nix @@ -214,24 +214,31 @@ in { on_attach = function(client, bufnr) default_on_attach(client, bufnr) local opts = { noremap=true, silent=true, buffer = bufnr } - vim.keymap.set("n", "rr", ":RustLsp runnables", opts) - vim.keymap.set("n", "rp", ":RustLsp parentModule", opts) - vim.keymap.set("n", "rm", ":RustLsp expandMacro", opts) - vim.keymap.set("n", "rc", ":RustLsp openCargo", opts) - vim.keymap.set("n", "rg", ":RustLsp crateGraph x11", opts) - ${optionalString cfg.dap.enable '' + + ${optionalString config.vim.vendoredKeymaps '' + vim.keymap.set("n", "rr", ":RustLsp runnables", opts) + vim.keymap.set("n", "rp", ":RustLsp parentModule", opts) + vim.keymap.set("n", "rm", ":RustLsp expandMacro", opts) + vim.keymap.set("n", "rc", ":RustLsp openCargo", opts) + vim.keymap.set("n", "rg", ":RustLsp crateGraph x11", opts) + ''} + + ${optionalString (cfg.dap.enable && config.vim.vendoredKeymaps) '' vim.keymap.set("n", "rd", ":RustLsp debuggables", opts) + ''} + + ${optionalString (cfg.dap.enable && config.vim.debugger.nvim-dap.mappings.continue != null) '' vim.keymap.set( - "n", "${config.vim.debugger.nvim-dap.mappings.continue}", - function() - local dap = require("dap") - if dap.status() == "" then - vim.cmd "RustLsp debuggables" - else - dap.continue() - end - end, - opts + "n", "${config.vim.debugger.nvim-dap.mappings.continue}", + function() + local dap = require("dap") + if dap.status() == "" then + vim.cmd "RustLsp debuggables" + else + dap.continue() + end + end, + opts ) ''} end diff --git a/modules/plugins/languages/scala.nix b/modules/plugins/languages/scala.nix index cf47352c..36fa9048 100644 --- a/modules/plugins/languages/scala.nix +++ b/modules/plugins/languages/scala.nix @@ -117,7 +117,9 @@ in { local attach_metals_keymaps = function(client, bufnr) 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}', 'lua ${listCommandsAction}', {noremap=true, silent=true, desc='Show all Metals commands'}) + ''} end metals_config = require('metals').bare_config() diff --git a/modules/plugins/terminal/toggleterm/config.nix b/modules/plugins/terminal/toggleterm/config.nix index 85cca09f..a93e2b43 100644 --- a/modules/plugins/terminal/toggleterm/config.nix +++ b/modules/plugins/terminal/toggleterm/config.nix @@ -54,7 +54,9 @@ in { 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}'}) + ''} ''; }; }; diff --git a/modules/plugins/ui/breadcrumbs/config.nix b/modules/plugins/ui/breadcrumbs/config.nix index 324501a5..0988d807 100644 --- a/modules/plugins/ui/breadcrumbs/config.nix +++ b/modules/plugins/ui/breadcrumbs/config.nix @@ -3,6 +3,7 @@ lib, ... }: let + inherit (lib.attrsets) filterAttrs mapAttrs'; inherit (lib.strings) optionalString; inherit (lib.modules) mkIf; inherit (lib.lists) optionals; @@ -30,57 +31,62 @@ in { ]; vim.ui.breadcrumbs.navbuddy.setupOpts = { - mappings = { - ${cfg.navbuddy.mappings.close} = mkLuaInline "actions.close()"; - ${cfg.navbuddy.mappings.nextSibling} = mkLuaInline "actions.next_sibling()"; - ${cfg.navbuddy.mappings.previousSibling} = mkLuaInline "actions.previous_sibling()"; - ${cfg.navbuddy.mappings.parent} = mkLuaInline "actions.parent()"; - ${cfg.navbuddy.mappings.children} = mkLuaInline "actions.children()"; - ${cfg.navbuddy.mappings.root} = mkLuaInline "actions.root()"; + mappings = + mapAttrs' (mapping-name: action: { + name = cfg.navbuddy.mappings.${mapping-name}; + value = action; + }) (filterAttrs (mapping-name: _action: cfg.navbuddy.mappings.${mapping-name} != null) + { + 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()"; - ${cfg.navbuddy.mappings.visualScope} = mkLuaInline "actions.visual_scope()"; + visualName = mkLuaInline "actions.visual_name()"; + visualScope = mkLuaInline "actions.visual_scope()"; - ${cfg.navbuddy.mappings.yankName} = mkLuaInline "actions.yank_name()"; - ${cfg.navbuddy.mappings.yankScope} = mkLuaInline "actions.yank_scope()"; + yankName = mkLuaInline "actions.yank_name()"; + yankScope = mkLuaInline "actions.yank_scope()"; - ${cfg.navbuddy.mappings.insertName} = mkLuaInline "actions.insert_name()"; - ${cfg.navbuddy.mappings.insertScope} = mkLuaInline "actions.insert_scope()"; + insertName = mkLuaInline "actions.insert_name()"; + insertScope = mkLuaInline "actions.insert_scope()"; - ${cfg.navbuddy.mappings.appendName} = mkLuaInline "actions.append_name()"; - ${cfg.navbuddy.mappings.appendScope} = mkLuaInline "actions.append_scope()"; + appendName = mkLuaInline "actions.append_name()"; + 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()"; - ${cfg.navbuddy.mappings.foldDelete} = mkLuaInline "actions.fold_delete()"; + foldCreate = mkLuaInline "actions.fold_create()"; + 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()"; - ${cfg.navbuddy.mappings.moveUp} = mkLuaInline "actions.move_up()"; + moveDown = mkLuaInline "actions.move_down()"; + 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()"; - ${cfg.navbuddy.mappings.hsplit} = mkLuaInline "actions.hsplit()"; + vsplit = mkLuaInline "actions.vsplit()"; + hsplit = mkLuaInline "actions.hsplit()"; - ${cfg.navbuddy.mappings.telescope} = mkLuaInline '' - actions.telescope({ - layout_strategy = "horizontal", - layout_config = { - height = 0.60, - width = 0.75, - prompt_position = "top", - preview_width = 0.50 - }, - })''; - ${cfg.navbuddy.mappings.help} = mkLuaInline "actions.help()"; - }; + telescope = mkLuaInline '' + actions.telescope({ + layout_strategy = "horizontal", + layout_config = { + height = 0.60, + width = 0.75, + prompt_position = "top", + preview_width = 0.50 + }, + })''; + help = mkLuaInline "actions.help()"; + }); }; vim.pluginRC.breadcrumbs = entryAfter ["lspconfig"] '' diff --git a/modules/plugins/utility/surround/surround.nix b/modules/plugins/utility/surround/surround.nix index 2819b6d6..cb067fd9 100644 --- a/modules/plugins/utility/surround/surround.nix +++ b/modules/plugins/utility/surround/surround.nix @@ -3,7 +3,7 @@ config, ... }: let - inherit (lib.options) mkOption; + inherit (lib.options) literalExpression mkOption; inherit (lib.types) bool str; inherit (lib.nvim.types) mkPluginSetupOption; @@ -64,7 +64,8 @@ in { useVendoredKeybindings = mkOption { type = bool; - default = true; + default = config.vim.vendoredKeymaps; + defaultText = literalExpression "config.vim.vendoredKeymaps"; description = '' Use alternative set of keybindings that avoids conflicts with other popular plugins, e.g. nvim-leap '';