Patch 8.0.0858
Problem: Can exit while a terminal is still running a job.
Solution: Consider a buffer with a running job like a changed file.
Files: src/undo.c, src/terminal.c, src/option.h, src/buffer.c,
src/ex_cmds.c, src/ex_cmds2.c, src/ex_docmd.c, src/normal.c,
src/window.c, src/testdir/test_terminal.vim
*** ../vim-8.0.0857/src/undo.c 2017-07-28 22:29:31.591928613 +0200
--- src/undo.c 2017-08-03 22:18:51.829975863 +0200
***************
*** 3522,3542 ****
int
bufIsChanged(buf_T *buf)
{
! return
! #ifdef FEAT_QUICKFIX
! !bt_dontwrite(buf) &&
#endif
! (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));
}
#if defined(FEAT_EVAL) || defined(PROTO)
--- 3522,3539 ----
int
bufIsChanged(buf_T *buf)
{
! #ifdef FEAT_TERMINAL
! if (term_job_running(buf->b_term))
! return TRUE;
#endif
! return !bt_dontwrite(buf)
! && (buf->b_changed || file_ff_differs(buf, TRUE));
}
int
curbufIsChanged(void)
{
! return bufIsChanged(curbuf);
}
#if defined(FEAT_EVAL) || defined(PROTO)
*** ../vim-8.0.0857/src/terminal.c 2017-08-03 20:59:25.939943837 +0200
--- src/terminal.c 2017-08-03 22:24:37.607498206 +0200
***************
*** 36,42 ****
* 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.
--- 36,41 ----
***************
*** 284,294 ****
}
curbuf->b_fname = curbuf->b_ffname;
/* 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_term_and_win_size(term);
setup_job_options(opt, term->tl_rows, term->tl_cols);
--- 283,298 ----
}
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 '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);
*** ../vim-8.0.0857/src/option.h 2017-07-23 22:56:56.196681386 +0200
--- src/option.h 2017-08-03 22:25:10.323263742 +0200
***************
*** 558,570 ****
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' */
--- 558,563 ----
*** ../vim-8.0.0857/src/buffer.c 2017-08-01 21:44:27.082445161 +0200
--- src/buffer.c 2017-08-03 22:25:58.878915745 +0200
***************
*** 1736,1742 ****
u_sync(FALSE);
close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf,
unload ? action : (action == DOBUF_GOTO
! && !P_HID(prevbuf)
&& !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, FALSE);
#ifdef FEAT_WINDOWS
if (curwin != previouswin && win_valid(previouswin))
--- 1736,1742 ----
u_sync(FALSE);
close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf,
unload ? action : (action == DOBUF_GOTO
! && !buf_hide(prevbuf)
&& !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, FALSE);
#ifdef FEAT_WINDOWS
if (curwin != previouswin && win_valid(previouswin))
***************
*** 4986,4997 ****
if (i == opened_len && !keep_tabs)/* close this window */
{
! if (P_HID(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
&& bufIsChanged(buf))
{
#ifdef FEAT_AUTOCMD
--- 4986,4997 ----
if (i == opened_len && !keep_tabs)/* close this window */
{
! 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 (!buf_hide(buf) && buf->b_nwindows <= 1
&& bufIsChanged(buf))
{
#ifdef FEAT_AUTOCMD
***************
*** 5018,5024 ****
#ifdef FEAT_WINDOWS
else
{
! win_close(wp, !P_HID(buf) && !bufIsChanged(buf));
# ifdef FEAT_AUTOCMD
/* check if autocommands removed the next window */
if (!win_valid(wpnext))
--- 5018,5024 ----
#ifdef FEAT_WINDOWS
else
{
! win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
# ifdef FEAT_AUTOCMD
/* check if autocommands removed the next window */
if (!win_valid(wpnext))
***************
*** 5117,5123 ****
}
(void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
ECMD_ONE,
! ((P_HID(curwin->w_buffer)
|| bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
+ ECMD_OLDBUF, curwin);
#ifdef FEAT_AUTOCMD
--- 5117,5123 ----
}
(void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
ECMD_ONE,
! ((buf_hide(curwin->w_buffer)
|| bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
+ ECMD_OLDBUF, curwin);
#ifdef FEAT_AUTOCMD
***************
*** 5372,5378 ****
*/
for (wp = lastwin; open_wins > count; )
{
! r = (P_HID(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
|| autowrite(wp->w_buffer, FALSE) == OK);
#ifdef FEAT_AUTOCMD
if (!win_valid(wp))
--- 5372,5378 ----
*/
for (wp = lastwin; open_wins > count; )
{
! r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
|| autowrite(wp->w_buffer, FALSE) == OK);
#ifdef FEAT_AUTOCMD
if (!win_valid(wp))
***************
*** 5384,5390 ****
#endif
if (r)
{
! win_close(wp, !P_HID(wp->w_buffer));
--open_wins;
wp = lastwin;
}
--- 5384,5390 ----
#endif
if (r)
{
! win_close(wp, !buf_hide(wp->w_buffer));
--open_wins;
wp = lastwin;
}
*** ../vim-8.0.0857/src/ex_cmds.c 2017-07-27 22:03:45.550703059 +0200
--- src/ex_cmds.c 2017-08-03 22:26:32.974671372 +0200
***************
*** 3561,3567 ****
if (other)
++no_wait_return; /* don't wait for autowrite message */
! if (other && !forceit && curbuf->b_nwindows == 1 && !P_HID(curbuf)
&& curbufIsChanged() && autowrite(curbuf, forceit) == FAIL)
{
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
--- 3561,3567 ----
if (other)
++no_wait_return; /* don't wait for autowrite message */
! 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,3596 ****
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),
curwin) == OK)
retval = GETFILE_OPEN_OTHER; /* opened another file */
else
--- 3590,3596 ----
retval = GETFILE_SAME_FILE; /* it's in the same file */
}
else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
! (buf_hide(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0),
curwin) == OK)
retval = GETFILE_OPEN_OTHER; /* opened another file */
else
***************
*** 8401,8407 ****
* Skip the check if the 'hidden' option is set, as in this case the
* buffer won't be lost.
*/
! if (!P_HID(curbuf))
{
# ifdef FEAT_WINDOWS
++emsg_off;
--- 8401,8407 ----
* Skip the check if the 'hidden' option is set, as in this case the
* buffer won't be lost.
*/
! if (!buf_hide(curbuf))
{
# ifdef FEAT_WINDOWS
++emsg_off;
*** ../vim-8.0.0857/src/ex_cmds2.c 2017-08-03 14:29:09.895896191 +0200
--- src/ex_cmds2.c 2017-08-03 22:37:46.329843865 +0200
***************
*** 2064,2070 ****
int
can_abandon(buf_T *buf, int forceit)
{
! return ( P_HID(buf)
|| !bufIsChanged(buf)
|| buf->b_nwindows > 1
|| autowrite(buf, forceit) == OK
--- 2064,2070 ----
int
can_abandon(buf_T *buf, int forceit)
{
! return ( buf_hide(buf)
|| !bufIsChanged(buf)
|| buf->b_nwindows > 1
|| autowrite(buf, forceit) == OK
***************
*** 2180,2186 ****
msg_col = 0;
msg_didout = FALSE;
}
! if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname))
{
save = no_wait_return;
--- 2180,2193 ----
msg_col = 0;
msg_didout = FALSE;
}
! 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,2746 ****
* the same buffer
*/
other = TRUE;
! if (P_HID(curbuf))
{
p = fix_fname(alist_name(&ARGLIST[argn]));
other = otherfile(p);
vim_free(p);
}
! if ((!P_HID(curbuf) || !other)
&& check_changed(curbuf, CCGD_AW
| (other ? 0 : CCGD_MULTWIN)
| (eap->forceit ? CCGD_FORCEIT : 0)
--- 2741,2753 ----
* the same buffer
*/
other = TRUE;
! if (buf_hide(curbuf))
{
p = fix_fname(alist_name(&ARGLIST[argn]));
other = otherfile(p);
vim_free(p);
}
! if ((!buf_hide(curbuf) || !other)
&& check_changed(curbuf, CCGD_AW
| (other ? 0 : CCGD_MULTWIN)
| (eap->forceit ? CCGD_FORCEIT : 0)
***************
*** 2761,2767 ****
* 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)
+ (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. */
--- 2768,2774 ----
* argument index. */
if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
eap, ECMD_LAST,
! (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,2788 ****
* check for changed buffer now, if this fails the argument list is not
* redefined.
*/
! if ( P_HID(curbuf)
|| eap->cmdidx == CMD_snext
|| !check_changed(curbuf, CCGD_AW
| (eap->forceit ? CCGD_FORCEIT : 0)
--- 2789,2795 ----
* check for changed buffer now, if this fails the argument list is not
* redefined.
*/
! if ( buf_hide(curbuf)
|| eap->cmdidx == CMD_snext
|| !check_changed(curbuf, CCGD_AW
| (eap->forceit ? CCGD_FORCEIT : 0)
***************
*** 2937,2943 ****
if (eap->cmdidx == CMD_windo
|| eap->cmdidx == CMD_tabdo
! || P_HID(curbuf)
|| !check_changed(curbuf, CCGD_AW
| (eap->forceit ? CCGD_FORCEIT : 0)
| CCGD_EXCMD))
--- 2944,2950 ----
if (eap->cmdidx == CMD_windo
|| eap->cmdidx == CMD_tabdo
! || buf_hide(curbuf)
|| !check_changed(curbuf, CCGD_AW
| (eap->forceit ? CCGD_FORCEIT : 0)
| CCGD_EXCMD))
*** ../vim-8.0.0857/src/ex_docmd.c 2017-07-27 22:56:56.251890982 +0200
--- src/ex_docmd.c 2017-08-03 22:27:21.266325242 +0200
***************
*** 7291,7297 ****
*/
if (check_more(FALSE, eap->forceit) == OK && only_one_window())
exiting = TRUE;
! if ((!P_HID(curbuf)
&& check_changed(curbuf, (p_awa ? CCGD_AW : 0)
| (eap->forceit ? CCGD_FORCEIT : 0)
| CCGD_EXCMD))
--- 7291,7297 ----
*/
if (check_more(FALSE, eap->forceit) == OK && only_one_window())
exiting = TRUE;
! if ((!buf_hide(curbuf)
&& check_changed(curbuf, (p_awa ? CCGD_AW : 0)
| (eap->forceit ? CCGD_FORCEIT : 0)
| CCGD_EXCMD))
***************
*** 7318,7324 ****
need_mouse_correct = TRUE;
# endif
/* close window; may free buffer */
! win_close(wp, !P_HID(wp->w_buffer) || eap->forceit);
#endif
}
}
--- 7318,7324 ----
need_mouse_correct = TRUE;
# endif
/* close window; may free buffer */
! win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit);
#endif
}
}
***************
*** 7438,7444 ****
buf_T *buf = win->w_buffer;
need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
! if (need_hide && !P_HID(buf) && !forceit)
{
# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
if ((p_confirm || cmdmod.confirm) && p_write)
--- 7438,7444 ----
buf_T *buf = win->w_buffer;
need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
! if (need_hide && !buf_hide(buf) && !forceit)
{
# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
if ((p_confirm || cmdmod.confirm) && p_write)
***************
*** 7465,7473 ****
/* free buffer when not hiding it or when it's a scratch buffer */
if (tp == NULL)
! win_close(win, !need_hide && !P_HID(buf));
else
! win_close_othertab(win, !need_hide && !P_HID(buf), tp);
}
/*
--- 7465,7473 ----
/* free buffer when not hiding it or when it's a scratch buffer */
if (tp == NULL)
! win_close(win, !need_hide && !buf_hide(buf));
else
! win_close_othertab(win, !need_hide && !buf_hide(buf), tp);
}
/*
***************
*** 7864,7870 ****
need_mouse_correct = TRUE;
# endif
/* Quit current window, may free the buffer. */
! win_close(curwin, !P_HID(curwin->w_buffer));
#endif
}
}
--- 7864,7870 ----
need_mouse_correct = TRUE;
# endif
/* Quit current window, may free the buffer. */
! win_close(curwin, !buf_hide(curwin->w_buffer));
#endif
}
}
***************
*** 7960,7966 ****
* 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)
{
++emsg_off;
split = check_changed(curbuf, CCGD_AW);
--- 7960,7966 ----
* We don't need to check if the 'hidden' option is set, as in this
* case the buffer won't be lost.
*/
! if (!buf_hide(curbuf) && !split)
{
++emsg_off;
split = check_changed(curbuf, CCGD_AW);
***************
*** 8747,8753 ****
(*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)
+ (eap->forceit ? ECMD_FORCEIT : 0)
/* after a split we can use an existing buffer */
+ (old_curwin != NULL ? ECMD_OLDBUF : 0)
--- 8747,8753 ----
(*eap->arg == NUL && eap->do_ecmd_lnum == 0
&& vim_strchr(p_cpo, CPO_GOTO1) != NULL)
? ECMD_ONE : eap->do_ecmd_lnum,
! (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,8767 ****
if (old_curwin != NULL)
{
need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
! if (!need_hide || P_HID(curbuf))
{
# if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
cleanup_T cs;
--- 8761,8767 ----
if (old_curwin != NULL)
{
need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
! if (!need_hide || buf_hide(curbuf))
{
# if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
cleanup_T cs;
***************
*** 8773,8779 ****
# ifdef FEAT_GUI
need_mouse_correct = TRUE;
# endif
! win_close(curwin, !need_hide && !P_HID(curbuf));
# if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not
--- 8773,8779 ----
# ifdef FEAT_GUI
need_mouse_correct = TRUE;
# endif
! win_close(curwin, !need_hide && !buf_hide(curbuf));
# if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not
*** ../vim-8.0.0857/src/normal.c 2017-07-31 22:56:19.964702432 +0200
--- src/normal.c 2017-08-03 22:27:42.334174234 +0200
***************
*** 6255,6265 ****
if (ptr != NULL)
{
/* do autowrite if necessary */
! if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf))
(void)autowrite(curbuf, FALSE);
setpcmark();
if (do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
! P_HID(curbuf) ? ECMD_HIDE : 0, curwin) == OK
&& cap->nchar == 'F' && lnum >= 0)
{
curwin->w_cursor.lnum = lnum;
--- 6255,6265 ----
if (ptr != NULL)
{
/* do autowrite if necessary */
! if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !buf_hide(curbuf))
(void)autowrite(curbuf, FALSE);
setpcmark();
if (do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
! buf_hide(curbuf) ? ECMD_HIDE : 0, curwin) == OK
&& cap->nchar == 'F' && lnum >= 0)
{
curwin->w_cursor.lnum = lnum;
*** ../vim-8.0.0857/src/window.c 2017-07-27 22:03:45.550703059 +0200
--- src/window.c 2017-08-03 22:27:51.978105108 +0200
***************
*** 3379,3385 ****
#endif
continue;
}
! win_close(wp, !P_HID(wp->w_buffer) && !bufIsChanged(wp->w_buffer));
}
}
--- 3379,3386 ----
#endif
continue;
}
! win_close(wp, !buf_hide(wp->w_buffer)
! && !bufIsChanged(wp->w_buffer));
}
}
*** ../vim-8.0.0857/src/testdir/test_terminal.vim 2017-08-03
21:08:01.216288078 +0200
--- src/testdir/test_terminal.vim 2017-08-03 22:42:37.215757639 +0200
***************
*** 63,69 ****
func Test_terminal_wipe_buffer()
let buf = Run_shell_in_terminal()
! exe buf . 'bwipe'
call WaitFor('job_status(g:job) == "dead"')
call assert_equal('dead', job_status(g:job))
call assert_equal("", bufname(buf))
--- 63,70 ----
func Test_terminal_wipe_buffer()
let buf = Run_shell_in_terminal()
! 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))
*** ../vim-8.0.0857/src/version.c 2017-08-03 21:08:01.216288078 +0200
--- src/version.c 2017-08-03 22:17:59.846348280 +0200
***************
*** 771,772 ****
--- 771,774 ----
{ /* Add new patch number below this line */
+ /**/
+ 858,
/**/
--
Trees moving back and forth is what makes the wind blow.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.