From af2b078258c029cb45eade52f229d9a31b7a7393 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 09:28:32 +0800 Subject: vim-patch:8.2.2030: some tests fail on Mac Problem: Some tests fail on Mac. Solution: Avoid Mac test failures. Add additional test for wildmenu. (Yegappan Lakshmanan, closes vim/vim#7341) https://github.com/vim/vim/commit/4b2ce1297e6e991bf6a674f9465d26d28e648de7 --- src/nvim/testdir/runtest.vim | 7 +++++++ src/nvim/testdir/test_cmdline.vim | 30 ++++++++++++++++++++++++++++++ src/nvim/testdir/test_options.vim | 8 +++++++- 3 files changed, 44 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index fcd3d5724c..206f335751 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -114,6 +114,13 @@ if has('win32') let $PROMPT = '$P$G' endif +if has('mac') + " In MacOS, when starting a shell in a terminal, a bash deprecation warning + " message is displayed. This breaks the terminal test. Disable the warning + " message. + let $BASH_SILENCE_DEPRECATION_WARNING = 1 +endif + " Prepare for calling test_garbagecollect_now(). let v:testing = 1 diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 35886d42c5..72d2dc9cbb 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -1809,6 +1809,36 @@ func Test_read_shellcmd() endif endfunc +" Test for going up and down the directory tree using 'wildmenu' +func Test_wildmenu_dirstack() + CheckUnix + %bw! + call mkdir('Xdir1/dir2/dir3', 'p') + call writefile([], 'Xdir1/file1_1.txt') + call writefile([], 'Xdir1/file1_2.txt') + call writefile([], 'Xdir1/dir2/file2_1.txt') + call writefile([], 'Xdir1/dir2/file2_2.txt') + call writefile([], 'Xdir1/dir2/dir3/file3_1.txt') + call writefile([], 'Xdir1/dir2/dir3/file3_2.txt') + cd Xdir1/dir2/dir3 + set wildmenu + + call feedkeys(":e \\\"\", 'xt') + call assert_equal('"e file3_1.txt', @:) + call feedkeys(":e \\\\"\", 'xt') + call assert_equal('"e ../dir3/', @:) + call feedkeys(":e \\\\\"\", 'xt') + call assert_equal('"e ../../dir2/', @:) + call feedkeys(":e \\\\\\"\", 'xt') + call assert_equal('"e ../../dir2/dir3/', @:) + call feedkeys(":e \\\\\\\"\", 'xt') + call assert_equal('"e ../../dir2/dir3/file3_1.txt', @:) + + cd - + call delete('Xdir1', 'rf') + set wildmenu& +endfunc + " Test for recalling newer or older cmdline from history with , , " , , , , , or . func Test_recalling_cmdline() diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index fdfc1c0f89..e9a62d00a9 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -774,7 +774,13 @@ func Test_shell() CheckUnix let save_shell = &shell set shell= - call assert_fails('shell', 'E91:') + let caught_e91 = 0 + try + shell + catch /E91:/ + let caught_e91 = 1 + endtry + call assert_equal(1, caught_e91) let &shell = save_shell endfunc -- cgit From b94cfaf08056a43efa83a1911d9d44ce1ae73711 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 09:48:11 +0800 Subject: vim-patch:8.2.2031: some tests fail when run under valgrind Problem: Some tests fail when run under valgrind. Solution: Avoid timing problems. https://github.com/vim/vim/commit/18dc355395f2eac72ab83d984cacd26ae61c791f --- src/nvim/testdir/test_clientserver.vim | 5 +++-- src/nvim/testdir/test_debugger.vim | 19 ++++++++++++------- src/nvim/testdir/test_quotestar.vim | 5 +++-- 3 files changed, 18 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim index edf36b413b..370d0cb190 100644 --- a/src/nvim/testdir/test_clientserver.vim +++ b/src/nvim/testdir/test_clientserver.vim @@ -66,8 +66,9 @@ func Test_client_server() call remote_send(name, ":gui -f\") endif " Wait for the server to be up and answering requests. - sleep 100m - call WaitForAssert({-> assert_true(name->remote_expr("v:version", "", 1) != "")}) + " When using valgrind this can be very, very slow. + sleep 1 + call WaitForAssert({-> assert_match('\d', name->remote_expr("v:version", "", 1))}, 10000) call remote_send(name, ":let testvar = 'maybe'\") call WaitForAssert({-> assert_equal('maybe', remote_expr(name, "testvar", "", 2))}) diff --git a/src/nvim/testdir/test_debugger.vim b/src/nvim/testdir/test_debugger.vim index e038c0096a..2be94409ca 100644 --- a/src/nvim/testdir/test_debugger.vim +++ b/src/nvim/testdir/test_debugger.vim @@ -15,14 +15,18 @@ func CheckCWD() endfunc command! -nargs=0 -bar CheckCWD call CheckCWD() +" "options" argument can contain: +" 'msec' - time to wait for a match +" 'match' - "pattern" to use "lines" as pattern instead of text func CheckDbgOutput(buf, lines, options = {}) " Verify the expected output let lnum = 20 - len(a:lines) + let msec = get(a:options, 'msec', 1000) for l in a:lines if get(a:options, 'match', 'equal') ==# 'pattern' - call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, 200) + call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, msec) else - call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200) + call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, msec) endif let lnum += 1 endfor @@ -198,7 +202,7 @@ func Test_Debugger() " Start a debug session, so that reading the last line from the terminal " works properly. - call RunDbgCmd(buf, ':debug echo Foo()') + call RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()']) " No breakpoints call RunDbgCmd(buf, 'breakl', ['No breakpoints defined']) @@ -814,9 +818,10 @@ func Test_Backtrace_CmdLine() \ '-S Xtest1.vim -c "debug call GlobalFunction()"', \ {'wait_for_ruler': 0}) - " Need to wait for the vim-in-terminal to be ready + " Need to wait for the vim-in-terminal to be ready. + " With valgrind this can take quite long. call CheckDbgOutput(buf, ['command line', - \ 'cmd: call GlobalFunction()']) + \ 'cmd: call GlobalFunction()'], #{msec: 5000}) " At this point the ontly thing in the stack is the cmdline call RunDbgCmd(buf, 'backtrace', [ @@ -967,14 +972,14 @@ func Test_debug_backtrace_level() " set a breakpoint and source file1.vim let buf = RunVimInTerminal( \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim', - \ #{ wait_for_ruler: 0 } ) + \ #{wait_for_ruler: 0}) call CheckDbgOutput(buf, [ \ 'Breakpoint in "' .. file1 .. '" line 1', \ 'Entering Debug mode. Type "cont" to continue.', \ 'command line..script ' .. file1, \ 'line 1: let s:file1_var = ''file1''' - \ ]) + \ ], #{msec: 5000}) " step through the initial declarations call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] ) diff --git a/src/nvim/testdir/test_quotestar.vim b/src/nvim/testdir/test_quotestar.vim index 93865869fa..e3ca141328 100644 --- a/src/nvim/testdir/test_quotestar.vim +++ b/src/nvim/testdir/test_quotestar.vim @@ -98,8 +98,6 @@ func Do_test_quotestar_for_x11() " Running in a terminal and the GUI is available: Tell the server to open " the GUI and check that the remote command still works. - " Need to wait for the GUI to start up, otherwise the send hangs in trying - " to send to the terminal window. if has('gui_athena') || has('gui_motif') " For those GUIs, ignore the 'failed to create input context' error. call remote_send(name, ":call test_ignore_error('E285') | gui -f\") @@ -107,7 +105,10 @@ func Do_test_quotestar_for_x11() call remote_send(name, ":gui -f\") endif " Wait for the server in the GUI to be up and answering requests. + " First need to wait for the GUI to start up, otherwise the send hangs in + " trying to send to the terminal window. " On some systems and with valgrind this can be very slow. + sleep 1 call WaitForAssert({-> assert_match("1", remote_expr(name, "has('gui_running')", "", 1))}, 10000) call remote_send(name, ":let @* = 'maybe'\") -- cgit From 4f6d0d6da971ee837864bf96aa28cc24c2d58b5a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 12:02:45 +0800 Subject: vim-patch:8.2.2289: Vim9: 'cpo' can become empty (#19887) Problem: Vim9: 'cpo' can become empty. Solution: Use empty_option instead of an empty string. Update quickfix buffer after restoring 'cpo'. (closes vim/vim#7608) https://github.com/vim/vim/commit/e5a2dc87fd9d63dfd0d9c379e363ee8b8c05b14c Omit test as it is Vim9 script. --- src/nvim/eval.c | 7 ++++++- src/nvim/eval/funcs.c | 11 ++++++++--- src/nvim/ex_eval.c | 2 +- src/nvim/quickfix.c | 15 +++++++++++++-- src/nvim/syntax.c | 4 ++-- 5 files changed, 30 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index cb46e26f82..a80d2e5fbb 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2192,7 +2192,7 @@ int pattern_match(char *pat, char *text, bool ic) // avoid 'l' flag in 'cpoptions' char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = ic; @@ -8389,6 +8389,11 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags p_cpo = save_cpo; } else { // Darn, evaluating {sub} expression or {expr} changed the value. + // If it's still empty it was changed and restored, need to restore in + // the complicated way. + if (*p_cpo == NUL) { + set_option_value("cpo", 0L, save_cpo, 0); + } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 9c3c859771..94bc2f5557 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -588,7 +588,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only) int save_magic = p_magic; p_magic = true; char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; buf_T *buf = buflist_findnr(buflist_findpat((char *)name, (char *)name + STRLEN(name), true, false, curtab_only)); @@ -4893,7 +4893,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, // Make 'cpoptions' empty, the 'l' flag should not be used here. char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; rettv->vval.v_number = -1; switch (type) { @@ -7413,6 +7413,11 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir p_cpo = save_cpo; } else { // Darn, evaluating the {skip} expression changed the value. + // If it's still empty it was changed and restored, need to restore in + // the complicated way. + if (*p_cpo == NUL) { + set_option_value("cpo", 0L, save_cpo, 0); + } free_string_option((char_u *)save_cpo); } @@ -8167,7 +8172,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Make 'cpoptions' empty, the 'l' flag should not be used here. char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; const char *str = tv_get_string(&argvars[0]); const char *pat = NULL; diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 69d509abb7..82d6e66290 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -1376,7 +1376,7 @@ void ex_catch(exarg_T *eap) *end = NUL; } save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; // Disable error messages, it will make current exception // invalid emsg_off++; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 17fbbe17b8..86054b50c6 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -7062,6 +7062,7 @@ void ex_helpgrep(exarg_T *eap) } } + bool updated = false; // Make 'cpoptions' empty, the 'l' flag should not be used here. char *const save_cpo = p_cpo; p_cpo = (char *)empty_option; @@ -7092,16 +7093,26 @@ void ex_helpgrep(exarg_T *eap) qfl->qf_ptr = qfl->qf_start; qfl->qf_index = 1; qf_list_changed(qfl); - qf_update_buffer(qi, NULL); + updated = true; } if ((char_u *)p_cpo == empty_option) { p_cpo = save_cpo; } else { - // Darn, some plugin changed the value. + // Darn, some plugin changed the value. If it's still empty it was + // changed and restored, need to restore in the complicated way. + if (*p_cpo == NUL) { + set_option_value("cpo", 0L, save_cpo, 0); + } free_string_option((char_u *)save_cpo); } + if (updated) { + // This may open a window and source scripts, do this after 'cpo' was + // restored. + qf_update_buffer(qi, NULL); + } + if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf); // When adding a location list to an existing location list stack, diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 2a3ec56451..005d7dc4e1 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -5070,7 +5070,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci) // Make 'cpoptions' empty, to avoid the 'l' flag cpo_save = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; ci->sp_prog = vim_regcomp((char *)ci->sp_pattern, RE_MAGIC); p_cpo = cpo_save; @@ -5231,7 +5231,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) // Make 'cpoptions' empty, to avoid the 'l' flag cpo_save = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; curwin->w_s->b_syn_linecont_prog = vim_regcomp((char *)curwin->w_s->b_syn_linecont_pat, RE_MAGIC); p_cpo = cpo_save; -- cgit From d4d27c41b3298c25ae62bc067472bef37bc61c99 Mon Sep 17 00:00:00 2001 From: Axel Forsman Date: Mon, 22 Aug 2022 06:48:18 +0200 Subject: fix(edit.c): indentkeys double indent after "!" #12894 which is both unexpected and different from the Vim behaviour. Indent was triggered once by the '!' check in insert_execute(), and inserting the char was correctly skipped, but then triggered again in insert_check() (provided that cindent was not being ignored after manual indentation, i.e. `can_cindent == true`). While this is the smallest fix, another solution would be to remove VimState#check and instead move that to *_enter()/-_execute(), since the control flow is pretty unnecessarily convoluted as is. That would also have the benefit of differing less from the Vim source code. --- src/nvim/edit.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 6583ac8584..dc856f01fe 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -624,16 +624,17 @@ static int insert_execute(VimState *state, int key) } if (cindent_on() && ctrl_x_mode_none()) { + s->line_is_white = inindent(0); // A key name preceded by a bang means this key is not to be // inserted. Skip ahead to the re-indenting below. - // A key name preceded by a star means that indenting has to be - // done before inserting the key. - s->line_is_white = inindent(0); - if (in_cinkeys(s->c, '!', s->line_is_white)) { - insert_do_cindent(s); + if (in_cinkeys(s->c, '!', s->line_is_white) + && stop_arrow() == OK) { + do_c_expr_indent(); return 1; // continue } + // A key name preceded by a star means that indenting has to be + // done before inserting the key. if (can_cindent && in_cinkeys(s->c, '*', s->line_is_white) && stop_arrow() == OK) { do_c_expr_indent(); @@ -3657,7 +3658,7 @@ void fix_indent(void) /// Check that "cinkeys" contains the key "keytyped", /// when == '*': Only if key is preceded with '*' (indent before insert) /// when == '!': Only if key is preceded with '!' (don't insert) -/// when == ' ': Only if key is not preceded with '*' (indent afterwards) +/// when == ' ': Only if key is not preceded with '*' or '!' (indent afterwards) /// /// "keytyped" can have a few special values: /// KEY_OPEN_FORW : @@ -3697,7 +3698,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) case '!': try_match = (*look == '!'); break; default: - try_match = (*look != '*'); break; + try_match = (*look != '*') && (*look != '!'); break; } if (*look == '*' || *look == '!') { look++; -- cgit From 2bed0d1d978b42184564201088ea5fef12ec8581 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 13:56:50 +0800 Subject: vim-patch:8.2.4753: error from setting an option is silently ignored (#19888) Problem: Error from setting an option is silently ignored. Solution: Handle option value errors better. Fix uses of N_(). https://github.com/vim/vim/commit/31e5c60a682840959cae6273ccadd9aae48c928d --- src/nvim/buffer.c | 6 ++--- src/nvim/diff.c | 2 +- src/nvim/eval.c | 2 +- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/vars.c | 2 +- src/nvim/ex_cmds2.c | 12 +++++----- src/nvim/ex_docmd.c | 18 +++++++-------- src/nvim/ex_getln.c | 4 ++-- src/nvim/getchar.c | 2 +- src/nvim/help.c | 2 +- src/nvim/highlight_group.c | 2 +- src/nvim/main.c | 20 ++++++++-------- src/nvim/memline.c | 2 +- src/nvim/option.c | 57 ++++++++++++++++++++++++++++++++-------------- src/nvim/optionstr.c | 28 ++++++++++++++--------- src/nvim/popupmenu.c | 10 ++++---- src/nvim/quickfix.c | 12 +++++----- src/nvim/runtime.c | 2 +- src/nvim/spell.c | 8 +++---- src/nvim/spellfile.c | 2 +- 20 files changed, 112 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index ab5b32bf3e..15fdd977c1 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4189,8 +4189,8 @@ void buf_open_scratch(handle_T bufnr, char *bufname) apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf); (void)setfname(curbuf, bufname, NULL, true); apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf); - set_option_value("bh", 0L, "hide", OPT_LOCAL); - set_option_value("bt", 0L, "nofile", OPT_LOCAL); - set_option_value("swf", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bh", 0L, "hide", OPT_LOCAL); + set_option_value_give_err("bt", 0L, "nofile", OPT_LOCAL); + set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL); RESET_BINDING(curwin); } diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 5485d528f7..bfafc3b4e0 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1374,7 +1374,7 @@ static void set_diff_option(win_T *wp, int value) curwin = wp; curbuf = curwin->w_buffer; curbuf->b_ro_locked++; - set_option_value("diff", (long)value, NULL, OPT_LOCAL); + set_option_value_give_err("diff", (long)value, NULL, OPT_LOCAL); curbuf->b_ro_locked--; curwin = old_curwin; curbuf = curwin->w_buffer; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a80d2e5fbb..04f7347e1c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8392,7 +8392,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags // If it's still empty it was changed and restored, need to restore in // the complicated way. if (*p_cpo == NUL) { - set_option_value("cpo", 0L, save_cpo, 0); + set_option_value_give_err("cpo", 0L, save_cpo, 0); } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 94bc2f5557..94fda654f3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7416,7 +7416,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir // If it's still empty it was changed and restored, need to restore in // the complicated way. if (*p_cpo == NUL) { - set_option_value("cpo", 0L, save_cpo, 0); + set_option_value_give_err("cpo", 0L, save_cpo, 0); } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index b38849730a..23d77e0687 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1627,7 +1627,7 @@ static void set_option_from_tv(const char *varname, typval_T *varp) strval = tv_get_string_buf_chk(varp, nbuf); } if (!error && strval != NULL) { - set_option_value(varname, numval, strval, OPT_LOCAL); + set_option_value_give_err(varname, numval, strval, OPT_LOCAL); } } diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 54315a6417..2ed45f7ab8 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -544,9 +544,9 @@ void ex_listdo(exarg_T *eap) // Clear 'shm' to avoid that the file message overwrites // any output from the command. p_shm_save = (char *)vim_strsave(p_shm); - set_option_value("shm", 0L, "", 0); + set_option_value_give_err("shm", 0L, "", 0); do_argfile(eap, i); - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); } if (curwin->w_arg_idx != i) { @@ -613,9 +613,9 @@ void ex_listdo(exarg_T *eap) // Go to the next buffer. Clear 'shm' to avoid that the file // message overwrites any output from the command. p_shm_save = (char *)vim_strsave(p_shm); - set_option_value("shm", 0L, "", 0); + set_option_value_give_err("shm", 0L, "", 0); goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); // If autocommands took us elsewhere, quit here. @@ -636,9 +636,9 @@ void ex_listdo(exarg_T *eap) // Clear 'shm' to avoid that the file message overwrites // any output from the command. p_shm_save = (char *)vim_strsave(p_shm); - set_option_value("shm", 0L, "", 0); + set_option_value_give_err("shm", 0L, "", 0); ex_cnext(eap); - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); // If jumping to the next quickfix entry fails, quit here. diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 7bf272fbba..3b1b6e81e3 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6945,15 +6945,15 @@ void dialog_msg(char *buff, char *format, char *fname) static void ex_behave(exarg_T *eap) { if (STRCMP(eap->arg, "mswin") == 0) { - set_option_value("selection", 0L, "exclusive", 0); - set_option_value("selectmode", 0L, "mouse,key", 0); - set_option_value("mousemodel", 0L, "popup", 0); - set_option_value("keymodel", 0L, "startsel,stopsel", 0); + set_option_value_give_err("selection", 0L, "exclusive", 0); + set_option_value_give_err("selectmode", 0L, "mouse,key", 0); + set_option_value_give_err("mousemodel", 0L, "popup", 0); + set_option_value_give_err("keymodel", 0L, "startsel,stopsel", 0); } else if (STRCMP(eap->arg, "xterm") == 0) { - set_option_value("selection", 0L, "inclusive", 0); - set_option_value("selectmode", 0L, "", 0); - set_option_value("mousemodel", 0L, "extend", 0); - set_option_value("keymodel", 0L, "", 0); + set_option_value_give_err("selection", 0L, "inclusive", 0); + set_option_value_give_err("selectmode", 0L, "", 0); + set_option_value_give_err("mousemodel", 0L, "extend", 0); + set_option_value_give_err("keymodel", 0L, "", 0); } else { semsg(_(e_invarg2), eap->arg); } @@ -7073,7 +7073,7 @@ static void ex_setfiletype(exarg_T *eap) arg += 9; } - set_option_value("filetype", 0L, arg, OPT_LOCAL); + set_option_value_give_err("filetype", 0L, arg, OPT_LOCAL); if (arg != eap->arg) { did_filetype = false; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a0bcccb5be..9a7b093282 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4074,7 +4074,7 @@ static int open_cmdwin(void) // Create empty command-line buffer. buf_open_scratch(0, _("[Command Line]")); // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. - set_option_value("bh", 0L, "wipe", OPT_LOCAL); + set_option_value_give_err("bh", 0L, "wipe", OPT_LOCAL); curwin->w_p_rl = cmdmsg_rl; cmdmsg_rl = false; curbuf->b_p_ma = true; @@ -4092,7 +4092,7 @@ static int open_cmdwin(void) add_map("", "", MODE_INSERT, true); add_map("", "a", MODE_NORMAL, true); } - set_option_value("ft", 0L, "vim", OPT_LOCAL); + set_option_value_give_err("ft", 0L, "vim", OPT_LOCAL); } curbuf->b_ro_locked--; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 0f55158733..c8d4ef18ac 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2112,7 +2112,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth) } del_typebuf(mlen, 0); // remove the chars - set_option_value("paste", !p_paste, NULL, 0); + set_option_value_give_err("paste", !p_paste, NULL, 0); if (!(State & MODE_INSERT)) { msg_col = 0; msg_row = Rows - 1; diff --git a/src/nvim/help.c b/src/nvim/help.c index 442f2e0b7b..5b2d3a17a3 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -652,7 +652,7 @@ void fix_help_buffer(void) // Set filetype to "help". if (STRCMP(curbuf->b_p_ft, "help") != 0) { curbuf->b_ro_locked++; - set_option_value("ft", 0L, "help", OPT_LOCAL); + set_option_value_give_err("ft", 0L, "help", OPT_LOCAL); curbuf->b_ro_locked--; } diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 77424de3b8..65a50df274 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1156,7 +1156,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (dark != -1 && dark != (*p_bg == 'd') && !option_was_set("bg")) { - set_option_value("bg", 0L, (dark ? "dark" : "light"), 0); + set_option_value_give_err("bg", 0L, (dark ? "dark" : "light"), 0); reset_option_was_set("bg"); } } diff --git a/src/nvim/main.c b/src/nvim/main.c index d06b475934..3cd0a96116 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1052,7 +1052,7 @@ static void command_line_scan(mparm_T *parmp) } else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0) { parmp->use_vimrc = "NONE"; parmp->clean = true; - set_option_value("shadafile", 0L, "NONE", 0); + set_option_value_give_err("shadafile", 0L, "NONE", 0); } else if (STRNICMP(argv[0] + argv_idx, "luamod-dev", 9) == 0) { nlua_disable_preload = true; } else { @@ -1066,7 +1066,7 @@ static void command_line_scan(mparm_T *parmp) } break; case 'A': // "-A" start in Arabic mode. - set_option_value("arabic", 1L, NULL, 0); + set_option_value_give_err("arabic", 1L, NULL, 0); break; case 'b': // "-b" binary mode. // Needs to be effective before expanding file names, because @@ -1097,10 +1097,10 @@ static void command_line_scan(mparm_T *parmp) os_exit(0); case 'H': // "-H" start in Hebrew mode: rl + hkmap set. p_hkmap = true; - set_option_value("rl", 1L, NULL, 0); + set_option_value_give_err("rl", 1L, NULL, 0); break; case 'l': // "-l" lisp mode, 'lisp' and 'showmatch' on. - set_option_value("lisp", 1L, NULL, 0); + set_option_value_give_err("lisp", 1L, NULL, 0); p_sm = true; break; case 'M': // "-M" no changes or writing of files @@ -1181,7 +1181,7 @@ static void command_line_scan(mparm_T *parmp) // default is 10: a little bit verbose p_verbose = get_number_arg(argv[0], &argv_idx, 10); if (argv[0][argv_idx] != NUL) { - set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0); + set_option_value_give_err("verbosefile", 0L, argv[0] + argv_idx, 0); argv_idx = (int)STRLEN(argv[0]); } break; @@ -1189,7 +1189,7 @@ static void command_line_scan(mparm_T *parmp) // "-w {scriptout}" write to script if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) { n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value("window", n, NULL, 0); + set_option_value_give_err("window", n, NULL, 0); break; } want_argument = true; @@ -1284,7 +1284,7 @@ static void command_line_scan(mparm_T *parmp) break; case 'i': // "-i {shada}" use for shada - set_option_value("shadafile", 0L, argv[0], 0); + set_option_value_give_err("shadafile", 0L, argv[0], 0); break; case 's': { // "-s {scriptin}" read from script file @@ -1334,7 +1334,7 @@ scripterror: if (ascii_isdigit(*((char_u *)argv[0]))) { argv_idx = 0; n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value("window", n, NULL, 0); + set_option_value_give_err("window", n, NULL, 0); argv_idx = -1; break; } @@ -1735,7 +1735,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd) p_shm_save = xstrdup((char *)p_shm); snprintf(buf, sizeof(buf), "F%s", p_shm); - set_option_value("shm", 0L, buf, 0); + set_option_value_give_err("shm", 0L, buf, 0); } } else { if (curwin->w_next == NULL) { // just checking @@ -1779,7 +1779,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd) } if (p_shm_save != NULL) { - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); } diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 23bc5d59c8..fd8b2c55b5 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -993,7 +993,7 @@ void ml_recover(bool checkext) set_fileformat(b0_ff - 1, OPT_LOCAL); } if (b0_fenc != NULL) { - set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL); + set_option_value_give_err("fenc", 0L, (char *)b0_fenc, OPT_LOCAL); xfree(b0_fenc); } unchanged(curbuf, true, true); diff --git a/src/nvim/option.c b/src/nvim/option.c index 5c487a7c62..0cf5b4bddf 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -91,6 +91,19 @@ #include "nvim/os/input.h" #include "nvim/os/lang.h" +static char e_unknown_option[] + = N_("E518: Unknown option"); +static char e_not_allowed_in_modeline[] + = N_("E520: Not allowed in a modeline"); +static char e_not_allowed_in_modeline_when_modelineexpr_is_off[] + = N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); +static char e_key_code_not_set[] + = N_("E846: Key code not set"); +static char e_number_required_after_equal[] + = N_("E521: Number required after ="); +static char e_preview_window_already_exists[] + = N_("E590: A preview window already exists"); + /* * The options that are local to a window or buffer have "indir" set to one of * these values. Special values: @@ -404,7 +417,7 @@ void set_init_1(bool clean_arg) // NOTE: mlterm's author is being asked to 'set' a variable // instead of an environment variable due to inheritance. if (os_env_exists("MLTERM")) { - set_option_value("tbidi", 1L, NULL, 0); + set_option_value_give_err("tbidi", 1L, NULL, 0); } didset_options2(); @@ -915,7 +928,7 @@ int do_set(char *arg, int opt_flags) nextchar = (uint8_t)arg[len]; if (opt_idx == -1 && key == 0) { // found a mismatch: skip - errmsg = N_("E518: Unknown option"); + errmsg = e_unknown_option; goto skip; } @@ -926,7 +939,7 @@ int do_set(char *arg, int opt_flags) if (vim_strchr("=:!&<", nextchar) == NULL && (!(options[opt_idx].flags & P_BOOL) || nextchar == '?')) { - errmsg = _(e_unsupportedoption); + errmsg = e_unsupportedoption; } goto skip; } @@ -953,11 +966,11 @@ int do_set(char *arg, int opt_flags) // Disallow changing some options from modelines. if (opt_flags & OPT_MODELINE) { if (flags & (P_SECURE | P_NO_ML)) { - errmsg = N_("E520: Not allowed in a modeline"); + errmsg = e_not_allowed_in_modeline; goto skip; } if ((flags & P_MLE) && !p_mle) { - errmsg = N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); + errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; goto skip; } // In diff mode some options are overruled. This avoids that @@ -1025,7 +1038,7 @@ int do_set(char *arg, int opt_flags) } } } else { - errmsg = N_("E846: Key code not set"); + errmsg = e_key_code_not_set; goto skip; } if (nextchar != '?' @@ -1118,11 +1131,11 @@ int do_set(char *arg, int opt_flags) // Allow negative, octal and hex numbers. vim_str2nr((char_u *)arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { - errmsg = N_("E521: Number required after ="); + errmsg = e_number_required_after_equal; goto skip; } } else { - errmsg = N_("E521: Number required after ="); + errmsg = e_number_required_after_equal; goto skip; } @@ -1971,6 +1984,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va { int old_value = *(int *)varp; int old_global_value = 0; + char *errmsg = NULL; // Disallow changing some options from secure mode if ((secure || sandbox != 0) @@ -2092,7 +2106,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va FOR_ALL_WINDOWS_IN_TAB(win, curtab) { if (win->w_p_pvw && win != curwin) { curwin->w_p_pvw = false; - return N_("E590: A preview window already exists"); + return e_preview_window_already_exists; } } } @@ -2151,10 +2165,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va } } else if ((int *)varp == &curwin->w_p_spell) { // 'spell' if (curwin->w_p_spell) { - char *errmsg = did_set_spelllang(curwin); - if (errmsg != NULL) { - emsg(_(errmsg)); - } + errmsg = did_set_spelllang(curwin); } } @@ -2191,7 +2202,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va p_deco = true; // Force-set the necessary keymap for arabic. - set_option_value("keymap", 0L, "arabic", OPT_LOCAL); + errmsg = set_option_value("keymap", 0L, "arabic", OPT_LOCAL); } else { /* * 'arabic' is reset, handle various sub-settings. @@ -2271,7 +2282,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va } check_redraw(options[opt_idx].flags); - return NULL; + return errmsg; } /// Set the value of a number option, taking care of side effects @@ -2898,7 +2909,7 @@ void set_tty_background(const char *value) ? "autocmd VimEnter * ++once ++nested set bg=light" : "autocmd VimEnter * ++once ++nested set bg=dark"); } else { - set_option_value("bg", 0L, value, 0); + set_option_value_give_err("bg", 0L, value, 0); reset_option_was_set("bg"); } } @@ -3147,7 +3158,7 @@ bool is_hidden_option(int opt_idx) /// is cleared (the exact semantics of this depend /// on the option). /// -/// @return NULL on success, error message on error. +/// @return NULL on success, an untranslated error message on error. char *set_option_value(const char *const name, const long number, const char *const string, const int opt_flags) FUNC_ATTR_NONNULL_ARG(1) @@ -3217,6 +3228,18 @@ char *set_option_value(const char *const name, const long number, const char *co return NULL; } +/// Call set_option_value() and when an error is returned report it. +/// +/// @param opt_flags OPT_LOCAL or 0 (both) +void set_option_value_give_err(const char *name, long number, const char *string, int opt_flags) +{ + char *errmsg = set_option_value(name, number, string, opt_flags); + + if (errmsg != NULL) { + emsg(_(errmsg)); + } +} + /// Return true if "name" is a string option. /// Returns false if option "name" does not exist. bool is_string_option(const char *name) diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index c50225dfdf..3287abdd9c 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -45,8 +45,14 @@ # include "optionstr.c.generated.h" #endif -static char e_unclosed_expression_sequence[] = N_("E540: Unclosed expression sequence"); -static char e_unbalanced_groups[] = N_("E542: unbalanced groups"); +static char e_unclosed_expression_sequence[] + = N_("E540: Unclosed expression sequence"); +static char e_unbalanced_groups[] + = N_("E542: unbalanced groups"); +static char e_backupext_and_patchmode_are_equal[] + = N_("E589: 'backupext' and 'patchmode' are equal"); +static char e_showbreak_contains_unprintable_or_wide_character[] + = N_("E595: 'showbreak' contains unprintable or wide character"); static char *(p_ambw_values[]) = { "single", "double", NULL }; static char *(p_bg_values[]) = { "light", "dark", NULL }; @@ -381,7 +387,7 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c /// @param[in] opt_flags Option flags: expected to contain #OPT_LOCAL and/or /// #OPT_GLOBAL. /// -/// @return NULL on success, error message on error. +/// @return NULL on success, an untranslated error message on error. char *set_string_option(const int opt_idx, const char *const value, const int opt_flags) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { @@ -413,15 +419,15 @@ char *set_string_option(const int opt_idx, const char *const value, const int op char *const saved_newval = xstrdup(s); int value_checked = false; - char *const r = did_set_string_option(opt_idx, (char_u **)varp, (char_u *)oldval, - NULL, 0, - opt_flags, &value_checked); - if (r == NULL) { + char *const errmsg = did_set_string_option(opt_idx, (char_u **)varp, (char_u *)oldval, + NULL, 0, + opt_flags, &value_checked); + if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } // call autocommand after handling side effects - if (r == NULL) { + if (errmsg == NULL) { if (!starting) { trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, saved_oldval_g, saved_newval); @@ -436,7 +442,7 @@ char *set_string_option(const int opt_idx, const char *const value, const int op xfree(saved_oldval_g); xfree(saved_newval); - return r; + return errmsg; } /// Return true if "val" is a valid 'filetype' name. @@ -679,7 +685,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode' if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex, *p_pm == '.' ? p_pm + 1 : p_pm) == 0) { - errmsg = N_("E589: 'backupext' and 'patchmode' are equal"); + errmsg = e_backupext_and_patchmode_are_equal; } } else if (varp == &curwin->w_p_briopt) { // 'breakindentopt' if (briopt_check(curwin) == FAIL) { @@ -1041,7 +1047,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er } else if (gvarp == &p_sbr) { // 'showbreak' for (s = (char *)(*varp); *s;) { if (ptr2cells(s) != 1) { - errmsg = N_("E595: 'showbreak' contains unprintable or wide character"); + errmsg = e_showbreak_contains_unprintable_or_wide_character; } MB_PTR_ADV(s); } diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index a4afe97ac8..d392bb5a2c 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -744,11 +744,11 @@ static bool pum_set_selected(int n, int repeat) if (res == OK) { // Edit a new, empty buffer. Set options for a "wipeout" // buffer. - set_option_value("swf", 0L, NULL, OPT_LOCAL); - set_option_value("bl", 0L, NULL, OPT_LOCAL); - set_option_value("bt", 0L, "nofile", OPT_LOCAL); - set_option_value("bh", 0L, "wipe", OPT_LOCAL); - set_option_value("diff", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bl", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bt", 0L, "nofile", OPT_LOCAL); + set_option_value_give_err("bh", 0L, "wipe", OPT_LOCAL); + set_option_value_give_err("diff", 0L, NULL, OPT_LOCAL); } } diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 86054b50c6..d5f4996f61 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3558,12 +3558,12 @@ static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsp static void qf_set_cwindow_options(void) { // switch off 'swapfile' - set_option_value("swf", 0L, NULL, OPT_LOCAL); - set_option_value("bt", 0L, "quickfix", OPT_LOCAL); - set_option_value("bh", 0L, "hide", OPT_LOCAL); + set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bt", 0L, "quickfix", OPT_LOCAL); + set_option_value_give_err("bh", 0L, "hide", OPT_LOCAL); RESET_BINDING(curwin); curwin->w_p_diff = false; - set_option_value("fdm", 0L, "manual", OPT_LOCAL); + set_option_value_give_err("fdm", 0L, "manual", OPT_LOCAL); } // Open a new quickfix or location list window, load the quickfix buffer and @@ -4108,7 +4108,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q // resembles reading a file into a buffer, it's more logical when using // autocommands. curbuf->b_ro_locked++; - set_option_value("ft", 0L, "qf", OPT_LOCAL); + set_option_value_give_err("ft", 0L, "qf", OPT_LOCAL); curbuf->b_p_ma = false; keep_filetype = true; // don't detect 'filetype' @@ -7102,7 +7102,7 @@ void ex_helpgrep(exarg_T *eap) // Darn, some plugin changed the value. If it's still empty it was // changed and restored, need to restore in the complicated way. if (*p_cpo == NUL) { - set_option_value("cpo", 0L, save_cpo, 0); + set_option_value_give_err("cpo", 0L, save_cpo, 0); } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 914b21bb02..537c496ae2 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -923,7 +923,7 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack) xstrlcat(new_rtp, afterdir, new_rtp_capacity); } - set_option_value("rtp", 0L, new_rtp, 0); + set_option_value_give_err("rtp", 0L, new_rtp, 0); xfree(new_rtp); retval = OK; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 1e44d328b3..da712a5753 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1828,8 +1828,8 @@ static int count_syllables(slang_T *slang, const char_u *word) return cnt; } -// Parse 'spelllang' and set w_s->b_langp accordingly. -// Returns NULL if it's OK, an error message otherwise. +/// Parse 'spelllang' and set w_s->b_langp accordingly. +/// @return NULL if it's OK, an untranslated error message otherwise. char *did_set_spelllang(win_T *wp) { garray_T ga; @@ -3155,8 +3155,8 @@ void ex_spelldump(exarg_T *eap) do_cmdline_cmd("new"); // enable spelling locally in the new window - set_option_value("spell", true, "", OPT_LOCAL); - set_option_value("spl", dummy, spl, OPT_LOCAL); + set_option_value_give_err("spell", true, "", OPT_LOCAL); + set_option_value_give_err("spl", dummy, spl, OPT_LOCAL); xfree(spl); if (!buf_is_empty(curbuf)) { diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index be1373f617..be19e1d655 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -5735,7 +5735,7 @@ static void init_spellfile(void) && strstr(path_tail((char *)fname), ".ascii.") != NULL) ? "ascii" : (const char *)spell_enc())); - set_option_value("spellfile", 0L, (const char *)buf, OPT_LOCAL); + set_option_value_give_err("spellfile", 0L, (const char *)buf, OPT_LOCAL); break; } aspath = false; -- cgit From 15a768eeb02e2af39eead1ea1eb4a5a60710d6fb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 18:06:18 +0800 Subject: fix(api): avoid side effects with nvim_parse_cmd (#19890) Save and restore the cursor and last search pattern and do not change search history. --- src/nvim/ex_docmd.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 3b1b6e81e3..5e8c7dbdda 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1361,6 +1361,13 @@ bool is_cmd_ni(cmdidx_T cmdidx) bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **errormsg) { char *after_modifier = NULL; + bool retval = false; + // parsing the command modifiers may set ex_pressedreturn + const bool save_ex_pressedreturn = ex_pressedreturn; + // parsing the command range may require moving the cursor + const pos_T save_cursor = curwin->w_cursor; + // parsing the command range may set the last search pattern + save_last_search_pattern(); // Initialize cmdinfo CLEAR_POINTER(cmdinfo); @@ -1375,13 +1382,10 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er .cookie = NULL, }; - const bool save_ex_pressedreturn = ex_pressedreturn; // Parse command modifiers if (parse_command_modifiers(eap, errormsg, &cmdinfo->cmdmod, false) == FAIL) { - ex_pressedreturn = save_ex_pressedreturn; - goto err; + goto end; } - ex_pressedreturn = save_ex_pressedreturn; after_modifier = eap->cmd; // Save location after command modifiers @@ -1394,21 +1398,21 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er char *p = find_ex_command(eap, NULL); if (p == NULL) { *errormsg = _(e_ambiguous_use_of_user_defined_command); - goto err; + goto end; } // Set command address type and parse command range set_cmd_addr_type(eap, p); eap->cmd = cmd; - if (parse_cmd_address(eap, errormsg, false) == FAIL) { - goto err; + if (parse_cmd_address(eap, errormsg, true) == FAIL) { + goto end; } // Skip colon and whitespace eap->cmd = skip_colon_white(eap->cmd, true); // Fail if command is a comment or if command doesn't exist if (*eap->cmd == NUL || *eap->cmd == '"') { - goto err; + goto end; } // Fail if command is invalid if (eap->cmdidx == CMD_SIZE) { @@ -1417,7 +1421,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er char *cmdname = after_modifier ? after_modifier : cmdline; append_command(cmdname); *errormsg = (char *)IObuff; - goto err; + goto end; } // Correctly set 'forceit' for commands @@ -1456,12 +1460,12 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er // Fail if command doesn't support bang but is used with a bang if (!(eap->argt & EX_BANG) && eap->forceit) { *errormsg = _(e_nobang); - goto err; + goto end; } // Fail if command doesn't support a range but it is given a range if (!(eap->argt & EX_RANGE) && eap->addr_count > 0) { *errormsg = _(e_norange); - goto err; + goto end; } // Set default range for command if required if ((eap->argt & EX_DFLALL) && eap->addr_count == 0) { @@ -1471,7 +1475,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er // Parse register and count parse_register(eap); if (parse_count(eap, errormsg, false) == FAIL) { - goto err; + goto end; } // Remove leading whitespace and colon from next command @@ -1487,10 +1491,15 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er cmdinfo->magic.bar = true; } - return true; -err: - undo_cmdmod(&cmdinfo->cmdmod); - return false; + retval = true; +end: + if (!retval) { + undo_cmdmod(&cmdinfo->cmdmod); + } + ex_pressedreturn = save_ex_pressedreturn; + curwin->w_cursor = save_cursor; + restore_last_search_pattern(); + return retval; } static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview) -- cgit From 3c1d70f20b5d5bad3bec121e589187d15f325a9b Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Mon, 25 Jul 2022 12:23:04 +0200 Subject: feat(treesitter): allow customizing language symbol name --- src/nvim/lua/treesitter.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index f0d847e352..90b13181fb 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -14,10 +14,12 @@ #include #include #include +#include #include "nvim/api/private/helpers.h" #include "nvim/buffer.h" #include "nvim/lib/kvec.h" +#include "nvim/log.h" #include "nvim/lua/treesitter.h" #include "nvim/memline.h" #include "tree_sitter/api.h" @@ -145,18 +147,27 @@ int tslua_has_language(lua_State *L) return 1; } +// Creates the language into the internal language map. +// +// Returns true if the language is correctly loaded in the language map int tslua_add_language(lua_State *L) { const char *path = luaL_checkstring(L, 1); const char *lang_name = luaL_checkstring(L, 2); + const char *symbol_name = lang_name; + + if (lua_gettop(L) >= 3 && !lua_isnil(L, 3)) { + symbol_name = luaL_checkstring(L, 3); + } if (pmap_has(cstr_t)(&langs, lang_name)) { - return 0; + lua_pushboolean(L, true); + return 1; } #define BUFSIZE 128 char symbol_buf[BUFSIZE]; - snprintf(symbol_buf, BUFSIZE, "tree_sitter_%s", lang_name); + snprintf(symbol_buf, BUFSIZE, "tree_sitter_%s", symbol_name); #undef BUFSIZE uv_lib_t lib; @@ -179,6 +190,7 @@ int tslua_add_language(lua_State *L) TSLanguage *lang = lang_parser(); if (lang == NULL) { + uv_dlclose(&lib); return luaL_error(L, "Failed to load parser %s: internal error", path); } -- cgit From baaaa1f2b3b6ae3a989d1362a27e55dc7b0b148a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 22:09:53 +0800 Subject: vim-patch:8.2.3421: a bit of code is not covered by tests (#19895) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: A bit of code is not covered by tests. Solution: Add a few more test cases. (Dominique PellĂ©, closes vim/vim#8857) https://github.com/vim/vim/commit/d176ca3dde47c11aae0376c31b7e1ba0939c8c6c Cherry-pick Test_trim() change from patch 8.2.0448. Cherry-pick Test_History() change from patch 8.2.1736. Cherry-pick charidx() and trim() type checks from patch 8.2.3135. --- src/nvim/eval/funcs.c | 8 +++++++- src/nvim/testdir/test_functions.vim | 9 ++++++--- src/nvim/testdir/test_history.vim | 17 +++++++++++++++++ src/nvim/testdir/test_startup.vim | 4 ++-- 4 files changed, 32 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 94fda654f3..181b17f747 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -874,7 +874,8 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER || (argvars[2].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_NUMBER)) { + && argvars[2].v_type != VAR_NUMBER + && argvars[2].v_type != VAR_BOOL)) { emsg(_(e_invarg)); return; } @@ -9460,6 +9461,11 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } + if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_STRING) { + semsg(_(e_invarg2), tv_get_string(&argvars[1])); + return; + } + if (argvars[1].v_type == VAR_STRING) { mask = (const char_u *)tv_get_string_buf_chk(&argvars[1], buf2); if (argvars[2].v_type != VAR_UNKNOWN) { diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 44b6f0373e..ee63c0e1bd 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1420,12 +1420,15 @@ func Test_trim() call assert_equal("vim", trim(" vim ", " ", 0)) call assert_equal("vim ", trim(" vim ", " ", 1)) call assert_equal(" vim", trim(" vim ", " ", 2)) - call assert_fails('call trim(" vim ", " ", [])', 'E745:') - call assert_fails('call trim(" vim ", " ", -1)', 'E475:') - call assert_fails('call trim(" vim ", " ", 3)', 'E475:') + call assert_fails('eval trim(" vim ", " ", [])', 'E745:') + call assert_fails('eval trim(" vim ", " ", -1)', 'E475:') + call assert_fails('eval trim(" vim ", " ", 3)', 'E475:') + call assert_fails('eval trim(" vim ", 0)', 'E475:') let chars = join(map(range(1, 0x20) + [0xa0], {n -> n->nr2char()}), '') call assert_equal("x", trim(chars . "x" . chars)) + + call assert_fails('let c=trim([])', 'E730:') endfunc " Test for reg_recording() and reg_executing() diff --git a/src/nvim/testdir/test_history.vim b/src/nvim/testdir/test_history.vim index feb521e232..f1c31dee04 100644 --- a/src/nvim/testdir/test_history.vim +++ b/src/nvim/testdir/test_history.vim @@ -95,6 +95,23 @@ function Test_History() call assert_fails('call histnr([])', 'E730:') call assert_fails('history xyz', 'E488:') call assert_fails('history ,abc', 'E488:') + call assert_fails('call histdel(":", "\\%(")', 'E53:') +endfunction + +function Test_history_truncates_long_entry() + " History entry short enough to fit on the screen should not be truncated. + call histadd(':', 'echo x' .. repeat('y', &columns - 17) .. 'z') + let a = execute('history : -1') + + call assert_match("^\n # cmd history\n" + \ .. "> *\\d\\+ echo x" .. repeat('y', &columns - 17) .. 'z$', a) + + " Long history entry should be truncated to fit on the screen, with, '...' + " inserted in the string to indicate the that there is truncation. + call histadd(':', 'echo x' .. repeat('y', &columns - 16) .. 'z') + let a = execute('history : -1') + call assert_match("^\n # cmd history\n" + \ .. "> *\\d\\+ echo xy\\+\.\.\.y\\+z$", a) endfunction function Test_Search_history_window() diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 39fafbf7b4..880ca62685 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -603,7 +603,7 @@ func Test_invalid_args() call assert_equal(0, v:shell_error) if has('quickfix') - " Detect invalid repeated arguments '-t foo -t foo", '-q foo -q foo'. + " Detect invalid repeated arguments '-t foo -t foo', '-q foo -q foo'. for opt in ['-t', '-q'] let out = split(system(GetVimCommand() .. repeat(' ' .. opt .. ' foo', 2)), "\n") call assert_equal(1, v:shell_error) @@ -855,7 +855,7 @@ func Test_t_arg() call writefile([' first', ' second', ' third'], 'Xfile1') for t_arg in ['-t second', '-tsecond'] - if RunVim(before, after, '-t second') + if RunVim(before, after, t_arg) call assert_equal(['Xfile1:L2C5'], readfile('Xtestout'), t_arg) call delete('Xtestout') endif -- cgit From 2fd25fb909fd4472c46c8c3c652b21d70bac9e77 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 07:20:23 +0800 Subject: vim-patch:8.1.0832: confirm() is not tested (#19896) Problem: confirm() is not tested. Solution: Add a test. (Dominique Pelle, closes vim/vim#3868) https://github.com/vim/vim/commit/2e0500921891e4fec57e97d3c0021aa2d2b4d7ae --- src/nvim/testdir/test_filechanged.vim | 6 ++-- src/nvim/testdir/test_functions.vim | 57 +++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_filechanged.vim b/src/nvim/testdir/test_filechanged.vim index b77f02afd1..fef0eb732f 100644 --- a/src/nvim/testdir/test_filechanged.vim +++ b/src/nvim/testdir/test_filechanged.vim @@ -140,7 +140,8 @@ func Test_FileChangedShell_edit() endfunc func Test_FileChangedShell_edit_dialog() - throw 'Skipped: requires a UI to be active' + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/filechanged_spec.lua' CheckNotGui CheckUnix " Using low level feedkeys() does not work on MS-Windows. @@ -190,7 +191,8 @@ func Test_FileChangedShell_edit_dialog() endfunc func Test_file_changed_dialog() - throw 'Skipped: requires a UI to be active' + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/filechanged_spec.lua' CheckUnix CheckNotGui au! FileChangedShell diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index ee63c0e1bd..05636199a4 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1700,6 +1700,63 @@ func Test_platform_name() endif endfunc +" Test confirm({msg} [, {choices} [, {default} [, {type}]]]) +func Test_confirm() + " requires a UI to be active + throw 'Skipped: use test/functional/vimscript/input_spec.lua' + if !has('unix') || has('gui_running') + return + endif + + call feedkeys('o', 'L') + let a = confirm('Press O to proceed') + call assert_equal(1, a) + + call feedkeys('y', 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(1, a) + + call feedkeys('n', 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(2, a) + + " confirm() should return 0 when pressing CTRL-C. + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(0, a) + + " requires another character to avoid it being seen as the start of an + " escape sequence. Zero should be harmless. + call feedkeys("\0", 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(0, a) + + " Default choice is returned when pressing . + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(1, a) + + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No", 2) + call assert_equal(2, a) + + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No", 0) + call assert_equal(0, a) + + " Test with the {type} 4th argument + for type in ['Error', 'Question', 'Info', 'Warning', 'Generic'] + call feedkeys('y', 'L') + let a = confirm('Are you sure?', "&Yes\n&No\n", 1, type) + call assert_equal(1, a) + endfor + + call assert_fails('call confirm([])', 'E730:') + call assert_fails('call confirm("Are you sure?", [])', 'E730:') + call assert_fails('call confirm("Are you sure?", "&Yes\n&No\n", [])', 'E745:') + call assert_fails('call confirm("Are you sure?", "&Yes\n&No\n", 0, [])', 'E730:') +endfunc + func Test_readdir() call mkdir('Xdir') call writefile([], 'Xdir/foo.txt') -- cgit From 48a4657aee76e41d097b0730c91bcca78b5bc9c7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 08:36:22 +0800 Subject: vim-patch:8.1.{1915,1921,1953} (#19900) vim-patch:8.1.1915: more functions can be used as methods Problem: More functions can be used as methods. Solution: Make various functions usable as a method. https://github.com/vim/vim/commit/1a3a89168d61c2fed91cbca812cf1c6983901b79 Move debugbreak() to the right place. vim-patch:8.1.1921: more functions can be used as methods Problem: More functions can be used as methods. Solution: Make various functions usable as a method. https://github.com/vim/vim/commit/a4208966fb289a505ebdef62bbc37c214069bab4 vim-patch:8.1.1953: more functions can be used as a method Problem: More functions can be used as a method. Solution: Allow more functions to be used as a method. https://github.com/vim/vim/commit/f9f24ce7a0e5988fedf2e2ff751818f9b07510a6 Omit test_termcodes.vim: cannot be used and superseded by later patches. Cherry-pick test_bufline.vim change from patch 8.1.1993. --- src/nvim/testdir/test_blob.vim | 2 +- src/nvim/testdir/test_bufline.vim | 2 +- src/nvim/testdir/test_cd.vim | 2 +- src/nvim/testdir/test_cursor_func.vim | 2 +- src/nvim/testdir/test_diffmode.vim | 6 +----- src/nvim/testdir/test_functions.vim | 7 ++++--- 6 files changed, 9 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index af42b3857d..70529c14d5 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -294,7 +294,7 @@ func Test_blob_index() call assert_equal(2, index(0zDEADBEEF, 0xBE)) call assert_equal(-1, index(0zDEADBEEF, 0)) call assert_equal(2, index(0z11111111, 0x11, 2)) - call assert_equal(3, index(0z11110111, 0x11, 2)) + call assert_equal(3, 0z11110111->index(0x11, 2)) call assert_equal(2, index(0z11111111, 0x11, -2)) call assert_equal(3, index(0z11110111, 0x11, -2)) diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim index 579d3a5eb5..939147b83b 100644 --- a/src/nvim/testdir/test_bufline.vim +++ b/src/nvim/testdir/test_bufline.vim @@ -19,7 +19,7 @@ func Test_setbufline_getbufline() let b = bufnr('%') wincmd w call assert_equal(1, setbufline(b, 5, ['x'])) - call assert_equal(1, setbufline(bufnr('$') + 1, 1, ['x'])) + call assert_equal(1, ['x']->setbufline(bufnr('$') + 1, 1)) call assert_equal(0, setbufline(b, 4, ['d', 'e'])) call assert_equal(['c'], b->getbufline(3)) call assert_equal(['d'], getbufline(b, 4)) diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim index a1e53df774..d6d44d1901 100644 --- a/src/nvim/testdir/test_cd.vim +++ b/src/nvim/testdir/test_cd.vim @@ -113,7 +113,7 @@ func Test_chdir_func() call assert_equal('z', fnamemodify(3->getcwd(2), ':t')) tabnext | wincmd t call assert_match('^\[tabpage\] .*/y$', trim(execute('verbose pwd'))) - call chdir('..') + eval '..'->chdir() call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t')) call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t')) call assert_equal('z', fnamemodify(getcwd(3, 2), ':t')) diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim index 3b8a5f27ad..f13842edc8 100644 --- a/src/nvim/testdir/test_cursor_func.vim +++ b/src/nvim/testdir/test_cursor_func.vim @@ -22,7 +22,7 @@ func Test_move_cursor() call cursor(3, 0) call assert_equal([3, 1, 0, 1], getcurpos()[1:]) " below last line goes to last line - call cursor(9, 1) + eval [9, 1]->cursor() call assert_equal([4, 1, 0, 1], getcurpos()[1:]) " pass string arguments call cursor('3', '3') diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index ea453b7174..1cb71664bd 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -744,17 +744,13 @@ func Test_diff_hlID() call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("") - call assert_equal(diff_hlID(1, 1), hlID("DiffChange")) call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange") - call assert_equal(diff_hlID(1, 2), hlID("DiffText")) call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText") call diff_hlID(2, 1)->synIDattr("name")->assert_equal("") - call assert_equal(diff_hlID(3, 1), hlID("DiffAdd")) call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd") - call diff_hlID(4, 1)->synIDattr("name")->assert_equal("") + eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("") wincmd w - call assert_equal(diff_hlID(1, 1), hlID("DiffChange")) call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange") call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "") call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "") diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 05636199a4..b024df5a45 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1713,7 +1713,7 @@ func Test_confirm() call assert_equal(1, a) call feedkeys('y', 'L') - let a = confirm('Are you sure?', "&Yes\n&No") + let a = 'Are you sure?'->confirm("&Yes\n&No") call assert_equal(1, a) call feedkeys('n', 'L') @@ -1727,7 +1727,7 @@ func Test_confirm() " requires another character to avoid it being seen as the start of an " escape sequence. Zero should be harmless. - call feedkeys("\0", 'L') + eval "\0"->feedkeys('L') let a = confirm('Are you sure?', "&Yes\n&No") call assert_equal(0, a) @@ -1784,7 +1784,7 @@ func Test_readdir() let files = readdir('Xdir', {x -> len(add(l, x)) == 2 ? -1 : 1}) call assert_equal(1, len(files)) - call delete('Xdir', 'rf') + eval 'Xdir'->delete('rf') endfunc func Test_delete_rf() @@ -1827,6 +1827,7 @@ endfunc func Test_char2nr() call assert_equal(12354, char2nr('ă‚', 1)) + call assert_equal(120, 'x'->char2nr()) endfunc func Test_charclass() -- cgit From d5328ea408d93d53b46417a65ca3b2fc99ab64b6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 10:38:53 +0800 Subject: vim-patch:8.2.0522: several errors are not tested for (#19901) Problem: Several errors are not tested for. Solution: Add tests. (Yegappan Lakshmanan, closes vim/vim#5892) https://github.com/vim/vim/commit/ee4e0c1e9a81cb5d96e0060203a9033c2f28588e Omit Test_range() change: reverted in patch 8.2.0615. Cherry-pick Test_z_no_space_before_xxx() from patch 8.2.0195. Cherry-pick Test_reverse_sort_uniq() change from patch 8.2.0183. Make uniq() error behavior consistent with sort(). Cherry-pick Test_set_ttytype() change from patch 8.1.1826. Cherry-pick quickfix checks from patch 8.1.2373 to test_preview.vim. Test_viminfo_error() is applicable. Cherry-pick E1058 from patch 8.2.0149 and port Test_deep_nest() to Lua. --- src/nvim/eval/typval.c | 8 ++--- src/nvim/eval/userfunc.c | 10 ++++-- src/nvim/testdir/test_autocmd.vim | 24 ++++++++++++++ src/nvim/testdir/test_clientserver.vim | 6 ++++ src/nvim/testdir/test_digraph.vim | 13 ++++++++ src/nvim/testdir/test_expr.vim | 1 + src/nvim/testdir/test_highlight.vim | 5 +-- src/nvim/testdir/test_lambda.vim | 18 +++++++++++ src/nvim/testdir/test_listdict.vim | 27 +++++++++------- src/nvim/testdir/test_options.vim | 58 +++++++++++++++++++--------------- src/nvim/testdir/test_preview.vim | 7 ++++ src/nvim/testdir/test_user_func.vim | 7 ++++ src/nvim/testdir/test_viminfo.vim | 21 ++++++++++++ src/nvim/testdir/test_vimscript.vim | 23 ++++++++++++++ 14 files changed, 182 insertions(+), 46 deletions(-) create mode 100644 src/nvim/testdir/test_viminfo.vim (limited to 'src') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 8822bb0491..7efbb1c793 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1247,15 +1247,15 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) ; li != NULL;) { listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li); if (item_compare_func_ptr(&prev_li, &li) == 0) { - if (info.item_compare_func_err) { // -V547 - emsg(_("E882: Uniq compare function failed")); - break; - } li = tv_list_item_remove(l, li); } else { idx++; li = TV_LIST_ITEM_NEXT(l, li); } + if (info.item_compare_func_err) { + emsg(_("E882: Uniq compare function failed")); + break; + } } } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index c46cb6ba5d..2542a5aeb0 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1885,6 +1885,8 @@ theend: return name; } +#define MAX_FUNC_NESTING 50 + /// ":function" void ex_function(exarg_T *eap) { @@ -2304,8 +2306,12 @@ void ex_function(exarg_T *eap) p += eval_fname_script((const char *)p); xfree(trans_function_name((char **)&p, true, 0, NULL, NULL)); if (*skipwhite((char *)p) == '(') { - nesting++; - indent += 2; + if (nesting == MAX_FUNC_NESTING - 1) { + emsg(_("E1058: function nesting too deep")); + } else { + nesting++; + indent += 2; + } } } diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 716511210d..5451dcf241 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -2724,6 +2724,30 @@ func Test_autocmd_FileReadCmd() delfunc ReadFileCmd endfunc +" Test for passing invalid arguments to autocmd +func Test_autocmd_invalid_args() + " Additional character after * for event + call assert_fails('autocmd *a Xfile set ff=unix', 'E215:') + augroup Test + augroup END + " Invalid autocmd event + call assert_fails('autocmd Bufabc Xfile set ft=vim', 'E216:') + " Invalid autocmd event in a autocmd group + call assert_fails('autocmd Test Bufabc Xfile set ft=vim', 'E216:') + augroup! Test + " Execute all autocmds + call assert_fails('doautocmd * BufEnter', 'E217:') + call assert_fails('augroup! x1a2b3', 'E367:') + call assert_fails('autocmd BufNew pwd', 'E680:') +endfunc + +" Test for deep nesting of autocmds +func Test_autocmd_deep_nesting() + autocmd BufEnter Xfile doautocmd BufEnter Xfile + call assert_fails('doautocmd BufEnter Xfile', 'E218:') + autocmd! BufEnter Xfile +endfunc + " Tests for SigUSR1 autocmd event, which is only available on posix systems. func Test_autocmd_sigusr1() CheckUnix diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim index 370d0cb190..66ee776a90 100644 --- a/src/nvim/testdir/test_clientserver.vim +++ b/src/nvim/testdir/test_clientserver.vim @@ -2,6 +2,11 @@ source check.vim CheckFeature job + +if !has('clientserver') + call assert_fails('call remote_startserver("local")', 'E942:') +endif + CheckFeature clientserver source shared.vim @@ -179,6 +184,7 @@ func Test_client_server() call assert_fails("let x = remote_peek([])", 'E730:') call assert_fails("let x = remote_read('vim10')", 'E277:') + call assert_fails("call server2client('abc', 'xyz')", 'E258:') endfunc " Uncomment this line to get a debugging log diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim index acc34e5e7c..f08dff8605 100644 --- a/src/nvim/testdir/test_digraph.vim +++ b/src/nvim/testdir/test_digraph.vim @@ -211,6 +211,8 @@ func Test_digraphs() call Put_Dig("00") call Put_Dig("el") call assert_equal(['â€', 'ĂĽ', 'âž', 'l'], getline(line('.')-3,line('.'))) + call assert_fails('exe "digraph a\ 100"', 'E104:') + call assert_fails('exe "digraph \a 100"', 'E104:') call assert_fails('digraph xy z', 'E39:') call assert_fails('digraph x', 'E1214:') bw! @@ -491,6 +493,17 @@ func Test_show_digraph_cp1251() bwipe! endfunc +" Test for error in a keymap file +func Test_loadkeymap_error() + if !has('keymap') + return + endif + call assert_fails('loadkeymap', 'E105:') + call writefile(['loadkeymap', 'a'], 'Xkeymap') + call assert_fails('source Xkeymap', 'E791:') + call delete('Xkeymap') +endfunc + " Test for the characters displayed on the screen when entering a digraph func Test_entering_digraph() CheckRunVimInTerminal diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index 5b10e691e5..15622cd6fe 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -547,6 +547,7 @@ func Test_funcref() call assert_fails('echo funcref("{")', 'E475:') let OneByRef = funcref("One", repeat(["foo"], 20)) call assert_fails('let OneByRef = funcref("One", repeat(["foo"], 21))', 'E118:') + call assert_fails('echo function("min") =~ function("min")', 'E694:') endfunc func Test_setmatches() diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim index efdf44a0d6..8e808a00d0 100644 --- a/src/nvim/testdir/test_highlight.vim +++ b/src/nvim/testdir/test_highlight.vim @@ -731,7 +731,8 @@ func Test_1_highlight_Normalgroup_exists() endif endfunc -function Test_no_space_before_xxx() +" Do this test last, sometimes restoring the columns doesn't work +func Test_z_no_space_before_xxx() " Note: we need to create this highlight group in the test because it does not exist in Neovim execute('hi StatusLineTermNC ctermfg=green') let l:org_columns = &columns @@ -739,7 +740,7 @@ function Test_no_space_before_xxx() let l:hi_StatusLineTermNC = join(split(execute('hi StatusLineTermNC'))) call assert_match('StatusLineTermNC xxx', l:hi_StatusLineTermNC) let &columns = l:org_columns -endfunction +endfunc " Test for :highlight command errors func Test_highlight_cmd_errors() diff --git a/src/nvim/testdir/test_lambda.vim b/src/nvim/testdir/test_lambda.vim index c1fe47d1c9..c178c87d3e 100644 --- a/src/nvim/testdir/test_lambda.vim +++ b/src/nvim/testdir/test_lambda.vim @@ -308,3 +308,21 @@ func Test_lambda_error() " This was causing a crash call assert_fails('ec{@{->{d->()()', 'E15') endfunc + +func Test_closure_error() + let l =<< trim END + func F1() closure + return 1 + endfunc + END + call writefile(l, 'Xscript') + let caught_932 = 0 + try + source Xscript + catch /E932:/ + let caught_932 = 1 + endtry + call assert_equal(1, caught_932) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim index 2f4e1db4a1..08c415a069 100644 --- a/src/nvim/testdir/test_listdict.vim +++ b/src/nvim/testdir/test_listdict.vim @@ -604,20 +604,23 @@ func Test_reverse_sort_uniq() call assert_equal(['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5], uniq(copy(l))) call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(l)) call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(reverse(l))) - call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(l)) - call assert_equal([[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'], reverse(sort(l))) - call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(reverse(sort(l)))) - call assert_equal(['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]], uniq(sort(l))) - - let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four'] - call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n')) - - let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] - call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1)) - call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i')) - call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l))) + if has('float') + call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(l)) + call assert_equal([[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'], reverse(sort(l))) + call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(reverse(sort(l)))) + call assert_equal(['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]], uniq(sort(l))) + + let l = [7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four'] + call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n')) + + let l = [7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] + call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1)) + call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i')) + call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l))) + endif call assert_fails('call reverse("")', 'E899:') + call assert_fails('call uniq([1, 2], {x, y -> []})', 'E882:') endfunc " reduce a list or a blob diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index e9a62d00a9..655d537336 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -234,6 +234,7 @@ func Test_complete() new call feedkeys("i\\", 'xt') bwipe! + call assert_fails('set complete=ix', 'E535:') set complete& endfun @@ -431,32 +432,37 @@ func Test_copy_context() endfunc func Test_set_ttytype() - " Nvim does not support 'ttytype'. - if !has('nvim') && !has('gui_running') && has('unix') - " Setting 'ttytype' used to cause a double-free when exiting vim and - " when vim is compiled with -DEXITFREE. - set ttytype=ansi - call assert_equal('ansi', &ttytype) - call assert_equal(&ttytype, &term) - set ttytype=xterm - call assert_equal('xterm', &ttytype) - call assert_equal(&ttytype, &term) - try - set ttytype= - call assert_report('set ttytype= did not fail') - catch /E529/ - endtry - - " Some systems accept any terminal name and return dumb settings, - " check for failure of finding the entry and for missing 'cm' entry. - try - set ttytype=xxx - call assert_report('set ttytype=xxx did not fail') - catch /E522\|E437/ - endtry - - set ttytype& - call assert_equal(&ttytype, &term) + throw "Skipped: Nvim does not support 'ttytype'" + CheckUnix + CheckNotGui + + " Setting 'ttytype' used to cause a double-free when exiting vim and + " when vim is compiled with -DEXITFREE. + set ttytype=ansi + call assert_equal('ansi', &ttytype) + call assert_equal(&ttytype, &term) + set ttytype=xterm + call assert_equal('xterm', &ttytype) + call assert_equal(&ttytype, &term) + try + set ttytype= + call assert_report('set ttytype= did not fail') + catch /E529/ + endtry + + " Some systems accept any terminal name and return dumb settings, + " check for failure of finding the entry and for missing 'cm' entry. + try + set ttytype=xxx + call assert_report('set ttytype=xxx did not fail') + catch /E522\|E437/ + endtry + + set ttytype& + call assert_equal(&ttytype, &term) + + if has('gui') && !has('gui_running') + call assert_fails('set term=gui', 'E531:') endif endfunc diff --git a/src/nvim/testdir/test_preview.vim b/src/nvim/testdir/test_preview.vim index 6c4ae414d3..b7b908e761 100644 --- a/src/nvim/testdir/test_preview.vim +++ b/src/nvim/testdir/test_preview.vim @@ -1,5 +1,8 @@ " Tests for the preview window +source check.vim +CheckFeature quickfix + func Test_Psearch() " this used to cause ml_get errors help @@ -13,6 +16,8 @@ func Test_Psearch() endfunc func Test_window_preview() + CheckFeature quickfix + " Open a preview window pedit Xa call assert_equal(2, winnr('$')) @@ -32,6 +37,8 @@ func Test_window_preview() endfunc func Test_window_preview_from_help() + CheckFeature quickfix + filetype on call writefile(['/* some C code */'], 'Xpreview.c') help diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim index 5231ef7b4f..c14624f5b4 100644 --- a/src/nvim/testdir/test_user_func.vim +++ b/src/nvim/testdir/test_user_func.vim @@ -169,3 +169,10 @@ endfunc func Test_failed_call_in_try() try | call UnknownFunc() | catch | endtry endfunc + +" Test for listing user-defined functions +func Test_function_list() + call assert_fails("function Xabc", 'E123:') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_viminfo.vim b/src/nvim/testdir/test_viminfo.vim new file mode 100644 index 0000000000..2d6d598011 --- /dev/null +++ b/src/nvim/testdir/test_viminfo.vim @@ -0,0 +1,21 @@ + +" Test for errors in setting 'viminfo' +func Test_viminfo_option_error() + " Missing number + call assert_fails('set viminfo=\"', 'E526:') + for c in split("'/:<@s", '\zs') + call assert_fails('set viminfo=' .. c, 'E526:') + endfor + + " Missing comma + call assert_fails('set viminfo=%10!', 'E527:') + call assert_fails('set viminfo=!%10', 'E527:') + call assert_fails('set viminfo=h%10', 'E527:') + call assert_fails('set viminfo=c%10', 'E527:') + call assert_fails('set viminfo=:10%10', 'E527:') + + " Missing ' setting + call assert_fails('set viminfo=%10', 'E528:') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index 0f204cdd0c..97e879c9ef 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1829,6 +1829,9 @@ func Test_missing_end() endtry call assert_equal(1, caught_e733) + " Using endfunc with :if + call assert_fails('exe "if 1 | endfunc | endif"', 'E193:') + " Missing 'in' in a :for statement call assert_fails('for i range(1) | endfor', 'E690:') endfunc @@ -1875,6 +1878,15 @@ func Test_deep_nest() @a let @a = '' endfunc + + " Deep nesting of function ... endfunction + func Test5() + let @a = join(repeat(['function X()'], 51), "\n") + let @a ..= "\necho v:true\n" + let @a ..= join(repeat(['endfunction'], 51), "\n") + @a + let @a = '' + endfunc [SCRIPT] call writefile(lines, 'Xscript') @@ -1882,20 +1894,31 @@ func Test_deep_nest() " Deep nesting of if ... endif call term_sendkeys(buf, ":call Test1()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))}) " Deep nesting of for ... endfor call term_sendkeys(buf, ":call Test2()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) " Deep nesting of while ... endwhile call term_sendkeys(buf, ":call Test3()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) " Deep nesting of try ... endtry call term_sendkeys(buf, ":call Test4()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))}) + " Deep nesting of function ... endfunction + call term_sendkeys(buf, ":call Test5()\n") + call term_wait(buf) + call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))}) + call term_sendkeys(buf, "\\n") + call term_wait(buf) + "let l = '' "for i in range(1, 6) " let l ..= term_getline(buf, i) . "\n" -- cgit From 63df91c10a7ec492adae91c78cb51eb231c77d89 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 11:24:46 +0800 Subject: vim-patch:8.2.1046: insufficient tests for src/buffer.c (#19903) Problem: Insufficient tests for src/buffer.c. Solution: Add more tests. Move comments related tests to a separate file. (Yegappan Lakshmanan, closes vim/vim#6325) https://github.com/vim/vim/commit/b7e2483655d9b68df0c7349918027d800051a28a --- src/nvim/testdir/test_buffer.vim | 206 ++++++++++++++++++++++++++ src/nvim/testdir/test_cmdline.vim | 1 + src/nvim/testdir/test_comments.vim | 277 +++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_normal.vim | 1 + src/nvim/testdir/test_textformat.vim | 272 ---------------------------------- 5 files changed, 485 insertions(+), 272 deletions(-) create mode 100644 src/nvim/testdir/test_comments.vim (limited to 'src') diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim index 67be3e6747..4def3b5df9 100644 --- a/src/nvim/testdir/test_buffer.vim +++ b/src/nvim/testdir/test_buffer.vim @@ -154,6 +154,24 @@ func Test_bdelete_cmd() set nobuflisted enew call assert_fails('bdelete ' .. bnr, 'E516:') + + " Deleting more than one buffer + new Xbuf1 + new Xbuf2 + exe 'bdel ' .. bufnr('Xbuf2') .. ' ' .. bufnr('Xbuf1') + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xbuf1')[0].loaded) + call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) + + " Deleting more than one buffer and an invalid buffer + new Xbuf1 + new Xbuf2 + let cmd = "exe 'bdel ' .. bufnr('Xbuf2') .. ' xxx ' .. bufnr('Xbuf1')" + call assert_fails(cmd, 'E94:') + call assert_equal(2, winnr('$')) + call assert_equal(1, getbufinfo('Xbuf1')[0].loaded) + call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) + %bwipe! endfunc @@ -168,6 +186,194 @@ func Test_buffer_error() %bwipe endfunc +" Test for the status messages displayed when unloading, deleting or wiping +" out buffers +func Test_buffer_statusmsg() + CheckEnglish + set report=1 + new Xbuf1 + new Xbuf2 + let bnr = bufnr() + exe "normal 2\" + call assert_match('buf ' .. bnr .. ':', v:statusmsg) + bunload Xbuf1 Xbuf2 + call assert_equal('2 buffers unloaded', v:statusmsg) + bdel Xbuf1 Xbuf2 + call assert_equal('2 buffers deleted', v:statusmsg) + bwipe Xbuf1 Xbuf2 + call assert_equal('2 buffers wiped out', v:statusmsg) + set report& +endfunc + +" Test for quitting the 'swapfile exists' dialog with the split buffer +" command. +func Test_buffer_sbuf_cleanup() + call writefile([], 'Xfile') + " first open the file in a buffer + new Xfile + let bnr = bufnr() + close + " create the swap file + call writefile([], '.Xfile.swp') + " Remove the catch-all that runtest.vim adds + au! SwapExists + augroup BufTest + au! + autocmd SwapExists Xfile let v:swapchoice='q' + augroup END + exe 'sbuf ' . bnr + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xfile')[0].loaded) + + " test for :sball + sball + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xfile')[0].loaded) + + %bw! + set shortmess+=F + let v:statusmsg = '' + edit Xfile + call assert_equal('', v:statusmsg) + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xfile')[0].loaded) + set shortmess& + + call delete('Xfile') + call delete('.Xfile.swp') + augroup BufTest + au! + augroup END + augroup! BufTest +endfunc + +" Test for deleting a modified buffer with :confirm +func Test_bdel_with_confirm() + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/buffer_spec.lua' + CheckUnix + CheckNotGui + CheckFeature dialog_con + new + call setline(1, 'test') + call assert_fails('bdel', 'E89:') + call feedkeys('c', 'L') + confirm bdel + call assert_equal(2, winnr('$')) + call assert_equal(1, &modified) + call feedkeys('n', 'L') + confirm bdel + call assert_equal(1, winnr('$')) +endfunc + +" Test for editing another buffer from a modified buffer with :confirm +func Test_goto_buf_with_confirm() + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/buffer_spec.lua' + CheckUnix + CheckNotGui + CheckFeature dialog_con + new Xfile + enew + call setline(1, 'test') + call assert_fails('b Xfile', 'E37:') + call feedkeys('c', 'L') + call assert_fails('confirm b Xfile', 'E37:') + call assert_equal(1, &modified) + call assert_equal('', @%) + call feedkeys('y', 'L') + call assert_fails('confirm b Xfile', 'E37:') + call assert_equal(1, &modified) + call assert_equal('', @%) + call feedkeys('n', 'L') + confirm b Xfile + call assert_equal('Xfile', @%) + close! +endfunc + +" Test for splitting buffer with 'switchbuf' +func Test_buffer_switchbuf() + new Xfile + wincmd w + set switchbuf=useopen + sbuf Xfile + call assert_equal(1, winnr()) + call assert_equal(2, winnr('$')) + set switchbuf=usetab + tabnew + sbuf Xfile + call assert_equal(1, tabpagenr()) + call assert_equal(2, tabpagenr('$')) + set switchbuf& + %bw +endfunc + +" Test for BufAdd autocommand wiping out the buffer +func Test_bufadd_autocmd_bwipe() + %bw! + augroup BufAdd_Wipe + au! + autocmd BufAdd Xfile %bw! + augroup END + edit Xfile + call assert_equal('', @%) + call assert_equal(0, bufexists('Xfile')) + augroup BufAdd_Wipe + au! + augroup END + augroup! BufAdd_Wipe +endfunc + +" Test for trying to load a buffer with text locked +" e in the command line is used to lock the text +func Test_load_buf_with_text_locked() + new Xfile1 + edit Xfile2 + let cmd = ":\eexecute(\"normal \\")\\" + call assert_fails("call feedkeys(cmd, 'xt')", 'E565:') + %bw! +endfunc + +" Test for using CTRL-^ to edit the alternative file keeping the cursor +" position with 'nostartofline'. Also test using the 'buf' command. +func Test_buffer_edit_altfile() + call writefile(repeat(['one two'], 50), 'Xfile1') + call writefile(repeat(['five six'], 50), 'Xfile2') + set nosol + edit Xfile1 + call cursor(25, 5) + edit Xfile2 + call cursor(30, 4) + exe "normal \" + call assert_equal([0, 25, 5, 0], getpos('.')) + exe "normal \" + call assert_equal([0, 30, 4, 0], getpos('.')) + buf Xfile1 + call assert_equal([0, 25, 5, 0], getpos('.')) + buf Xfile2 + call assert_equal([0, 30, 4, 0], getpos('.')) + set sol& + call delete('Xfile1') + call delete('Xfile2') +endfunc + +" Test for running the :sball command with a maximum window count and a +" modified buffer +func Test_sball_with_count() + %bw! + edit Xfile1 + call setline(1, ['abc']) + new Xfile2 + new Xfile3 + new Xfile4 + 2sball + call assert_equal(bufnr('Xfile4'), winbufnr(1)) + call assert_equal(bufnr('Xfile1'), winbufnr(2)) + call assert_equal(0, getbufinfo('Xfile2')[0].loaded) + call assert_equal(0, getbufinfo('Xfile3')[0].loaded) + %bw! +endfunc + func Test_badd_options() new SomeNewBuffer setlocal numberwidth=3 diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 72d2dc9cbb..b7c6c1e4d1 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -514,6 +514,7 @@ func Test_getcompletion() call delete('Xtags') set tags& + call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:') call assert_fails('call getcompletion("", "burp")', 'E475:') call assert_fails('call getcompletion("abc", [])', 'E475:') endfunc diff --git a/src/nvim/testdir/test_comments.vim b/src/nvim/testdir/test_comments.vim new file mode 100644 index 0000000000..c34b85c42d --- /dev/null +++ b/src/nvim/testdir/test_comments.vim @@ -0,0 +1,277 @@ +" Tests for the various flags in the 'comments' option + +" Test for the 'n' flag in 'comments' +func Test_comment_nested() + new + setlocal comments=n:> fo+=ro + exe "normal i> B\nD\ggOA\joC\Go\>>> F\nH" + exe "normal 5GOE\6GoG" + let expected =<< trim END + > A + > B + > C + > D + >>>> E + >>>> F + >>>> G + >>>> H + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for the 'b' flag in 'comments' +func Test_comment_blank() + new + setlocal comments=b:* fo+=ro + exe "normal i* E\nF\n\G\nH\ggOC\O\B\OA\2joD" + let expected =<< trim END + A + *B + * C + * D + * E + * F + *G + H + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for the 'f' flag in 'comments' (only the first line has a comment +" string) +func Test_comment_firstline() + new + setlocal comments=f:- fo+=ro + exe "normal i- B\nD\ggoC\ggOA\" + call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$')) + %d + setlocal comments=:- + exe "normal i- B\nD\ggoC\ggOA\" + call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$')) + close! +endfunc + +" Test for the 's', 'm' and 'e' flags in 'comments' +" Test for automatically adding comment leaders in insert mode +func Test_comment_threepiece() + new + setlocal expandtab + call setline(1, ["\t/*"]) + setlocal formatoptions=croql + call cursor(1, 3) + call feedkeys("A\\/", '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\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 'r' flag in 'comments' (right align comment) +func Test_comment_rightalign() + new + setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro + exe "normal i=\o\t /***\nD\n/" + exe "normal 2GOA\joB\jOC\joE\GOF\joG" + let expected =<< trim END + = + A + /*** + ** B + ** C + ** D + ** E + ** F + ******/ + G + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for the 'O' flag in 'comments' +func Test_comment_O() + new + setlocal comments=Ob:* fo+=ro + exe "normal i* B\nD\kOA\joC" + let expected =<< trim END + A + * B + * C + * D + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for using a multibyte character as a comment leader +func Test_comment_multibyte_leader() + new + let t =<< trim END + { + X + Xa + XaY + XY + XYZ + X Y + X YZ + XX + XXa + XXY + } + END + call setline(1, t) + call cursor(2, 1) + + set tw=2 fo=cqm comments=n:X + exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq" + let t =<< trim END + X + Xa + XaY + XY + XYZ + X Y + X YZ + XX + XXa + XXY + END + exe "normal o\n" . join(t, "\n") + + let expected =<< trim END + { + X + Xa + Xa + XY + XY + XY + XZ + X Y + X Y + X Z + XX + XXa + XXY + + X + Xa + Xa + XY + XY + XY + XZ + X Y + X Y + X Z + XX + XXa + XXY + } + END + call assert_equal(expected, getline(1, '$')) + + set tw& fo& comments& + close! +endfunc + +" Test for a space character in 'comments' setting +func Test_comment_space() + new + setlocal comments=b:\ > fo+=ro + exe "normal i> B\nD\ggOA\joC" + exe "normal Go > F\nH\kOE\joG" + let expected =<< trim END + A + > B + C + D + > E + > F + > G + > H + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for formatting lines with and without comments +func Test_comment_format_lines() + new + call setline(1, ['one', '/* two */', 'three']) + normal gggqG + call assert_equal(['one', '/* two */', 'three'], getline(1, '$')) + close! +endfunc + +" Test for using 'a' in 'formatoptions' with comments +func Test_comment_autoformat() + new + setlocal formatoptions+=a + call feedkeys("a- one\n- two\n", 'xt') + call assert_equal(['- one', '- two', ''], getline(1, '$')) + + %d + call feedkeys("a\none\n", 'xt') + call assert_equal(['', 'one', ''], getline(1, '$')) + + setlocal formatoptions+=aw + %d + call feedkeys("aone \ntwo\n", 'xt') + call assert_equal(['one two', ''], getline(1, '$')) + + %d + call feedkeys("aone\ntwo\n", 'xt') + call assert_equal(['one', 'two', ''], getline(1, '$')) + + close! +endfunc + +" Test for joining lines with comments ('j' flag in 'formatoptions') +func Test_comment_join_lines_fo_j() + new + setlocal fo+=j comments=:// + call setline(1, ['i++; // comment1', ' // comment2']) + normal J + call assert_equal('i++; // comment1 comment2', getline(1)) + setlocal fo-=j + call setline(1, ['i++; // comment1', ' // comment2']) + normal J + call assert_equal('i++; // comment1 // comment2', getline(1)) + " Test with nested comments + setlocal fo+=j comments=n:>,n:) + call setline(1, ['i++; > ) > ) comment1', ' > ) comment2']) + normal J + call assert_equal('i++; > ) > ) comment1 comment2', getline(1)) + close! +endfunc + +" Test for formatting lines where only the first line has a comment. +func Test_comment_format_firstline_comment() + new + setlocal formatoptions=tcq + call setline(1, ['- one two', 'three']) + normal gggqG + call assert_equal(['- one two three'], getline(1, '$')) + + %d + call setline(1, ['- one', '- two']) + normal gggqG + call assert_equal(['- one', '- two'], getline(1, '$')) + close! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 2092b508ea..4f842189b6 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -1455,6 +1455,7 @@ func Test_normal21_nv_hat() edit Xfoo | %bw call assert_fails(':buffer #', 'E86') call assert_fails(':execute "normal! \"', 'E23') + call assert_fails("normal i\#", 'E23:') " Test for the expected behavior when switching between two named buffers. edit Xfoo | edit Xbar diff --git a/src/nvim/testdir/test_textformat.vim b/src/nvim/testdir/test_textformat.vim index 0fc56083aa..4eb6e69adf 100644 --- a/src/nvim/testdir/test_textformat.vim +++ b/src/nvim/testdir/test_textformat.vim @@ -962,78 +962,6 @@ func Test_tw_2_fo_tm_noai() bwipe! endfunc -func Test_tw_2_fo_cqm_com() - new - let t =<< trim END - { - X - Xa - XaY - XY - XYZ - X Y - X YZ - XX - XXa - XXY - } - END - call setline(1, t) - call cursor(2, 1) - - set tw=2 fo=cqm comments=n:X - exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq" - let t =<< trim END - X - Xa - XaY - XY - XYZ - X Y - X YZ - XX - XXa - XXY - END - exe "normal o\n" . join(t, "\n") - - let expected =<< trim END - { - X - Xa - Xa - XY - XY - XY - XZ - X Y - X Y - X Z - XX - XXa - XXY - - X - Xa - Xa - XY - XY - XY - XZ - X Y - X Y - X Z - XX - XXa - XXY - } - END - call assert_equal(expected, getline(1, '$')) - - set tw& fo& comments& - bwipe! -endfunc - func Test_tw_2_fo_tm_replace() new let t =<< trim END @@ -1161,140 +1089,6 @@ 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\\/", '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\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() - new - setlocal comments=f:- fo+=ro - exe "normal i- B\nD\ggoC\ggOA\" - call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$')) - %d - setlocal comments=:- - exe "normal i- B\nD\ggoC\ggOA\" - call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$')) - %bw! -endfunc - -" Test for the 'r' flag in 'comments' (right align comment) -func Test_comment_rightalign() - new - setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro - exe "normal i=\o\t /***\nD\n/" - exe "normal 2GOA\joB\jOC\joE\GOF\joG" - let expected =<< trim END - = - A - /*** - ** B - ** C - ** D - ** E - ** F - ******/ - G - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for the 'b' flag in 'comments' -func Test_comment_blank() - new - setlocal comments=b:* fo+=ro - exe "normal i* E\nF\n\G\nH\ggOC\O\B\OA\2joD" - let expected =<< trim END - A - *B - * C - * D - * E - * F - *G - H - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for the 'n' flag in comments -func Test_comment_nested() - new - setlocal comments=n:> fo+=ro - exe "normal i> B\nD\ggOA\joC\Go\>>> F\nH" - exe "normal 5GOE\6GoG" - let expected =<< trim END - > A - > B - > C - > D - >>>> E - >>>> F - >>>> G - >>>> H - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for a space character in 'comments' setting -func Test_comment_space() - new - setlocal comments=b:\ > fo+=ro - exe "normal i> B\nD\ggOA\joC" - exe "normal Go > F\nH\kOE\joG" - let expected =<< trim END - A - > B - C - D - > E - > F - > G - > H - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for the 'O' flag in 'comments' -func Test_comment_O() - new - setlocal comments=Ob:* fo+=ro - exe "normal i* B\nD\kOA\joC" - let expected =<< trim END - A - * B - * C - * D - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - " Test for 'a' and 'w' flags in 'formatoptions' func Test_fo_a_w() new @@ -1334,25 +1128,6 @@ func Test_fo_a_w() %bw! endfunc -" Test for 'j' flag in 'formatoptions' -func Test_fo_j() - new - setlocal fo+=j comments=:// - call setline(1, ['i++; // comment1', ' // comment2']) - normal J - call assert_equal('i++; // comment1 comment2', getline(1)) - setlocal fo-=j - call setline(1, ['i++; // comment1', ' // comment2']) - normal J - call assert_equal('i++; // comment1 // comment2', getline(1)) - " Test with nested comments - setlocal fo+=j comments=n:>,n:) - call setline(1, ['i++; > ) > ) comment1', ' > ) comment2']) - normal J - call assert_equal('i++; > ) > ) comment1 comment2', getline(1)) - %bw! -endfunc - " Test for formatting lines using gq in visual mode func Test_visual_gq_format() new @@ -1487,53 +1262,6 @@ func Test_fo_2() close! endfunc -" Test for formatting lines where only the first line has a comment. -func Test_fo_gq_with_firstline_comment() - new - setlocal formatoptions=tcq - call setline(1, ['- one two', 'three']) - normal gggqG - call assert_equal(['- one two three'], getline(1, '$')) - - %d - call setline(1, ['- one', '- two']) - normal gggqG - call assert_equal(['- one', '- two'], getline(1, '$')) - close! -endfunc - -" Test for trying to join a comment line with a non-comment line -func Test_join_comments() - new - call setline(1, ['one', '/* two */', 'three']) - normal gggqG - call assert_equal(['one', '/* two */', 'three'], getline(1, '$')) - close! -endfunc - -" Test for using 'a' in 'formatoptions' with comments -func Test_autoformat_comments() - new - setlocal formatoptions+=a - call feedkeys("a- one\n- two\n", 'xt') - call assert_equal(['- one', '- two', ''], getline(1, '$')) - - %d - call feedkeys("a\none\n", 'xt') - call assert_equal(['', 'one', ''], getline(1, '$')) - - setlocal formatoptions+=aw - %d - call feedkeys("aone \ntwo\n", 'xt') - call assert_equal(['one two', ''], getline(1, '$')) - - %d - call feedkeys("aone\ntwo\n", 'xt') - call assert_equal(['one', 'two', ''], getline(1, '$')) - - close! -endfunc - " This was leaving the cursor after the end of a line. Complicated way to " have the problem show up with valgrind. func Test_correct_cursor_position() -- cgit From ffa1335047047ac00280ac742bcc6dfcc7fa3589 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 20 Aug 2022 07:54:14 +0800 Subject: vim-patch:8.2.4726: cannot use expand() to get the script name Problem: Cannot use expand() to get the script name. Solution: Support expand('