]> granicus.if.org Git - vim/commitdiff
patch 8.0.0858: can exit while a terminal is still running a job v8.0.0858
authorBram Moolenaar <Bram@vim.org>
Thu, 3 Aug 2017 20:44:55 +0000 (22:44 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 3 Aug 2017 20:44:55 +0000 (22:44 +0200)
Problem:    Can exit while a terminal is still running a job.
Solution:   Consider a buffer with a running job like a changed file.

src/buffer.c
src/ex_cmds.c
src/ex_cmds2.c
src/ex_docmd.c
src/normal.c
src/option.h
src/terminal.c
src/testdir/test_terminal.vim
src/undo.c
src/version.c
src/window.c

index dd72b1ff7bb9850accd387e1011c4fc2ca99a072..181145d42cabb68d22a6800094f7238d7ccf09f2 100644 (file)
@@ -1736,7 +1736,7 @@ set_curbuf(buf_T *buf, int action)
                u_sync(FALSE);
            close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf,
                    unload ? action : (action == DOBUF_GOTO
-                       && !P_HID(prevbuf)
+                       && !buf_hide(prevbuf)
                        && !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, FALSE);
 #ifdef FEAT_WINDOWS
            if (curwin != previouswin && win_valid(previouswin))
@@ -4986,12 +4986,12 @@ do_arg_all(
 
            if (i == opened_len && !keep_tabs)/* close this window */
            {
-               if (P_HID(buf) || forceit || buf->b_nwindows > 1
+               if (buf_hide(buf) || forceit || buf->b_nwindows > 1
                                                        || !bufIsChanged(buf))
                {
                    /* If the buffer was changed, and we would like to hide it,
                     * try autowriting. */
-                   if (!P_HID(buf) && buf->b_nwindows <= 1
+                   if (!buf_hide(buf) && buf->b_nwindows <= 1
                                                         && bufIsChanged(buf))
                    {
 #ifdef FEAT_AUTOCMD
@@ -5018,7 +5018,7 @@ do_arg_all(
 #ifdef FEAT_WINDOWS
                    else
                    {
-                       win_close(wp, !P_HID(buf) && !bufIsChanged(buf));
+                       win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
 # ifdef FEAT_AUTOCMD
                        /* check if autocommands removed the next window */
                        if (!win_valid(wpnext))
@@ -5117,7 +5117,7 @@ do_arg_all(
            }
            (void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
                      ECMD_ONE,
-                     ((P_HID(curwin->w_buffer)
+                     ((buf_hide(curwin->w_buffer)
                           || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
                                                       + ECMD_OLDBUF, curwin);
 #ifdef FEAT_AUTOCMD
@@ -5372,7 +5372,7 @@ ex_buffer_all(exarg_T *eap)
      */
     for (wp = lastwin; open_wins > count; )
     {
-       r = (P_HID(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
+       r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
                                     || autowrite(wp->w_buffer, FALSE) == OK);
 #ifdef FEAT_AUTOCMD
        if (!win_valid(wp))
@@ -5384,7 +5384,7 @@ ex_buffer_all(exarg_T *eap)
 #endif
            if (r)
        {
-           win_close(wp, !P_HID(wp->w_buffer));
+           win_close(wp, !buf_hide(wp->w_buffer));
            --open_wins;
            wp = lastwin;
        }
index 6ec3ded90b0816e730ad86e15d0160ba512cc7b6..61c85a917f3bbd296520895c58aefb04e63d338d 100644 (file)
@@ -3561,7 +3561,7 @@ getfile(
 
     if (other)
        ++no_wait_return;           /* don't wait for autowrite message */
-    if (other && !forceit && curbuf->b_nwindows == 1 && !P_HID(curbuf)
+    if (other && !forceit && curbuf->b_nwindows == 1 && !buf_hide(curbuf)
                   && curbufIsChanged() && autowrite(curbuf, forceit) == FAIL)
     {
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
@@ -3590,7 +3590,7 @@ getfile(
        retval = GETFILE_SAME_FILE;     /* it's in the same file */
     }
     else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
-               (P_HID(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0),
+            (buf_hide(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0),
                curwin) == OK)
        retval = GETFILE_OPEN_OTHER;    /* opened another file */
     else
@@ -8401,7 +8401,7 @@ ex_drop(exarg_T *eap)
         * Skip the check if the 'hidden' option is set, as in this case the
         * buffer won't be lost.
         */
-       if (!P_HID(curbuf))
+       if (!buf_hide(curbuf))
        {
 # ifdef FEAT_WINDOWS
            ++emsg_off;
index 381c5d1c25be7094dec140638064691d42c6870e..26b588c650a5cc210dc4787f12c1b0a16c54d84c 100644 (file)
@@ -2064,7 +2064,7 @@ dialog_changed(
     int
 can_abandon(buf_T *buf, int forceit)
 {
-    return (      P_HID(buf)
+    return (      buf_hide(buf)
                || !bufIsChanged(buf)
                || buf->b_nwindows > 1
                || autowrite(buf, forceit) == OK
@@ -2180,7 +2180,14 @@ check_changed_any(
            msg_col = 0;
            msg_didout = FALSE;
        }
-       if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
+       if (
+#ifdef FEAT_TERMINAL
+               term_job_running(buf->b_term)
+                   ? EMSG2(_("E947: Job still running in buffer \"%s\""),
+                                                                 buf->b_fname)
+                   :
+#endif
+               EMSG2(_("E162: No write since last change for buffer \"%s\""),
                    buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
        {
            save = no_wait_return;
@@ -2734,13 +2741,13 @@ do_argfile(exarg_T *eap, int argn)
             * the same buffer
             */
            other = TRUE;
-           if (P_HID(curbuf))
+           if (buf_hide(curbuf))
            {
                p = fix_fname(alist_name(&ARGLIST[argn]));
                other = otherfile(p);
                vim_free(p);
            }
-           if ((!P_HID(curbuf) || !other)
+           if ((!buf_hide(curbuf) || !other)
                  && check_changed(curbuf, CCGD_AW
                                         | (other ? 0 : CCGD_MULTWIN)
                                         | (eap->forceit ? CCGD_FORCEIT : 0)
@@ -2761,7 +2768,7 @@ do_argfile(exarg_T *eap, int argn)
         * argument index. */
        if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
                      eap, ECMD_LAST,
-                     (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
+                     (buf_hide(curwin->w_buffer) ? ECMD_HIDE : 0)
                         + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
            curwin->w_arg_idx = old_arg_idx;
        /* like Vi: set the mark where the cursor is in the file. */
@@ -2782,7 +2789,7 @@ ex_next(exarg_T *eap)
      * check for changed buffer now, if this fails the argument list is not
      * redefined.
      */
-    if (       P_HID(curbuf)
+    if (       buf_hide(curbuf)
            || eap->cmdidx == CMD_snext
            || !check_changed(curbuf, CCGD_AW
                                    | (eap->forceit ? CCGD_FORCEIT : 0)
@@ -2937,7 +2944,7 @@ ex_listdo(exarg_T *eap)
 
     if (eap->cmdidx == CMD_windo
            || eap->cmdidx == CMD_tabdo
-           || P_HID(curbuf)
+           || buf_hide(curbuf)
            || !check_changed(curbuf, CCGD_AW
                                    | (eap->forceit ? CCGD_FORCEIT : 0)
                                    | CCGD_EXCMD))
index f913b19cdfbe143a73220ae7305f4f916474461d..c61cd2e95546eb4c2a7dd99916b10d303800fa47 100644 (file)
@@ -7291,7 +7291,7 @@ ex_quit(exarg_T *eap)
      */
     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
        exiting = TRUE;
-    if ((!P_HID(curbuf)
+    if ((!buf_hide(curbuf)
                && check_changed(curbuf, (p_awa ? CCGD_AW : 0)
                                       | (eap->forceit ? CCGD_FORCEIT : 0)
                                       | CCGD_EXCMD))
@@ -7318,7 +7318,7 @@ ex_quit(exarg_T *eap)
        need_mouse_correct = TRUE;
 # endif
        /* close window; may free buffer */
-       win_close(wp, !P_HID(wp->w_buffer) || eap->forceit);
+       win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit);
 #endif
     }
 }
@@ -7438,7 +7438,7 @@ ex_win_close(
     buf_T      *buf = win->w_buffer;
 
     need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
-    if (need_hide && !P_HID(buf) && !forceit)
+    if (need_hide && !buf_hide(buf) && !forceit)
     {
 # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
        if ((p_confirm || cmdmod.confirm) && p_write)
@@ -7465,9 +7465,9 @@ ex_win_close(
 
     /* free buffer when not hiding it or when it's a scratch buffer */
     if (tp == NULL)
-       win_close(win, !need_hide && !P_HID(buf));
+       win_close(win, !need_hide && !buf_hide(buf));
     else
-       win_close_othertab(win, !need_hide && !P_HID(buf), tp);
+       win_close_othertab(win, !need_hide && !buf_hide(buf), tp);
 }
 
 /*
@@ -7864,7 +7864,7 @@ ex_exit(exarg_T *eap)
        need_mouse_correct = TRUE;
 # endif
        /* Quit current window, may free the buffer. */
-       win_close(curwin, !P_HID(curwin->w_buffer));
+       win_close(curwin, !buf_hide(curwin->w_buffer));
 #endif
     }
 }
@@ -7960,7 +7960,7 @@ handle_drop(
      * We don't need to check if the 'hidden' option is set, as in this
      * case the buffer won't be lost.
      */
-    if (!P_HID(curbuf) && !split)
+    if (!buf_hide(curbuf) && !split)
     {
        ++emsg_off;
        split = check_changed(curbuf, CCGD_AW);
@@ -8747,7 +8747,7 @@ do_exedit(
                    (*eap->arg == NUL && eap->do_ecmd_lnum == 0
                                      && vim_strchr(p_cpo, CPO_GOTO1) != NULL)
                                               ? ECMD_ONE : eap->do_ecmd_lnum,
-                   (P_HID(curbuf) ? ECMD_HIDE : 0)
+                   (buf_hide(curbuf) ? ECMD_HIDE : 0)
                    + (eap->forceit ? ECMD_FORCEIT : 0)
                      /* after a split we can use an existing buffer */
                    + (old_curwin != NULL ? ECMD_OLDBUF : 0)
@@ -8761,7 +8761,7 @@ do_exedit(
            if (old_curwin != NULL)
            {
                need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
-               if (!need_hide || P_HID(curbuf))
+               if (!need_hide || buf_hide(curbuf))
                {
 # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
                    cleanup_T   cs;
@@ -8773,7 +8773,7 @@ do_exedit(
 # ifdef FEAT_GUI
                    need_mouse_correct = TRUE;
 # endif
-                   win_close(curwin, !need_hide && !P_HID(curbuf));
+                   win_close(curwin, !need_hide && !buf_hide(curbuf));
 
 # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
                    /* Restore the error/interrupt/exception state if not
index d655c74677bd2631bf6e917f7194deef16b1a316..16f9f0ea5ad7f7ca3185792aef14ab9898a603c6 100644 (file)
@@ -6255,11 +6255,11 @@ nv_gotofile(cmdarg_T *cap)
     if (ptr != NULL)
     {
        /* do autowrite if necessary */
-       if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf))
+       if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !buf_hide(curbuf))
            (void)autowrite(curbuf, FALSE);
        setpcmark();
        if (do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
-                                  P_HID(curbuf) ? ECMD_HIDE : 0, curwin) == OK
+                               buf_hide(curbuf) ? ECMD_HIDE : 0, curwin) == OK
                && cap->nchar == 'F' && lnum >= 0)
        {
            curwin->w_cursor.lnum = lnum;
index 89c79220501867ef03d90af90000aa2cf5140303..9b7e88f0d2eb7eb14b3e978b41ae025252455ad3 100644 (file)
@@ -558,13 +558,6 @@ EXTERN long        p_hh;           /* 'helpheight' */
 EXTERN char_u  *p_hlg;         /* 'helplang' */
 #endif
 EXTERN int     p_hid;          /* 'hidden' */
-/* Use P_HID to check if a buffer is to be hidden when it is no longer
- * visible in a window. */
-#ifndef FEAT_QUICKFIX
-# define P_HID(dummy) (p_hid || cmdmod.hide)
-#else
-# define P_HID(buf) (buf_hide(buf))
-#endif
 EXTERN char_u  *p_hl;          /* 'highlight' */
 EXTERN int     p_hls;          /* 'hlsearch' */
 EXTERN long    p_hi;           /* 'history' */
index d153187999de02e397ea8ae53aba2efd07beb5c6..a4120b39c63f150e69eda3be8abada7eb08ed3f9 100644 (file)
@@ -36,7 +36,6 @@
  * that buffer, attributes come from the scrollback buffer tl_scrollback.
  *
  * TODO:
- * - don't allow exiting Vim when a terminal is still running a job
  * - MS-Windows: no redraw for 'updatetime'  #1915
  * - in bash mouse clicks are inserting characters.
  * - mouse scroll: when over other window, scroll that window.
@@ -284,11 +283,16 @@ term_start(char_u *cmd, jobopt_T *opt)
     }
     curbuf->b_fname = curbuf->b_ffname;
 
+    set_string_option_direct((char_u *)"buftype", -1,
+                                 (char_u *)"terminal", OPT_FREE|OPT_LOCAL, 0);
+
     /* Mark the buffer as not modifiable. It can only be made modifiable after
      * the job finished. */
     curbuf->b_p_ma = FALSE;
-    set_string_option_direct((char_u *)"buftype", -1,
-                                 (char_u *)"terminal", OPT_FREE|OPT_LOCAL, 0);
+
+    /* Set 'bufhidden' to "hide": allow closing the window. */
+    set_string_option_direct((char_u *)"bufhidden", -1,
+                                     (char_u *)"hide", OPT_FREE|OPT_LOCAL, 0);
 
     set_term_and_win_size(term);
     setup_job_options(opt, term->tl_rows, term->tl_cols);
index 3f5e268b5b48f54e4bc13cc77dc58e15f3f10d77..98bc75843e9b4ceae85c5d19d53d244ef1411f34 100644 (file)
@@ -63,7 +63,8 @@ endfunc
 
 func Test_terminal_wipe_buffer()
   let buf = Run_shell_in_terminal()
-  exe buf . 'bwipe'
+  call assert_fails(buf . 'bwipe', 'E517')
+  exe buf . 'bwipe!'
   call WaitFor('job_status(g:job) == "dead"')
   call assert_equal('dead', job_status(g:job))
   call assert_equal("", bufname(buf))
index 6ab8572aa03f9856772fcdc5673bfd82af2bd3b5..b913841f709af2e2929ac7457c6706fabdb147f7 100644 (file)
@@ -3522,21 +3522,18 @@ u_save_line(linenr_T lnum)
     int
 bufIsChanged(buf_T *buf)
 {
-    return
-#ifdef FEAT_QUICKFIX
-           !bt_dontwrite(buf) &&
+#ifdef FEAT_TERMINAL
+    if (term_job_running(buf->b_term))
+       return TRUE;
 #endif
-           (buf->b_changed || file_ff_differs(buf, TRUE));
+    return !bt_dontwrite(buf)
+       && (buf->b_changed || file_ff_differs(buf, TRUE));
 }
 
     int
 curbufIsChanged(void)
 {
-    return
-#ifdef FEAT_QUICKFIX
-       !bt_dontwrite(curbuf) &&
-#endif
-       (curbuf->b_changed || file_ff_differs(curbuf, TRUE));
+    return bufIsChanged(curbuf);
 }
 
 #if defined(FEAT_EVAL) || defined(PROTO)
index 1c01f4f041a934dcd441b643d7946bb9d868ed8a..e50eeaf637a61226b013504c44fd54a337f5ce25 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    858,
 /**/
     857,
 /**/
index 948303c093a5c1a4f48b63adb8a2f46e554689ac..311009837cf8b43d39c532d5b98c3e7ce7506c79 100644 (file)
@@ -3379,7 +3379,8 @@ close_others(
 #endif
                    continue;
            }
-           win_close(wp, !P_HID(wp->w_buffer) && !bufIsChanged(wp->w_buffer));
+           win_close(wp, !buf_hide(wp->w_buffer)
+                                              && !bufIsChanged(wp->w_buffer));
        }
     }