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 | |
| 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')
| -rw-r--r-- | lua/nvim-lsp-installer.lua | 140 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/log.lua | 3 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/platform.lua | 2 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/process.lua | 4 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/server.lua | 6 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/servers/init.lua | 8 |
6 files changed, 129 insertions, 34 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. diff --git a/lua/nvim-lsp-installer/log.lua b/lua/nvim-lsp-installer/log.lua index d93fa444..a395a049 100644 --- a/lua/nvim-lsp-installer/log.lua +++ b/lua/nvim-lsp-installer/log.lua @@ -1,6 +1,7 @@ local Data = require "nvim-lsp-installer.data" local path = require "nvim-lsp-installer.path" local settings = require "nvim-lsp-installer.settings" +local platform = require "nvim-lsp-installer.platform" local tbl_pack = Data.tbl_pack @@ -10,7 +11,7 @@ local config = { -- Should print the output to neovim while running -- values: 'sync','async',false - use_console = false, + use_console = platform.is_headless, -- Should highlighting be used in console (using echohl) highlights = true, diff --git a/lua/nvim-lsp-installer/platform.lua b/lua/nvim-lsp-installer/platform.lua index 44b99199..9ab54c6a 100644 --- a/lua/nvim-lsp-installer/platform.lua +++ b/lua/nvim-lsp-installer/platform.lua @@ -28,4 +28,6 @@ M.is_linux = not M.is_mac and M.is_unix -- PATH separator M.path_sep = M.is_win and ";" or ":" +M.is_headless = #vim.api.nvim_list_uis() == 0 + return M diff --git a/lua/nvim-lsp-installer/process.lua b/lua/nvim-lsp-installer/process.lua index ad17465c..7fe3625c 100644 --- a/lua/nvim-lsp-installer/process.lua +++ b/lua/nvim-lsp-installer/process.lua @@ -214,8 +214,8 @@ end function M.simple_sink() return { - stdout = vim.schedule_wrap(print), - stderr = vim.schedule_wrap(vim.api.nvim_err_writeln), + stdout = vim.schedule_wrap(vim.api.nvim_out_write), + stderr = vim.schedule_wrap(vim.api.nvim_err_write), } end diff --git a/lua/nvim-lsp-installer/server.lua b/lua/nvim-lsp-installer/server.lua index f1e0fdef..b1081d7a 100644 --- a/lua/nvim-lsp-installer/server.lua +++ b/lua/nvim-lsp-installer/server.lua @@ -65,10 +65,12 @@ function M.Server:setup(opts) end end +---@return table @A deep copy of this server's default options. Note that these default options are nvim-lsp-installer specific, and does not include any default options provided by lspconfig. function M.Server:get_default_options() return vim.deepcopy(self._default_options) end +---@return string[] @The list of supported filetypes. function M.Server:get_supported_filetypes() local metadata = require "nvim-lsp-installer._generated.metadata" @@ -79,6 +81,7 @@ function M.Server:get_supported_filetypes() return {} end +---@return boolean function M.Server:is_installed() return servers.is_server_installed(self.name) end @@ -87,10 +90,13 @@ function M.Server:create_root_dir() fs.mkdirp(self.root_dir) end +---Queues the server to be asynchronously installed. Also opens the UI window. function M.Server:install() status_win().install_server(self) end +---@param context ServerInstallContext +---@param callback ServerInstallCallback function M.Server:install_attached(context, callback) local uninstall_ok, uninstall_err = pcall(self.uninstall, self) if not uninstall_ok then diff --git a/lua/nvim-lsp-installer/servers/init.lua b/lua/nvim-lsp-installer/servers/init.lua index d98bd224..3f252b83 100644 --- a/lua/nvim-lsp-installer/servers/init.lua +++ b/lua/nvim-lsp-installer/servers/init.lua @@ -154,14 +154,10 @@ function M.is_server_installed(server_name) return scanned_server_dirs[dirname] or false end ----@class ServerTuple ----@field public [1] string The server name. ----@field public [2] string|nil The requested server version. - ---@param server_identifier string @The server identifier to parse. ----@return ServerTuple +---@return string, string|nil @Returns a (server_name, requested_version) tuple, where requested_version may be nil. function M.parse_server_identifier(server_identifier) - return vim.split(server_identifier, "@") + return unpack(vim.split(server_identifier, "@")) end ---@param server_name string |
