Skip to content

Commit eb44a68

Browse files
committed
patch 8.0.0858: can exit while a terminal is still running a job
Problem: Can exit while a terminal is still running a job. Solution: Consider a buffer with a running job like a changed file.
1 parent 620d064 commit eb44a68

File tree

11 files changed

+55
-50
lines changed

11 files changed

+55
-50
lines changed

src/buffer.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,7 @@ set_curbuf(buf_T *buf, int action)
17361736
u_sync(FALSE);
17371737
close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf,
17381738
unload ? action : (action == DOBUF_GOTO
1739-
&& !P_HID(prevbuf)
1739+
&& !buf_hide(prevbuf)
17401740
&& !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, FALSE);
17411741
#ifdef FEAT_WINDOWS
17421742
if (curwin != previouswin && win_valid(previouswin))
@@ -4986,12 +4986,12 @@ do_arg_all(
49864986

49874987
if (i == opened_len && !keep_tabs)/* close this window */
49884988
{
4989-
if (P_HID(buf) || forceit || buf->b_nwindows > 1
4989+
if (buf_hide(buf) || forceit || buf->b_nwindows > 1
49904990
|| !bufIsChanged(buf))
49914991
{
49924992
/* If the buffer was changed, and we would like to hide it,
49934993
* try autowriting. */
4994-
if (!P_HID(buf) && buf->b_nwindows <= 1
4994+
if (!buf_hide(buf) && buf->b_nwindows <= 1
49954995
&& bufIsChanged(buf))
49964996
{
49974997
#ifdef FEAT_AUTOCMD
@@ -5018,7 +5018,7 @@ do_arg_all(
50185018
#ifdef FEAT_WINDOWS
50195019
else
50205020
{
5021-
win_close(wp, !P_HID(buf) && !bufIsChanged(buf));
5021+
win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
50225022
# ifdef FEAT_AUTOCMD
50235023
/* check if autocommands removed the next window */
50245024
if (!win_valid(wpnext))
@@ -5117,7 +5117,7 @@ do_arg_all(
51175117
}
51185118
(void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
51195119
ECMD_ONE,
5120-
((P_HID(curwin->w_buffer)
5120+
((buf_hide(curwin->w_buffer)
51215121
|| bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
51225122
+ ECMD_OLDBUF, curwin);
51235123
#ifdef FEAT_AUTOCMD
@@ -5372,7 +5372,7 @@ ex_buffer_all(exarg_T *eap)
53725372
*/
53735373
for (wp = lastwin; open_wins > count; )
53745374
{
5375-
r = (P_HID(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
5375+
r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
53765376
|| autowrite(wp->w_buffer, FALSE) == OK);
53775377
#ifdef FEAT_AUTOCMD
53785378
if (!win_valid(wp))
@@ -5384,7 +5384,7 @@ ex_buffer_all(exarg_T *eap)
53845384
#endif
53855385
if (r)
53865386
{
5387-
win_close(wp, !P_HID(wp->w_buffer));
5387+
win_close(wp, !buf_hide(wp->w_buffer));
53885388
--open_wins;
53895389
wp = lastwin;
53905390
}

src/ex_cmds.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3561,7 +3561,7 @@ getfile(
35613561

35623562
if (other)
35633563
++no_wait_return; /* don't wait for autowrite message */
3564-
if (other && !forceit && curbuf->b_nwindows == 1 && !P_HID(curbuf)
3564+
if (other && !forceit && curbuf->b_nwindows == 1 && !buf_hide(curbuf)
35653565
&& curbufIsChanged() && autowrite(curbuf, forceit) == FAIL)
35663566
{
35673567
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
@@ -3590,7 +3590,7 @@ getfile(
35903590
retval = GETFILE_SAME_FILE; /* it's in the same file */
35913591
}
35923592
else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
3593-
(P_HID(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0),
3593+
(buf_hide(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0),
35943594
curwin) == OK)
35953595
retval = GETFILE_OPEN_OTHER; /* opened another file */
35963596
else
@@ -8401,7 +8401,7 @@ ex_drop(exarg_T *eap)
84018401
* Skip the check if the 'hidden' option is set, as in this case the
84028402
* buffer won't be lost.
84038403
*/
8404-
if (!P_HID(curbuf))
8404+
if (!buf_hide(curbuf))
84058405
{
84068406
# ifdef FEAT_WINDOWS
84078407
++emsg_off;

src/ex_cmds2.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,7 +2064,7 @@ dialog_changed(
20642064
int
20652065
can_abandon(buf_T *buf, int forceit)
20662066
{
2067-
return ( P_HID(buf)
2067+
return ( buf_hide(buf)
20682068
|| !bufIsChanged(buf)
20692069
|| buf->b_nwindows > 1
20702070
|| autowrite(buf, forceit) == OK
@@ -2180,7 +2180,14 @@ check_changed_any(
21802180
msg_col = 0;
21812181
msg_didout = FALSE;
21822182
}
2183-
if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
2183+
if (
2184+
#ifdef FEAT_TERMINAL
2185+
term_job_running(buf->b_term)
2186+
? EMSG2(_("E947: Job still running in buffer \"%s\""),
2187+
buf->b_fname)
2188+
:
2189+
#endif
2190+
EMSG2(_("E162: No write since last change for buffer \"%s\""),
21842191
buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
21852192
{
21862193
save = no_wait_return;
@@ -2734,13 +2741,13 @@ do_argfile(exarg_T *eap, int argn)
27342741
* the same buffer
27352742
*/
27362743
other = TRUE;
2737-
if (P_HID(curbuf))
2744+
if (buf_hide(curbuf))
27382745
{
27392746
p = fix_fname(alist_name(&ARGLIST[argn]));
27402747
other = otherfile(p);
27412748
vim_free(p);
27422749
}
2743-
if ((!P_HID(curbuf) || !other)
2750+
if ((!buf_hide(curbuf) || !other)
27442751
&& check_changed(curbuf, CCGD_AW
27452752
| (other ? 0 : CCGD_MULTWIN)
27462753
| (eap->forceit ? CCGD_FORCEIT : 0)
@@ -2761,7 +2768,7 @@ do_argfile(exarg_T *eap, int argn)
27612768
* argument index. */
27622769
if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
27632770
eap, ECMD_LAST,
2764-
(P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
2771+
(buf_hide(curwin->w_buffer) ? ECMD_HIDE : 0)
27652772
+ (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
27662773
curwin->w_arg_idx = old_arg_idx;
27672774
/* like Vi: set the mark where the cursor is in the file. */
@@ -2782,7 +2789,7 @@ ex_next(exarg_T *eap)
27822789
* check for changed buffer now, if this fails the argument list is not
27832790
* redefined.
27842791
*/
2785-
if ( P_HID(curbuf)
2792+
if ( buf_hide(curbuf)
27862793
|| eap->cmdidx == CMD_snext
27872794
|| !check_changed(curbuf, CCGD_AW
27882795
| (eap->forceit ? CCGD_FORCEIT : 0)
@@ -2937,7 +2944,7 @@ ex_listdo(exarg_T *eap)
29372944

29382945
if (eap->cmdidx == CMD_windo
29392946
|| eap->cmdidx == CMD_tabdo
2940-
|| P_HID(curbuf)
2947+
|| buf_hide(curbuf)
29412948
|| !check_changed(curbuf, CCGD_AW
29422949
| (eap->forceit ? CCGD_FORCEIT : 0)
29432950
| CCGD_EXCMD))

src/ex_docmd.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7291,7 +7291,7 @@ ex_quit(exarg_T *eap)
72917291
*/
72927292
if (check_more(FALSE, eap->forceit) == OK && only_one_window())
72937293
exiting = TRUE;
7294-
if ((!P_HID(curbuf)
7294+
if ((!buf_hide(curbuf)
72957295
&& check_changed(curbuf, (p_awa ? CCGD_AW : 0)
72967296
| (eap->forceit ? CCGD_FORCEIT : 0)
72977297
| CCGD_EXCMD))
@@ -7318,7 +7318,7 @@ ex_quit(exarg_T *eap)
73187318
need_mouse_correct = TRUE;
73197319
# endif
73207320
/* close window; may free buffer */
7321-
win_close(wp, !P_HID(wp->w_buffer) || eap->forceit);
7321+
win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit);
73227322
#endif
73237323
}
73247324
}
@@ -7438,7 +7438,7 @@ ex_win_close(
74387438
buf_T *buf = win->w_buffer;
74397439

74407440
need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
7441-
if (need_hide && !P_HID(buf) && !forceit)
7441+
if (need_hide && !buf_hide(buf) && !forceit)
74427442
{
74437443
# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
74447444
if ((p_confirm || cmdmod.confirm) && p_write)
@@ -7465,9 +7465,9 @@ ex_win_close(
74657465

74667466
/* free buffer when not hiding it or when it's a scratch buffer */
74677467
if (tp == NULL)
7468-
win_close(win, !need_hide && !P_HID(buf));
7468+
win_close(win, !need_hide && !buf_hide(buf));
74697469
else
7470-
win_close_othertab(win, !need_hide && !P_HID(buf), tp);
7470+
win_close_othertab(win, !need_hide && !buf_hide(buf), tp);
74717471
}
74727472

74737473
/*
@@ -7864,7 +7864,7 @@ ex_exit(exarg_T *eap)
78647864
need_mouse_correct = TRUE;
78657865
# endif
78667866
/* Quit current window, may free the buffer. */
7867-
win_close(curwin, !P_HID(curwin->w_buffer));
7867+
win_close(curwin, !buf_hide(curwin->w_buffer));
78687868
#endif
78697869
}
78707870
}
@@ -7960,7 +7960,7 @@ handle_drop(
79607960
* We don't need to check if the 'hidden' option is set, as in this
79617961
* case the buffer won't be lost.
79627962
*/
7963-
if (!P_HID(curbuf) && !split)
7963+
if (!buf_hide(curbuf) && !split)
79647964
{
79657965
++emsg_off;
79667966
split = check_changed(curbuf, CCGD_AW);
@@ -8747,7 +8747,7 @@ do_exedit(
87478747
(*eap->arg == NUL && eap->do_ecmd_lnum == 0
87488748
&& vim_strchr(p_cpo, CPO_GOTO1) != NULL)
87498749
? ECMD_ONE : eap->do_ecmd_lnum,
8750-
(P_HID(curbuf) ? ECMD_HIDE : 0)
8750+
(buf_hide(curbuf) ? ECMD_HIDE : 0)
87518751
+ (eap->forceit ? ECMD_FORCEIT : 0)
87528752
/* after a split we can use an existing buffer */
87538753
+ (old_curwin != NULL ? ECMD_OLDBUF : 0)
@@ -8761,7 +8761,7 @@ do_exedit(
87618761
if (old_curwin != NULL)
87628762
{
87638763
need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
8764-
if (!need_hide || P_HID(curbuf))
8764+
if (!need_hide || buf_hide(curbuf))
87658765
{
87668766
# if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
87678767
cleanup_T cs;
@@ -8773,7 +8773,7 @@ do_exedit(
87738773
# ifdef FEAT_GUI
87748774
need_mouse_correct = TRUE;
87758775
# endif
8776-
win_close(curwin, !need_hide && !P_HID(curbuf));
8776+
win_close(curwin, !need_hide && !buf_hide(curbuf));
87778777

87788778
# if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
87798779
/* Restore the error/interrupt/exception state if not

src/normal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6255,11 +6255,11 @@ nv_gotofile(cmdarg_T *cap)
62556255
if (ptr != NULL)
62566256
{
62576257
/* do autowrite if necessary */
6258-
if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf))
6258+
if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !buf_hide(curbuf))
62596259
(void)autowrite(curbuf, FALSE);
62606260
setpcmark();
62616261
if (do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
6262-
P_HID(curbuf) ? ECMD_HIDE : 0, curwin) == OK
6262+
buf_hide(curbuf) ? ECMD_HIDE : 0, curwin) == OK
62636263
&& cap->nchar == 'F' && lnum >= 0)
62646264
{
62656265
curwin->w_cursor.lnum = lnum;

src/option.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -558,13 +558,6 @@ EXTERN long p_hh; /* 'helpheight' */
558558
EXTERN char_u *p_hlg; /* 'helplang' */
559559
#endif
560560
EXTERN int p_hid; /* 'hidden' */
561-
/* Use P_HID to check if a buffer is to be hidden when it is no longer
562-
* visible in a window. */
563-
#ifndef FEAT_QUICKFIX
564-
# define P_HID(dummy) (p_hid || cmdmod.hide)
565-
#else
566-
# define P_HID(buf) (buf_hide(buf))
567-
#endif
568561
EXTERN char_u *p_hl; /* 'highlight' */
569562
EXTERN int p_hls; /* 'hlsearch' */
570563
EXTERN long p_hi; /* 'history' */

src/terminal.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
* that buffer, attributes come from the scrollback buffer tl_scrollback.
3737
*
3838
* TODO:
39-
* - don't allow exiting Vim when a terminal is still running a job
4039
* - MS-Windows: no redraw for 'updatetime' #1915
4140
* - in bash mouse clicks are inserting characters.
4241
* - mouse scroll: when over other window, scroll that window.
@@ -284,11 +283,16 @@ term_start(char_u *cmd, jobopt_T *opt)
284283
}
285284
curbuf->b_fname = curbuf->b_ffname;
286285

286+
set_string_option_direct((char_u *)"buftype", -1,
287+
(char_u *)"terminal", OPT_FREE|OPT_LOCAL, 0);
288+
287289
/* Mark the buffer as not modifiable. It can only be made modifiable after
288290
* the job finished. */
289291
curbuf->b_p_ma = FALSE;
290-
set_string_option_direct((char_u *)"buftype", -1,
291-
(char_u *)"terminal", OPT_FREE|OPT_LOCAL, 0);
292+
293+
/* Set 'bufhidden' to "hide": allow closing the window. */
294+
set_string_option_direct((char_u *)"bufhidden", -1,
295+
(char_u *)"hide", OPT_FREE|OPT_LOCAL, 0);
292296

293297
set_term_and_win_size(term);
294298
setup_job_options(opt, term->tl_rows, term->tl_cols);

src/testdir/test_terminal.vim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ endfunc
6363

6464
func Test_terminal_wipe_buffer()
6565
let buf = Run_shell_in_terminal()
66-
exe buf . 'bwipe'
66+
call assert_fails(buf . 'bwipe', 'E517')
67+
exe buf . 'bwipe!'
6768
call WaitFor('job_status(g:job) == "dead"')
6869
call assert_equal('dead', job_status(g:job))
6970
call assert_equal("", bufname(buf))

src/undo.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3522,21 +3522,18 @@ u_save_line(linenr_T lnum)
35223522
int
35233523
bufIsChanged(buf_T *buf)
35243524
{
3525-
return
3526-
#ifdef FEAT_QUICKFIX
3527-
!bt_dontwrite(buf) &&
3525+
#ifdef FEAT_TERMINAL
3526+
if (term_job_running(buf->b_term))
3527+
return TRUE;
35283528
#endif
3529-
(buf->b_changed || file_ff_differs(buf, TRUE));
3529+
return !bt_dontwrite(buf)
3530+
&& (buf->b_changed || file_ff_differs(buf, TRUE));
35303531
}
35313532

35323533
int
35333534
curbufIsChanged(void)
35343535
{
3535-
return
3536-
#ifdef FEAT_QUICKFIX
3537-
!bt_dontwrite(curbuf) &&
3538-
#endif
3539-
(curbuf->b_changed || file_ff_differs(curbuf, TRUE));
3536+
return bufIsChanged(curbuf);
35403537
}
35413538

35423539
#if defined(FEAT_EVAL) || defined(PROTO)

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+
858,
772774
/**/
773775
857,
774776
/**/

0 commit comments

Comments
 (0)