aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/process.lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2022-05-11 16:10:57 +0200
committerGitHub <noreply@github.com>2022-05-11 16:10:57 +0200
commit5e3385d90668c792919c7e2791620a6c0d569538 (patch)
tree4b0158d3ac7765db47411d57ec754a96f8eaf1f9 /lua/nvim-lsp-installer/process.lua
parentchore!: remove zeta_note (diff)
downloadmason-5e3385d90668c792919c7e2791620a6c0d569538.tar
mason-5e3385d90668c792919c7e2791620a6c0d569538.tar.gz
mason-5e3385d90668c792919c7e2791620a6c0d569538.tar.bz2
mason-5e3385d90668c792919c7e2791620a6c0d569538.tar.lz
mason-5e3385d90668c792919c7e2791620a6c0d569538.tar.xz
mason-5e3385d90668c792919c7e2791620a6c0d569538.tar.zst
mason-5e3385d90668c792919c7e2791620a6c0d569538.zip
chore: further decouple module structure (#685)
Diffstat (limited to 'lua/nvim-lsp-installer/process.lua')
-rw-r--r--lua/nvim-lsp-installer/process.lua316
1 files changed, 0 insertions, 316 deletions
diff --git a/lua/nvim-lsp-installer/process.lua b/lua/nvim-lsp-installer/process.lua
deleted file mode 100644
index 4c5bb11c..00000000
--- a/lua/nvim-lsp-installer/process.lua
+++ /dev/null
@@ -1,316 +0,0 @@
-local log = require "nvim-lsp-installer.log"
-local Data = require "nvim-lsp-installer.data"
-local platform = require "nvim-lsp-installer.platform"
-local uv = vim.loop
-
-local list_any = Data.list_any
-
----@alias luv_pipe any
----@alias luv_handle any
-
----@class StdioSink
----@field stdout fun(chunk: string)
----@field stderr fun(chunk: string)
-
-local M = {}
-
----@param pipe luv_pipe
----@param sink fun(chunk: string)
-local function connect_sink(pipe, sink)
- ---@param err string | nil
- ---@param data string | nil
- return function(err, data)
- if err then
- log.error("Unexpected error when reading pipe.", err)
- end
- if data ~= nil then
- sink(data)
- else
- pipe:read_stop()
- pipe:close()
- end
- end
-end
-
--- We gather the root env immediately, primarily because of E5560.
--- Also, there's no particular reason we need to refresh the environment (yet).
-local initial_environ = vim.fn.environ()
-
----@param new_paths string[] @A list of paths to prepend the existing PATH with.
-function M.extend_path(new_paths)
- local new_path_str = table.concat(new_paths, platform.path_sep)
- return ("%s%s%s"):format(new_path_str, platform.path_sep, initial_environ.PATH or "")
-end
-
----Merges the provided env param with the user's full environent. Provided env has precedence.
----@param env table<string, string>
----@param excluded_var_names string[]|nil
-function M.graft_env(env, excluded_var_names)
- local excluded_var_names_set = excluded_var_names and Data.set_of(excluded_var_names) or {}
- local merged_env = {}
- for key, val in pairs(initial_environ) do
- if not excluded_var_names_set[key] and env[key] == nil then
- merged_env[#merged_env + 1] = key .. "=" .. val
- end
- end
- for key, val in pairs(env) do
- if not excluded_var_names_set[key] then
- merged_env[#merged_env + 1] = key .. "=" .. val
- end
- end
- return merged_env
-end
-
----@param env_list string[]
-local function sanitize_env_list(env_list)
- local sanitized_list = {}
- for _, env in ipairs(env_list) do
- local safe_envs = {
- "GO111MODULE",
- "GOBIN",
- "GOPATH",
- "PATH",
- "GEM_HOME",
- "GEM_PATH",
- }
- local is_safe_env = list_any(safe_envs, function(safe_env)
- return env:find(safe_env .. "=") == 1
- end)
- if is_safe_env then
- sanitized_list[#sanitized_list + 1] = env
- else
- local idx = env:find "="
- sanitized_list[#sanitized_list + 1] = env:sub(1, idx) .. "<redacted>"
- end
- end
- return sanitized_list
-end
-
----@alias JobSpawnCallback fun(success: boolean, exit_code: integer)
-
----@class JobSpawnOpts
----@field env string[] @List of "key=value" string.
----@field args string[]
----@field cwd string
----@field stdio_sink StdioSink
-
----@param cmd string @The command/executable.
----@param opts JobSpawnOpts
----@param callback JobSpawnCallback
----@return luv_handle,luv_pipe[]|nil @Returns the job handle and the stdio array on success, otherwise returns nil.
-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 }
-
- local spawn_opts = {
- env = opts.env,
- stdio = stdio,
- args = opts.args,
- cwd = opts.cwd,
- detached = false,
- hide = true,
- }
-
- log.lazy_debug(function()
- local sanitized_env = opts.env and sanitize_env_list(opts.env) or nil
- return "Spawning cmd=%s, spawn_opts=%s",
- cmd,
- {
- args = opts.args,
- cwd = opts.cwd,
- env = sanitized_env,
- }
- end)
-
- local handle, pid_or_err
- handle, pid_or_err = 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, exit_code)
- end)
-
- log.fmt_debug("Job pid=%s exited with exit_code=%s, signal=%s", pid_or_err, exit_code, signal)
- end)
-
- if handle == nil then
- log.fmt_error("Failed to spawn process. cmd=%s, err=%s", cmd, pid_or_err)
- if type(pid_or_err) == "string" and pid_or_err:find "ENOENT" == 1 then
- opts.stdio_sink.stderr(("Could not find executable %q in path.\n"):format(cmd))
- else
- opts.stdio_sink.stderr(("Failed to spawn process cmd=%s err=%s\n"):format(cmd, pid_or_err))
- end
- callback(false)
- return nil, nil
- end
-
- log.debug("Spawned with pid", pid_or_err)
-
- stdout:read_start(connect_sink(stdout, opts.stdio_sink.stdout))
- stderr:read_start(connect_sink(stderr, opts.stdio_sink.stderr))
-
- return handle, stdio
-end
-
----@param opts JobSpawnOpts @The job spawn opts to apply in every job in this "chain".
-function M.chain(opts)
- local jobs = {}
- return {
- ---@param cmd string
- ---@param args string[]
- run = function(cmd, args)
- jobs[#jobs + 1] = M.lazy_spawn(
- cmd,
- vim.tbl_deep_extend("force", opts, {
- args = args,
- })
- )
- end,
- ---@param callback JobSpawnCallback
- spawn = function(callback)
- local function execute(idx)
- local ok, err = pcall(jobs[idx], function(successful)
- if successful and jobs[idx + 1] then
- -- iterate
- execute(idx + 1)
- else
- -- we done
- callback(successful)
- end
- end)
- if not ok then
- log.fmt_error("Chained job failed to execute. Error=%s", tostring(err))
- callback(false)
- 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 = vim.schedule_wrap(vim.api.nvim_out_write),
- stderr = vim.schedule_wrap(vim.api.nvim_err_write),
- }
-end
-
-function M.in_memory_sink()
- local buffers = { stdout = {}, stderr = {} }
- return {
- buffers = buffers,
- sink = {
- stdout = function(chunk)
- buffers.stdout[#buffers.stdout + 1] = chunk
- end,
- stderr = function(chunk)
- buffers.stderr[#buffers.stderr + 1] = chunk
- end,
- },
- }
-end
-
---- This probably belongs elsewhere ¯\_(ツ)_/¯
----@generic T
----@param debounced_fn fun(arg1: T)
----@return fun(arg1: T)
-function M.debounced(debounced_fn)
- local queued = false
- local last_arg = nil
- return function(a)
- last_arg = a
- if queued then
- return
- end
- queued = true
- vim.schedule(function()
- debounced_fn(last_arg)
- queued = false
- last_arg = nil
- end)
- end
-end
-
----@alias LazyJob fun(callback: JobSpawnCallback)
-
----@param cmd string
----@param opts JobSpawnOpts
-function M.lazy_spawn(cmd, opts)
- ---@param callback JobSpawnCallback
- return function(callback)
- return M.spawn(cmd, opts, callback)
- end
-end
-
----@class JobAttemptOpts
----@field jobs LazyJob[]
----@field on_finish JobSpawnCallback
----@field on_iterate fun()
-
----@param opts JobAttemptOpts
-function M.attempt(opts)
- local jobs, on_finish, on_iterate = opts.jobs, opts.on_finish, opts.on_iterate
- if #jobs == 0 then
- error "process.attempt(...) needs at least one job."
- end
-
- local spawn, on_job_exit
-
- on_job_exit = function(cur_idx, success)
- if success then
- -- this job succeeded. exit early
- on_finish(true)
- elseif jobs[cur_idx + 1] then
- -- iterate
- if on_iterate then
- on_iterate()
- end
- log.debug "Previous job failed, attempting next."
- spawn(cur_idx + 1)
- else
- -- we exhausted all jobs without success
- log.debug "All jobs failed."
- on_finish(false)
- end
- end
-
- spawn = function(idx)
- local ok, err = pcall(jobs[idx], function(success)
- on_job_exit(idx, success)
- end)
- if not ok then
- log.fmt_error("Job failed to execute. Error=%s", tostring(err))
- on_job_exit(idx, false)
- on_finish(false)
- end
- end
-
- spawn(1)
-end
-
-return M