aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer.lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2021-10-26 09:47:20 +0200
committerGitHub <noreply@github.com>2021-10-26 09:47:20 +0200
commitc7ef12d8f99490c984ec171c7341577513b435a8 (patch)
treeaea6fa17846dbc45c832fa28da1025ef03861d31 /lua/nvim-lsp-installer.lua
parentmac's not fun (diff)
downloadmason-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.lua140
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.