diff --git a/nvim/.config/nvim/after/ftplugin/c.lua b/nvim/.config/nvim/after/ftplugin/c.lua index b6c651d..427c9c5 100644 --- a/nvim/.config/nvim/after/ftplugin/c.lua +++ b/nvim/.config/nvim/after/ftplugin/c.lua @@ -1,8 +1,3 @@ -local lsp_utils = require('lsp-utils') -local clangd_config = lsp_utils.clangd_config() - -vim.lsp.start(clangd_config) - vim.bo.makeprg = 'meson compile -C build' vim.keymap.set('n', 'gh', ":ClangdSwitchSourceHeader", { noremap=true, buffer=0 }) diff --git a/nvim/.config/nvim/after/ftplugin/elixir.lua b/nvim/.config/nvim/after/ftplugin/elixir.lua deleted file mode 100644 index a450c02..0000000 --- a/nvim/.config/nvim/after/ftplugin/elixir.lua +++ /dev/null @@ -1,4 +0,0 @@ -local lsp_utils = require('lsp-utils') -local elixir_config = lsp_utils.elixir_config() - -vim.lsp.start(elixir_config) diff --git a/nvim/.config/nvim/after/ftplugin/gleam.lua b/nvim/.config/nvim/after/ftplugin/gleam.lua deleted file mode 100644 index f48fc6b..0000000 --- a/nvim/.config/nvim/after/ftplugin/gleam.lua +++ /dev/null @@ -1,4 +0,0 @@ -local lsp_utils = require('lsp-utils') -local gleam_config = lsp_utils.gleam_config() - -vim.lsp.start(gleam_config) diff --git a/nvim/.config/nvim/after/ftplugin/go.lua b/nvim/.config/nvim/after/ftplugin/go.lua deleted file mode 100644 index b1999b3..0000000 --- a/nvim/.config/nvim/after/ftplugin/go.lua +++ /dev/null @@ -1,4 +0,0 @@ -local lsp_utils = require('lsp-utils') -local gopls_config = lsp_utils.gopls_config() - -vim.lsp.start(gopls_config) diff --git a/nvim/.config/nvim/after/ftplugin/haskell.lua b/nvim/.config/nvim/after/ftplugin/haskell.lua index 75487e9..ef2b13c 100644 --- a/nvim/.config/nvim/after/ftplugin/haskell.lua +++ b/nvim/.config/nvim/after/ftplugin/haskell.lua @@ -1,8 +1,3 @@ -local lsp_utils = require('lsp-utils') -local hls_config = lsp_utils.hls_config() - -vim.lsp.start(hls_config) - vim.bo.makeprg = 'cabal build --write-ghc-environment-files=always all' vim.api.nvim_create_autocmd({ "BufWritePost" }, { diff --git a/nvim/.config/nvim/after/ftplugin/javascript.lua b/nvim/.config/nvim/after/ftplugin/javascript.lua deleted file mode 100644 index 34850a1..0000000 --- a/nvim/.config/nvim/after/ftplugin/javascript.lua +++ /dev/null @@ -1,13 +0,0 @@ -local lsp_utils = require('lsp-utils') -local tsserver_config = lsp_utils.tsserver_config() - -vim.lsp.start(tsserver_config) - -vim.keymap.set('n', 'gq', "!npx prettier --write %:p:e", { noremap=true, silent=true, buffer=0 }) - -vim.api.nvim_create_autocmd({ "BufReadPre", "BufWinEnter" }, { - pattern = { "*/node_modules/*" }, - callback = function() - vim.bo.buflisted = false - end, -}) diff --git a/nvim/.config/nvim/after/ftplugin/lean.lua b/nvim/.config/nvim/after/ftplugin/lean.lua deleted file mode 100644 index 5e8994c..0000000 --- a/nvim/.config/nvim/after/ftplugin/lean.lua +++ /dev/null @@ -1,4 +0,0 @@ -local lsp_utils = require('lsp-utils') -local leanls_config = lsp_utils.leanls_config() - -vim.lsp.start(leanls_config) diff --git a/nvim/.config/nvim/after/ftplugin/purescript.lua b/nvim/.config/nvim/after/ftplugin/purescript.lua index a7ad853..e2a219f 100644 --- a/nvim/.config/nvim/after/ftplugin/purescript.lua +++ b/nvim/.config/nvim/after/ftplugin/purescript.lua @@ -1,11 +1,6 @@ vim.bo.textwidth = 0 vim.bo.wrapmargin = 0 -local lsp_utils = require('lsp-utils') -local puresls_config = lsp_utils.pursls_config() - -vim.lsp.start(puresls_config) - vim.api.nvim_create_autocmd({ "BufReadPre", "BufWinEnter" }, { pattern = { "*.spago/*" }, callback = function() diff --git a/nvim/.config/nvim/after/ftplugin/python.lua b/nvim/.config/nvim/after/ftplugin/python.lua index 3c294b7..b962e95 100644 --- a/nvim/.config/nvim/after/ftplugin/python.lua +++ b/nvim/.config/nvim/after/ftplugin/python.lua @@ -1,8 +1,3 @@ -local lsp_utils = require('lsp-utils') -local ruff_config = lsp_utils.ruff_config() - -vim.lsp.start(ruff_config) - vim.bo.textwidth = 0 vim.api.nvim_create_autocmd({ "BufWritePost" }, { diff --git a/nvim/.config/nvim/after/ftplugin/racket.lua b/nvim/.config/nvim/after/ftplugin/racket.lua deleted file mode 100644 index d4e13ea..0000000 --- a/nvim/.config/nvim/after/ftplugin/racket.lua +++ /dev/null @@ -1,4 +0,0 @@ -local lsp_utils = require('lsp-utils') -local scheme_config = lsp_utils.scheme_config() - -vim.lsp.start(scheme_config) diff --git a/nvim/.config/nvim/after/ftplugin/rust.lua b/nvim/.config/nvim/after/ftplugin/rust.lua index 68b2c89..ef89a4e 100644 --- a/nvim/.config/nvim/after/ftplugin/rust.lua +++ b/nvim/.config/nvim/after/ftplugin/rust.lua @@ -1,8 +1,3 @@ -local lsp_utils = require('lsp-utils') -local ra_config = lsp_utils.ra_config() - -vim.lsp.start(ra_config) - vim.cmd.compiler('cargo') vim.bo.makeprg = 'cargo build --workspace' diff --git a/nvim/.config/nvim/after/ftplugin/typescript.lua b/nvim/.config/nvim/after/ftplugin/typescript.lua deleted file mode 100644 index 24f80cd..0000000 --- a/nvim/.config/nvim/after/ftplugin/typescript.lua +++ /dev/null @@ -1,13 +0,0 @@ -local lsp_utils = require('lsp-utils') -local typescript_config = lsp_utils.typescript_config() - -vim.lsp.start(typescript_config) - -vim.keymap.set('n', 'gq', "!npx prettier --write %:p:e", { noremap=true, silent=true, buffer=0 }) - -vim.api.nvim_create_autocmd({ "BufReadPre", "BufWinEnter" }, { - pattern = { "*/node_modules/*" }, - callback = function() - vim.bo.buflisted = false - end, -}) diff --git a/nvim/.config/nvim/after/ftplugin/zig.lua b/nvim/.config/nvim/after/ftplugin/zig.lua index 05a84a6..b495e49 100644 --- a/nvim/.config/nvim/after/ftplugin/zig.lua +++ b/nvim/.config/nvim/after/ftplugin/zig.lua @@ -1,8 +1,3 @@ -local lsp_utils = require('lsp-utils') -local zls_config = lsp_utils.zls_config() - -vim.lsp.start(zls_config) - vim.cmd.compiler('zig_build') vim.api.nvim_create_autocmd({ "BufReadPre", "BufWinEnter" }, { diff --git a/nvim/.config/nvim/lua/lsp-configs.lua b/nvim/.config/nvim/lua/lsp-configs.lua new file mode 100644 index 0000000..efa6264 --- /dev/null +++ b/nvim/.config/nvim/lua/lsp-configs.lua @@ -0,0 +1,74 @@ +return { + ["clangd"] = { + cmd = { 'clangd', '--background-index', '--pch-storage=memory', '--clang-tidy', '--header-insertion=never' }, + filetypes = { 'c', 'cpp' }, + root_markers = { '.clangd', '.clang-tidy', '.clang-format', 'compile_commands.json', 'compile_flags.txt' }, + }, + ["elixirls"] = { + cmd = { 'elixir-ls' }, + filetypes = { 'elixir', 'eelixir', 'heex', 'surface' }, + root_markers = { 'mix.exs' }, + }, + ["gleam"] = { + cmd = { 'gleam', 'lsp' }, + filetypes = { 'gleam' }, + root_markers = { 'gleam.toml' }, + }, + ["gopls"] = { + cmd = { 'gopls' }, + filetypes = { 'go', 'gomod', 'gowork', 'gotmpl' }, + root_markers = { 'go.mod', 'go.work' }, + }, + ["leanls"] = { + cmd = { 'lake', 'serve', '--' }, + filetypes = { 'lean' }, + root_markers = { 'lakefile.lean', 'lean-toolchain', 'leanpkg.toml' }, + }, + ["purescriptls"] = { + cmd = { 'purescript-language-server', '--stdio' }, + filetypes = { 'purescript' }, + root_markers = { 'bower.json', 'psc-package.json', 'spago.dhall' }, + settings = { + purescript = { + formatter = 'purs-tidy', + } + }, + }, + ["rust_analyzer"] = { + cmd = { 'rust-analyzer' }, + filetypes = { 'rust' }, + root_markers = { "Cargo.toml" }, + settings = { + ["rust-analyzer"] = { + checkOnSave = { + command = 'clippy' + }, + diagnostics = { + -- https://rust-analyzer.github.io/manual.html#diagnostics + disabled = { + 'macro-def-error', + 'macro-error' + }, + }, + procMacro = { + enable = false + }, + }, + }, + }, + ["ruff"] = { + cmd = { 'ruff', 'server' }, + filetypes = { 'python' }, + root_markers = { 'pyproject.toml', 'ruff.toml', '.ruff.toml' }, + }, + ["staticls"] = { + cmd = { 'static-ls' }, + filetypes = { 'haskell' }, + root_markers = { '.hiedb', '.hiefiles' }, + }, + ["zls"] = { + cmd = { 'zls' }, + filetypes = { 'zig', 'zir' }, + root_markers = { 'zls.json', 'build.zig' }, + } +} diff --git a/nvim/.config/nvim/lua/lsp-utils.lua b/nvim/.config/nvim/lua/lsp-utils.lua deleted file mode 100644 index 590c0fb..0000000 --- a/nvim/.config/nvim/lua/lsp-utils.lua +++ /dev/null @@ -1,332 +0,0 @@ -local M = {} - --- All configuration is taken from nvim-lspconfig except for may be minor changes --- --- Deno specific functions -local buf_cache = function(bufnr, client) - local params = { - command = 'deno.cache', - arguments = { {}, vim.uri_from_bufnr(bufnr) }, - } - client.request('workspace/executeCommand', params, function(err, _result, ctx) - if err then - local uri = ctx.params.arguments[2] - vim.api.nvim_err_writeln('Cache command failed for ' .. vim.uri_to_fname(uri)) - end - end, bufnr) - -end - -local virtual_text_document_handler = function(uri, res, client) - if not res then - return nil - end - - local lines = vim.split(res.result, '\n') - local bufnr = vim.uri_to_bufnr(uri) - - local current_buf = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) - if #current_buf ~= 0 then - return nil - end - - vim.api.nvim_buf_set_lines(bufnr, 0, -1, nil, lines) - - vim.api.nvim_set_option_value('readonly' , true, { buf = bufnr }) - vim.api.nvim_set_option_value('modified' , false, { buf = bufnr }) - vim.api.nvim_set_option_value('modifiable', false, { buf = bufnr }) - - vim.lsp.buf_attach_client(bufnr, client.id) -end - -local virtual_text_document = function(uri, client) - local params = { - textDocument = { - uri = uri, - }, - } - local result = client.request_sync('deno/virtualTextDocument', params) - - virtual_text_document_handler(uri, result, client) -end - -local denols_handler = function(err, result, ctx) - if not result or vim.tbl_isempty(result) then - return nil - end - - local client = vim.lsp.get_client_by_id(ctx.client_id) - - for _, res in pairs(result) do - local uri = res.uri or res.targetUri - - if uri:match '^deno:' then - virtual_text_document(uri, client) - res['uri'] = uri - res['targetUri'] = uri - end - end - - vim.lsp.handlers[ctx.method](err, result, ctx) -end --- End of deno specific functions - -local get_root_directory = function(root_files) - return vim.fs.root(0, root_files) -end - -local default_capabilities = vim.lsp.protocol.make_client_capabilities() - -function M.clangd_config() - local root_files = { '.clangd', '.clang-tidy', '.clang-format', 'compile_commands.json', 'compile_flags.txt' } - local clangd_cmd = { "clangd", "--background-index", "--pch-storage=memory", "--clang-tidy", "--header-insertion=never" } - local root_directory = get_root_directory(root_files) - local clangd_caps = { - textDocument = { completion = { editsNearCursor = true } }, - offsetEncoding = { 'utf-8', 'utf-16' }, - } - - return { - name = "clangd", - cmd = clangd_cmd, - capabilities = clangd_caps, - root_dir = root_directory, - filetypes = { 'c', 'cpp' }, - single_file_support = false, - } -end - - -function M.deno_config() - local root_files = { 'deno.json', 'deno.jsonc' } - local file_types = { 'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx' } - local root_directory = get_root_directory(root_files) - - return { - cmd = { 'deno', 'lsp' }, - capabilities = default_capabilities, - filetypes = file_types, - root_dir = root_directory, - settings = { - deno = { - enable = true, - suggest = { - imports = { - hosts = { - ['https://deno.land'] = true, - }, - }, - }, - }, - }, - handlers = { - ['textDocument/definition'] = denols_handler, - ['textDocument/typeDefinition'] = denols_handler, - ['textDocument/references'] = denols_handler, - }, - commands = { - DenolsCache = { - function() - local clients = vim.lsp.get_clients({ bufnr = 0, name = 'denols' }) - if #clients > 0 then - buf_cache(0, clients[#clients]) - end - end, - description = 'Cache a module and all of its dependencies.', - }, - } - } -end - -function M.elixir_config() - local root_files = { 'mix.exs' } - local root_directory = get_root_directory(root_files) - - return { - name = "elixirls", - cmd = { "elixir-ls" }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = { 'elixir', 'eelixir', 'heex', 'surface' }, - single_file_support = true, - } -end - -function M.gleam_config() - local root_files = { 'gleam.toml' } - local root_directory = get_root_directory(root_files) - - return { - name = "gleam", - cmd = { 'gleam', 'lsp' }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = { 'gleam' }, - } -end - -function M.gopls_config() - local root_files = { 'go.mod', 'go.work', '.git' } - local root_directory = get_root_directory(root_files) - - return { - name = "gopls", - cmd = { "gopls" }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = { 'go', 'gomod', 'gowork', 'gotmpl' }, - } -end - -function M.hls_config() - local root_files = { '*.cabal', 'cabal.project', 'hie.yaml', 'package.yaml', 'stack.yaml' } - local root_directory = get_root_directory(root_files) - - return { - name = "static-ls", - cmd = { 'static-ls' }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = { 'haskell' }, - } -end - -function M.leanls_config() - local root_files = { 'lakefile.lean', 'lean-toolchain', 'leanpkg.toml' } - local root_directory = get_root_directory(root_files) - - return { - name = "leanls", - cmd = { 'lake', 'serve', '--' }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = { 'lean' }, - single_file_support = true, - } -end - -function M.pursls_config() - local root_files = { 'bower.json', 'psc-package.json', 'spago.dhall' } - local root_directory = get_root_directory(root_files) - - return { - name = "purescriptls", - cmd = { 'purescript-language-server', '--stdio' }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = { 'purescript' }, - single_file_support = false, - settings = { - purescript = { - formatter = 'purs-tidy', - } - }, - } -end - -function M.ra_config() - local root_files = { "Cargo.toml" } - local root_directory = get_root_directory(root_files) - local ra_caps = vim.lsp.protocol.make_client_capabilities() - - ra_caps.experimental = { - serverStatusNotification = true, - } - - return { - name = "rust-analyzer", - cmd = { "rust-analyzer" }, - capabilities = ra_caps, - root_dir = root_directory, - settings = { - ["rust-analyzer"] = { - checkOnSave = { - command = "clippy" - }, - diagnostics = { - -- https://rust-analyzer.github.io/manual.html#diagnostics - disabled = { - "macro-def-error", - "macro-error" - }, - }, - procMacro = { - enable = false - }, - }, - }, - } -end - -function M.ruff_config() - local root_files = { 'pyproject.toml', 'ruff.toml', '.ruff.toml' } - local root_directory = get_root_directory(root_files) - - return { - name = "ruff", - cmd = { 'ruff', 'server' }, - filetypes = { 'python' }, - capabilities = default_capabilities, - root_dir = root_directory, - single_file_support = true, - } -end - -function M.scheme_config() - local root_files = { '.git' } - local root_directory = get_root_directory(root_files) - - return { - name = "racket-langserver", - cmd = { 'racket', '--lib', 'racket-langserver' }, - capabilities = default_capabilities, - filetypes = { 'scheme', 'racket' }, - root_dir = root_directory, - single_file_support = true, - } -end - -function M.tsserver_config() - local root_files = { 'jsconfig.json', 'tsconfig.json', 'package.json' } - local file_types = { 'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx' } - local root_directory = get_root_directory(root_files) - - return { - name = "ts_ls", - cmd = { "typescript-language-server", "--stdio" }, - init_options = { hostInfo = 'neovim' }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = file_types - } -end - -function M.typescript_config() - local root_files = { 'jsconfig.json', 'tsconfig.json', 'package.json' } - local root_dir = get_root_directory(root_files) - - -- Look for npm based typescript files first and if found return tsserver - -- configuration, else return deno configuration. This allows us to work - -- with both npm and deno based typescript projects. - if root_dir then - return M.tsserver_config() - else - return M.deno_config() - end -end - -function M.zls_config() - local root_files = { 'zls.json', 'build.zig' } - local root_directory = get_root_directory(root_files) - - return { - name = "zls", - cmd = { "zls" }, - capabilities = default_capabilities, - root_dir = root_directory, - filetypes = { 'zig', 'zir' }, - single_file_support = true, - } -end - -return M diff --git a/nvim/.config/nvim/lua/lsp.lua b/nvim/.config/nvim/lua/lsp.lua index ed824b0..3b5f794 100644 --- a/nvim/.config/nvim/lua/lsp.lua +++ b/nvim/.config/nvim/lua/lsp.lua @@ -1,5 +1,6 @@ -local protocol = require 'vim.lsp.protocol' -local lsp_util = vim.lsp.util +local lsp_configs = require 'lsp-configs' +local lsp_util = vim.lsp.util +local protocol = require 'vim.lsp.protocol' vim.lsp.set_log_level("OFF") @@ -161,12 +162,6 @@ local client_custom_setup = function(client, bufnr) if client.name == 'rust-analyzer' then vim.api.nvim_buf_create_user_command(bufnr, "CargoReload", cargo_reload_workspace, {desc = 'Reload current cargo workspace'}) end - - if client.name == 'tsserver' then - -- Disable tsserver formatting, we want formatting via prettier - client.server_capabilities.documentFormattingProvider = false - client.server_capabilities.documentRangeFormattingProvider = false - end end local client_custom_cleanup = function(client, bufnr) @@ -309,3 +304,8 @@ vim.api.nvim_create_autocmd("LspProgress", { group = lsp_augroup_id, command = "redrawstatus" }) + +for lsp, config in pairs(lsp_configs) do + vim.lsp.config[lsp] = config + vim.lsp.enable(lsp) +end