Merge pull request #19404 from zeertzjq/vim-8.2.0670

vim-patch:8.2.{0670,0698,1294,1984,2424,2426,2427,5029}: textlock patches
This commit is contained in:
zeertzjq 2022-07-17 14:15:32 +08:00 committed by GitHub
commit 9e7f92e59a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 545 additions and 384 deletions

View File

@ -136,7 +136,6 @@ static char *ctrl_x_mode_names[] = {
}; };
static char e_hitend[] = N_("Hit end of paragraph"); static char e_hitend[] = N_("Hit end of paragraph");
static char e_complwin[] = N_("E839: Completion function changed window");
static char e_compldel[] = N_("E840: Completion function deleted text"); static char e_compldel[] = N_("E840: Completion function deleted text");
/* /*
@ -3939,8 +3938,6 @@ static void expand_by_function(int type, char_u *base)
dict_T *matchdict = NULL; dict_T *matchdict = NULL;
char_u *funcname; char_u *funcname;
pos_T pos; pos_T pos;
win_T *curwin_save;
buf_T *curbuf_save;
typval_T rettv; typval_T rettv;
const int save_State = State; const int save_State = State;
@ -3959,9 +3956,9 @@ static void expand_by_function(int type, char_u *base)
args[1].vval.v_string = base != NULL ? (char *)base : ""; args[1].vval.v_string = base != NULL ? (char *)base : "";
pos = curwin->w_cursor; pos = curwin->w_cursor;
curwin_save = curwin; // Lock the text to avoid weird things from happening. Also disallow
curbuf_save = curbuf; // switching to another window, it should not be needed and may end up in
// Lock the text to avoid weird things from happening. // Insert mode in another buffer.
textlock++; textlock++;
// Call a function, which returns a list or dict. // Call a function, which returns a list or dict.
@ -3983,10 +3980,6 @@ static void expand_by_function(int type, char_u *base)
} }
textlock--; textlock--;
if (curwin_save != curwin || curbuf_save != curbuf) {
emsg(_(e_complwin));
goto theend;
}
curwin->w_cursor = pos; // restore the cursor position curwin->w_cursor = pos; // restore the cursor position
validate_cursor(); validate_cursor();
if (!equalpos(curwin->w_cursor, pos)) { if (!equalpos(curwin->w_cursor, pos)) {
@ -5224,8 +5217,6 @@ static int ins_complete(int c, bool enable_pum)
// set to 1 to obtain the length of text to use for completion. // set to 1 to obtain the length of text to use for completion.
char_u *funcname; char_u *funcname;
pos_T pos; pos_T pos;
win_T *curwin_save;
buf_T *curbuf_save;
const int save_State = State; const int save_State = State;
// Call 'completefunc' or 'omnifunc' and get pattern length as a string // Call 'completefunc' or 'omnifunc' and get pattern length as a string
@ -5246,15 +5237,11 @@ static int ins_complete(int c, bool enable_pum)
args[1].vval.v_string = ""; args[1].vval.v_string = "";
pos = curwin->w_cursor; pos = curwin->w_cursor;
curwin_save = curwin; textlock++;
curbuf_save = curbuf;
colnr_T col = (colnr_T)call_func_retnr((char *)funcname, 2, args); colnr_T col = (colnr_T)call_func_retnr((char *)funcname, 2, args);
textlock--;
State = save_State; State = save_State;
if (curwin_save != curwin || curbuf_save != curbuf) {
emsg(_(e_complwin));
return FAIL;
}
curwin->w_cursor = pos; // restore the cursor position curwin->w_cursor = pos; // restore the cursor position
validate_cursor(); validate_cursor();
if (!equalpos(curwin->w_cursor, pos)) { if (!equalpos(curwin->w_cursor, pos)) {

View File

@ -1062,11 +1062,6 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return; return;
} }
const int save_textlock = textlock;
// "textlock" is set when evaluating 'completefunc' but we can change text
// here.
textlock = 0;
// Check for undo allowed here, because if something was already inserted // Check for undo allowed here, because if something was already inserted
// the line was already saved for undo and this check isn't done. // the line was already saved for undo and this check isn't done.
if (!undo_allowed(curbuf)) { if (!undo_allowed(curbuf)) {
@ -1081,7 +1076,6 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
set_completion(startcol - 1, argvars[1].vval.v_list); set_completion(startcol - 1, argvars[1].vval.v_list);
} }
} }
textlock = save_textlock;
} }
/// "complete_add()" function /// "complete_add()" function

File diff suppressed because it is too large Load Diff

View File

@ -57,11 +57,12 @@
#define EX_BUFUNL 0x10000 // accepts unlisted buffer too #define EX_BUFUNL 0x10000 // accepts unlisted buffer too
#define EX_ARGOPT 0x20000 // allow "++opt=val" argument #define EX_ARGOPT 0x20000 // allow "++opt=val" argument
#define EX_SBOXOK 0x40000 // allowed in the sandbox #define EX_SBOXOK 0x40000 // allowed in the sandbox
#define EX_CMDWIN 0x80000 // allowed in cmdline window; when missing #define EX_CMDWIN 0x80000 // allowed in cmdline window
// disallows editing another buffer when
// current buffer is locked
#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer #define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer
#define EX_FLAGS 0x200000 // allow flags after count in argument #define EX_FLAGS 0x200000 // allow flags after count in argument
#define EX_LOCK_OK 0x1000000 // command can be executed when textlock is
// set; when missing disallows editing another
// buffer when current buffer is locked
#define EX_KEEPSCRIPT 0x4000000 // keep sctx of where command was invoked #define EX_KEEPSCRIPT 0x4000000 // keep sctx of where command was invoked
#define EX_PREVIEW 0x8000000 // allow incremental command preview #define EX_PREVIEW 0x8000000 // allow incremental command preview
#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed #define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed

View File

@ -1590,9 +1590,15 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
&& !(curbuf->terminal && eap->cmdidx == CMD_put)) { && !(curbuf->terminal && eap->cmdidx == CMD_put)) {
ERROR(_(e_modifiable)); ERROR(_(e_modifiable));
} }
if (text_locked() && !(eap->argt & EX_CMDWIN) if (!IS_USER_CMDIDX(eap->cmdidx)) {
&& !IS_USER_CMDIDX(eap->cmdidx)) { if (cmdwin_type != 0 && !(eap->argt & EX_CMDWIN)) {
ERROR(_(get_text_locked_msg())); // Command not allowed in the command line window
ERROR(_(e_cmdwin));
}
if (text_locked() && !(eap->argt & EX_LOCK_OK)) {
// Command not allowed when text is locked
ERROR(_(get_text_locked_msg()));
}
} }
// Disallow editing another buffer when "curbuf->b_ro_locked" is set. // Disallow editing another buffer when "curbuf->b_ro_locked" is set.
// Do allow ":checktime" (it is postponed). // Do allow ":checktime" (it is postponed).
@ -1967,11 +1973,17 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
goto doend; goto doend;
} }
if (text_locked() && !(ea.argt & EX_CMDWIN) if (!IS_USER_CMDIDX(ea.cmdidx)) {
&& !IS_USER_CMDIDX(ea.cmdidx)) { if (cmdwin_type != 0 && !(ea.argt & EX_CMDWIN)) {
// Command not allowed when editing the command line. // Command not allowed in the command line window
errormsg = _(get_text_locked_msg()); errormsg = _(e_cmdwin);
goto doend; goto doend;
}
if (text_locked() && !(ea.argt & EX_LOCK_OK)) {
// Command not allowed when text is locked
errormsg = _(get_text_locked_msg());
goto doend;
}
} }
// Disallow editing another buffer when "curbuf->b_ro_locked" is set. // Disallow editing another buffer when "curbuf->b_ro_locked" is set.

View File

@ -2696,14 +2696,12 @@ char_u *get_cmdprompt(void)
return ccline.cmdprompt; return ccline.cmdprompt;
} }
/* /// Return true when the text must not be changed and we can't switch to
* Return TRUE when the text must not be changed and we can't switch to /// another window or buffer. True when editing the command line etc.
* another window or buffer. Used when editing the command line etc. bool text_locked(void)
*/
int text_locked(void)
{ {
if (cmdwin_type != 0) { if (cmdwin_type != 0) {
return TRUE; return true;
} }
return textlock != 0; return textlock != 0;
} }

View File

@ -55,6 +55,14 @@ func CheckMSWindows()
endif endif
endfunc endfunc
" Command to check for NOT running on MS-Windows
command CheckNotMSWindows call CheckNotMSWindows()
func CheckNotMSWindows()
if has('win32')
throw 'Skipped: does not work on MS-Windows'
endif
endfunc
" Command to check for running on Unix " Command to check for running on Unix
command CheckUnix call CheckUnix() command CheckUnix call CheckUnix()
func CheckUnix() func CheckUnix()
@ -129,14 +137,6 @@ func CheckEnglish()
endif endif
endfunc endfunc
" Command to check for NOT running on MS-Windows
command CheckNotMSWindows call CheckNotMSWindows()
func CheckNotMSWindows()
if has('win32')
throw 'Skipped: does not work on MS-Windows'
endif
endfunc
" Command to check for not running under ASAN " Command to check for not running under ASAN
command CheckNotAsan call CheckNotAsan() command CheckNotAsan call CheckNotAsan()
func CheckNotAsan() func CheckNotAsan()

View File

@ -349,8 +349,8 @@ func Test_edit_11_indentexpr()
bw! bw!
endfunc endfunc
" Test changing indent in replace mode
func Test_edit_12() func Test_edit_12()
" Test changing indent in replace mode
new new
call setline(1, ["\tabc", "\tdef"]) call setline(1, ["\tabc", "\tdef"])
call cursor(2, 4) call cursor(2, 4)
@ -389,15 +389,15 @@ func Test_edit_12()
call feedkeys("R\<c-t>\<c-t>", 'tnix') call feedkeys("R\<c-t>\<c-t>", 'tnix')
call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
call assert_equal([0, 2, 2, 0], getpos('.')) call assert_equal([0, 2, 2, 0], getpos('.'))
set et set sw&
set sw& et&
" In replace mode, after hitting enter in a line with tab characters,
" pressing backspace should restore the tab characters.
%d %d
call setline(1, ["\t/*"]) setlocal autoindent backspace=2
set formatoptions=croql call setline(1, "\tone\t\ttwo")
call cursor(1, 3) exe "normal ggRred\<CR>six" .. repeat("\<BS>", 8)
call feedkeys("A\<cr>\<cr>/", 'tnix') call assert_equal(["\tone\t\ttwo"], getline(1, '$'))
call assert_equal(["\t/*", " *", " */"], getline(1, '$'))
set formatoptions&
bw! bw!
endfunc endfunc

View File

@ -191,6 +191,9 @@ func Test_ex_mode_errors()
endfunc endfunc
func Test_ex_mode_count_overflow() func Test_ex_mode_count_overflow()
" The multiplication causes an integer overflow
CheckNotAsan
" this used to cause a crash " this used to cause a crash
let lines =<< trim END let lines =<< trim END
call feedkeys("\<Esc>gQ\<CR>") call feedkeys("\<Esc>gQ\<CR>")

View File

@ -601,6 +601,87 @@ func Test_ins_compl_tag_sft()
%bwipe! %bwipe!
endfunc endfunc
" Test for 'completefunc' deleting text
func Test_completefunc_error()
new
" delete text when called for the first time
func CompleteFunc(findstart, base)
if a:findstart == 1
normal dd
return col('.') - 1
endif
return ['a', 'b']
endfunc
set completefunc=CompleteFunc
call setline(1, ['', 'abcd', ''])
call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:')
" delete text when called for the second time
func CompleteFunc2(findstart, base)
if a:findstart == 1
return col('.') - 1
endif
normal dd
return ['a', 'b']
endfunc
set completefunc=CompleteFunc2
call setline(1, ['', 'abcd', ''])
call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:')
" Jump to a different window from the complete function
func CompleteFunc3(findstart, base)
if a:findstart == 1
return col('.') - 1
endif
wincmd p
return ['a', 'b']
endfunc
set completefunc=CompleteFunc3
new
call assert_fails('exe "normal a\<C-X>\<C-U>"', 'E565:')
close!
set completefunc&
delfunc CompleteFunc
delfunc CompleteFunc2
delfunc CompleteFunc3
close!
endfunc
" Test for returning non-string values from 'completefunc'
func Test_completefunc_invalid_data()
new
func! CompleteFunc(findstart, base)
if a:findstart == 1
return col('.') - 1
endif
return [{}, '', 'moon']
endfunc
set completefunc=CompleteFunc
exe "normal i\<C-X>\<C-U>"
call assert_equal('moon', getline(1))
set completefunc&
close!
endfunc
" Test for errors in using complete() function
func Test_complete_func_error()
call assert_fails('call complete(1, ["a"])', 'E785:')
func ListColors()
call complete(col('.'), "blue")
endfunc
call assert_fails('exe "normal i\<C-R>=ListColors()\<CR>"', 'E474:')
func ListMonths()
call complete(col('.'), test_null_list())
endfunc
" Nvim allows a NULL list
" call assert_fails('exe "normal i\<C-R>=ListMonths()\<CR>"', 'E474:')
delfunc ListColors
delfunc ListMonths
call assert_fails('call complete_info({})', 'E714:')
call assert_equal([], complete_info(['items']).items)
endfunc
" Test for completing words following a completed word in a line " Test for completing words following a completed word in a line
func Test_complete_wrapscan() func Test_complete_wrapscan()
" complete words from another buffer " complete words from another buffer

View File

@ -382,11 +382,11 @@ func Test_completefunc_opens_new_window_two()
setlocal completefunc=DummyCompleteTwo setlocal completefunc=DummyCompleteTwo
call setline(1, 'two') call setline(1, 'two')
/^two /^two
call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E764:') call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E565:')
call assert_notequal(winid, win_getid())
q!
call assert_equal(winid, win_getid()) call assert_equal(winid, win_getid())
call assert_equal('two', getline(1)) " v8.2.1919 hasn't been ported yet
" call assert_equal('twodef', getline(1))
call assert_equal('twoDEF', getline(1))
q! q!
endfunc endfunc
@ -655,8 +655,8 @@ func Test_complete_func_mess()
set completefunc=MessComplete set completefunc=MessComplete
new new
call setline(1, 'Ju') call setline(1, 'Ju')
call feedkeys("A\<c-x>\<c-u>/\<esc>", 'tx') call assert_fails('call feedkeys("A\<c-x>\<c-u>/\<esc>", "tx")', 'E565:')
call assert_equal('Oct/Oct', getline(1)) call assert_equal('Jan/', getline(1))
bwipe! bwipe!
set completefunc= set completefunc=
endfunc endfunc

View File

@ -3124,20 +3124,80 @@ func Test_file_from_copen()
endfunc endfunc
func Test_resize_from_copen() func Test_resize_from_copen()
augroup QF_Test
au!
au FileType qf resize 5
augroup END
try
" This should succeed without any exception. No other buffers are
" involved in the autocmd.
copen
finally
augroup QF_Test augroup QF_Test
au! au!
au FileType qf resize 5
augroup END augroup END
try augroup! QF_Test
" This should succeed without any exception. No other buffers are endtry
" involved in the autocmd. endfunc
copen
finally func Test_vimgrep_with_textlock()
augroup QF_Test new
au!
augroup END " Simple way to execute something with "textlock" set.
augroup! QF_Test " Check that vimgrep without jumping can be executed.
endtry au InsertCharPre * vimgrep /RunTheTest/j runtest.vim
normal ax
let qflist = getqflist()
call assert_true(len(qflist) > 0)
call assert_match('RunTheTest', qflist[0].text)
call setqflist([], 'r')
au! InsertCharPre
" Check that vimgrepadd without jumping can be executed.
au InsertCharPre * vimgrepadd /RunTheTest/j runtest.vim
normal ax
let qflist = getqflist()
call assert_true(len(qflist) > 0)
call assert_match('RunTheTest', qflist[0].text)
call setqflist([], 'r')
au! InsertCharPre
" Check that lvimgrep without jumping can be executed.
au InsertCharPre * lvimgrep /RunTheTest/j runtest.vim
normal ax
let qflist = getloclist(0)
call assert_true(len(qflist) > 0)
call assert_match('RunTheTest', qflist[0].text)
call setloclist(0, [], 'r')
au! InsertCharPre
" Check that lvimgrepadd without jumping can be executed.
au InsertCharPre * lvimgrepadd /RunTheTest/j runtest.vim
normal ax
let qflist = getloclist(0)
call assert_true(len(qflist) > 0)
call assert_match('RunTheTest', qflist[0].text)
call setloclist(0, [], 'r')
au! InsertCharPre
" trying to jump will give an error
au InsertCharPre * vimgrep /RunTheTest/ runtest.vim
call assert_fails('normal ax', 'E565:')
au! InsertCharPre
au InsertCharPre * vimgrepadd /RunTheTest/ runtest.vim
call assert_fails('normal ax', 'E565:')
au! InsertCharPre
au InsertCharPre * lvimgrep /RunTheTest/ runtest.vim
call assert_fails('normal ax', 'E565:')
au! InsertCharPre
au InsertCharPre * lvimgrepadd /RunTheTest/ runtest.vim
call assert_fails('normal ax', 'E565:')
au! InsertCharPre
bwipe!
endfunc endfunc
" Tests for the quickfix buffer b:changedtick variable " Tests for the quickfix buffer b:changedtick variable

View File

@ -1161,6 +1161,30 @@ func Test_whichwrap_multi_byte()
bwipe! bwipe!
endfunc endfunc
" Test for automatically adding comment leaders in insert mode
func Test_threepiece_comment()
new
setlocal expandtab
call setline(1, ["\t/*"])
setlocal formatoptions=croql
call cursor(1, 3)
call feedkeys("A\<cr>\<cr>/", 'tnix')
call assert_equal(["\t/*", " *", " */"], getline(1, '$'))
" If a comment ends in a single line, then don't add it in the next line
%d
call setline(1, '/* line1 */')
call feedkeys("A\<CR>next line", 'xt')
call assert_equal(['/* line1 */', 'next line'], getline(1, '$'))
%d
" Copy the trailing indentation from the leader comment to a new line
setlocal autoindent noexpandtab
call feedkeys("a\t/*\tone\ntwo\n/", 'xt')
call assert_equal(["\t/*\tone", "\t *\ttwo", "\t */"], getline(1, '$'))
close!
endfunc
" Test for the 'f' flag in 'comments' (only the first line has the comment " Test for the 'f' flag in 'comments' (only the first line has the comment
" string) " string)
func Test_firstline_comment() func Test_firstline_comment()