-
-
Notifications
You must be signed in to change notification settings - Fork 123
Async infrastructure changes notice
This document is intended for users who have implemented a custom server installer.
Ask questions here: https://github.com/williamboman/nvim-lsp-installer/discussions/619
Asynchronous code execution capabilities was recently added to nvim-lsp-installer. Under the hood it leverages Lua coroutines to suspend asynchronous code until it resolves (similar to async/await
in JavaScript, but without the keywords). This is currently opt-in by specifying an async = true
property in the Server
constructor args (soon this will become the default mode).
As a result of this, all core installers (std
, npm
, pip3
, gem
, etc.) have been rewritten in an asynchronous fashion. If you have custom server installers, you will have to make changes!
An installer is now simply just an async function that receives a single ctx: InstallContext
argument. This ctx
argument is used to spawn processes, manage the working directory, accessing contextual information such as requested version (the 1.0.0
part in :LspInstall [email protected]
), and print feedback messages to the stdout/stderr sinks/outlets.
The following is an example snippet of an asynchronous installer function that spawns two bash
processes, and then downloads and unzips a file:
---@async
---@param ctx InstallContext
local function installer(ctx)
-- Will spawn a bash process with the provided arguments.
-- By spawning the process via `ctx.spawn`, all stdout and stderr output will be captured in an appropriate outlet (for example the :LspInstallInfo window).
-- Also, the working directory of the spawned process will automatically be set to the temporary installation directory for you.
ctx.spawn.bash { "-c", 'echo "Hello $WORLD"', env = { WORLD = "World!" } }
-- We can use normal Lua control primitives, for example catching erroneous exit codes.
ctx.stdio_sink.stderr "I will spawn a command that will fail.\n"
pcall(function ()
ctx.spawn.bash { "-c", "exit 1" }
end)
ctx.stdio_sink.stdout "I will do some cool stuff now.\n"
-- We can also, for example, make use of the async std functions in nvim-lsp-installer.core.managers.std
std.download_file("https://some.url/file.zip", "file.zip")
std.unzip("file.zip", ".")
end
Refer to the source code for all managers here, and their tests here.
If you have custom servers that only leverage an existing package manager (npm, pip3, etc.), the changes you need to do will be very simple.
- Change the import from
nvim-lsp-installer.installers.*
tonvim-lsp-installer.core.managers.*
- Add
async = true
to theServer
constructor
Example:
diff --git a/a.lua b/b.lua
index 34e37b6..e58fe5e 100644
--- a/a.lua
+++ b/b.lua
@@ -1,11 +1,13 @@
local server = require "nvim-lsp-installer.server"
-local npm = require "nvim-lsp-installer.installers.npm"
+local npm = require "nvim-lsp-installer.core.managers.npm"
local my_server = server.Server:new {
name = server_name,
root_dir = root_dir,
+ async = true,
installer = npm.packages { "something" },
default_options = {
cmd_env = npm.env(root_dir),
},
}
If you have custom servers that run custom commands (either via the std
installer functions or by spawning custom commands), you will be required to make some more fundamental changes. Refer to the source code, tests, as well as the introduction text on this page!
Examples:
diff --git a/a.lua b/b.lua
index ec1e051..0d2c587 100644
--- a/a.lua
+++ b/b.lua
@@ -1,22 +1,15 @@
local process = require "nvim-lsp-installer.process"
-local std = require "nvim-lsp-installer.installers.std"
+local std = require "nvim-lsp-installer.core.managers.std"
local server = require "nvim-lsp-installer.server"
local my_server = server.Server:new {
name = server_name,
root_dir = root_dir,
- installer = {
- function (_, callback, context)
- process.spawn("bash", {
- args = { "-c", 'echo "Hello $WORLD"' },
- stdio_sink = context.stdio_sink,
- env = process.graft_env {
- HELLO = "World!"
- }
- }, callback)
- end,
- std.download_file("https://my.url/file.zip", "file.zip"),
+ async = true,
+ installer = function (ctx)
+ ctx.spawn.bash { "-c", 'echo "Hello World!"', env = { HELLO = "World!" } }
+ std.download_file("https://my.url/file.zip", "file.zip")
std.unzip("file.zip")
- },
+ end,
default_options = {},
}