Compare commits

...

3 Commits

Author SHA1 Message Date
Jongwook Choi ec3ea47be9
Merge 91aa36cf10 into 5e98439f6d 2024-05-05 22:58:34 +08:00
Evgeni Chasnovski 5e98439f6d
fix(defaults): diagnostic mappings descriptions #28646 2024-05-05 07:45:47 -07:00
Jongwook Choi 91aa36cf10 fix(vim.system): make wait() with timeout = 0 work correctly
Problem:

- `vim.system(...):wait(0)` was simply returning `nil`, not a valid
  `vim.SystemCompleted` object.

- Upon timeout after `:wait(timeout)`, SIGKILL (9) would be sent instead
  of SIGTERM (15) as in the case of `vim.system()` with `timeout` being
  set in the `opts` table. Such a different behavior is confusing.

Solution:

- Wait for at least 1 milliseconds so that the asynchronous
  `on_exit()` callback can be scheduled and executed by the uv loop.

- Always send SIGTERM when the process times out, for both use cases.

- In addition, the docs for the `timeout` parameter in `vim.system`
  are revised.
2024-05-03 21:03:22 -04:00
5 changed files with 58 additions and 43 deletions

View File

@ -1780,15 +1780,15 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
will be written to stdin and closed. Defaults to `false`.
• stdout: (boolean|function) Handle output from stdout.
When passed as a function must have the signature
`fun(err: string, data: string)`. Defaults to `true`
`fun(err: string, data: string)`. Defaults to `true`.
• stderr: (boolean|function) Handle output from stderr.
When passed as a function must have the signature
`fun(err: string, data: string)`. Defaults to `true`.
• text: (boolean) Handle stdout and stderr as text.
Replaces `\r\n` with `\n`.
• timeout: (integer) Run the command with a time limit.
Upon timeout the process is sent the TERM signal (15) and
the exit code is set to 124.
• timeout: (integer) Run the command with a time limit
(given in milliseconds). Upon timeout the process is sent
the TERM signal (15) and the exit code is set to 124.
• detach: (boolean) If true, spawn the child process in a
detached state - this will make it a process group
leader, and will effectively enable the child to keep
@ -1805,15 +1805,16 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
(`vim.SystemObj`) Object with the fields:
• cmd (string[]) Command name and args
• pid (integer) Process ID
• wait (fun(timeout: integer|nil): SystemCompleted) Wait for the
process to complete. Upon timeout the process is sent the KILL
signal (9) and the exit code is set to 124. Cannot be called in
|api-fast|.
• SystemCompleted is an object with the fields:
• code: (integer)
• signal: (integer)
• stdout: (string), nil if stdout argument is passed
• stderr: (string), nil if stderr argument is passed
• wait (fun(timeout: integer|nil): vim.SystemCompleted) Wait for the
process to complete, for {timeout} milliseconds (if {timeout} is
given) or the timeout specified in {opts}. Upon timeout the process
is sent the TERM signal (15) and the exit code is set to 124. Cannot
be called in |api-fast|.
• vim.SystemCompleted is an object with the fields:
• code: (integer)
• signal: (integer)
• stdout: (string), nil if stdout argument is passed
• stderr: (string), nil if stderr argument is passed
• kill (fun(signal: integer|string))
• write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to
close the stream.

View File

@ -183,26 +183,22 @@ do
do
vim.keymap.set('n', ']d', function()
vim.diagnostic.goto_next({ float = false })
end, {
desc = 'Jump to the next diagnostic with the highest severity',
})
end, { desc = 'Jump to the next diagnostic' })
vim.keymap.set('n', '[d', function()
vim.diagnostic.goto_prev({ float = false })
end, {
desc = 'Jump to the previous diagnostic with the highest severity',
})
end, { desc = 'Jump to the previous diagnostic' })
vim.keymap.set('n', '<C-W>d', function()
vim.diagnostic.open_float()
end, {
desc = 'Open a floating window showing diagnostics under the cursor',
})
end, { desc = 'Show diagnostics under the cursor' })
vim.keymap.set('n', '<C-W><C-D>', '<C-W>d', {
remap = true,
desc = 'Open a floating window showing diagnostics under the cursor',
})
vim.keymap.set(
'n',
'<C-W><C-D>',
'<C-W>d',
{ remap = true, desc = 'Show diagnostics under the cursor' }
)
end
end

View File

@ -105,13 +105,13 @@ vim.log = {
--- and closed. Defaults to `false`.
--- - stdout: (boolean|function)
--- Handle output from stdout. When passed as a function must have the signature `fun(err: string, data: string)`.
--- Defaults to `true`
--- Defaults to `true`.
--- - stderr: (boolean|function)
--- Handle output from stderr. When passed as a function must have the signature `fun(err: string, data: string)`.
--- Defaults to `true`.
--- - text: (boolean) Handle stdout and stderr as text. Replaces `\r\n` with `\n`.
--- - timeout: (integer) Run the command with a time limit. Upon timeout the process is sent the
--- TERM signal (15) and the exit code is set to 124.
--- - timeout: (integer) Run the command with a time limit (given in milliseconds).
--- Upon timeout the process is sent the TERM signal (15) and the exit code is set to 124.
--- - detach: (boolean) If true, spawn the child process in a detached state - this will make it
--- a process group leader, and will effectively enable the child to keep running after the
--- parent exits. Note that the child process will still keep the parent's event loop alive
@ -123,14 +123,15 @@ vim.log = {
--- @return vim.SystemObj Object with the fields:
--- - cmd (string[]) Command name and args
--- - pid (integer) Process ID
--- - wait (fun(timeout: integer|nil): SystemCompleted) Wait for the process to complete. Upon
--- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot
--- be called in |api-fast|.
--- - SystemCompleted is an object with the fields:
--- - code: (integer)
--- - signal: (integer)
--- - stdout: (string), nil if stdout argument is passed
--- - stderr: (string), nil if stderr argument is passed
--- - wait (fun(timeout: integer|nil): vim.SystemCompleted) Wait for the process to complete,
--- for {timeout} milliseconds (if {timeout} is given) or the timeout specified in {opts}.
--- Upon timeout the process is sent the TERM signal (15) and the exit code is set to 124.
--- Cannot be called in |api-fast|.
--- - vim.SystemCompleted is an object with the fields:
--- - code: (integer)
--- - signal: (integer)
--- - stdout: (string), nil if stdout argument is passed
--- - stderr: (string), nil if stderr argument is passed
--- - kill (fun(signal: integer|string))
--- - write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to close the stream.
--- - is_closing (fun(): boolean)

View File

@ -90,19 +90,24 @@ end
local MAX_TIMEOUT = 2 ^ 31
--- @param timeout? integer
--- @param timeout? integer timeout (in milliseconds), must be >= 0.
--- @return vim.SystemCompleted
function SystemObj:wait(timeout)
local state = self._state
local done = vim.wait(timeout or state.timeout or MAX_TIMEOUT, function()
-- If timeout == 0, vim.wait() will return immediately and uv timer won't schedule on_exit()
-- in which state.result will be set
timeout = math.max(1, timeout or state.timeout or MAX_TIMEOUT)
local done = vim.wait(timeout, function()
return state.result ~= nil
end, nil, true)
if not done then
-- Send sigkill since this cannot be caught
self:_timeout(SIG.KILL)
vim.wait(timeout or state.timeout or MAX_TIMEOUT, function()
-- Send SIGTERM since this cannot be caught
self:_timeout(SIG.TERM)
-- wait a bit more until state.result is set
vim.wait(timeout, function()
return state.result ~= nil
end, nil, true)
end

View File

@ -75,7 +75,7 @@ describe('vim.system', function()
it('supports timeout', function()
eq({
code = 124,
signal = 15,
signal = 15, -- SIGTERM
stdout = '',
stderr = '',
}, system({ 'sleep', '10' }, { timeout = 1000 }))
@ -83,6 +83,18 @@ describe('vim.system', function()
end)
end
it('supports timeout = 0', function()
local ret = exec_lua [[
return vim.system({ 'sleep', '1' }):wait(0)
]] --[[ @as any ]]
eq({
code = 124,
signal = 15, -- SIGTERM
stdout = '',
stderr = '',
}, ret)
end)
it('kill processes', function()
exec_lua([[
local signal