From aa236a7f7e9c0aaae52618ec962d1f61c74e39e9 Mon Sep 17 00:00:00 2001 From: Kalle Jepsen Date: Fri, 4 Oct 2024 10:22:04 +0200 Subject: [PATCH] languages/scala: Add scala language support Adds LSP support for Scala via nvim-metals --- configuration.nix | 1 + flake.lock | 17 ++++ flake.nix | 6 ++ modules/plugins/languages/default.nix | 1 + modules/plugins/languages/scala.nix | 141 ++++++++++++++++++++++++++ 5 files changed, 166 insertions(+) create mode 100644 modules/plugins/languages/scala.nix diff --git a/configuration.nix b/configuration.nix index b21b26aa..ff9af12a 100644 --- a/configuration.nix +++ b/configuration.nix @@ -68,6 +68,7 @@ isMaximal: { lsp.server = "clangd"; }; + scala.enable = isMaximal; rust = { enable = isMaximal; crates.enable = isMaximal; diff --git a/flake.lock b/flake.lock index 7775fb1f..eb34f95c 100644 --- a/flake.lock +++ b/flake.lock @@ -1149,6 +1149,22 @@ "type": "github" } }, + "plugin-nvim-metals": { + "flake": false, + "locked": { + "lastModified": 1728033462, + "narHash": "sha256-XqOkZ/5eex1mrNUf6vrJjDjibBbb0bSMYSciKAoVD0A=", + "owner": "ksonj", + "repo": "nvim-metals", + "rev": "4d86c32f6c028de197e28dab0f6a0250c0d1c16a", + "type": "github" + }, + "original": { + "owner": "ksonj", + "repo": "nvim-metals", + "type": "github" + } + }, "plugin-nvim-navbuddy": { "flake": false, "locked": { @@ -1863,6 +1879,7 @@ "plugin-nvim-docs-view": "plugin-nvim-docs-view", "plugin-nvim-lightbulb": "plugin-nvim-lightbulb", "plugin-nvim-lspconfig": "plugin-nvim-lspconfig", + "plugin-nvim-metals": "plugin-nvim-metals", "plugin-nvim-navbuddy": "plugin-nvim-navbuddy", "plugin-nvim-navic": "plugin-nvim-navic", "plugin-nvim-neoclip": "plugin-nvim-neoclip", diff --git a/flake.nix b/flake.nix index 987e3e59..9f45eb6f 100644 --- a/flake.nix +++ b/flake.nix @@ -206,6 +206,12 @@ flake = false; }; + plugin-nvim-metals = { + url = "github:ksonj/nvim-metals"; + flake = false; + }; + + # Copying/Registers plugin-registers = { url = "github:tversteeg/registers.nvim"; diff --git a/modules/plugins/languages/default.nix b/modules/plugins/languages/default.nix index 28c1fd8f..1c2e2bac 100644 --- a/modules/plugins/languages/default.nix +++ b/modules/plugins/languages/default.nix @@ -19,6 +19,7 @@ in { ./python.nix ./r.nix ./rust.nix + ./scala.nix ./sql.nix ./svelte.nix ./tailwind.nix diff --git a/modules/plugins/languages/scala.nix b/modules/plugins/languages/scala.nix new file mode 100644 index 00000000..417cefbc --- /dev/null +++ b/modules/plugins/languages/scala.nix @@ -0,0 +1,141 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (lib) types optionalString; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.nvim.types) mkGrammarOption; + inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.nvim.dag) entryAfter; + + mkBinding = binding: "vim.api.nvim_buf_set_keymap(bufnr, 'n', '${binding.value}', 'lua ${binding.action}', {noremap=true, silent=true, desc='${binding.description}'})"; + + listCommandsBinding = { + value = cfg.lsp.extraMappings.listCommands; + description = "List Metals commands"; + action = + if config.vim.telescope.enable + then ''require("telescope").extensions.metals.commands()'' + else ''require("metals").commands()''; + }; + + cfg = config.vim.languages.scala; + + usingDap = config.vim.debugger.nvim-dap.enable && cfg.dap.enable; + usingLualine = config.vim.statusline.lualine.enable; +in { + options.vim.languages.scala = { + enable = mkEnableOption "Scala language support"; + treesitter = { + enable = mkEnableOption "Scala treesitter" // {default = config.vim.languages.enableTreesitter;}; + package = mkGrammarOption pkgs "scala"; + }; + lsp = { + enable = mkEnableOption "Scala LSP support (metals)" // {default = config.vim.languages.enableLSP;}; + package = mkOption { + type = types.package; + default = pkgs.metals; + description = '' + metals package to use + ''; + }; + extraMappings = { + listCommands = mkMappingOption "List Metals commands" "lc"; + }; + }; + dap = { + enable = mkOption { + description = "Scala Debug Adapter support"; + type = types.bool; + default = config.vim.languages.enableDAP; + }; + config = mkOption { + description = "Lua configuration for dap"; + type = types.str; + default = '' + dap.configurations.scala = { + { + type = "scala", + request = "launch", + name = "RunOrTest", + metals = { + runType = "runOrTestFile", + --args = { "firstArg", "secondArg", "thirdArg" }, -- here just as an example + }, + }, + { + type = "scala", + request = "launch", + name = "Test Target", + metals = { + runType = "testTarget", + }, + }, + } + ''; + }; + }; + }; + config = mkIf cfg.enable ( + mkMerge [ + (mkIf cfg.treesitter.enable { + vim.treesitter.enable = true; + vim.treesitter.grammars = [cfg.treesitter.package]; + }) + (mkIf (cfg.lsp.enable || cfg.dap.enable) { + vim = { + startPlugins = ["nvim-metals"]; + luaConfigRC.nvim-metals = entryAfter ["lsp-setup"] '' + -- Scala nvim-metals config + local metals_caps = capabilities -- from lsp-setup + + local attach_metals_keymaps = function(client, bufnr) + attach_keymaps(client, bufnr) -- from lsp-setup + ${mkBinding listCommandsBinding} + end + + metals_config = require('metals').bare_config() + ${optionalString usingLualine "metals_config.init_options.statusBarProvider = 'on'"} + + metals_config.capabilities = metals_caps + metals_config.on_attach = function(client, bufnr) + ${optionalString usingDap "require('metals').setup_dap()"} + attach_metals_keymaps(client, bufnr) + end + metals_config.settings = { + metalsBinaryPath = "${cfg.lsp.package}/bin/metals", + showImplicitArguments = true, + showImplicitConversionsAndClasses = true, + showInferredType = true, + excludedPackages = { + "akka.actor.typed.javadsl", + "com.github.swagger.akka.javadsl" + }, + + } + + metals_config.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( + vim.lsp.diagnostic.on_publish_diagnostics, { + virtual_text = { + prefix = '⚠', + } + } + ) + + + -- without doing this, autocommands that deal with filetypes prohibit messages from being shown + vim.opt_global.shortmess:remove("F") + + vim.cmd([[augroup lsp]]) + vim.cmd([[autocmd!]]) + vim.cmd([[autocmd FileType java,scala,sbt lua require('metals').initialize_or_attach(metals_config)]]) + vim.cmd([[augroup end]]) + ''; + }; + }) + ] + ); +}