local map = vim.keymap.set ---------------------- -- Language servers -- ---------------------- -- NOTE: put settings into `settings` -- use another `on_attach` field if needed local servers = { clangd = {}, -- C/CPP cssls = {}, -- CSS html = {}, -- HTML jsonls = {}, -- JSON lemminx = {}, -- XML phpactor = {}, -- PHP pylsp = {}, -- Python pyright = {}, taplo = {}, -- TOML texlab = {}, -- texlab ts_ls = {}, -- TypeScript vimls = {}, -- Vim Script ocamllsp = {}, -- OCaml gleam = {}, -- Gleam yamlls = {}, -- yaml gopls = {}, -- Golang elmls = {}, -- elm -- -- fix this, it shows spamming message on top -- golangci_lint_ls = {}, fish_lsp = {}, bashls = { -- Bash on_attach = function(_, bufno) map("n", "f", function() local saved = vim.fn.winsaveview() vim.cmd([[silent exec "%!shfmt"]]) vim.fn.winrestview(saved) end, { buffer = bufno }) end, }, tinymist = { on_attach = function(_, bufno) map("n", "f", function() local saved = vim.fn.winsaveview() vim.cmd([[silent exec "%!typstyle -c 100"]]) vim.fn.winrestview(saved) end, { buffer = bufno }) end, }, lua_ls = { -- Lua on_attach = function(_, bufno) map("n", "f", function() local saved = vim.fn.winsaveview() vim.cmd([[silent exec "!stylua %"]]) vim.fn.winrestview(saved) end, { buffer = bufno }) end, settings = { Lua = { workspace = { checkThirdParty = "Disable", library = { vim.env.VIMRUNTIME }, }, }, }, }, nil_ls = { -- Nix settings = { ["nil"] = { formatting = { command = { "alejandra" } } } }, }, } ------------- -- Helpers -- ------------- -- Helix style border local border = { { " ", "FloatBorder" }, { " ", "FloatBorder" }, { " ", "FloatBorder" }, { " ", "FloatBorder" }, { " ", "FloatBorder" }, { " ", "FloatBorder" }, { " ", "FloatBorder" }, { " ", "FloatBorder" }, } local orig_util_open_floating_preview = vim.lsp.util.open_floating_preview function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...) opts = opts or {} opts.border = border return orig_util_open_floating_preview(contents, syntax, opts, ...) end -- Diagnostic display configuration vim.diagnostic.config { virtual_text = false, severity_sort = true } -- Set log level vim.lsp.set_log_level("off") -- Gutter symbols setup vim.fn.sign_define("DiagnosticSignError", { text = "E", texthl = "DiagnosticSignError", numhl = "DiagnosticSignError" }) vim.fn.sign_define("DiagnosticSignWarn", { text = "W", texthl = "DiagnosticSignWarn", numhl = "DiagnosticSignWarn" }) vim.fn.sign_define("DiagnosticSignHint", { text = "H", texthl = "DiagnosticSignHint", numhl = "DiagnosticSignHint" }) vim.fn.sign_define("DiagnosticSignInfo", { text = "ยท", texthl = "DiagnosticSignInfo", numhl = "DiagnosticSignInfo" }) -- Capabilities local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require("cmp_nvim_lsp").default_capabilities(capabilities) ---------- -- Init -- ---------- require("fidget").setup() local mylsp = require('lsp') for name, config in pairs(servers) do require("lspconfig")[name].setup { capabilities = capabilities, settings = config.settings, -- NOTE: https://github.com/neovim/neovim/issues/30675 offset_encoding = config.offset_encoding or "utf-8", on_attach = function(client, bufno) mylsp.on_attach(client, bufno); (config.on_attach or function(...) end)(client, bufno) end, } end ------------------------ -- Standalone plugins -- ------------------------ -- Java local config = { on_attach = mylsp.on_attach, capabilities = capabilities, cmd = { -- https://github.com/NixOS/nixpkgs/issues/232822#issuecomment-1564243667 -- `-data` argument is necessary "jdtls", "-data", vim.fn.expand("~/.cache/jdtls") .. vim.fn.expand("%:p:h"), }, root_dir = vim.fs.dirname(vim.fs.find({ "gradlew", ".git", "mvnw" }, { upward = true })[1]), } local jdtls_group = vim.api.nvim_create_augroup("jdtls", { clear = true }) vim.api.nvim_create_autocmd("FileType", { pattern = { "java" }, callback = function() require("jdtls").start_or_attach(config) end, group = jdtls_group, }) -- Scala local metals = require("metals") local metals_config = metals.bare_config() metals_config.capabilities = capabilities metals_config.settings.useGlobalExecutable = true require("dap").configurations.scala = { { type = "scala", request = "launch", name = "RunOrTest", metals = { runType = "runOrTestFile" }, }, { type = "scala", request = "launch", name = "Test Target", metals = { runType = "testTarget" }, }, } metals_config.on_attach = function(client, bufnr) metals.setup_dap() map("n", "ws", metals.hover_worksheet) map("n", "dc", require("dap").continue) map("n", "dr", require("dap").repl.toggle) map("n", "dK", require("dap.ui.widgets").hover) map("n", "dt", require("dap").toggle_breakpoint) map("n", "dso", require("dap").step_over) map("n", "dsi", require("dap").step_into) map("n", "dl", require("dap").run_last) mylsp.on_attach(client, bufnr) end local nvim_metals_group = vim.api.nvim_create_augroup("nvim-metals", { clear = true }) vim.api.nvim_create_autocmd("FileType", { pattern = { "scala", "sbt" }, callback = function() require("metals").initialize_or_attach(metals_config) end, group = nvim_metals_group, }) -- Haskell vim.g.haskell_tools = { tools = { log = { level = vim.log.levels.OFF }, hover = { border = border, stylize_markdown = true, }, }, hls = { on_attach = function(client, bufnr) local ht = require("haskell-tools") local opts = { buffer = bufnr } map("n", "hhe", ht.lsp.buf_eval_all, opts) map("n", "hhs", ht.hoogle.hoogle_signature, opts) map("n", "hhr", ht.repl.toggle, opts) vim.opt_local.shiftwidth = 2 mylsp.on_attach(client, bufnr) end, default_settings = { haskell = { checkProject = false, -- PERF: don't check the entire project on initial load formattingProvider = "fourmolu", plugin = { rename = { config = { diff = true, -- (experimental) rename across modules }, }, }, }, }, settings = function(project_root) local ht = require("haskell-tools") return ht.lsp.load_hls_settings(project_root, { settings_file_pattern = "hls.json" }) end, }, } ---------- -- Rust -- ---------- vim.g.rustaceanvim = { server = { on_attach = mylsp.on_attach, settings = { ["rust-analyzer"] = { files = { excludeDirs = { ".direnv/" } } }, }, }, tools = { hover = { border = border, stylize_markdown = true, }, log = { level = vim.log.levels.OFF }, }, }