Patch 9.0.0710
Problem: Quitting/unloading/hiding a terminal buffer does not always work
properly.
Solution: Avoid that ":q!" leaves an empty buffer behind. ":bunload!" also
kills the job and unloads the buffer. ":hide" does not unload the
buffer. (Yee Cheng Chin, closes #11323)
Files: runtime/doc/terminal.txt, src/buffer.c,
src/testdir/test_terminal.vim
*** ../vim-9.0.0709/runtime/doc/terminal.txt 2022-06-28 11:21:06.000000000 +0100
--- runtime/doc/terminal.txt 2022-10-10 11:41:36.766702704 +0100
***************
*** 288,296 ****
So long as the job is running the window behaves like it contains a modified
buffer. Trying to close the window with `CTRL-W :quit` fails. When using
! `CTRL-W :quit!` the job is ended. The text in the window is lost. The buffer
! still exists, but getting it in a window with `:buffer` will show an empty
! buffer.
Trying to close the window with `CTRL-W :close` also fails. Using
`CTRL-W :close!` will close the window and make the buffer hidden.
--- 288,295 ----
So long as the job is running the window behaves like it contains a modified
buffer. Trying to close the window with `CTRL-W :quit` fails. When using
! `CTRL-W :quit!` the job is ended. The text in the window is lost, the buffer
! is deleted. With `CTRL-W :bunload!` the buffer remains but will be empty.
Trying to close the window with `CTRL-W :close` also fails. Using
`CTRL-W :close!` will close the window and make the buffer hidden.
*** ../vim-9.0.0709/src/buffer.c 2022-10-09 18:53:29.020591194 +0100
--- src/buffer.c 2022-10-10 11:42:12.886653780 +0100
***************
*** 538,544 ****
unload_buf = TRUE;
#ifdef FEAT_TERMINAL
! if (bt_terminal(buf) && (buf->b_nwindows == 1 || del_buf))
{
CHECK_CURBUF;
if (term_job_running(buf->b_term))
--- 538,545 ----
unload_buf = TRUE;
#ifdef FEAT_TERMINAL
! // depending on how we get here b_nwindows may already be zero
! if (bt_terminal(buf) && (buf->b_nwindows <= 1 || del_buf))
{
CHECK_CURBUF;
if (term_job_running(buf->b_term))
***************
*** 550,555 ****
--- 551,561 ----
// Wiping out or unloading a terminal buffer kills the job.
free_terminal(buf);
+
+ // A terminal buffer is wiped out when job has finished.
+ del_buf = TRUE;
+ unload_buf = TRUE;
+ wipe_buf = TRUE;
}
else
{
***************
*** 565,574 ****
}
else
{
! // A terminal buffer is wiped out if the job has finished.
! del_buf = TRUE;
! unload_buf = TRUE;
! wipe_buf = TRUE;
}
CHECK_CURBUF;
}
--- 571,586 ----
}
else
{
! if (del_buf || unload_buf)
! {
! // A terminal buffer is wiped out if the job has finished.
! // We only do this when there's an intention to unload the
! // buffer. This way, :hide and other similar commands won't
! // wipe the buffer.
! del_buf = TRUE;
! unload_buf = TRUE;
! wipe_buf = TRUE;
! }
}
CHECK_CURBUF;
}
*** ../vim-9.0.0709/src/testdir/test_terminal.vim 2022-10-09 18:53:29.024591198 +0100
--- src/testdir/test_terminal.vim 2022-10-10 11:36:01.663167849 +0100
***************
*** 96,101 ****
--- 96,111 ----
unlet g:job
endfunc
+ func Test_terminal_unload_buffer()
+ let buf = Run_shell_in_terminal({})
+ call assert_fails(buf . 'bunload', 'E948:')
+ exe buf . 'bunload!'
+ call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
+ call assert_equal("", bufname(buf))
+
+ unlet g:job
+ endfunc
+
func Test_terminal_wipe_buffer()
let buf = Run_shell_in_terminal({})
call assert_fails(buf . 'bwipe', 'E948:')
***************
*** 202,208 ****
quit!
call assert_notequal(buf, bufnr())
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
! exec buf .. 'bwipe!'
unlet g:job
endfunc
--- 212,218 ----
quit!
call assert_notequal(buf, bufnr())
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
! call assert_equal("", bufname(buf))
unlet g:job
endfunc
***************
*** 237,243 ****
quit!
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
! exe buf . 'bwipe'
unlet g:job
endfunc
--- 247,253 ----
quit!
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
! call assert_equal("", bufname(buf))
unlet g:job
endfunc
***************
*** 261,276 ****
func Test_terminal_hide_buffer_job_finished()
term echo hello
let buf = bufnr()
- setlocal bufhidden=hide
call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
call assert_true(bufloaded(buf))
call assert_true(buflisted(buf))
edit Xasdfasdf
call assert_true(bufloaded(buf))
call assert_true(buflisted(buf))
exe buf .. 'buf'
call assert_equal(buf, bufnr())
setlocal bufhidden=
edit Xasdfasdf
call assert_false(bufloaded(buf))
call assert_false(buflisted(buf))
--- 271,298 ----
func Test_terminal_hide_buffer_job_finished()
term echo hello
let buf = bufnr()
call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
+
+ call assert_true(bufloaded(buf))
+ call assert_true(buflisted(buf))
+
+ " Test :hide
+ hide
call assert_true(bufloaded(buf))
call assert_true(buflisted(buf))
+ split
+ exe buf .. 'buf'
+ call assert_equal(buf, bufnr())
+
+ " Test bufhidden, which exercises a different code path
+ setlocal bufhidden=hide
edit Xasdfasdf
call assert_true(bufloaded(buf))
call assert_true(buflisted(buf))
exe buf .. 'buf'
call assert_equal(buf, bufnr())
setlocal bufhidden=
+
edit Xasdfasdf
call assert_false(bufloaded(buf))
call assert_false(buflisted(buf))
*** ../vim-9.0.0709/src/version.c 2022-10-09 21:53:35.323363028 +0100
--- src/version.c 2022-10-10 11:45:15.202409411 +0100
***************
*** 701,702 ****
--- 701,704 ----
{ /* Add new patch number below this line */
+ /**/
+ 710,
/**/
--
Have you heard about the new Barbie doll? It's called Divorce
Barbie. It comes with most of Ken's stuff.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///