diff --git a/lib/languages.nix b/lib/languages.nix index a202ff14..c4074144 100644 --- a/lib/languages.nix +++ b/lib/languages.nix @@ -1,10 +1,11 @@ -# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/booleans.nix {lib}: let inherit (builtins) isString getAttr; inherit (lib.options) mkOption; - inherit (lib.types) bool; + inherit (lib.types) listOf bool str submodule attrsOf anything either nullOr; inherit (lib.nvim.attrsets) mapListToAttrs; + inherit (lib.nvim.types) luaInline; in { + # TODO: remove diagnosticsToLua = { lang, config, @@ -32,4 +33,48 @@ in { type = bool; description = "Turn on ${desc} for enabled languages by default"; }; + + lspOptions = submodule { + freeformType = attrsOf anything; + options = { + enable = mkOption { + type = bool; + default = true; + description = "Whether to enable this LSP server."; + }; + + capabilities = mkOption { + type = nullOr (either luaInline (attrsOf anything)); + default = null; + description = "LSP capabilitiess to pass to lspconfig"; + }; + + on_attach = mkOption { + type = nullOr luaInline; + default = null; + description = "Function to execute when an LSP server attaches to a buffer"; + }; + + filetypes = mkOption { + type = nullOr (listOf str); + default = null; + description = "Filetypes to auto-attach LSP in"; + }; + + cmd = mkOption { + type = nullOr (listOf str); + default = null; + description = "Command used to start the LSP server"; + }; + + root_markers = mkOption { + type = nullOr (listOf str); + default = null; + description = '' + "root markers" used to determine the root directory of the workspace, and + the filetypes associated with this LSP server. + ''; + }; + }; + }; } diff --git a/modules/neovim/init/default.nix b/modules/neovim/init/default.nix index 0e7a4c6b..7db6f2ef 100644 --- a/modules/neovim/init/default.nix +++ b/modules/neovim/init/default.nix @@ -5,6 +5,7 @@ ./debug.nix ./diagnostics.nix ./highlight.nix + ./lsp.nix ./spellcheck.nix ]; } diff --git a/modules/neovim/init/lsp.nix b/modules/neovim/init/lsp.nix new file mode 100644 index 00000000..faef0f93 --- /dev/null +++ b/modules/neovim/init/lsp.nix @@ -0,0 +1,82 @@ +{ + config, + lib, + ... +}: let + inherit (builtins) filter; + inherit (lib.modules) mkIf mkMerge mkDefault; + inherit (lib.options) mkOption; + inherit (lib.types) attrsOf; + inherit (lib.strings) concatLines; + inherit (lib.attrsets) mapAttrsToList attrNames filterAttrs; + inherit (lib.generators) mkLuaInline; + inherit (lib.nvim.languages) lspOptions; + inherit (lib.nvim.dag) entryAnywhere; + inherit (lib.nvim.lua) toLuaObject; + + cfg = config.vim.lsp; + + lspConfigurations = + mapAttrsToList ( + name: value: '' + vim.lsp.config["${name}"] = ${toLuaObject value} + '' + ) + cfg.servers; + + enabledServers = filterAttrs (_: u: u.enable) cfg.servers; +in { + options = { + vim.lsp.servers = mkOption { + type = attrsOf lspOptions; + default = {}; + example = '' + { + "*" = { + root_markers = [".git"]; + capabilities = { + textDocument = { + semanticTokens = { + multilineTokenSupport = true; + }; + }; + }; + }; + + "clangd" = { + filetypes = ["c"]; + }; + } + ''; + description = '' + LSP configurations that will be managed using `vim.lsp.config()` and + related utilities added in Neovim 0.11. LSPs defined here will be + added to the resulting {file}`init.lua` using `vim.lsp.config` and + enabled through `vim.lsp.enable` below the configuration table. + + You may review the generated configuration by running {command}`nvf-print-config` + in a shell. Please see {command}`:help lsp-config` for more details + on the underlying API. + ''; + }; + }; + + config = mkMerge [ + { + vim.lsp.servers."*" = { + capabilities = mkDefault (mkLuaInline "capabilities"); + on_attach = mkDefault (mkLuaInline "default_on_attach"); + }; + } + + (mkIf (cfg.servers != {}) { + vim.luaConfigRC.lsp-servers = entryAnywhere '' + -- Individual LSP configurations managed by nvf. + ${concatLines lspConfigurations} + + -- Enable configured LSPs explicitly + vim.lsp.enable(${toLuaObject (filter (name: name != "*") (attrNames enabledServers))}) + ''; + }) + ]; +} diff --git a/modules/plugins/languages/default.nix b/modules/plugins/languages/default.nix index c3312135..b889e60a 100644 --- a/modules/plugins/languages/default.nix +++ b/modules/plugins/languages/default.nix @@ -1,4 +1,8 @@ -{lib, ...}: let +{ + config, + lib, + ... +}: let inherit (lib.nvim.languages) mkEnable; in { imports = [ @@ -47,7 +51,11 @@ in { ]; options.vim.languages = { - enableLSP = mkEnable "LSP"; + # LSPs are now built into Neovim, and we should enable them by default + # if `vim.lsp.enable` is true. + enableLSP = mkEnable "LSP" // {default = config.vim.lsp.enable;}; + + # Those are still managed by plugins, and should be enabled here. enableDAP = mkEnable "Debug Adapter"; enableTreesitter = mkEnable "Treesitter"; enableFormat = mkEnable "Formatting";