diff options
-rw-r--r-- | lua/lvim/config/init.lua | 7 | ||||
-rw-r--r-- | lua/lvim/core/builtins/init.lua | 1 | ||||
-rw-r--r-- | lua/lvim/core/info.lua | 4 | ||||
-rw-r--r-- | lua/lvim/core/mason.lua | 41 | ||||
-rw-r--r-- | lua/lvim/core/which-key.lua | 2 | ||||
-rw-r--r-- | lua/lvim/lsp/config.lua | 13 | ||||
-rw-r--r-- | lua/lvim/lsp/init.lua | 5 | ||||
-rw-r--r-- | lua/lvim/lsp/manager.lua | 67 | ||||
-rw-r--r-- | lua/lvim/lsp/templates.lua | 11 | ||||
-rw-r--r-- | lua/lvim/lsp/utils.lua | 29 | ||||
-rw-r--r-- | lua/lvim/plugins.lua | 6 | ||||
-rw-r--r-- | snapshots/default.json | 9 | ||||
-rw-r--r-- | tests/minimal_lsp.lua | 59 | ||||
-rw-r--r-- | tests/specs/lsp_spec.lua | 6 |
14 files changed, 168 insertions, 92 deletions
diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index 4343ace9..c6765f56 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -99,6 +99,13 @@ local function handle_deprecated_settings() "Use vim.api.nvim_create_autocmd instead or check LunarVim#2592 to learn about the new syntax" ) end + + if lvim.lsp.automatic_servers_installation then + deprecation_notice( + "lvim.lsp.automatic_servers_installation", + "Use `lvim.lsp.installer.setup.automatic_installation` instead" + ) + end end --- Override the configuration with a user provided one diff --git a/lua/lvim/core/builtins/init.lua b/lua/lvim/core/builtins/init.lua index e219d45e..5cad2a00 100644 --- a/lua/lvim/core/builtins/init.lua +++ b/lua/lvim/core/builtins/init.lua @@ -16,6 +16,7 @@ local builtins = { "lvim.core.notify", "lvim.core.lualine", "lvim.core.alpha", + "lvim.core.mason", } function M.config(config) diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua index ac7d690a..da9ddbe6 100644 --- a/lua/lvim/core/info.lua +++ b/lua/lvim/core/info.lua @@ -111,9 +111,9 @@ local function make_auto_lsp_info(ft) return info_lines end - local available = lsp_utils.get_supported_servers_per_filetype(ft) + local supported = lsp_utils.get_supported_servers(ft) local skipped = vim.tbl_filter(function(name) - return vim.tbl_contains(available, name) + return vim.tbl_contains(supported, name) end, skipped_servers) if #skipped == 0 then diff --git a/lua/lvim/core/mason.lua b/lua/lvim/core/mason.lua new file mode 100644 index 00000000..39be4f42 --- /dev/null +++ b/lua/lvim/core/mason.lua @@ -0,0 +1,41 @@ +local M = {} + +function M.config() + lvim.builtin.mason = { + ui = { + keymaps = { + toggle_package_expand = "<CR>", + install_package = "i", + update_package = "u", + check_package_version = "c", + update_all_packages = "U", + check_outdated_packages = "C", + uninstall_package = "X", + cancel_installation = "<C-c>", + apply_language_filter = "<C-f>", + }, + }, + log_level = vim.log.levels.INFO, + max_concurrent_installers = 4, + + github = { + -- The template URL to use when downloading assets from GitHub. + -- The placeholders are the following (in order): + -- 1. The repository (e.g. "rust-lang/rust-analyzer") + -- 2. The release version (e.g. "v0.3.0") + -- 3. The asset name (e.g. "rust-analyzer-v0.3.0-x86_64-unknown-linux-gnu.tar.gz") + download_url_template = "https://github.com/%s/releases/download/%s/%s", + }, + } +end + +function M.setup() + local status_ok, mason = pcall(require, "mason") + if not status_ok then + return + end + + mason.setup(lvim.builtin.mason) +end + +return M diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index 8f0f964f..6d0dc9fc 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -160,7 +160,7 @@ M.config = function() w = { "<cmd>Telescope diagnostics<cr>", "Diagnostics" }, f = { require("lvim.lsp.utils").format, "Format" }, i = { "<cmd>LspInfo<cr>", "Info" }, - I = { "<cmd>LspInstallInfo<cr>", "Installer Info" }, + I = { "<cmd>Mason<cr>", "Mason Info" }, j = { vim.diagnostic.goto_next, "Next Diagnostic", diff --git a/lua/lvim/lsp/config.lua b/lua/lvim/lsp/config.lua index e3cd503b..41290787 100644 --- a/lua/lvim/lsp/config.lua +++ b/lua/lvim/lsp/config.lua @@ -88,7 +88,6 @@ return { }, on_attach_callback = nil, on_init_callback = nil, - automatic_servers_installation = true, automatic_configuration = { ---@usage list of servers that the automatic installer will skip skipped_servers = skipped_servers, @@ -131,12 +130,8 @@ return { installer = { setup = { ensure_installed = {}, - ui = { - icons = { - server_installed = "✓", - server_pending = "", - server_uninstalled = "✗", - }, + automatic_installation = { + exclude = {}, }, }, }, @@ -153,6 +148,8 @@ return { setup = {}, config = {}, }, - ---@deprecated use automatic_configuration.skipped_servers instead + ---@deprecated use lvim.lsp.automatic_configuration.skipped_servers instead override = {}, + ---@deprecated use lvim.lsp.installer.setup.automatic_installation instead + automatic_servers_installation = nil, } diff --git a/lua/lvim/lsp/init.lua b/lua/lvim/lsp/init.lua index 53b4f248..0b361972 100644 --- a/lua/lvim/lsp/init.lua +++ b/lua/lvim/lsp/init.lua @@ -110,7 +110,10 @@ function M.setup() end) pcall(function() - require("nvim-lsp-installer").setup(lvim.lsp.installer.setup) + require("mason-lspconfig").setup(lvim.lsp.installer.setup) + local util = require "lspconfig.util" + -- automatic_installation is handled by lsp-manager + util.on_setup = nil end) require("lvim.lsp.null-ls").setup() diff --git a/lua/lvim/lsp/manager.lua b/lua/lvim/lsp/manager.lua index 00643815..aa76af6c 100644 --- a/lua/lvim/lsp/manager.lua +++ b/lua/lvim/lsp/manager.lua @@ -1,7 +1,30 @@ local M = {} local Log = require "lvim.core.log" +local fmt = string.format local lvim_lsp_utils = require "lvim.lsp.utils" +local is_windows = vim.loop.os_uname().version:match "Windows" + +local function resolve_mason_config(server_name) + local found, mason_config = pcall(require, "mason-lspconfig.server_configurations." .. server_name) + if not found then + Log:debug(fmt("mason configuration not found for %s", server_name)) + return {} + end + local server_mapping = require "mason-lspconfig.mappings.server" + local path = require "mason-core.path" + local pkg_name = server_mapping.lspconfig_to_package[server_name] + local install_dir = path.package_prefix(pkg_name) + local conf = mason_config(install_dir) + if is_windows and conf.cmd and conf.cmd[1] then + local exepath = vim.fn.exepath(conf.cmd[1]) + if exepath ~= "" then + conf.cmd[1] = exepath + end + end + Log:debug(fmt("resolved mason configuration for %s, got %s", server_name, vim.inspect(mason_config))) + return mason_config or {} +end ---Resolve the configuration for a server by merging with the default config ---@param server_name string @@ -65,35 +88,45 @@ function M.setup(server_name, user_config) return end - local servers = require "nvim-lsp-installer.servers" - local server_available, server = servers.get_server(server_name) + local server_mapping = require "mason-lspconfig.mappings.server" + local registry = require "mason-registry" - if not server_available then + local pkg_name = server_mapping.lspconfig_to_package[server_name] + if not pkg_name then local config = resolve_config(server_name, user_config) launch_server(server_name, config) return end - local install_in_progress = false + local should_auto_install = function() + local installer_settings = lvim.lsp.installer.setup + return installer_settings.automatic_installation + and not vim.tbl_contains(installer_settings.automatic_installation.exclude, server_name) + end - if not server:is_installed() then - if lvim.lsp.automatic_servers_installation then + if not registry.is_installed(pkg_name) then + if should_auto_install(server_name) then Log:debug "Automatic server installation detected" - server:install() - install_in_progress = true + vim.notify_once(string.format("Installation in progoress for [%s] server", server_name), vim.log.levels.INFO) + local pkg = registry.get_package(pkg_name) + pkg:install():once("closed", function() + if pkg:is_installed() then + vim.schedule(function() + vim.notify_once(string.format("Installation complete for [%s] server", server_name), vim.log.levels.INFO) + -- mason config is only available once the server has been installed + local config = resolve_config(server_name, resolve_mason_config(server_name), user_config) + launch_server(server_name, config) + end) + end + end) + return else - Log:debug(server.name .. " is not managed by the automatic installer") + Log:debug(server_name .. " is not managed by the automatic installer") end end - server:on_ready(function() - if install_in_progress then - vim.notify(string.format("Installation complete for [%s] server", server.name), vim.log.levels.INFO) - end - install_in_progress = false - local config = resolve_config(server_name, server:get_default_options(), user_config) - launch_server(server_name, config) - end) + local config = resolve_config(server_name, resolve_mason_config(server_name), user_config) + launch_server(server_name, config) end return M diff --git a/lua/lvim/lsp/templates.lua b/lua/lvim/lsp/templates.lua index 578362a7..dc2e5b11 100644 --- a/lua/lvim/lsp/templates.lua +++ b/lua/lvim/lsp/templates.lua @@ -56,21 +56,12 @@ end ---The files are generated to a runtimepath: "$LUNARVIM_RUNTIME_DIR/site/after/ftplugin/template.lua" ---@param servers_names? table list of servers to be enabled. Will add all by default function M.generate_templates(servers_names) - servers_names = servers_names or {} + servers_names = servers_names or lvim_lsp_utils.get_supported_servers() Log:debug "Templates installation in progress" M.remove_template_files() - if vim.tbl_isempty(servers_names) then - local available_servers = require("nvim-lsp-installer.servers").get_available_servers() - - for _, server in pairs(available_servers) do - table.insert(servers_names, server.name) - table.sort(servers_names) - end - end - -- create the directory if it didn't exist if not utils.is_directory(lvim.lsp.templates_dir) then vim.fn.mkdir(ftplugin_dir, "p") diff --git a/lua/lvim/lsp/utils.lua b/lua/lvim/lsp/utils.lua index fa1ac6d9..b92ef11c 100644 --- a/lua/lvim/lsp/utils.lua +++ b/lua/lvim/lsp/utils.lua @@ -51,37 +51,34 @@ end ---Get supported filetypes per server ---@param server_name string can be any server supported by nvim-lsp-installer ----@return table supported filestypes as a list of strings +---@return string[] supported filestypes as a list of strings function M.get_supported_filetypes(server_name) - local status_ok, lsp_installer_servers = pcall(require, "nvim-lsp-installer.servers") + local status_ok, config = pcall(require, ("lspconfig.server_configurations.%s"):format(server_name)) if not status_ok then return {} end - local server_available, requested_server = lsp_installer_servers.get_server(server_name) - if not server_available then - return {} - end - - return requested_server:get_supported_filetypes() + return config.default_config.filetypes or {} end ---Get supported servers per filetype ----@param filetype string ----@return table list of names of supported servers -function M.get_supported_servers_per_filetype(filetype) - local filetype_server_map = require "nvim-lsp-installer._generated.filetype_map" - return filetype_server_map[filetype] +---@param filter { filetype: string | string[] }?: (optional) Used to filter the list of server names. +---@return string[] list of names of supported servers +function M.get_supported_servers(filter) + local _, supported_servers = pcall(function() + return require("mason-lspconfig").get_available_servers(filter) + end) + return supported_servers or {} end ---Get all supported filetypes by nvim-lsp-installer ----@return table supported filestypes as a list of strings +---@return string[] supported filestypes as a list of strings function M.get_all_supported_filetypes() - local status_ok, lsp_installer_filetypes = pcall(require, "nvim-lsp-installer._generated.filetype_map") + local status_ok, filetype_server_map = pcall(require, "mason-lspconfig.mappings.filetype") if not status_ok then return {} end - return vim.tbl_keys(lsp_installer_filetypes or {}) + return vim.tbl_keys(filetype_server_map or {}) end function M.setup_document_highlight(client, bufnr) diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index fec91bc9..24f71204 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -7,8 +7,12 @@ local core_plugins = { "jose-elias-alvarez/null-ls.nvim", }, { "antoinemadec/FixCursorHold.nvim" }, -- Needed while issue https://github.com/neovim/neovim/issues/12587 is still open + { "williamboman/mason-lspconfig.nvim" }, { - "williamboman/nvim-lsp-installer", + "williamboman/mason.nvim", + config = function() + require("lvim.core.mason").setup() + end, }, { "lunarvim/onedarker.nvim", diff --git a/snapshots/default.json b/snapshots/default.json index 564e26b3..9bb8e9e7 100644 --- a/snapshots/default.json +++ b/snapshots/default.json @@ -41,6 +41,12 @@ "lualine.nvim": { "commit": "8d956c1" }, + "mason-lspconfig.nvim": { + "commit": "e48a41e" + }, + "mason.nvim": { + "commit": "6fa15d7" + }, "nlsp-settings.nvim": { "commit": "6c4e1a4" }, @@ -56,9 +62,6 @@ "nvim-dap": { "commit": "c0f43f4" }, - "nvim-lsp-installer": { - "commit": "45571e1" - }, "nvim-lspconfig": { "commit": "3479473" }, diff --git a/tests/minimal_lsp.lua b/tests/minimal_lsp.lua index a610fd7f..09224f94 100644 --- a/tests/minimal_lsp.lua +++ b/tests/minimal_lsp.lua @@ -16,7 +16,7 @@ local package_root = join_paths(temp_dir, "nvim", "site", "pack") local install_path = join_paths(package_root, "packer", "start", "packer.nvim") local compile_path = join_paths(install_path, "plugin", "packer_compiled.lua") --- Choose whether to use the executable that's managed by lsp-installer +-- Choose whether to use the executable that's managed by mason local use_lsp_installer = true local function load_plugins() @@ -24,7 +24,8 @@ local function load_plugins() { "wbthomason/packer.nvim", "neovim/nvim-lspconfig", - { "williamboman/nvim-lsp-installer", disable = not use_lsp_installer }, + "williamboman/mason-lspconfig.nvim", + "williamboman/mason.nvim", }, config = { package_root = package_root, @@ -44,9 +45,6 @@ _G.load_config = function() require("vim.lsp.log").set_format_func(vim.inspect) local nvim_lsp = require "lspconfig" local on_attach = function(_, bufnr) - local function buf_set_keymap(...) - vim.api.nvim_buf_set_keymap(bufnr, ...) - end local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end @@ -54,24 +52,26 @@ _G.load_config = function() buf_set_option("omnifunc", "v:lua.vim.lsp.omnifunc") -- Mappings. - local opts = { noremap = true, silent = true } - buf_set_keymap("n", "gD", "<Cmd>lua vim.lsp.buf.declaration()<CR>", opts) - buf_set_keymap("n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>", opts) - buf_set_keymap("n", "K", "<Cmd>lua vim.lsp.buf.hover()<CR>", opts) - buf_set_keymap("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", opts) - buf_set_keymap("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>", opts) - buf_set_keymap("n", "<space>wa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>", opts) - buf_set_keymap("n", "<space>wr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>", opts) - buf_set_keymap("n", "<space>wl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>", opts) - buf_set_keymap("n", "<space>lD", "<cmd>lua vim.lsp.buf.type_definition()<CR>", opts) - buf_set_keymap("n", "<space>lr", "<cmd>lua vim.lsp.buf.rename()<CR>", opts) - buf_set_keymap("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", opts) - buf_set_keymap("n", "gl", "<cmd>lua vim.diagnostic.open_float(0,{scope='line'})<CR>", opts) - buf_set_keymap("n", "<space>lk", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opts) - buf_set_keymap("n", "<space>lj", "<cmd>lua vim.diagnostic.goto_next()<CR>", opts) - buf_set_keymap("n", "<space>lq", "<cmd>lua vim.diagnostic.setloclist()<CR>", opts) - buf_set_keymap("n", "<space>li", "<cmd>LspInfo<CR>", opts) - buf_set_keymap("n", "<space>lI", "<cmd>LspInstallInfo<CR>", opts) + local opts = { buffer = bufnr, noremap = true, silent = true } + vim.keymap.set("n", "gD", vim.lsp.buf.declaration, opts) + vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) + vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) + vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts) + vim.keymap.set("n", "<C-k>", vim.lsp.buf.signature_help, opts) + vim.keymap.set("n", "<space>wa", vim.lsp.buf.add_workspace_folder, opts) + vim.keymap.set("n", "<space>wr", vim.lsp.buf.remove_workspace_folder, opts) + vim.keymap.set("n", "<space>wl", function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, opts) + vim.keymap.set("n", "<space>lD", vim.lsp.buf.type_definition, opts) + vim.keymap.set("n", "<space>lr", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "gr", vim.lsp.buf.references, opts) + vim.keymap.set("n", "gl", vim.diagnostic.open_float, opts) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) + vim.keymap.set("n", "<space>q", vim.diagnostic.setloclist, opts) + vim.keymap.set("n", "<space>li", "<cmd>LspInfo<CR>", opts) + vim.keymap.set("n", "<space>lI", "<cmd>MasonCR>", opts) end -- Add the server that troubles you here, e.g. "clangd", "pyright", "tsserver" @@ -81,15 +81,6 @@ _G.load_config = function() on_attach = on_attach, } - if use_lsp_installer then - local server_available, server = require("nvim-lsp-installer.servers").get_server(name) - if not server_available then - server:install() - end - local default_opts = server:get_default_options() - setup_opts = vim.tbl_deep_extend("force", setup_opts, default_opts) - end - if not name then print "You have not defined a server name, please edit minimal_init.lua" end @@ -99,6 +90,10 @@ _G.load_config = function() end nvim_lsp[name].setup(setup_opts) + if use_lsp_installer then + require("mason-lspconfig").setup { automatic_installation = true } + end + print [[You can find your log at $HOME/.cache/nvim/lsp.log. Please paste in a github issue under a details tag as described in the issue template.]] end diff --git a/tests/specs/lsp_spec.lua b/tests/specs/lsp_spec.lua index 7d9a3386..01e5e1d3 100644 --- a/tests/specs/lsp_spec.lua +++ b/tests/specs/lsp_spec.lua @@ -53,10 +53,14 @@ a.describe("lsp workflow", function() a.it("should only include one server per generated template", function() require("lvim.lsp").setup() + local allowed_dupes = { "tailwindcss" } for _, file in ipairs(vim.fn.glob(lvim.lsp.templates_dir .. "/*.lua", 1, 1)) do local content = {} for entry in io.lines(file) do - table.insert(content, entry) + local server_name = entry:match [[.*setup%("(.*)"%)]] + if not vim.tbl_contains(allowed_dupes, server_name) then + table.insert(content, server_name) + end end local err_msg = "" if #content > 1 then |