mirror of
https://github.com/neovim/neovim.git
synced 2026-09-20 04:28:18 +00:00
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:
@@ -136,7 +136,6 @@ static char *ctrl_x_mode_names[] = {
|
||||
};
|
||||
|
||||
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");
|
||||
|
||||
/*
|
||||
@@ -3939,8 +3938,6 @@ static void expand_by_function(int type, char_u *base)
|
||||
dict_T *matchdict = NULL;
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
win_T *curwin_save;
|
||||
buf_T *curbuf_save;
|
||||
typval_T rettv;
|
||||
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 : "";
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
curbuf_save = curbuf;
|
||||
// Lock the text to avoid weird things from happening.
|
||||
// Lock the text to avoid weird things from happening. Also disallow
|
||||
// switching to another window, it should not be needed and may end up in
|
||||
// Insert mode in another buffer.
|
||||
textlock++;
|
||||
|
||||
// Call a function, which returns a list or dict.
|
||||
@@ -3983,10 +3980,6 @@ static void expand_by_function(int type, char_u *base)
|
||||
}
|
||||
textlock--;
|
||||
|
||||
if (curwin_save != curwin || curbuf_save != curbuf) {
|
||||
emsg(_(e_complwin));
|
||||
goto theend;
|
||||
}
|
||||
curwin->w_cursor = pos; // restore the cursor position
|
||||
validate_cursor();
|
||||
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.
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
win_T *curwin_save;
|
||||
buf_T *curbuf_save;
|
||||
const int save_State = State;
|
||||
|
||||
// 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 = "";
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
curbuf_save = curbuf;
|
||||
textlock++;
|
||||
colnr_T col = (colnr_T)call_func_retnr((char *)funcname, 2, args);
|
||||
textlock--;
|
||||
|
||||
State = save_State;
|
||||
if (curwin_save != curwin || curbuf_save != curbuf) {
|
||||
emsg(_(e_complwin));
|
||||
return FAIL;
|
||||
}
|
||||
curwin->w_cursor = pos; // restore the cursor position
|
||||
validate_cursor();
|
||||
if (!equalpos(curwin->w_cursor, pos)) {
|
||||
|
||||
@@ -1062,11 +1062,6 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
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
|
||||
// the line was already saved for undo and this check isn't done.
|
||||
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);
|
||||
}
|
||||
}
|
||||
textlock = save_textlock;
|
||||
}
|
||||
|
||||
/// "complete_add()" function
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -57,11 +57,12 @@
|
||||
#define EX_BUFUNL 0x10000 // accepts unlisted buffer too
|
||||
#define EX_ARGOPT 0x20000 // allow "++opt=val" argument
|
||||
#define EX_SBOXOK 0x40000 // allowed in the sandbox
|
||||
#define EX_CMDWIN 0x80000 // allowed in cmdline window; when missing
|
||||
// disallows editing another buffer when
|
||||
// current buffer is locked
|
||||
#define EX_CMDWIN 0x80000 // allowed in cmdline window
|
||||
#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer
|
||||
#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_PREVIEW 0x8000000 // allow incremental command preview
|
||||
#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
|
||||
|
||||
@@ -1590,9 +1590,15 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
|
||||
&& !(curbuf->terminal && eap->cmdidx == CMD_put)) {
|
||||
ERROR(_(e_modifiable));
|
||||
}
|
||||
if (text_locked() && !(eap->argt & EX_CMDWIN)
|
||||
&& !IS_USER_CMDIDX(eap->cmdidx)) {
|
||||
ERROR(_(get_text_locked_msg()));
|
||||
if (!IS_USER_CMDIDX(eap->cmdidx)) {
|
||||
if (cmdwin_type != 0 && !(eap->argt & EX_CMDWIN)) {
|
||||
// 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.
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (text_locked() && !(ea.argt & EX_CMDWIN)
|
||||
&& !IS_USER_CMDIDX(ea.cmdidx)) {
|
||||
// Command not allowed when editing the command line.
|
||||
errormsg = _(get_text_locked_msg());
|
||||
goto doend;
|
||||
if (!IS_USER_CMDIDX(ea.cmdidx)) {
|
||||
if (cmdwin_type != 0 && !(ea.argt & EX_CMDWIN)) {
|
||||
// Command not allowed in the command line window
|
||||
errormsg = _(e_cmdwin);
|
||||
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.
|
||||
|
||||
@@ -2696,14 +2696,12 @@ char_u *get_cmdprompt(void)
|
||||
return ccline.cmdprompt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE when the text must not be changed and we can't switch to
|
||||
* another window or buffer. Used when editing the command line etc.
|
||||
*/
|
||||
int text_locked(void)
|
||||
/// 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.
|
||||
bool text_locked(void)
|
||||
{
|
||||
if (cmdwin_type != 0) {
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
return textlock != 0;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,14 @@ func CheckMSWindows()
|
||||
endif
|
||||
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 CheckUnix call CheckUnix()
|
||||
func CheckUnix()
|
||||
@@ -129,14 +137,6 @@ func CheckEnglish()
|
||||
endif
|
||||
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 CheckNotAsan call CheckNotAsan()
|
||||
func CheckNotAsan()
|
||||
|
||||
@@ -349,8 +349,8 @@ func Test_edit_11_indentexpr()
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" Test changing indent in replace mode
|
||||
func Test_edit_12()
|
||||
" Test changing indent in replace mode
|
||||
new
|
||||
call setline(1, ["\tabc", "\tdef"])
|
||||
call cursor(2, 4)
|
||||
@@ -389,15 +389,15 @@ func Test_edit_12()
|
||||
call feedkeys("R\<c-t>\<c-t>", 'tnix')
|
||||
call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
|
||||
call assert_equal([0, 2, 2, 0], getpos('.'))
|
||||
set et
|
||||
set sw& et&
|
||||
set sw&
|
||||
|
||||
" In replace mode, after hitting enter in a line with tab characters,
|
||||
" pressing backspace should restore the tab characters.
|
||||
%d
|
||||
call setline(1, ["\t/*"])
|
||||
set formatoptions=croql
|
||||
call cursor(1, 3)
|
||||
call feedkeys("A\<cr>\<cr>/", 'tnix')
|
||||
call assert_equal(["\t/*", " *", " */"], getline(1, '$'))
|
||||
set formatoptions&
|
||||
setlocal autoindent backspace=2
|
||||
call setline(1, "\tone\t\ttwo")
|
||||
exe "normal ggRred\<CR>six" .. repeat("\<BS>", 8)
|
||||
call assert_equal(["\tone\t\ttwo"], getline(1, '$'))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
|
||||
@@ -191,6 +191,9 @@ func Test_ex_mode_errors()
|
||||
endfunc
|
||||
|
||||
func Test_ex_mode_count_overflow()
|
||||
" The multiplication causes an integer overflow
|
||||
CheckNotAsan
|
||||
|
||||
" this used to cause a crash
|
||||
let lines =<< trim END
|
||||
call feedkeys("\<Esc>gQ\<CR>")
|
||||
|
||||
@@ -601,6 +601,87 @@ func Test_ins_compl_tag_sft()
|
||||
%bwipe!
|
||||
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
|
||||
func Test_complete_wrapscan()
|
||||
" complete words from another buffer
|
||||
|
||||
@@ -382,11 +382,11 @@ func Test_completefunc_opens_new_window_two()
|
||||
setlocal completefunc=DummyCompleteTwo
|
||||
call setline(1, 'two')
|
||||
/^two
|
||||
call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E764:')
|
||||
call assert_notequal(winid, win_getid())
|
||||
q!
|
||||
call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E565:')
|
||||
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!
|
||||
endfunc
|
||||
|
||||
@@ -655,8 +655,8 @@ func Test_complete_func_mess()
|
||||
set completefunc=MessComplete
|
||||
new
|
||||
call setline(1, 'Ju')
|
||||
call feedkeys("A\<c-x>\<c-u>/\<esc>", 'tx')
|
||||
call assert_equal('Oct/Oct', getline(1))
|
||||
call assert_fails('call feedkeys("A\<c-x>\<c-u>/\<esc>", "tx")', 'E565:')
|
||||
call assert_equal('Jan/', getline(1))
|
||||
bwipe!
|
||||
set completefunc=
|
||||
endfunc
|
||||
|
||||
@@ -3124,20 +3124,80 @@ func Test_file_from_copen()
|
||||
endfunc
|
||||
|
||||
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
|
||||
au!
|
||||
au FileType qf resize 5
|
||||
au!
|
||||
augroup END
|
||||
try
|
||||
" This should succeed without any exception. No other buffers are
|
||||
" involved in the autocmd.
|
||||
copen
|
||||
finally
|
||||
augroup QF_Test
|
||||
au!
|
||||
augroup END
|
||||
augroup! QF_Test
|
||||
endtry
|
||||
augroup! QF_Test
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
func Test_vimgrep_with_textlock()
|
||||
new
|
||||
|
||||
" Simple way to execute something with "textlock" set.
|
||||
" Check that vimgrep without jumping can be executed.
|
||||
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
|
||||
|
||||
" Tests for the quickfix buffer b:changedtick variable
|
||||
|
||||
@@ -1161,6 +1161,30 @@ func Test_whichwrap_multi_byte()
|
||||
bwipe!
|
||||
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
|
||||
" string)
|
||||
func Test_firstline_comment()
|
||||
|
||||
Reference in New Issue
Block a user