aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/process.lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2021-09-07 02:44:09 +0200
committerGitHub <noreply@github.com>2021-09-07 02:44:09 +0200
commit00294b84031711013a385f18c0fb0e8db84ebaf9 (patch)
treee45de668229c6b41643c5d1fa0fdb5beb0ff60fa /lua/nvim-lsp-installer/process.lua
parentlazily require servers for faster startup times (#77) (diff)
downloadmason-00294b84031711013a385f18c0fb0e8db84ebaf9.tar
mason-00294b84031711013a385f18c0fb0e8db84ebaf9.tar.gz
mason-00294b84031711013a385f18c0fb0e8db84ebaf9.tar.bz2
mason-00294b84031711013a385f18c0fb0e8db84ebaf9.tar.lz
mason-00294b84031711013a385f18c0fb0e8db84ebaf9.tar.xz
mason-00294b84031711013a385f18c0fb0e8db84ebaf9.tar.zst
mason-00294b84031711013a385f18c0fb0e8db84ebaf9.zip
add direct integration with libuv instead of going through termopen, also implement a UI (#79)
* add direct integration with libuv instead of going through termopen, also implement a UI * alleged free perf boosts yo that's free cycles
Diffstat (limited to 'lua/nvim-lsp-installer/process.lua')
-rw-r--r--lua/nvim-lsp-installer/process.lua135
1 files changed, 135 insertions, 0 deletions
diff --git a/lua/nvim-lsp-installer/process.lua b/lua/nvim-lsp-installer/process.lua
new file mode 100644
index 00000000..61097a88
--- /dev/null
+++ b/lua/nvim-lsp-installer/process.lua
@@ -0,0 +1,135 @@
+local log = require "nvim-lsp-installer.log"
+local uv = vim.loop
+
+local M = {}
+
+local function connect_sink(pipe, sink)
+ return function(err, data)
+ if err then
+ log.error { "Unexpected error when reading pipe.", err }
+ end
+ if data ~= nil then
+ local lines = vim.split(data, "\n")
+ for i = 1, #lines do
+ sink(lines[i])
+ end
+ else
+ pipe:read_stop()
+ pipe:close()
+ end
+ end
+end
+
+function M.graft_env(env)
+ local root_env = {}
+ for key, val in pairs(vim.fn.environ()) do
+ root_env[#root_env + 1] = key .. "=" .. val
+ end
+ for key, val in pairs(env) do
+ root_env[#root_env + 1] = key .. "=" .. val
+ end
+ return root_env
+end
+
+function M.spawn(cmd, opts, callback)
+ local stdin = uv.new_pipe(false)
+ local stdout = uv.new_pipe(false)
+ local stderr = uv.new_pipe(false)
+
+ local stdio = { stdin, stdout, stderr }
+
+ log.debug { "Spawning", cmd, opts }
+
+ local spawn_opts = {
+ env = opts.env,
+ stdio = stdio,
+ args = opts.args,
+ cwd = opts.cwd,
+ detached = false,
+ hide = true,
+ }
+
+ local handle, pid
+ handle, pid = uv.spawn(cmd, spawn_opts, function(exit_code, signal)
+ local successful = exit_code == 0 and signal == 0
+ handle:close()
+ if not stdin:is_closing() then
+ stdin:close()
+ end
+
+ -- ensure all pipes are closed, for I am a qualified plumber
+ local check = uv.new_check()
+ check:start(function()
+ for i = 1, #stdio do
+ local pipe = stdio[i]
+ if not pipe:is_closing() then
+ return
+ end
+ end
+ check:stop()
+ callback(successful)
+ end)
+ end)
+
+ if handle == nil then
+ opts.stdio_sink.stderr(("Failed to spawn process cmd=%s pid=%s"):format(cmd, pid))
+ callback(false)
+ return nil, nil
+ end
+
+ handle:unref()
+ log.debug { "Spawned with pid", pid }
+
+ stdout:read_start(connect_sink(stdout, opts.stdio_sink.stdout))
+ stderr:read_start(connect_sink(stderr, opts.stdio_sink.stderr))
+
+ return handle, stdio
+end
+
+function M.chain(opts)
+ local stack = {}
+ return {
+ run = function(cmd, args)
+ stack[#stack + 1] = { cmd = cmd, args = args }
+ end,
+ spawn = function(callback)
+ local function execute(idx)
+ local item = stack[idx]
+ M.spawn(
+ item.cmd,
+ vim.tbl_deep_extend("force", opts, {
+ args = item.args,
+ }),
+ function(successful)
+ if successful and stack[idx + 1] then
+ -- iterate
+ execute(idx + 1)
+ else
+ -- we done
+ callback(successful)
+ end
+ end
+ )
+ end
+
+ execute(1)
+ end,
+ }
+end
+
+function M.empty_sink()
+ local function noop() end
+ return {
+ stdout = noop,
+ stderr = noop,
+ }
+end
+
+function M.simple_sink()
+ return {
+ stdout = print,
+ stderr = vim.api.nvim_err_writeln,
+ }
+end
+
+return M