Skip to content

Commit 94053a5

Browse files
committed
patch 8.0.0838: buffer hangs around whem terminal window is closed
Problem: Buffer hangs around whem terminal window is closed. Solution: When the job has ended wipe out a terminal buffer when the window is closed.
1 parent 0792048 commit 94053a5

File tree

5 files changed

+72
-14
lines changed

5 files changed

+72
-14
lines changed

src/buffer.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,31 @@ close_buffer(
468468
int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE);
469469
int wipe_buf = (action == DOBUF_WIPE);
470470

471+
#ifdef FEAT_TERMINAL
472+
if (bt_terminal(buf))
473+
{
474+
if (term_job_running(buf->b_term))
475+
{
476+
if (wipe_buf)
477+
/* Wiping out a terminal buffer kills the job. */
478+
free_terminal(buf);
479+
else
480+
{
481+
/* The job keeps running, hide the buffer. */
482+
del_buf = FALSE;
483+
unload_buf = FALSE;
484+
}
485+
}
486+
else
487+
{
488+
/* A terminal buffer is wiped out if the job has finished. */
489+
del_buf = TRUE;
490+
unload_buf = TRUE;
491+
wipe_buf = TRUE;
492+
}
493+
}
494+
else
495+
#endif
471496
/*
472497
* Force unloading or deleting when 'bufhidden' says so.
473498
* The caller must take care of NOT deleting/freeing when 'bufhidden' is

src/proto/terminal.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
void ex_terminal(exarg_T *eap);
33
void free_terminal(buf_T *buf);
44
void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
5+
int term_job_running(term_T *term);
56
int term_in_terminal_mode(void);
67
void term_leave_terminal_mode(void);
78
int term_use_loop(void);

src/terminal.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@
3636
* that buffer, attributes come from the scrollback buffer tl_scrollback.
3737
*
3838
* TODO:
39-
* - When closing a window with a terminal buffer where the job has ended, wipe
40-
* out the buffer. Like 'bufhidden' is "wipe".
41-
* - When a buffer with a terminal is wiped out, kill the job and close the
42-
* channel.
39+
* - don't allow exiting Vim when a terminal is still running a job
4340
* - in bash mouse clicks are inserting characters.
4441
* - mouse scroll: when over other window, scroll that window.
4542
* - typing CTRL-C is not sent to the terminal. need to setup controlling tty?
@@ -59,12 +56,8 @@
5956
* - do not store terminal window in viminfo. Or prefix term:// ?
6057
* - add a character in :ls output
6158
* - add 't' to mode()
62-
* - When making a change after the job has ended, make the buffer a normal
63-
* buffer; needs to be written.
64-
* - when closing window and job has not ended, make terminal hidden?
65-
* - when closing window and job has ended, make buffer hidden?
66-
* - don't allow exiting Vim when a terminal is still running a job
6759
* - use win_del_lines() to make scroll-up efficient.
60+
* - implement term_setsize()
6861
* - add test for giving error for invalid 'termsize' value.
6962
* - support minimal size when 'termsize' is "rows*cols".
7063
* - support minimal size when 'termsize' is empty?
@@ -573,7 +566,7 @@ term_convert_key(term_T *term, int c, char *buf)
573566
/*
574567
* Return TRUE if the job for "term" is still running.
575568
*/
576-
static int
569+
int
577570
term_job_running(term_T *term)
578571
{
579572
/* Also consider the job finished when the channel is closed, to avoid a

src/testdir/test_terminal.vim

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ endif
66

77
source shared.vim
88

9+
" Open a terminal with a shell, assign the job to g:job and return the buffer
10+
" number.
911
func Run_shell_in_terminal()
1012
let buf = term_start(&shell)
1113

@@ -16,22 +18,31 @@ func Run_shell_in_terminal()
1618
let g:job = term_getjob(buf)
1719
call assert_equal(v:t_job, type(g:job))
1820

19-
call term_sendkeys(buf, "exit\r")
21+
return buf
22+
endfunc
23+
24+
" Stops the shell started by Run_shell_in_terminal().
25+
func Stop_shell_in_terminal(buf)
26+
call term_sendkeys(a:buf, "exit\r")
2027
call WaitFor('job_status(g:job) == "dead"')
2128
call assert_equal('dead', job_status(g:job))
22-
23-
return buf
2429
endfunc
2530

2631
func Test_terminal_basic()
2732
let buf = Run_shell_in_terminal()
33+
call Stop_shell_in_terminal(buf)
34+
call term_wait(buf)
35+
36+
" closing window wipes out the terminal buffer a with finished job
37+
close
38+
call assert_equal("", bufname(buf))
2839

29-
exe buf . 'bwipe'
3040
unlet g:job
3141
endfunc
3242

3343
func Test_terminal_make_change()
3444
let buf = Run_shell_in_terminal()
45+
call Stop_shell_in_terminal(buf)
3546
call term_wait(buf)
3647

3748
setlocal modifiable
@@ -43,6 +54,32 @@ func Test_terminal_make_change()
4354
unlet g:job
4455
endfunc
4556

57+
func Test_terminal_wipe_buffer()
58+
let buf = Run_shell_in_terminal()
59+
exe buf . 'bwipe'
60+
call WaitFor('job_status(g:job) == "dead"')
61+
call assert_equal('dead', job_status(g:job))
62+
call assert_equal("", bufname(buf))
63+
64+
unlet g:job
65+
endfunc
66+
67+
func Test_terminal_hide_buffer()
68+
let buf = Run_shell_in_terminal()
69+
quit
70+
for nr in range(1, winnr('$'))
71+
call assert_notequal(winbufnr(nr), buf)
72+
endfor
73+
call assert_true(bufloaded(buf))
74+
call assert_true(buflisted(buf))
75+
76+
exe 'split ' . buf . 'buf'
77+
call Stop_shell_in_terminal(buf)
78+
exe buf . 'bwipe'
79+
80+
unlet g:job
81+
endfunc
82+
4683
func Check_123(buf)
4784
let l = term_scrape(a:buf, 1)
4885
call assert_true(len(l) > 0)

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,8 @@ static char *(features[]) =
769769

770770
static int included_patches[] =
771771
{ /* Add new patch number below this line */
772+
/**/
773+
838,
772774
/**/
773775
837,
774776
/**/

0 commit comments

Comments
 (0)