diff options
| author | William Boman <william@redwill.se> | 2021-10-26 09:47:20 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-26 09:47:20 +0200 |
| commit | c7ef12d8f99490c984ec171c7341577513b435a8 (patch) | |
| tree | aea6fa17846dbc45c832fa28da1025ef03861d31 /lua/nvim-lsp-installer.lua | |
| parent | mac's not fun (diff) | |
| download | mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.gz mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.bz2 mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.lz mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.xz mason-c7ef12d8f99490c984ec171c7341577513b435a8.tar.zst mason-c7ef12d8f99490c984ec171c7341577513b435a8.zip | |
add synchronous variants of commands for better headless interop (#189)
Diffstat (limited to 'lua/nvim-lsp-installer.lua')
| -rw-r--r-- | lua/nvim-lsp-installer.lua | 140 |
1 files changed, 115 insertions, 25 deletions
diff --git a/lua/nvim-lsp-installer.lua b/lua/nvim-lsp-installer.lua index 6b2f4a06..5253e654 100644 --- a/lua/nvim-lsp-installer.lua +++ b/lua/nvim-lsp-installer.lua @@ -6,6 +6,7 @@ local status_win = require "nvim-lsp-installer.ui.status-win" local servers = require "nvim-lsp-installer.servers" local settings = require "nvim-lsp-installer.settings" local log = require "nvim-lsp-installer.log" +local platform = require "nvim-lsp-installer.platform" local M = {} @@ -16,11 +17,93 @@ function M.display() status_win().open() end +---Raises an error with the provided message. If in a headless environment, +---will also schedule an immediate shutdown with the provided exit code. +---@param msg string +---@param code number @The exit code to use when in headless mode. +local function raise_error(msg, code) + if platform.is_headless then + vim.schedule(function() + -- We schedule the exit to make sure the call stack is exhausted + os.exit(code or 1) + end) + end + error(msg) +end + +---Installs the provided servers synchronously (blocking call). It's recommended to only use this in headless environments. +---@param server_identifiers string[] @A list of server identifiers (for example {"rust_analyzer@nightly", "tsserver"}). +function M.install_sync(server_identifiers) + local completed_servers = {} + local failed_servers = {} + local server_tuples = {} + + -- Collect all servers and exit early if unable to find one. + for _, server_identifier in pairs(server_identifiers) do + local server_name, version = servers.parse_server_identifier(server_identifier) + local ok, server = servers.get_server(server_name) + if not ok then + raise_error(("Could not find server %q."):format(server_name)) + end + table.insert(server_tuples, { server, version }) + end + + -- Start all installations. + for _, server_tuple in ipairs(server_tuples) do + local server, version = unpack(server_tuple) + + server:install_attached({ + stdio_sink = process.simple_sink(), + requested_server_version = version, + }, function(success) + table.insert(completed_servers, server) + if not success then + table.insert(failed_servers, server) + end + end) + end + + -- Poll for completion. + if vim.wait(60000 * 15, function() + return #completed_servers >= #server_identifiers + end, 100) then + if #failed_servers > 0 then + for _, server in pairs(failed_servers) do + log.fmt_error("Server %s failed to install.", server.name) + end + raise_error(("%d/%d servers failed to install."):format(#failed_servers, #completed_servers)) + end + + for _, server in pairs(completed_servers) do + log.fmt_info("Server %s was successfully installed.", server.name) + end + end +end + +---Unnstalls the provided servers synchronously (blocking call). It's recommended to only use this in headless environments. +---@param server_identifiers string[] @A list of server identifiers (for example {"rust_analyzer@nightly", "tsserver"}). +function M.uninstall_sync(server_identifiers) + for _, server_identifier in pairs(server_identifiers) do + local server_name = servers.parse_server_identifier(server_identifier) + local ok, server = servers.get_server(server_name) + if not ok then + log.error(server) + raise_error(("Could not find server %q."):format(server_name)) + end + local uninstall_ok, uninstall_error = pcall(server.uninstall, server) + if not uninstall_ok then + log.error(tostring(uninstall_error)) + raise_error(("Failed to uninstall server %q."):format(server.name)) + end + log.fmt_info("Successfully uninstalled server %s.", server.name) + end +end + --- Queues a server to be installed. Will also open the status window. --- Use the .on_server_ready(cb) function to register a handler to be executed when a server is ready to be set up. ---@param server_identifier string @The server to install. This can also include a requested version, for example "rust_analyzer@nightly". function M.install(server_identifier) - local server_name, version = unpack(servers.parse_server_identifier(server_identifier)) + local server_name, version = servers.parse_server_identifier(server_identifier) local ok, server = servers.get_server(server_name) if not ok then return notify(("Unable to find LSP server %s.\n\n%s"):format(server_name, server), vim.log.levels.ERROR) @@ -41,35 +124,42 @@ function M.uninstall(server_name) end --- Queues all servers to be uninstalled. Will also open the status window. -function M.uninstall_all() - local choice = vim.fn.confirm( - ("This will uninstall all servers currently installed at %q. Continue?"):format( - vim.fn.fnamemodify(settings.current.install_root_dir, ":~") - ), - "&Yes\n&No", - 2 - ) - if settings.current.install_root_dir ~= settings._DEFAULT_SETTINGS.install_root_dir then - choice = vim.fn.confirm( - ( - "WARNING: You are using a non-default install_root_dir (%q). This command will delete the entire directory. Continue?" - ):format(vim.fn.fnamemodify(settings.current.install_root_dir, ":~")), +function M.uninstall_all(no_confirm) + if not no_confirm then + local choice = vim.fn.confirm( + ("This will uninstall all servers currently installed at %q. Continue?"):format( + vim.fn.fnamemodify(settings.current.install_root_dir, ":~") + ), "&Yes\n&No", 2 ) + if settings.current.install_root_dir ~= settings._DEFAULT_SETTINGS.install_root_dir then + choice = vim.fn.confirm( + ( + "WARNING: You are using a non-default install_root_dir (%q). This command will delete the entire directory. Continue?" + ):format(vim.fn.fnamemodify(settings.current.install_root_dir, ":~")), + "&Yes\n&No", + 2 + ) + end + + if choice ~= 1 then + print "Uninstalling all servers was aborted." + return + end end - if choice == 1 then - log.info "Uninstalling all servers." - status_win().open() - vim.schedule(function() - if fs.dir_exists(settings.current.install_root_dir) then - fs.rmrf(settings.current.install_root_dir) - status_win().mark_all_servers_uninstalled() - end - end) - else - print "Uninstalling all servers was aborted." + + log.info "Uninstalling all servers." + if fs.dir_exists(settings.current.install_root_dir) then + local ok, err = pcall(fs.rmrf, settings.current.install_root_dir) + if not ok then + log.error(err) + raise_error "Failed to uninstall all servers." + end end + log.info "Successfully uninstalled all servers." + status_win().mark_all_servers_uninstalled() + status_win().open() end ---@param cb fun(server: Server) @Callback to be executed whenever a server is ready to be set up. |
