Merge remote-tracking branch 'vim/master'

This commit is contained in:
Kazuki Sakamoto
2016-09-04 20:25:23 -07:00
20 changed files with 261 additions and 134 deletions
+1 -1
View File
@@ -2059,7 +2059,7 @@ test1 \
test_utf8 \
test_wordcount \
test2 test3 test4 test5 test6 test7 test8 test9 \
test11 test12 test13 test14 test15 test17 test18 test19 \
test11 test12 test14 test15 test17 test18 test19 \
test20 test21 test22 test23 test24 test25 test26 test27 test28 test29 \
test30 test31 test32 test33 test34 test36 test37 test38 test39 \
test40 test41 test42 test43 test44 test45 test48 test49 \
+39 -11
View File
@@ -450,6 +450,11 @@ close_buffer(
int is_curbuf;
int nwindows;
bufref_T bufref;
# ifdef FEAT_WINDOWS
int is_curwin = (curwin!= NULL && curwin->w_buffer == buf);
win_T *the_curwin = curwin;
tabpage_T *the_curtab = curtab;
# endif
#endif
int unload_buf = (action != 0);
int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE);
@@ -476,6 +481,16 @@ close_buffer(
unload_buf = TRUE;
#endif
#ifdef FEAT_AUTOCMD
/* Disallow deleting the buffer when it is locked (already being closed or
* halfway a command that relies on it). Unloading is allowed. */
if (buf->b_locked > 0 && (del_buf || wipe_buf))
{
EMSG(_("E937: Attempt to delete a buffer that is in use"));
return;
}
#endif
if (win != NULL
#ifdef FEAT_WINDOWS
&& win_valid_any_tab(win) /* in case autocommands closed the window */
@@ -499,7 +514,7 @@ close_buffer(
/* When the buffer is no longer in a window, trigger BufWinLeave */
if (buf->b_nwindows == 1)
{
buf->b_closing = TRUE;
++buf->b_locked;
if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
FALSE, buf)
&& !bufref_valid(&bufref))
@@ -509,7 +524,7 @@ aucmd_abort:
EMSG(_(e_auabort));
return;
}
buf->b_closing = FALSE;
--buf->b_locked;
if (abort_if_last && one_window())
/* Autocommands made this the only window. */
goto aucmd_abort;
@@ -518,13 +533,13 @@ aucmd_abort:
* BufHidden */
if (!unload_buf)
{
buf->b_closing = TRUE;
++buf->b_locked;
if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
FALSE, buf)
&& !bufref_valid(&bufref))
/* Autocommands deleted the buffer. */
goto aucmd_abort;
buf->b_closing = FALSE;
--buf->b_locked;
if (abort_if_last && one_window())
/* Autocommands made this the only window. */
goto aucmd_abort;
@@ -534,6 +549,19 @@ aucmd_abort:
return;
# endif
}
# ifdef FEAT_WINDOWS
/* If the buffer was in curwin and the window has changed, go back to that
* window, if it still exists. This avoids that ":edit x" triggering a
* "tabnext" BufUnload autocmd leaves a window behind without a buffer. */
if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin))
{
block_autocmds();
goto_tabpage_win(the_curtab, the_curwin);
unblock_autocmds();
}
# endif
nwindows = buf->b_nwindows;
#endif
@@ -683,13 +711,13 @@ buf_freeall(buf_T *buf, int flags)
int is_curbuf = (buf == curbuf);
bufref_T bufref;
# ifdef FEAT_WINDOWS
int is_curwin = (curwin!= NULL && curwin->w_buffer == buf);
int is_curwin = (curwin != NULL && curwin->w_buffer == buf);
win_T *the_curwin = curwin;
tabpage_T *the_curtab = curtab;
# endif
/* Make sure the buffer isn't closed by autocommands. */
buf->b_closing = TRUE;
++buf->b_locked;
set_bufref(&bufref, buf);
if (buf->b_ml.ml_mfp != NULL)
{
@@ -715,7 +743,7 @@ buf_freeall(buf_T *buf, int flags)
/* autocommands deleted the buffer */
return;
}
buf->b_closing = FALSE;
--buf->b_locked;
# ifdef FEAT_WINDOWS
/* If the buffer was in curwin and the window has changed, go back to that
@@ -748,7 +776,7 @@ buf_freeall(buf_T *buf, int flags)
#endif
#ifdef FEAT_SYN_HL
/* Remove any ownsyntax, unless exiting. */
if (firstwin != NULL && curwin->w_buffer == buf)
if (curwin != NULL && curwin->w_buffer == buf)
reset_synblock(curwin);
#endif
@@ -764,7 +792,7 @@ buf_freeall(buf_T *buf, int flags)
clearFolding(win);
}
# else
if (curwin->w_buffer == buf)
if (curwin != NULL && curwin->w_buffer == buf)
clearFolding(curwin);
# endif
#endif
@@ -1373,7 +1401,7 @@ do_buffer(
*/
while (buf == curbuf
# ifdef FEAT_AUTOCMD
&& !(curwin->w_closing || curwin->w_buffer->b_closing)
&& !(curwin->w_closing || curwin->w_buffer->b_locked > 0)
# endif
&& (firstwin != lastwin || first_tabpage->tp_next != NULL))
{
@@ -5110,7 +5138,7 @@ ex_buffer_all(exarg_T *eap)
#endif
) && firstwin != lastwin
#ifdef FEAT_AUTOCMD
&& !(wp->w_closing || wp->w_buffer->b_closing)
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)
#endif
)
{
+3 -7
View File
@@ -2163,7 +2163,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
}
else
{
typval_T *tv;
typval_T *tv = NULL;
typval_T res_tv;
typval_T err_tv;
char_u *json = NULL;
@@ -2180,8 +2180,6 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
ch_logs(channel, "Calling '%s'", (char *)arg);
if (func_call(arg, &argv[2], NULL, NULL, &res_tv) == OK)
tv = &res_tv;
else
tv = NULL;
}
if (argv[id_idx].v_type == VAR_NUMBER)
@@ -2195,11 +2193,9 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
/* If evaluation failed or the result can't be encoded
* then return the string "ERROR". */
vim_free(json);
free_tv(tv);
err_tv.v_type = VAR_STRING;
err_tv.vval.v_string = (char_u *)"ERROR";
tv = &err_tv;
json = json_encode_nr_expr(id, tv, options | JSON_NL);
json = json_encode_nr_expr(id, &err_tv, options | JSON_NL);
}
if (json != NULL)
{
@@ -2212,7 +2208,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
--emsg_skip;
if (tv == &res_tv)
clear_tv(tv);
else if (tv != &err_tv)
else
free_tv(tv);
}
}
+1 -1
View File
@@ -7648,7 +7648,7 @@ max_min(typval_T *argvars, typval_T *rettv, int domax)
}
}
else
EMSG(_(e_listdictarg));
EMSG2(_(e_listdictarg), domax ? "max()" : "min()");
rettv->vval.v_number = error ? 0 : n;
}
+5 -8
View File
@@ -3872,8 +3872,8 @@ do_ecmd(
oldbuf = TRUE;
set_bufref(&bufref, buf);
(void)buf_check_timestamp(buf, FALSE);
/* Check if autocommands made buffer invalid or changed the current
* buffer. */
/* Check if autocommands made the buffer invalid or changed the
* current buffer. */
if (!bufref_valid(&bufref)
#ifdef FEAT_AUTOCMD
|| curbuf != old_curbuf.br_buf
@@ -3938,8 +3938,9 @@ do_ecmd(
win_T *the_curwin = curwin;
/* Set the w_closing flag to avoid that autocommands close the
* window. */
* window. And set b_locked for the same reason. */
the_curwin->w_closing = TRUE;
++buf->b_locked;
if (curbuf == old_curbuf.br_buf)
#endif
@@ -3953,6 +3954,7 @@ do_ecmd(
#ifdef FEAT_AUTOCMD
the_curwin->w_closing = FALSE;
--buf->b_locked;
# ifdef FEAT_EVAL
/* autocmds may abort script processing */
@@ -4139,11 +4141,6 @@ do_ecmd(
/* Assume success now */
retval = OK;
/*
* Reset cursor position, could be used by autocommands.
*/
check_cursor();
/*
* Check if we are editing the w_arg_idx file in the argument list.
*/
+3 -3
View File
@@ -7218,7 +7218,7 @@ ex_quit(exarg_T *eap)
/* Refuse to quit when locked or when the buffer in the last window is
* being closed (can only happen in autocommands). */
if (curbuf_locked() || (wp->w_buffer->b_nwindows == 1
&& wp->w_buffer->b_closing))
&& wp->w_buffer->b_locked > 0))
return;
#endif
@@ -7300,7 +7300,7 @@ ex_quit_all(exarg_T *eap)
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
/* Refuse to quit when locked or when the buffer in the last window is
* being closed (can only happen in autocommands). */
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0))
return;
#endif
@@ -7682,7 +7682,7 @@ ex_exit(exarg_T *eap)
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
/* Refuse to quit when locked or when the buffer in the last window is
* being closed (can only happen in autocommands). */
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0))
return;
#endif
+22
View File
@@ -504,6 +504,28 @@ get_cursor_rel_lnum(
return retval;
}
/*
* Make sure "pos.lnum" and "pos.col" are valid in "buf".
* This allows for the col to be on the NUL byte.
*/
void
check_pos(buf_T *buf, pos_T *pos)
{
char_u *line;
colnr_T len;
if (pos->lnum > buf->b_ml.ml_line_count)
pos->lnum = buf->b_ml.ml_line_count;
if (pos->col > 0)
{
line = ml_get_buf(buf, pos->lnum, FALSE);
len = (colnr_T)STRLEN(line);
if (pos->col > len)
pos->col = len;
}
}
/*
* Make sure curwin->w_cursor.lnum is valid.
*/
+1
View File
@@ -2508,6 +2508,7 @@ onepage(int dir, long count)
foldAdjustCursor();
#endif
cursor_correct();
check_cursor_col();
if (retval == OK)
beginline(BL_SOL | BL_FIX);
curwin->w_valid &= ~(VALID_WCOL|VALID_WROW|VALID_VIRTCOL);
+3
View File
@@ -9485,7 +9485,10 @@ get_op_vcol(
#ifdef FEAT_MBYTE
/* prevent from moving onto a trail byte */
if (has_mbyte)
{
check_pos(curwin->w_buffer, &oap->end);
mb_adjustpos(curwin->w_buffer, &oap->end);
}
#endif
getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
+8 -1
View File
@@ -4741,6 +4741,7 @@ fex_format(
int use_sandbox = was_set_insecurely((char_u *)"formatexpr",
OPT_LOCAL);
int r;
char_u *fex;
/*
* Set v:lnum to the first line number and v:count to the number of lines.
@@ -4750,16 +4751,22 @@ fex_format(
set_vim_var_nr(VV_COUNT, count);
set_vim_var_char(c);
/* Make a copy, the option could be changed while calling it. */
fex = vim_strsave(curbuf->b_p_fex);
if (fex == NULL)
return 0;
/*
* Evaluate the function.
*/
if (use_sandbox)
++sandbox;
r = (int)eval_to_number(curbuf->b_p_fex);
r = (int)eval_to_number(fex);
if (use_sandbox)
--sandbox;
set_vim_var_string(VV_CHAR, NULL, -1);
vim_free(fex);
return r;
}
+1
View File
@@ -12,6 +12,7 @@ int dec_cursor(void);
int dec(pos_T *lp);
int decl(pos_T *lp);
linenr_T get_cursor_rel_lnum(win_T *wp, linenr_T lnum);
void check_pos(buf_T *buf, pos_T *pos);
void check_cursor_lnum(void);
void check_cursor_col(void);
void check_cursor_col_win(win_T *win);
+2 -2
View File
@@ -1848,8 +1848,8 @@ struct file_buffer
int b_flags; /* various BF_ flags */
#ifdef FEAT_AUTOCMD
int b_closing; /* buffer is being closed, don't let
autocommands close it too. */
int b_locked; /* Buffer is being closed or referenced, don't
let autocommands wipe it out. */
#endif
/*
-1
View File
@@ -111,7 +111,6 @@ SCRIPTS_MORE1 = \
SCRIPTS_MORE2 = \
test2.out \
test12.out \
test13.out \
test25.out \
test49.out \
test97.out \
-64
View File
@@ -1,64 +0,0 @@
Tests for autocommands on :close command
Write three files and open them, each in a window.
Then go to next window, with autocommand that deletes the previous one.
Do this twice, writing the file.
Also test deleting the buffer on a Unload event. If this goes wrong there
will be the ATTENTION prompt.
Also test changing buffers in a BufDel autocommand. If this goes wrong there
are ml_line errors and/or a Crash.
STARTTEST
:so small.vim
:/^start of testfile/,/^end of testfile/w! Xtestje1
:/^start of testfile/,/^end of testfile/w! Xtestje2
:/^start of testfile/,/^end of testfile/w! Xtestje3
:e Xtestje1
otestje1
:w
:sp Xtestje2
otestje2
:w
:sp Xtestje3
otestje3
:w

:au WinLeave Xtestje2 bwipe

:w! test.out
:au WinLeave Xtestje1 bwipe Xtestje3
:close
:w >>test.out
:e Xtestje1
:bwipe Xtestje2 Xtestje3 test.out
:au!
:au! BufUnload Xtestje1 bwipe
:e Xtestje3
:w >>test.out
:e Xtestje2
:sp Xtestje1
:e
:w >>test.out
:au!
:only
:e Xtestje1
:bwipe Xtestje2 Xtestje3 test.out test13.in
:au BufWipeout Xtestje1 buf Xtestje1
:bwipe
:w >>test.out
:only
:help
:wincmd w
:1quit
:$put ='Final line'
:$w >>test.out
:qa!
ENDTEST
start of testfile
contents
contents
contents
end of testfile
-31
View File
@@ -1,31 +0,0 @@
start of testfile
testje1
contents
contents
contents
end of testfile
start of testfile
testje1
contents
contents
contents
end of testfile
start of testfile
testje3
contents
contents
contents
end of testfile
start of testfile
testje2
contents
contents
contents
end of testfile
start of testfile
testje1
contents
contents
contents
end of testfile
Final line
+108
View File
@@ -77,11 +77,59 @@ function Test_autocmd_bufunload_with_tabnext()
quit
call assert_equal(2, tabpagenr('$'))
autocmd! test_autocmd_bufunload_with_tabnext_group
augroup! test_autocmd_bufunload_with_tabnext_group
tablast
quit
endfunc
function Test_autocmd_bufwinleave_with_tabfirst()
tabedit
augroup sample
autocmd!
autocmd BufWinLeave <buffer> tabfirst
augroup END
call setline(1, ['a', 'b', 'c'])
edit! a.txt
endfunc
" SEGV occurs in older versions. (At least 7.4.2321 or older)
function Test_autocmd_bufunload_avoiding_SEGV_01()
split aa.txt
let lastbuf = bufnr('$')
augroup test_autocmd_bufunload
autocmd!
exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
augroup END
call assert_fails('edit bb.txt', 'E937:')
autocmd! test_autocmd_bufunload
augroup! test_autocmd_bufunload
bwipe! aa.txt
bwipe! bb.txt
endfunc
" SEGV occurs in older versions. (At least 7.4.2321 or older)
function Test_autocmd_bufunload_avoiding_SEGV_02()
setlocal buftype=nowrite
let lastbuf = bufnr('$')
augroup test_autocmd_bufunload
autocmd!
exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
augroup END
normal! i1
call assert_fails('edit a.txt', 'E517:')
call feedkeys("\<CR>")
autocmd! test_autocmd_bufunload
augroup! test_autocmd_bufunload
bwipe! a.txt
endfunc
func Test_win_tab_autocmd()
let g:record = []
@@ -196,3 +244,63 @@ func Test_augroup_deleted()
au! VimEnter
endfunc
" Tests for autocommands on :close command.
" This used to be in test13.
func Test_three_windows()
" Write three files and open them, each in a window.
" Then go to next window, with autocommand that deletes the previous one.
" Do this twice, writing the file.
e! Xtestje1
call setline(1, 'testje1')
w
sp Xtestje2
call setline(1, 'testje2')
w
sp Xtestje3
call setline(1, 'testje3')
w
wincmd w
au WinLeave Xtestje2 bwipe
wincmd w
call assert_equal('Xtestje1', expand('%'))
au WinLeave Xtestje1 bwipe Xtestje3
close
call assert_equal('Xtestje1', expand('%'))
" Test deleting the buffer on a Unload event. If this goes wrong there
" will be the ATTENTION prompt.
e Xtestje1
au!
au! BufUnload Xtestje1 bwipe
call assert_fails('e Xtestje3', 'E937:')
call assert_equal('Xtestje3', expand('%'))
e Xtestje2
sp Xtestje1
call assert_fails('e', 'E937:')
call assert_equal('Xtestje2', expand('%'))
" Test changing buffers in a BufWipeout autocommand. If this goes wrong
" there are ml_line errors and/or a Crash.
au!
only
e Xanother
e Xtestje1
bwipe Xtestje2
bwipe Xtestje3
au BufWipeout Xtestje1 buf Xtestje1
bwipe
call assert_equal('Xanother', expand('%'))
only
help
wincmd w
1quit
call assert_equal('Xanother', expand('%'))
au!
call delete('Xtestje1')
call delete('Xtestje2')
call delete('Xtestje3')
endfunc
+7
View File
@@ -335,6 +335,13 @@ function Test_printf_errors()
call assert_fails('echo printf("%d", 1.2)', 'E805:')
endfunc
function Test_max_min_errors()
call assert_fails('call max(v:true)', 'E712:')
call assert_fails('call max(v:true)', 'max()')
call assert_fails('call min(v:true)', 'E712:')
call assert_fails('call min(v:true)', 'min()')
endfunc
function Test_printf_64bit()
if has('num64')
call assert_equal("123456789012345", printf('%d', 123456789012345))
+33
View File
@@ -192,6 +192,30 @@ func! Test_normal05_formatexpr()
bw!
endfu
func Test_normal05_formatexpr_newbuf()
" Edit another buffer in the 'formatexpr' function
new
func! Format()
edit another
endfunc
set formatexpr=Format()
norm gqG
bw!
set formatexpr=
endfunc
func Test_normal05_formatexpr_setopt()
" Change the 'formatexpr' value in the function
new
func! Format()
set formatexpr=
endfunc
set formatexpr=Format()
norm gqG
bw!
set formatexpr=
endfunc
func! Test_normal06_formatprg()
" basic test for formatprg
" only test on non windows platform
@@ -398,6 +422,15 @@ func! Test_normal14_page()
bw!
endfu
func! Test_normal14_page_eol()
10new
norm oxxxxxxx
exe "norm 2\<c-f>"
" check with valgrind that cursor is put back in column 1
exe "norm 2\<c-b>"
bw!
endfunc
func! Test_normal15_z_scroll_vert()
" basic test for z commands that scroll the window
call Setup_NewWindow()
+18
View File
@@ -778,6 +778,24 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2330,
/**/
2329,
/**/
2328,
/**/
2327,
/**/
2326,
/**/
2325,
/**/
2324,
/**/
2323,
/**/
2322,
/**/
2321,
/**/
+6 -4
View File
@@ -2132,7 +2132,7 @@ close_windows(
{
if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)
#ifdef FEAT_AUTOCMD
&& !(wp->w_closing || wp->w_buffer->b_closing)
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)
#endif
)
{
@@ -2153,7 +2153,7 @@ close_windows(
for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
if (wp->w_buffer == buf
#ifdef FEAT_AUTOCMD
&& !(wp->w_closing || wp->w_buffer->b_closing)
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)
#endif
)
{
@@ -2292,7 +2292,8 @@ win_close(win_T *win, int free_buf)
}
#ifdef FEAT_AUTOCMD
if (win->w_closing || (win->w_buffer != NULL && win->w_buffer->b_closing))
if (win->w_closing || (win->w_buffer != NULL
&& win->w_buffer->b_locked > 0))
return FAIL; /* window is already being closed */
if (win == aucmd_win)
{
@@ -2508,7 +2509,8 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
#ifdef FEAT_AUTOCMD
/* Get here with win->w_buffer == NULL when win_close() detects the tab
* page changed. */
if (win->w_closing || (win->w_buffer != NULL && win->w_buffer->b_closing))
if (win->w_closing || (win->w_buffer != NULL
&& win->w_buffer->b_locked > 0))
return; /* window is already being closed */
#endif