diff options
Diffstat (limited to 'lua/nvim-lsp-installer/core/spawn.lua')
| -rw-r--r-- | lua/nvim-lsp-installer/core/spawn.lua | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/lua/nvim-lsp-installer/core/spawn.lua b/lua/nvim-lsp-installer/core/spawn.lua new file mode 100644 index 00000000..992b1557 --- /dev/null +++ b/lua/nvim-lsp-installer/core/spawn.lua @@ -0,0 +1,79 @@ +local a = require "nvim-lsp-installer.core.async" +local Result = require "nvim-lsp-installer.core.result" +local process = require "nvim-lsp-installer.process" +local platform = require "nvim-lsp-installer.platform" + +local async_spawn = a.promisify(process.spawn) + +---@alias JobSpawn Record<string, async fun(opts: JobSpawnOpts): Result> +---@type JobSpawn +local spawn = { + _aliases = { + npm = platform.is_win and "npm.cmd" or "npm", + gem = platform.is_win and "gem.cmd" or "gem", + composer = platform.is_win and "composer.bat" or "composer", + }, + -- Utility function for optionally including arguments. + ---@generic T + ---@param condition boolean + ---@param value T + ---@return T + _when = function(condition, value) + return condition and value or vim.NIL + end, +} + +local function Failure(err, cmd) + return Result.failure(setmetatable(err, { + __tostring = function() + return ("spawn: %s failed with exit code %d"):format(cmd, err.exit_code) + end, + })) +end + +setmetatable(spawn, { + __index = function(self, k) + ---@param args string|nil|string[][] + return function(args) + local cmd_args = {} + for _, arg in ipairs(args) do + if type(arg) == "table" then + vim.list_extend(cmd_args, arg) + elseif arg ~= vim.NIL then + cmd_args[#cmd_args + 1] = arg + end + end + ---@type JobSpawnOpts + local spawn_args = { + stdio_sink = args.stdio_sink, + cwd = args.cwd, + env = args.env, + args = cmd_args, + } + + local stdio + if not spawn_args.stdio_sink then + stdio = process.in_memory_sink() + spawn_args.stdio_sink = stdio.sink + end + + local cmd = self._aliases[k] or k + local _, exit_code = async_spawn(cmd, spawn_args) + + if exit_code == 0 then + return Result.success { + stdout = stdio and table.concat(stdio.buffers.stdout, "") or nil, + stderr = stdio and table.concat(stdio.buffers.stderr, "") or nil, + } + else + return Failure({ + exit_code = exit_code, + stdout = stdio and table.concat(stdio.buffers.stdout, "") or nil, + stderr = stdio and table.concat(stdio.buffers.stderr, "") or nil, + }, cmd) + end + end + end, +}) + +return spawn |
