mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 9.0.0708: :confirm does not work properly for a terminal buffer
Problem: :confirm does not work properly for a terminal buffer. Solution: Handle :confirm for a terminal buffer differently. (Yee Cheng Chin, closes #11312)
This commit is contained in:
parent
118c235112
commit
15b314ffbb
@ -129,6 +129,12 @@ an <silent> 10.330 &File.&Close<Tab>:close
|
|||||||
\ else <Bar>
|
\ else <Bar>
|
||||||
\ confirm close <Bar>
|
\ confirm close <Bar>
|
||||||
\ endif<CR>
|
\ endif<CR>
|
||||||
|
tln <silent> 10.330 &File.&Close<Tab>:close
|
||||||
|
\ <C-W>:if winheight(2) < 0 && tabpagewinnr(2) == 0 <Bar>
|
||||||
|
\ confirm enew <Bar>
|
||||||
|
\ else <Bar>
|
||||||
|
\ confirm close <Bar>
|
||||||
|
\ endif<CR>
|
||||||
an 10.335 &File.-SEP1- <Nop>
|
an 10.335 &File.-SEP1- <Nop>
|
||||||
an <silent> 10.340 &File.&Save<Tab>:w :if expand("%") == ""<Bar>browse confirm w<Bar>else<Bar>confirm w<Bar>endif<CR>
|
an <silent> 10.340 &File.&Save<Tab>:w :if expand("%") == ""<Bar>browse confirm w<Bar>else<Bar>confirm w<Bar>endif<CR>
|
||||||
an 10.350 &File.Save\ &As\.\.\.<Tab>:sav :browse confirm saveas<CR>
|
an 10.350 &File.Save\ &As\.\.\.<Tab>:sav :browse confirm saveas<CR>
|
||||||
|
51
src/buffer.c
51
src/buffer.c
@ -49,6 +49,7 @@ static int append_arg_number(win_T *wp, char_u *buf, int buflen, int add_file);
|
|||||||
static void free_buffer(buf_T *);
|
static void free_buffer(buf_T *);
|
||||||
static void free_buffer_stuff(buf_T *buf, int free_options);
|
static void free_buffer_stuff(buf_T *buf, int free_options);
|
||||||
static int bt_nofileread(buf_T *buf);
|
static int bt_nofileread(buf_T *buf);
|
||||||
|
static void no_write_message_buf(buf_T *buf);
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
# define dev_T dev_t
|
# define dev_T dev_t
|
||||||
@ -1367,6 +1368,15 @@ do_buffer_ext(
|
|||||||
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
||||||
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
||||||
{
|
{
|
||||||
|
# ifdef FEAT_TERMINAL
|
||||||
|
if (term_job_running(buf->b_term))
|
||||||
|
{
|
||||||
|
if (term_confirm_stop(buf) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
dialog_changed(buf, FALSE);
|
dialog_changed(buf, FALSE);
|
||||||
if (!bufref_valid(&bufref))
|
if (!bufref_valid(&bufref))
|
||||||
// Autocommand deleted buffer, oops! It's not changed
|
// Autocommand deleted buffer, oops! It's not changed
|
||||||
@ -1377,11 +1387,11 @@ do_buffer_ext(
|
|||||||
if (bufIsChanged(buf))
|
if (bufIsChanged(buf))
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
semsg(_(e_no_write_since_last_change_for_buffer_nr_add_bang_to_override),
|
no_write_message_buf(buf);
|
||||||
buf->b_fnum);
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1552,6 +1562,18 @@ do_buffer_ext(
|
|||||||
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
||||||
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
||||||
{
|
{
|
||||||
|
# ifdef FEAT_TERMINAL
|
||||||
|
if (term_job_running(curbuf->b_term))
|
||||||
|
{
|
||||||
|
if (term_confirm_stop(curbuf) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
// Manually kill the terminal here because this command will
|
||||||
|
// hide it otherwise.
|
||||||
|
free_terminal(curbuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
bufref_T bufref;
|
bufref_T bufref;
|
||||||
|
|
||||||
set_bufref(&bufref, buf);
|
set_bufref(&bufref, buf);
|
||||||
@ -1559,8 +1581,15 @@ do_buffer_ext(
|
|||||||
if (!bufref_valid(&bufref))
|
if (!bufref_valid(&bufref))
|
||||||
// Autocommand deleted buffer, oops!
|
// Autocommand deleted buffer, oops!
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
|
||||||
if (bufIsChanged(curbuf))
|
if (bufIsChanged(curbuf))
|
||||||
|
{
|
||||||
|
no_write_message();
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
no_write_message();
|
no_write_message();
|
||||||
@ -1940,6 +1969,18 @@ do_autochdir(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
no_write_message_buf(buf_T *buf UNUSED)
|
||||||
|
{
|
||||||
|
#ifdef FEAT_TERMINAL
|
||||||
|
if (term_job_running(buf->b_term))
|
||||||
|
emsg(_(e_job_still_running_add_bang_to_end_the_job));
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
semsg(_(e_no_write_since_last_change_for_buffer_nr_add_bang_to_override),
|
||||||
|
buf->b_fnum);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
no_write_message(void)
|
no_write_message(void)
|
||||||
{
|
{
|
||||||
@ -5751,8 +5792,8 @@ bt_nofile(buf_T *buf)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return TRUE if "buf" is a "nowrite", "nofile", "terminal" or "prompt"
|
* Return TRUE if "buf" is a "nowrite", "nofile", "terminal", "prompt", or
|
||||||
* buffer.
|
* "popup" buffer.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
bt_dontwrite(buf_T *buf)
|
bt_dontwrite(buf_T *buf)
|
||||||
|
@ -86,6 +86,13 @@ check_changed(buf_T *buf, int flags)
|
|||||||
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
||||||
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
||||||
{
|
{
|
||||||
|
# ifdef FEAT_TERMINAL
|
||||||
|
if (term_job_running(buf->b_term))
|
||||||
|
{
|
||||||
|
return term_confirm_stop(buf) == FAIL;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
buf_T *buf2;
|
buf_T *buf2;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
@ -198,6 +205,7 @@ dialog_changed(
|
|||||||
|| (cmdmod.cmod_flags & CMOD_BROWSE)
|
|| (cmdmod.cmod_flags & CMOD_BROWSE)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
|
&& !bt_dontwrite(buf2)
|
||||||
&& !buf2->b_p_ro)
|
&& !buf2->b_p_ro)
|
||||||
{
|
{
|
||||||
bufref_T bufref;
|
bufref_T bufref;
|
||||||
|
@ -6061,6 +6061,19 @@ ex_win_close(
|
|||||||
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
||||||
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write)
|
||||||
{
|
{
|
||||||
|
# ifdef FEAT_TERMINAL
|
||||||
|
if (term_job_running(buf->b_term))
|
||||||
|
{
|
||||||
|
if (term_confirm_stop(buf) == FAIL)
|
||||||
|
return;
|
||||||
|
// Manually kill the terminal here because this command will
|
||||||
|
// hide it otherwise.
|
||||||
|
free_terminal(buf);
|
||||||
|
need_hide = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
bufref_T bufref;
|
bufref_T bufref;
|
||||||
|
|
||||||
set_bufref(&bufref, buf);
|
set_bufref(&bufref, buf);
|
||||||
@ -6069,6 +6082,7 @@ ex_win_close(
|
|||||||
return;
|
return;
|
||||||
need_hide = FALSE;
|
need_hide = FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@ void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
|
|||||||
int term_job_running(term_T *term);
|
int term_job_running(term_T *term);
|
||||||
int term_job_running_not_none(term_T *term);
|
int term_job_running_not_none(term_T *term);
|
||||||
int term_none_open(term_T *term);
|
int term_none_open(term_T *term);
|
||||||
|
int term_confirm_stop(buf_T *buf);
|
||||||
int term_try_stop_job(buf_T *buf);
|
int term_try_stop_job(buf_T *buf);
|
||||||
int term_check_timers(int next_due_arg, proftime_T *now);
|
int term_check_timers(int next_due_arg, proftime_T *now);
|
||||||
int term_in_normal_mode(void);
|
int term_in_normal_mode(void);
|
||||||
|
@ -1651,6 +1651,25 @@ term_none_open(term_T *term)
|
|||||||
&& term->tl_job->jv_channel->ch_keep_open;
|
&& term->tl_job->jv_channel->ch_keep_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Used to confirm whether we would like to kill a terminal.
|
||||||
|
// Return OK when the user confirms to kill it.
|
||||||
|
// Return FAIL if the user selects otherwise.
|
||||||
|
//
|
||||||
|
int
|
||||||
|
term_confirm_stop(buf_T *buf)
|
||||||
|
{
|
||||||
|
char_u buff[DIALOG_MSG_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dialog_msg(buff, _("Kill job in \"%s\"?"), buf_get_fname(buf));
|
||||||
|
ret = vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1);
|
||||||
|
if (ret == VIM_YES)
|
||||||
|
return OK;
|
||||||
|
else
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used when exiting: kill the job in "buf" if so desired.
|
* Used when exiting: kill the job in "buf" if so desired.
|
||||||
* Return OK when the job finished.
|
* Return OK when the job finished.
|
||||||
@ -1666,14 +1685,9 @@ term_try_stop_job(buf_T *buf)
|
|||||||
if ((how == NULL || *how == NUL)
|
if ((how == NULL || *how == NUL)
|
||||||
&& (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)))
|
&& (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)))
|
||||||
{
|
{
|
||||||
char_u buff[DIALOG_MSG_SIZE];
|
if (term_confirm_stop(buf) == OK)
|
||||||
int ret;
|
|
||||||
|
|
||||||
dialog_msg(buff, _("Kill job in \"%s\"?"), buf_get_fname(buf));
|
|
||||||
ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
|
|
||||||
if (ret == VIM_YES)
|
|
||||||
how = "kill";
|
how = "kill";
|
||||||
else if (ret == VIM_CANCEL)
|
else
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -98,7 +98,7 @@ endfunc
|
|||||||
|
|
||||||
func Test_terminal_wipe_buffer()
|
func Test_terminal_wipe_buffer()
|
||||||
let buf = Run_shell_in_terminal({})
|
let buf = Run_shell_in_terminal({})
|
||||||
call assert_fails(buf . 'bwipe', 'E89:')
|
call assert_fails(buf . 'bwipe', 'E948:')
|
||||||
exe buf . 'bwipe!'
|
exe buf . 'bwipe!'
|
||||||
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
|
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
|
||||||
call assert_equal("", bufname(buf))
|
call assert_equal("", bufname(buf))
|
||||||
@ -106,6 +106,126 @@ func Test_terminal_wipe_buffer()
|
|||||||
unlet g:job
|
unlet g:job
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test that using ':confirm bwipe' on terminal works
|
||||||
|
func Test_terminal_confirm_wipe_buffer()
|
||||||
|
CheckUnix
|
||||||
|
CheckNotGui
|
||||||
|
CheckFeature dialog_con
|
||||||
|
let buf = Run_shell_in_terminal({})
|
||||||
|
call assert_fails(buf . 'bwipe', 'E948:')
|
||||||
|
call feedkeys('n', 'L')
|
||||||
|
call assert_fails('confirm ' .. buf .. 'bwipe', 'E517:')
|
||||||
|
call assert_equal(buf, bufnr())
|
||||||
|
call assert_equal(1, &modified)
|
||||||
|
call feedkeys('y', 'L')
|
||||||
|
exe 'confirm ' .. buf .. 'bwipe'
|
||||||
|
call assert_notequal(buf, bufnr())
|
||||||
|
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
|
||||||
|
call assert_equal("", bufname(buf))
|
||||||
|
|
||||||
|
unlet g:job
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test that using :b! will hide the terminal
|
||||||
|
func Test_terminal_goto_buffer()
|
||||||
|
let buf_mod = bufnr()
|
||||||
|
let buf_term = Run_shell_in_terminal({})
|
||||||
|
call assert_equal(buf_term, bufnr())
|
||||||
|
call assert_fails(buf_mod . 'b', 'E948:')
|
||||||
|
exe buf_mod . 'b!'
|
||||||
|
call assert_equal(buf_mod, bufnr())
|
||||||
|
call assert_equal('run', job_status(g:job))
|
||||||
|
call assert_notequal('', bufname(buf_term))
|
||||||
|
exec buf_mod .. 'bwipe!'
|
||||||
|
exec buf_term .. 'bwipe!'
|
||||||
|
|
||||||
|
unlet g:job
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test that using ':confirm :b' will kill terminal
|
||||||
|
func Test_terminal_confirm_goto_buffer()
|
||||||
|
CheckUnix
|
||||||
|
CheckNotGui
|
||||||
|
CheckFeature dialog_con
|
||||||
|
let buf_mod = bufnr()
|
||||||
|
let buf_term = Run_shell_in_terminal({})
|
||||||
|
call feedkeys('n', 'L')
|
||||||
|
exe 'confirm ' .. buf_mod .. 'b'
|
||||||
|
call assert_equal(buf_term, bufnr())
|
||||||
|
call feedkeys('y', 'L')
|
||||||
|
exec 'confirm ' .. buf_mod .. 'b'
|
||||||
|
call assert_equal(buf_mod, bufnr())
|
||||||
|
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
|
||||||
|
call assert_equal("", bufname(buf_term))
|
||||||
|
exec buf_mod .. 'bwipe!'
|
||||||
|
|
||||||
|
unlet g:job
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test that using :close! will hide the terminal
|
||||||
|
func Test_terminal_close_win()
|
||||||
|
let buf = Run_shell_in_terminal({})
|
||||||
|
call assert_equal(buf, bufnr())
|
||||||
|
call assert_fails('close', 'E948:')
|
||||||
|
close!
|
||||||
|
call assert_notequal(buf, bufnr())
|
||||||
|
call assert_equal('run', job_status(g:job))
|
||||||
|
call assert_notequal('', bufname(buf))
|
||||||
|
exec buf .. 'bwipe!'
|
||||||
|
|
||||||
|
unlet g:job
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test that using ':confirm close' will kill terminal
|
||||||
|
func Test_terminal_confirm_close_win()
|
||||||
|
CheckUnix
|
||||||
|
CheckNotGui
|
||||||
|
CheckFeature dialog_con
|
||||||
|
let buf = Run_shell_in_terminal({})
|
||||||
|
call feedkeys('n', 'L')
|
||||||
|
confirm close
|
||||||
|
call assert_equal(buf, bufnr())
|
||||||
|
call feedkeys('y', 'L')
|
||||||
|
confirm close
|
||||||
|
call assert_notequal(buf, bufnr())
|
||||||
|
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
|
||||||
|
call assert_equal("", bufname(buf))
|
||||||
|
|
||||||
|
unlet g:job
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test that using :quit! will kill the terminal
|
||||||
|
func Test_terminal_quit()
|
||||||
|
let buf = Run_shell_in_terminal({})
|
||||||
|
call assert_equal(buf, bufnr())
|
||||||
|
call assert_fails('quit', 'E948:')
|
||||||
|
quit!
|
||||||
|
call assert_notequal(buf, bufnr())
|
||||||
|
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
|
||||||
|
exec buf .. 'bwipe!'
|
||||||
|
|
||||||
|
unlet g:job
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test that using ':confirm quit' will kill terminal
|
||||||
|
func Test_terminal_confirm_quit()
|
||||||
|
CheckUnix
|
||||||
|
CheckNotGui
|
||||||
|
CheckFeature dialog_con
|
||||||
|
let buf = Run_shell_in_terminal({})
|
||||||
|
call feedkeys('n', 'L')
|
||||||
|
confirm quit
|
||||||
|
call assert_equal(buf, bufnr())
|
||||||
|
call feedkeys('y', 'L')
|
||||||
|
confirm quit
|
||||||
|
call assert_notequal(buf, bufnr())
|
||||||
|
call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
|
||||||
|
|
||||||
|
unlet g:job
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test :q or :next
|
||||||
|
|
||||||
func Test_terminal_split_quit()
|
func Test_terminal_split_quit()
|
||||||
let buf = Run_shell_in_terminal({})
|
let buf = Run_shell_in_terminal({})
|
||||||
split
|
split
|
||||||
@ -707,7 +827,7 @@ endfunc
|
|||||||
|
|
||||||
func Test_terminal_list_args()
|
func Test_terminal_list_args()
|
||||||
let buf = term_start([&shell, &shellcmdflag, 'echo "123"'])
|
let buf = term_start([&shell, &shellcmdflag, 'echo "123"'])
|
||||||
call assert_fails(buf . 'bwipe', 'E89:')
|
call assert_fails(buf . 'bwipe', 'E948:')
|
||||||
exe buf . 'bwipe!'
|
exe buf . 'bwipe!'
|
||||||
call assert_equal("", bufname(buf))
|
call assert_equal("", bufname(buf))
|
||||||
endfunction
|
endfunction
|
||||||
@ -1235,7 +1355,7 @@ func Test_terminal_qall_prompt()
|
|||||||
|
|
||||||
" make Vim exit, it will prompt to kill the shell
|
" make Vim exit, it will prompt to kill the shell
|
||||||
call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>")
|
call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>")
|
||||||
call WaitForAssert({-> assert_match('ancel:', term_getline(buf, 20))})
|
call WaitForAssert({-> assert_match('\[Y\]es, (N)o:', term_getline(buf, 20))})
|
||||||
call term_sendkeys(buf, "y")
|
call term_sendkeys(buf, "y")
|
||||||
call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
|
call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
|
||||||
|
|
||||||
|
@ -699,6 +699,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
708,
|
||||||
/**/
|
/**/
|
||||||
707,
|
707,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user