diff --git a/modules/default.nix b/modules/default.nix index b0fa8f54..085eaf5d 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -18,6 +18,7 @@ ./highlights.nix ./keymaps.nix ./lazyload.nix + ./lsp.nix ./lua-loader.nix ./opts.nix ./output.nix diff --git a/modules/lsp.nix b/modules/lsp.nix new file mode 100644 index 00000000..49291ddc --- /dev/null +++ b/modules/lsp.nix @@ -0,0 +1,151 @@ +{ + lib, + config, + ... +}: +let + inherit (lib) mkOption types; + inherit (lib.nixvim) toLuaObject; + + cfg = config.lsp; + + serverType = types.submodule { + options = { + enable = lib.mkEnableOption "the language server"; + + activate = lib.mkOption { + type = types.bool; + description = '' + Whether to call `vim.lsp.enable()` for this server. + ''; + default = true; + example = false; + }; + + package = lib.mkOption { + type = with types; nullOr package; + default = null; + description = '' + Package to use for this language server. + + Alternatively, the language server should be available on your `$PATH`. + ''; + }; + + config = mkOption { + type = with types; attrsOf anything; + description = '' + Configurations for each language server. + ''; + default = { }; + example = { + cmd = [ + "clangd" + "--background-index" + ]; + root_markers = [ + "compile_commands.json" + "compile_flags.txt" + ]; + filetypes = [ + "c" + "cpp" + ]; + }; + }; + }; + }; +in +{ + options.lsp = { + luaConfig = lib.mkOption { + type = lib.types.pluginLuaConfig; + default = { }; + description = '' + Lua code configuring LSP. + ''; + }; + + inlayHints = { + enable = lib.mkEnableOption "inlay hints globally"; + }; + + servers = mkOption { + type = types.attrsOf serverType; + description = '' + LSP servers to enable and/or configure. + + This option is implemented using neovim's `vim.lsp` lua API. + If you prefer to use [nvim-lspconfig], see [`plugins.lsp`]. + + [nvim-lspconfig]: https://github.com/neovim/nvim-lspconfig + [`plugins.lsp`]: https://nix-community.github.io/nixvim/plugins/lsp/index.html + ''; + default = { }; + example = { + "*".config = { + root_markers = [ ".git" ]; + capabilities.textDocument.semanticTokens = { + multilineTokenSupport = true; + }; + }; + luals.enable = true; + clangd = { + enable = true; + config = { + cmd = [ + "clangd" + "--background-index" + ]; + root_markers = [ + "compile_commands.json" + "compile_flags.txt" + ]; + filetypes = [ + "c" + "cpp" + ]; + }; + }; + }; + }; + }; + + config = + let + enabledServers = lib.filterAttrs (_: v: v.enable) cfg.servers; + in + { + extraPackages = lib.pipe enabledServers [ + builtins.attrValues + (builtins.catAttrs "package") + ]; + + lsp.luaConfig.content = + let + mkServerConfig = + name: props: + let + luaName = toLuaObject name; + in + '' + vim.lsp.config(${luaName}, ${toLuaObject props.config}) + '' + + lib.optionalString props.activate '' + vim.lsp.enable(${luaName}) + ''; + in + lib.mkMerge ( + lib.optional cfg.inlayHints.enable "vim.lsp.inlay_hint.enable(true)" + ++ lib.mapAttrsToList mkServerConfig enabledServers + ); + + extraConfigLua = lib.mkIf (cfg.luaConfig.content != "") '' + -- LSP {{{ + do + ${cfg.luaConfig.content} + end + -- }}} + ''; + }; +} diff --git a/tests/test-sources/modules/lsp.nix b/tests/test-sources/modules/lsp.nix new file mode 100644 index 00000000..9b645bdc --- /dev/null +++ b/tests/test-sources/modules/lsp.nix @@ -0,0 +1,30 @@ +{ + example = { + lsp.servers = { + "*".config = { + root_markers = [ ".git" ]; + capabilities.textDocument.semanticTokens = { + multilineTokenSupport = true; + }; + }; + luals.enable = true; + clangd = { + enable = true; + config = { + cmd = [ + "clangd" + "--background-index" + ]; + root_markers = [ + "compile_commands.json" + "compile_flags.txt" + ]; + filetypes = [ + "c" + "cpp" + ]; + }; + }; + }; + }; +}