aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2021-08-31 07:24:25 -0700
committerGitHub <noreply@github.com>2021-08-31 07:24:25 -0700
commit284199bc4bf36bb74c481da9c8b2a43c1bbbeb51 (patch)
tree336bf2b82126e5efa3d6f149d4a6026ef1a24d54
parent9695691ee4868ea9fdd8a6d84b9980fc22c77aa3 (diff)
parent3c081d028062f793b63b8689f854bbea30e15752 (diff)
downloadrneovim-284199bc4bf36bb74c481da9c8b2a43c1bbbeb51.tar.gz
rneovim-284199bc4bf36bb74c481da9c8b2a43c1bbbeb51.tar.bz2
rneovim-284199bc4bf36bb74c481da9c8b2a43c1bbbeb51.zip
Merge #15402 fix(terminal): close without ! if the job is stopped
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt2
-rw-r--r--src/nvim/buffer.c32
-rw-r--r--src/nvim/eval/funcs.c11
-rw-r--r--test/functional/terminal/buffer_spec.lua18
4 files changed, 42 insertions, 21 deletions
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index e0589ba7b8..0bf58f85fc 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -13,7 +13,7 @@ from the connected program.
Terminal buffers behave like normal buffers, except:
- With 'modifiable', lines can be edited but not deleted.
- 'scrollback' controls how many lines are kept.
-- Output is followed if the cursor is on the last line.
+- Output is followed ("tailed") if cursor is on the last line.
- 'modified' is the default. You can set 'nomodified' to avoid a warning when
closing the terminal buffer.
- 'bufhidden' defaults to "hide".
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index fdb3ffdc7e..81f8b9073e 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1218,8 +1218,8 @@ do_buffer(
return FAIL;
}
- if (!forceit && (buf->terminal || bufIsChanged(buf))) {
- if ((p_confirm || cmdmod.confirm) && p_write && !buf->terminal) {
+ if (!forceit && bufIsChanged(buf)) {
+ if ((p_confirm || cmdmod.confirm) && p_write) {
dialog_changed(buf, false);
if (!bufref_valid(&bufref)) {
// Autocommand deleted buffer, oops! It's not changed now.
@@ -1231,22 +1231,22 @@ do_buffer(
return FAIL;
}
} else {
- if (buf->terminal) {
- if (p_confirm || cmdmod.confirm) {
- if (!dialog_close_terminal(buf)) {
- return FAIL;
- }
- } else {
- EMSG2(_("E89: %s will be killed (add ! to override)"),
- (char *)buf->b_fname);
- return FAIL;
- }
- } else {
- EMSGN(_("E89: No write since last change for buffer %" PRId64
- " (add ! to override)"),
- buf->b_fnum);
+ EMSGN(_("E89: No write since last change for buffer %" PRId64
+ " (add ! to override)"),
+ buf->b_fnum);
+ return FAIL;
+ }
+ }
+
+ if (!forceit && buf->terminal && terminal_running(buf->terminal)) {
+ if (p_confirm || cmdmod.confirm) {
+ if (!dialog_close_terminal(buf)) {
return FAIL;
}
+ } else {
+ EMSG2(_("E89: %s will be killed (add ! to override)"),
+ (char *)buf->b_fname);
+ return FAIL;
}
}
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 8a1258efd4..99f9f17e0a 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -5404,14 +5404,19 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
TV_LIST_ITER_CONST(args, arg, {
Channel *chan = NULL;
if (TV_LIST_ITEM_TV(arg)->v_type != VAR_NUMBER
- || !(chan = find_job(TV_LIST_ITEM_TV(arg)->vval.v_number, false))) {
+ || !(chan = find_channel(TV_LIST_ITEM_TV(arg)->vval.v_number))
+ || chan->streamtype != kChannelStreamProc) {
+ jobs[i] = NULL; // Invalid job.
+ } else if (process_is_stopped(&chan->stream.proc)) {
+ // Job is stopped but not fully destroyed.
+ // Ensure all callbacks on its event queue are executed. #15402
+ process_wait(&chan->stream.proc, -1, NULL);
jobs[i] = NULL; // Invalid job.
} else {
jobs[i] = chan;
channel_incref(chan);
if (chan->stream.proc.status < 0) {
- // Process any pending events on the job's queue before temporarily
- // replacing it.
+ // Flush any events in the job's queue before temporarily replacing it.
multiqueue_process_events(chan->events);
multiqueue_replace_parent(chan->events, waiting_jobs);
}
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index c61bf108cb..c0af932e68 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -7,6 +7,7 @@ local eq, neq = helpers.eq, helpers.neq
local write_file = helpers.write_file
local command= helpers.command
local exc_exec = helpers.exc_exec
+local matches = helpers.matches
describe(':terminal buffer', function()
local screen
@@ -255,8 +256,23 @@ describe(':terminal buffer', function()
command('bdelete!')
end)
- it('handles wqall', function()
+ it('requires bang (!) to close a running job #15402', function()
eq('Vim(wqall):E948: Job still running', exc_exec('wqall'))
+ for _, cmd in ipairs({ 'bdelete', '%bdelete', 'bwipeout', 'bunload' }) do
+ matches('^Vim%('..cmd:gsub('%%', '')..'%):E89: term://.*tty%-test.* will be killed %(add %! to override%)$',
+ exc_exec(cmd))
+ end
+ command('call jobstop(&channel)')
+ assert(0 >= eval('jobwait([&channel], 1000)[0]'))
+ command('bdelete')
+ end)
+
+ it('stops running jobs with :quit', function()
+ -- Open in a new window to avoid terminating the nvim instance
+ command('split')
+ command('terminal')
+ command('set nohidden')
+ command('quit')
end)
it('does not segfault when pasting empty buffer #13955', function()