diff --git a/plugins/lsp/default.nix b/plugins/lsp/default.nix index 90a563c9..ca590e68 100644 --- a/plugins/lsp/default.nix +++ b/plugins/lsp/default.nix @@ -1,231 +1,222 @@ -{ - lib, - helpers, - config, - pkgs, - ... -}: -with lib; +{ lib, ... }: let - cfg = config.plugins.lsp; + inherit (lib) mkOption types; in -{ +lib.nixvim.plugins.mkNeovimPlugin { + name = "lsp"; + packPathName = "nvim-lspconfig"; + package = "nvim-lspconfig"; + + callSetup = false; + hasSettings = false; + + maintainers = [ lib.maintainers.HeitorAugustoLN ]; + imports = [ ./language-servers ]; - options = { - plugins.lsp = { - enable = mkEnableOption "neovim's built-in LSP"; - - package = lib.mkPackageOption pkgs [ - "vimPlugins" - "nvim-lspconfig" - ] { }; - - keymaps = { - silent = mkOption { - type = types.bool; - description = "Whether nvim-lsp keymaps should be silent"; - default = false; - }; - - diagnostic = mkOption { - type = with types; attrsOf (either str (attrsOf anything)); - description = "Mappings for `vim.diagnostic.` functions to be added when an LSP is attached."; - example = { - "k" = "goto_prev"; - "j" = "goto_next"; - }; - default = { }; - }; - - lspBuf = mkOption { - type = with types; attrsOf (either str (attrsOf anything)); - description = "Mappings for `vim.lsp.buf.` functions to be added when an LSP it attached."; - example = { - "gd" = "definition"; - "gD" = "references"; - "gt" = "type_definition"; - "gi" = "implementation"; - "K" = "hover"; - }; - default = { }; - }; - - extra = mkOption { - 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. - ''; - example = [ - { - key = "lx"; - action = "LspStop"; - } - { - key = "ls"; - action = "LspStart"; - } - { - key = "lr"; - action = "LspRestart"; - } - { - key = "gd"; - action.__raw = "require('telescope.builtin').lsp_definitions"; - } - { - key = "K"; - action = "Lspsaga hover_doc"; - } - ]; - default = [ ]; - }; + extraOptions = { + keymaps = { + silent = mkOption { + type = types.bool; + description = "Whether nvim-lsp keymaps should be silent"; + default = false; }; - enabledServers = mkOption { - type = - with types; - listOf (oneOf [ - str - (submodule { - options = { - name = mkOption { - type = str; - description = "The server's name"; - }; + diagnostic = mkOption { + type = with types; attrsOf (either str (attrsOf anything)); + description = "Mappings for `vim.diagnostic.` functions to be added when an LSP is attached."; + example = { + "k" = "goto_prev"; + "j" = "goto_next"; + }; + default = { }; + }; - capabilities = mkOption { - type = types.nullOr (types.attrsOf types.bool); - description = "Control resolved capabilities for the language server."; - default = null; - example = { - documentFormattingProvider = false; - }; - }; + lspBuf = mkOption { + type = with types; attrsOf (either str (attrsOf anything)); + description = "Mappings for `vim.lsp.buf.` functions to be added when an LSP it attached."; + example = { + "gd" = "definition"; + "gD" = "references"; + "gt" = "type_definition"; + "gi" = "implementation"; + "K" = "hover"; + }; + default = { }; + }; - extraOptions = mkOption { - type = attrsOf anything; - description = "Extra options for the server"; + extra = mkOption { + type = types.listOf lib.nixvim.keymaps.deprecatedMapOptionSubmodule; + apply = map lib.nixvim.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. + ''; + example = [ + { + key = "lx"; + action = "LspStop"; + } + { + key = "ls"; + action = "LspStart"; + } + { + key = "lr"; + action = "LspRestart"; + } + { + key = "gd"; + action.__raw = "require('telescope.builtin').lsp_definitions"; + } + { + key = "K"; + action = "Lspsaga hover_doc"; + } + ]; + default = [ ]; + }; + }; + + enabledServers = mkOption { + type = + with types; + listOf (oneOf [ + str + (submodule { + options = { + name = mkOption { + type = str; + description = "The server's name"; + }; + + capabilities = mkOption { + type = nullOr (attrsOf bool); + description = "Control resolved capabilities for the language server."; + default = null; + example = { + documentFormattingProvider = false; }; }; - }) - ]); - description = "A list of enabled LSP servers. Don't use this directly."; - default = [ ]; - internal = true; - visible = false; - }; - inlayHints = mkOption { - description = '' - Whether to enable LSP inlay-hints. - Only affects language servers with inlay-hints support. + extraOptions = mkOption { + type = attrsOf anything; + description = "Extra options for the server"; + }; + }; + }) + ]); + description = "A list of enabled LSP servers. Don't use this directly."; + default = [ ]; + internal = true; + visible = false; + }; - See [`:h lsp-inlay_hint`](https://neovim.io/doc/user/lsp.html#lsp-inlay_hint). - ''; - type = types.bool; - default = false; - example = true; - }; + inlayHints = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable LSP inlay-hints. + Only affects language servers with inlay-hints support. - onAttach = mkOption { - type = types.lines; - description = "A lua function to be run when a new LSP buffer is attached. The argument `client` and `bufnr` is provided."; - default = ""; - }; + See [`:h lsp-inlay_hint`](https://neovim.io/doc/user/lsp.html#lsp-inlay_hint). + ''; + }; - capabilities = mkOption { - type = types.lines; - description = "Lua code that modifies inplace the `capabilities` table."; - default = ""; - }; + onAttach = mkOption { + type = types.lines; + description = "A lua function to be run when a new LSP buffer is attached. The argument `client` and `bufnr` is provided."; + default = ""; + }; - setupWrappers = mkOption { - type = with types; listOf (functionTo str); - description = "Code to be run to wrap the setup args. Takes in an argument containing the previous results, and returns a new string of code."; - default = [ ]; - }; + capabilities = mkOption { + type = types.lines; + description = "Lua code that modifies inplace the `capabilities` table."; + default = ""; + }; - preConfig = mkOption { - type = types.lines; - description = "Code to be run before loading the LSP. Useful for requiring plugins"; - default = ""; - }; + setupWrappers = mkOption { + type = with types; listOf (functionTo str); + description = "Code to be run to wrap the setup args. Takes in an argument containing the previous results, and returns a new string of code."; + default = [ ]; + }; - postConfig = mkOption { - type = types.lines; - description = "Code to be run after loading the LSP. This is an internal option"; - default = ""; - }; + preConfig = mkOption { + type = types.lines; + description = "Code to be run before loading the LSP. Useful for requiring plugins"; + default = ""; + }; + + postConfig = mkOption { + type = types.lines; + description = "Code to be run after loading the LSP. This is an internal option"; + default = ""; }; }; - config = - let - runWrappers = - wrappers: s: if wrappers == [ ] then s else (head wrappers) (runWrappers (tail wrappers) s); - updateCapabilities = - let - servers = builtins.filter ( - server: server.capabilities != null && server.capabilities != { } - ) cfg.enabledServers; - in - lib.concatMapStringsSep "\n" ( - server: + extraConfig = cfg: { + keymapsOnEvents.LspAttach = + let + mkMaps = + prefix: descPrefix: + lib.mapAttrsToList ( + key: action: + let + actionStr = action.action or action; + actionProps = lib.optionalAttrs (builtins.isAttrs action) ( + builtins.removeAttrs action [ "action" ] + ); + in + { + inherit key; + mode = "n"; + action = lib.nixvim.mkRaw (prefix + actionStr); + + options = { + inherit (cfg.keymaps) silent; + desc = "${descPrefix} ${actionStr}"; + } // actionProps; + } + ); + in + mkMaps "vim.diagnostic." "Lsp diagnostic" cfg.keymaps.diagnostic + ++ mkMaps "vim.lsp.buf." "Lsp buf" cfg.keymaps.lspBuf + ++ cfg.keymaps.extra; + + plugins.lsp.onAttach = lib.mkIf cfg.inlayHints '' + -- LSP Inlay Hints {{{ + if client.server_capabilities.inlayHintProvider and vim.lsp.inlay_hint then + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) + end + -- }}} + ''; + + plugins.lsp.luaConfig.content = + let + runWrappers = + wrappers: s: + if wrappers == [ ] then s else (builtins.head wrappers) (runWrappers (builtins.tail wrappers) s); + updateCapabilities = let - updates = lib.concatMapStringsSep "\n" (name: '' - client.server_capabilities.${name} = ${lib.nixvim.toLuaObject server.capabilities.${name}} - '') (builtins.attrNames server.capabilities); + servers = builtins.filter ( + server: server.capabilities != null && server.capabilities != { } + ) cfg.enabledServers; in - '' - if client.name == "${server.name}" then - ${updates} - end - '' - ) servers; - in - mkIf cfg.enable { - extraPlugins = [ cfg.package ]; - - keymapsOnEvents.LspAttach = - let - mkMaps = - prefix: descPrefix: - mapAttrsToList ( - key: action: - let - actionStr = action.action or action; - actionProps = optionalAttrs (isAttrs action) (removeAttrs action [ "action" ]); - in - { - mode = "n"; - inherit key; - action = helpers.mkRaw (prefix + actionStr); - - options = { - inherit (cfg.keymaps) silent; - desc = "${descPrefix} ${actionStr}"; - } // actionProps; - } - ); - in - mkMaps "vim.diagnostic." "Lsp diagnostic" cfg.keymaps.diagnostic - ++ mkMaps "vim.lsp.buf." "Lsp buf" cfg.keymaps.lspBuf - ++ cfg.keymaps.extra; - - # Enable inlay-hints - plugins.lsp.onAttach = mkIf cfg.inlayHints '' - -- LSP Inlay Hints {{{ - if client.server_capabilities.inlayHintProvider and vim.lsp.inlay_hint then - vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) - end - -- }}} - ''; - - # Enable all LSP servers - extraConfigLua = '' + lib.concatMapStringsSep "\n" ( + server: + let + updates = lib.concatMapStringsSep "\n" (name: '' + client.server_capabilities.${name} = ${lib.nixvim.toLuaObject server.capabilities.${name}} + '') (builtins.attrNames server.capabilities); + in + '' + if client.name == "${server.name}" then + ${updates} + end + '' + ) servers; + in + '' -- LSP {{{ do ${cfg.preConfig} @@ -247,12 +238,12 @@ in local __setup = ${runWrappers cfg.setupWrappers "{ on_attach = _M.lspOnAttach, - capabilities = __lspCapabilities() + capabilities = __lspCapabilities(), }"} - for i,server in ipairs(__lspServers) do + for i, server in ipairs(__lspServers) do if type(server) == "string" then - require('lspconfig')[server].setup(__setup) + require("lspconfig")[server].setup(__setup) else local options = ${runWrappers cfg.setupWrappers "server.extraOptions"} @@ -262,7 +253,7 @@ in options = vim.tbl_extend("keep", options, __setup) end - require('lspconfig')[server.name].setup(options) + require("lspconfig")[server.name].setup(options) end end @@ -270,5 +261,5 @@ in end -- }}} ''; - }; + }; }