Skip to content

Commit

Permalink
feat(process): close method
Browse files Browse the repository at this point in the history
  • Loading branch information
rcarriga committed Apr 2, 2024
1 parent 33c62b3 commit 173f285
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 11 deletions.
15 changes: 12 additions & 3 deletions doc/nio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ result, with the same signature as the callback for `nio.run`.
This is useful for APIs where users don't want to create async
contexts but which are still used in async contexts internally.
Parameters~
{func} `(async fun(...))`
{func} `(async)` function
{argc?} `(integer)` The number of arguments of func. Must be included if there
are arguments.

Expand Down Expand Up @@ -403,13 +403,15 @@ Fields~
{pid} `(integer)` ID of the invoked process
{signal} `(fun(signal: integer|uv.aliases.signals))` Send a signal to the
process
{result} `(async fun(): number)` Wait for the process to exit and return the
exit code
{result} `(async fun(close: boolean): number,(string|nil)[])` Wait for the
process to exit and return the exit code, optionally closing all streams.
{stdin} `(nio.streams.OSStreamWriter)` Stream to write to the process stdin.
{stdout} `(nio.streams.OSStreamReader)` Stream to read from the process
stdout.
{stderr} `(nio.streams.OSStreamReader)` Stream to read from the process
stderr.
{close} `(async fun():(string|nil)[])` Close all streams, returning any errors
that occurred.

*nio.process.run()*
`run`({opts})
Expand All @@ -422,6 +424,8 @@ Run a process asynchronously.

local output = second.stdout.read()
print(output)

process.close()
<

Processes can be chained together, passing output of one process as input to
Expand All @@ -437,6 +441,9 @@ another.

local output = second.stdout.read()
print(output)

first.close()
second.close()
<

The stdio fields can also be file objects.
Expand All @@ -454,6 +461,8 @@ The stdio fields can also be file objects.

local output = file.read(nil, 0)
print(output)

process.close() -- Closes the file
<
Parameters~
{opts} `(nio.process.RunOpts)`
Expand Down
25 changes: 22 additions & 3 deletions lua/nio/process.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ nio.process = {}
---@class nio.process.Process
---@field pid integer ID of the invoked process
---@field signal fun(signal: integer|uv.aliases.signals) Send a signal to the process
---@field result async fun(): number Wait for the process to exit and return the exit code
---@field result async fun(close: boolean): number,(string|nil)[] Wait for the process to exit and return the exit code, optionally closing all streams.
---@field stdin nio.streams.OSStreamWriter Stream to write to the process stdin.
---@field stdout nio.streams.OSStreamReader Stream to read from the process stdout.
---@field stderr nio.streams.OSStreamReader Stream to read from the process stderr.
---@field close async fun():(string|nil)[] Close all streams, returning any errors that occurred.

--- Run a process asynchronously.
--- ```lua
Expand All @@ -24,6 +25,8 @@ nio.process = {}
---
--- local output = second.stdout.read()
--- print(output)
---
--- process.close()
--- ```
---
--- Processes can be chained together, passing output of one process as input to
Expand All @@ -39,6 +42,9 @@ nio.process = {}
---
--- local output = second.stdout.read()
--- print(output)
---
--- first.close()
--- second.close()
--- ```
---
--- The stdio fields can also be file objects.
Expand All @@ -56,6 +62,8 @@ nio.process = {}
---
--- local output = file.read(nil, 0)
--- print(output)
---
--- process.close() -- Closes the file
--- ```
---@param opts nio.process.RunOpts
---@return nio.process.Process? Process object for the running process
Expand Down Expand Up @@ -114,7 +122,8 @@ function nio.process.run(opts)
end

---@type nio.process.Process
local process = {
local process
process = {
pid = pid_or_error,
signal = function(signal)
vim.loop.process_kill(handle, signal)
Expand All @@ -134,7 +143,17 @@ function nio.process.run(opts)
fd = stderr_fd,
close = stderr.close,
},
result = exit_code_future.wait,
result = function(close)
local result = exit_code_future.wait()
local errors = {}
if close then
errors = process.close()
end
return result, errors
end,
close = function()
return { stdin.close(), stdout.close(), stderr.close() }
end,
}
return process
end
Expand Down
29 changes: 24 additions & 5 deletions tests/process_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,36 @@ describe("process", function()
end)

a.it("returns exit code", function()
local pipe = assert(vim.loop.new_pipe())
local process = assert(nio.process.run({
cmd = "bash",
args = { "-c", "exit 1" },
}))

local exit_code = process.result()
assert.equal(1, exit_code)
end)

a.it("with returns exit code", function()
local process = assert(nio.process.run({
cmd = "bash",
args = { "-c", "exit 1" },
stdin = pipe,
}))

process.signal(15)
local exit_code = process.with(function() end)

local exit_code = process.result()
assert.equal(0, exit_code)
assert.equal(1, exit_code)
end)

a.it("with closes streams", function()
local process = assert(nio.process.run({
cmd = "echo",
args = { "test" },
}))

process.with(function() end)

local stdout, stdout_err = process.stdout.read()
assert.equal("", stdout)
assert.Not.Nil(stdout_err)
end)
end)

0 comments on commit 173f285

Please sign in to comment.