diff --git a/modules/lsp/default.nix b/modules/lsp/default.nix index b64720d4..c8a35fb6 100644 --- a/modules/lsp/default.nix +++ b/modules/lsp/default.nix @@ -137,6 +137,10 @@ in }; }; + imports = [ + ./keymaps.nix + ]; + config = let enabledServers = lib.pipe cfg.servers [ diff --git a/modules/lsp/keymaps.nix b/modules/lsp/keymaps.nix new file mode 100644 index 00000000..4b63ceb3 --- /dev/null +++ b/modules/lsp/keymaps.nix @@ -0,0 +1,123 @@ +{ lib, config, ... }: +let + inherit (lib) types; + inherit (lib.nixvim.keymaps) mkMapOptionSubmodule; + + cfg = config.lsp; + + # An extra module to include in the keymap option submodule + # Declares and implements a specialised `lspBufAction` option + extraKeymapModule = + { config, options, ... }: + { + options.lspBufAction = lib.mkOption { + type = types.nullOr types.str; + description = '' + LSP buffer action to use for `action`. + + If non-null, the keymap's `action` will be defined as `vim.lsp.buf.`. + + See [`:h lsp-buf`](https://neovim.io/doc/user/lsp.html#lsp-buf) + ''; + default = null; + example = "hover"; + }; + + config.action = lib.mkIf (config.lspBufAction != null) ( + lib.mkDerivedConfig options.lspBufAction ( + action: lib.nixvim.mkRaw "vim.lsp.buf[${lib.nixvim.toLuaObject action}]" + ) + ); + }; +in +{ + options.lsp = { + keymaps = lib.mkOption { + type = types.listOf (mkMapOptionSubmodule { + action.example = "LspRestart"; + extraModules = [ extraKeymapModule ]; + }); + description = '' + Keymaps to register when a language server is attached. + ''; + default = [ ]; + example = [ + { + key = "gd"; + lspBufAction = "definition"; + } + { + key = "gD"; + lspBufAction = "references"; + } + { + key = "gt"; + lspBufAction = "type_definition"; + } + { + key = "gi"; + lspBufAction = "implementation"; + } + { + key = "K"; + lspBufAction = "hover"; + } + + { + key = "k"; + action = lib.nixvim.nestedLiteralLua "function() vim.diagnostic.jump({ count=-1, float=true }) end"; + } + { + key = "j"; + action = lib.nixvim.nestedLiteralLua "function() vim.diagnostic.jump({ count=1, float=true }) end"; + } + { + key = "lx"; + action = "LspStop"; + } + { + key = "ls"; + action = "LspStart"; + } + { + key = "lr"; + action = "LspRestart"; + } + { + key = "gd"; + action = lib.nixvim.nestedLiteralLua "require('telescope.builtin').lsp_definitions"; + } + { + key = "K"; + action = "Lspsaga hover_doc"; + } + ]; + }; + }; + + config = lib.mkIf (cfg.keymaps != [ ]) { + autoGroups.nixvim_lsp_binds.clear = false; + + autoCmd = [ + { + event = "LspAttach"; + group = "nixvim_lsp_binds"; + callback = lib.nixvim.mkRaw '' + function(args) + ${lib.concatMapStringsSep "\n" ( + keymap: + # lua + '' + do + local map = ${lib.nixvim.toLuaObject keymap} + local options = vim.tbl_extend("keep", map.options or {}, { buffer = args.buf }) + vim.keymap.set(map.mode, map.key, map.action, options) + end + '') cfg.keymaps} + end + ''; + desc = "Load LSP keymaps"; + } + ]; + }; +}