plugins/lsp: migrate to mkNeovimPlugin

This commit is contained in:
Heitor Augusto 2024-12-17 14:48:03 -03:00 committed by nix-infra-bot
parent 65d082069e
commit 48eeef58e1

View file

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