From 9355ae41497cbcce58ddd79f9125eb3e9dfe0a43 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 8 Mar 2021 19:04:05 +0100 Subject: [PATCH 01/44] patch 8.2.2577: compiler warning for type conversion Problem: Compiler warning for type conversion. Solution: Add a typecast. (Mike Williams) --- src/drawline.c | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/drawline.c b/src/drawline.c index 03a229eaec..fcb996b4b9 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -1034,7 +1034,7 @@ win_line( p_extra_free = alloc(MAX_MCO * fdc + 1); if (p_extra_free != NULL) { - n_extra = fill_foldcolumn(p_extra_free, wp, + n_extra = (int)fill_foldcolumn(p_extra_free, wp, FALSE, lnum); p_extra_free[n_extra] = NUL; p_extra = p_extra_free; diff --git a/src/version.c b/src/version.c index 5cbf287705..f7c2171de6 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2577, /**/ 2576, /**/ From 86c3a2162c2e78b4f0b87b47779cc1452990ee1b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 8 Mar 2021 19:50:24 +0100 Subject: [PATCH 02/44] patch 8.2.2578: Lua cannot handle a passed in lambda Problem: Lua cannot handle a passed in lambda. Solution: Handle VAR_PARTIAL. (Prabir Shrestha, closes #7937, closes #7936) --- src/if_lua.c | 5 +++++ src/testdir/test_lua.vim | 9 +++++++++ src/version.c | 2 ++ 3 files changed, 16 insertions(+) diff --git a/src/if_lua.c b/src/if_lua.c index e20298311d..abcd850b3d 100644 --- a/src/if_lua.c +++ b/src/if_lua.c @@ -568,6 +568,11 @@ luaV_pushtypval(lua_State *L, typval_T *tv) case VAR_FUNC: luaV_pushfuncref(L, tv->vval.v_string); break; + case VAR_PARTIAL: + // TODO: handle partial arguments + luaV_pushfuncref(L, partial_name(tv->vval.v_partial)); + break; + case VAR_BLOB: luaV_pushblob(L, tv->vval.v_blob); break; diff --git a/src/testdir/test_lua.vim b/src/testdir/test_lua.vim index 43b4aa30ff..7de4574530 100644 --- a/src/testdir/test_lua.vim +++ b/src/testdir/test_lua.vim @@ -121,6 +121,15 @@ func Test_lua_eval() lua v = nil endfunc +" Test luaeval() with lambda +func Test_luaeval_with_lambda() + lua function hello_luaeval_lambda(a, cb) return a .. cb() end + call assert_equal('helloworld', + \ luaeval('hello_luaeval_lambda(_A[1], _A[2])', + \ ['hello', {->'world'}])) + lua hello_luaeval_lambda = nil +endfunc + " Test vim.window() func Test_lua_window() e Xfoo2 diff --git a/src/version.c b/src/version.c index f7c2171de6..6c9617596b 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2578, /**/ 2577, /**/ From d00a7fb81aff367c5dd5d86fb3883f1e7a58fed5 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 8 Mar 2021 20:47:14 +0100 Subject: [PATCH 03/44] patch 8.2.2579: Vim9: crash in garbagecollect after for loop Problem: Vim9: crash in garbagecollect after for loop. Solution: Do not set a reference in script item when the name was cleared. (closes #7935) --- src/evalvars.c | 3 ++- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/evalvars.c b/src/evalvars.c index 22d39a72f6..eac66b2b92 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -319,7 +319,8 @@ garbage_collect_scriptvars(int copyID) { svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; - abort = abort || set_ref_in_item(sv->sv_tv, copyID, NULL, NULL); + if (sv->sv_name != NULL) + abort = abort || set_ref_in_item(sv->sv_tv, copyID, NULL, NULL); } } diff --git a/src/version.c b/src/version.c index 6c9617596b..4a4d65a21f 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2579, /**/ 2578, /**/ From e3ffcd9902efc756178900d9bd972c74a09c3fcd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 8 Mar 2021 21:47:13 +0100 Subject: [PATCH 04/44] patch 8.2.2580: Vim9: checking vararg type may be wrong Problem: Vim9: checking vararg type is wrong when function is auto-loaded. Solution: Use the member type. (closes #7933) --- src/testdir/test_vim9_script.vim | 6 ++++++ src/version.c | 2 ++ src/vim9execute.c | 7 +++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 2743668ee5..32312b0a2a 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -3154,6 +3154,10 @@ def Test_vim9_autoload() return 'test' enddef g:some#name = 'name' + + def some#varargs(a1: string, ...l: list): string + return a1 .. l[0] .. l[1] + enddef END mkdir('Xdir/autoload', 'p') @@ -3166,6 +3170,8 @@ def Test_vim9_autoload() g:some#other = 'other' assert_equal('other', g:some#other) + assert_equal('abc', some#varargs('a', 'b', 'c')) + # upper case script name works lines =<< trim END vim9script diff --git a/src/version.c b/src/version.c index 4a4d65a21f..f3c79c82f3 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2580, /**/ 2579, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 2e7e204e3c..d4435c4c5f 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -807,9 +807,12 @@ call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) // types are correct. for (i = 0; i < argcount; ++i) { - type_T *type = i < ufunc->uf_args.ga_len - ? ufunc->uf_arg_types[i] : ufunc->uf_va_type; + type_T *type = NULL; + if (i < ufunc->uf_args.ga_len) + type = ufunc->uf_arg_types[i]; + else if (ufunc->uf_va_type != NULL) + type = ufunc->uf_va_type->tt_member; if (type != NULL && check_typval_arg_type(type, &argv[i], i + 1) == FAIL) return FAIL; From 37294bd6a2afbf0fc8a1c34cbe102336b0bd0a82 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 13:40:08 +0100 Subject: [PATCH 05/44] patch 8.2.2581: Vim9: sourcing Vim9 script triggers a redraw Problem: Vim9: sourcing Vim9 script triggers a redraw. Solution: Do not let setting/restoring 'cpoptions' cause a redraw. (closes #7920) --- src/option.c | 11 +++++--- src/optionstr.c | 9 ++++--- src/scriptfile.c | 2 +- src/testdir/dumps/Test_vim9_no_redraw.dump | 6 +++++ src/testdir/test_vim9_script.vim | 31 ++++++++++++++++++++++ src/version.c | 2 ++ src/vim.h | 1 + src/vim9script.c | 2 +- 8 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 src/testdir/dumps/Test_vim9_no_redraw.dump diff --git a/src/option.c b/src/option.c index 9db9c2633f..b9d7edbbb0 100644 --- a/src/option.c +++ b/src/option.c @@ -3176,7 +3176,9 @@ set_bool_option( if (curwin->w_curswant != MAXCOL && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) curwin->w_set_curswant = TRUE; - check_redraw(options[opt_idx].flags); + + if ((opt_flags & OPT_NO_REDRAW) == 0) + check_redraw(options[opt_idx].flags); return NULL; } @@ -3192,8 +3194,8 @@ set_num_option( long value, // new value char *errbuf, // buffer for error messages size_t errbuflen, // length of "errbuf" - int opt_flags) // OPT_LOCAL, OPT_GLOBAL and - // OPT_MODELINE + int opt_flags) // OPT_LOCAL, OPT_GLOBAL, + // OPT_MODELINE, etc. { char *errmsg = NULL; long old_value = *(long *)varp; @@ -3734,7 +3736,8 @@ set_num_option( if (curwin->w_curswant != MAXCOL && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) curwin->w_set_curswant = TRUE; - check_redraw(options[opt_idx].flags); + if ((opt_flags & OPT_NO_REDRAW) == 0) + check_redraw(options[opt_idx].flags); return errmsg; } diff --git a/src/optionstr.c b/src/optionstr.c index a1cbe262f4..521242dbcb 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -2461,11 +2461,14 @@ ambw_end: && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0) curwin->w_set_curswant = TRUE; + if ((opt_flags & OPT_NO_REDRAW) == 0) + { #ifdef FEAT_GUI - // check redraw when it's not a GUI option or the GUI is active. - if (!redraw_gui_only || gui.in_use) + // check redraw when it's not a GUI option or the GUI is active. + if (!redraw_gui_only || gui.in_use) #endif - check_redraw(get_option_flags(opt_idx)); + check_redraw(get_option_flags(opt_idx)); + } #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS) if (did_swaptcap) diff --git a/src/scriptfile.c b/src/scriptfile.c index 82ae42a1a6..1e4b5ccf7e 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1459,7 +1459,7 @@ almosttheend: si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_save_cpo != NULL) { - set_option_value((char_u *)"cpo", 0L, si->sn_save_cpo, 0); + set_option_value((char_u *)"cpo", 0L, si->sn_save_cpo, OPT_NO_REDRAW); VIM_CLEAR(si->sn_save_cpo); } diff --git a/src/testdir/dumps/Test_vim9_no_redraw.dump b/src/testdir/dumps/Test_vim9_no_redraw.dump new file mode 100644 index 0000000000..1d77a08d07 --- /dev/null +++ b/src/testdir/dumps/Test_vim9_no_redraw.dump @@ -0,0 +1,6 @@ +|s+0&#ffffff0|o+0&#e0e0e08|m|e| |t|e|x|t| | +0&#ffffff0@64 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|'|<|,|'|>> @68 diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 32312b0a2a..58a72efbb5 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -5,6 +5,7 @@ source term_util.vim source view_util.vim source vim9.vim source shared.vim +source screendump.vim def Test_range_only() new @@ -3338,6 +3339,36 @@ def Test_restoring_cpo() set cpo&vim enddef +def Test_no_redraw_when_restoring_cpo() + CheckScreendump + + var lines =<< trim END + vim9script + def script#func() + enddef + END + mkdir('Xdir/autoload', 'p') + writefile(lines, 'Xdir/autoload/script.vim') + + lines =<< trim END + vim9script + set cpo+=M + exe 'set rtp^=' .. getcwd() .. '/Xdir' + au CmdlineEnter : ++once timer_start(0, () => script#func()) + setline(1, 'some text') + END + writefile(lines, 'XTest_redraw_cpo') + var buf = RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6}) + term_sendkeys(buf, "V:") + VerifyScreenDump(buf, 'Test_vim9_no_redraw', {}) + + # clean up + term_sendkeys(buf, "\u") + StopVimInTerminal(buf) + delete('XTest_redraw_cpo') + delete('Xdir', 'rf') +enddef + def Test_unset_any_variable() var lines =<< trim END diff --git a/src/version.c b/src/version.c index f3c79c82f3..5ae184e4ec 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2581, /**/ 2580, /**/ diff --git a/src/vim.h b/src/vim.h index e27bf8bb74..5dd69f6ee7 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1200,6 +1200,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #define OPT_WINONLY 0x10 // only set window-local options #define OPT_NOWIN 0x20 // don't set window-local options #define OPT_ONECOLUMN 0x40 // list options one per line +#define OPT_NO_REDRAW 0x80 // ignore redraw flags on option // Magic chars used in confirm dialog strings #define DLG_BUTTON_SEP '\n' diff --git a/src/vim9script.c b/src/vim9script.c index 5ce7c3bdb7..cd60b250f9 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -75,7 +75,7 @@ ex_vim9script(exarg_T *eap UNUSED) if (STRCMP(p_cpo, CPO_VIM) != 0) { si->sn_save_cpo = vim_strsave(p_cpo); - set_option_value((char_u *)"cpo", 0L, (char_u *)CPO_VIM, 0); + set_option_value((char_u *)"cpo", 0L, (char_u *)CPO_VIM, OPT_NO_REDRAW); } #else // No check for this being the first command, it doesn't matter. From ffb7dcdb773c250a6acf45d5670a508be9248cb6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 14:00:18 +0100 Subject: [PATCH 06/44] patch 8.2.2582: Vim9: screendump test fails on MS-Windows Problem: Vim9: screendump test fails on MS-Windows. Solution: Use :function instead of :def. --- src/testdir/test_vim9_script.vim | 32 +++++++++++++++++--------------- src/version.c | 2 ++ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 58a72efbb5..95c6a5b10b 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -3339,35 +3339,37 @@ def Test_restoring_cpo() set cpo&vim enddef -def Test_no_redraw_when_restoring_cpo() +" Use :function so we can use Check commands +func Test_no_redraw_when_restoring_cpo() CheckScreendump + CheckFeature timers - var lines =<< trim END + let lines =<< trim END vim9script def script#func() enddef END - mkdir('Xdir/autoload', 'p') - writefile(lines, 'Xdir/autoload/script.vim') + call mkdir('Xdir/autoload', 'p') + call writefile(lines, 'Xdir/autoload/script.vim') - lines =<< trim END + let lines =<< trim END vim9script set cpo+=M exe 'set rtp^=' .. getcwd() .. '/Xdir' au CmdlineEnter : ++once timer_start(0, () => script#func()) setline(1, 'some text') END - writefile(lines, 'XTest_redraw_cpo') - var buf = RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6}) - term_sendkeys(buf, "V:") - VerifyScreenDump(buf, 'Test_vim9_no_redraw', {}) + call writefile(lines, 'XTest_redraw_cpo') + let buf = RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6}) + call term_sendkeys(buf, "V:") + call VerifyScreenDump(buf, 'Test_vim9_no_redraw', {}) - # clean up - term_sendkeys(buf, "\u") - StopVimInTerminal(buf) - delete('XTest_redraw_cpo') - delete('Xdir', 'rf') -enddef + " clean up + call term_sendkeys(buf, "\u") + call StopVimInTerminal(buf) + call delete('XTest_redraw_cpo') + call delete('Xdir', 'rf') +endfunc def Test_unset_any_variable() diff --git a/src/version.c b/src/version.c index 5ae184e4ec..447b6e6e34 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2582, /**/ 2581, /**/ From 7ad67d1150a1e48371d64e2919591c38b80e7cfc Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 16:08:26 +0100 Subject: [PATCH 07/44] patch 8.2.2583: Vim9: cannot compare result of getenv() with null Problem: Vim9: cannot compare result of getenv() with null. Solution: Make the return type of getenv() "any". (closes #7943) --- src/evalfunc.c | 2 +- src/testdir/test_vim9_builtin.vim | 13 +++++++++++++ src/version.c | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index bee76c6eaf..29bbe8ab87 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1021,7 +1021,7 @@ static funcentry_T global_functions[] = {"getcwd", 0, 2, FEARG_1, NULL, ret_string, f_getcwd}, {"getenv", 1, 1, FEARG_1, NULL, - ret_string, f_getenv}, + ret_any, f_getenv}, {"getfontname", 0, 1, 0, NULL, ret_string, f_getfontname}, {"getfperm", 1, 1, FEARG_1, NULL, diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 3ee8a620f6..8ec3db1482 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -472,6 +472,19 @@ def Test_getchar() getchar(true)->assert_equal(0) enddef +def Test_getenv() + if getenv('does-not_exist') == '' + assert_report('getenv() should return null') + endif + if getenv('does-not_exist') == null + else + assert_report('getenv() should return null') + endif + $SOMEENVVAR = 'some' + assert_equal('some', getenv('SOMEENVVAR')) + unlet $SOMEENVVAR +enddef + def Test_getcompletion() set wildignore=*.vim,*~ var l = getcompletion('run', 'file', true) diff --git a/src/version.c b/src/version.c index 447b6e6e34..2dbf24a64f 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2583, /**/ 2582, /**/ From d345fb921678613ffc66a8afc82bc0e815c72312 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 18:43:09 +0100 Subject: [PATCH 08/44] patch 8.2.2584: Vim9: type error for assigning "any" to a list Problem: Vim9: type error for assigning the result of list concatenation to a list. Solution: Do not consider concatenation result in a constant. (closes #7942) --- src/testdir/test_vim9_expr.vim | 3 +++ src/version.c | 2 ++ src/vim9compile.c | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index a55de7e83a..a78cf1983f 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1370,6 +1370,9 @@ def Test_expr5_list_add() dany[i] = i endfor assert_equal({a: 'a', 12: 12}, dany) + + # result of glob() is "any", runtime type check + var sl: list = glob('*.txt', false, true) + [''] enddef " test multiply, divide, modulo diff --git a/src/version.c b/src/version.c index 2dbf24a64f..65a3f50192 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2584, /**/ 2583, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index c781060237..7c1dca533a 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4450,7 +4450,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) } /* - * + number addition + * + number addition or list/blobl concatenation * - number subtraction * .. string concatenation */ @@ -4532,6 +4532,7 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) else { generate_ppconst(cctx, ppconst); + ppconst->pp_is_const = FALSE; if (*op == '.') { if (may_generate_2STRING(-2, cctx) == FAIL From c23555de346c53f8f6c478635c2d9e5f2992dd7f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 19:04:07 +0100 Subject: [PATCH 09/44] patch 8.2.2585: Vim9: illegal memory access Problem: Vim9: illegal memory access. Solution: Check byte right after "null", not one more. --- src/version.c | 2 ++ src/vim9compile.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/version.c b/src/version.c index 65a3f50192..b8ce28af88 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2585, /**/ 2584, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 7c1dca533a..d29c66b66b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4184,7 +4184,7 @@ compile_expr7( * "null" constant */ case 'n': if (STRNCMP(*arg, "null", 4) == 0 - && !eval_isnamec((*arg)[5])) + && !eval_isnamec((*arg)[4])) { *arg += 4; rettv->v_type = VAR_SPECIAL; From f52f0606ed9ea19bcfc3a8343af9958f2d99eaf7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 21:26:37 +0100 Subject: [PATCH 10/44] patch 8.2.2586: process id may be invalid Problem: Process id may be invalid. Solution: Use sysinfo.uptime to check for recent reboot. (suggested by Hugo van der Sanden, closes #7947) --- src/auto/configure | 29 ++++++++++++++ src/config.h.in | 1 + src/configure.ac | 14 +++++++ src/globals.h | 1 + src/memline.c | 36 +++++++++++++---- src/testdir/test_recover.vim | 77 +++++++++++++++++++++++++++++++----- src/testing.c | 3 ++ src/version.c | 2 + 8 files changed, 147 insertions(+), 16 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index 818349991d..a9e2145d8b 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -13918,6 +13918,35 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysinfo.uptime" >&5 +$as_echo_n "checking for sysinfo.uptime... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ + struct sysinfo sinfo; + long ut; + + (void)sysinfo(&sinfo); + ut = sinfo.uptime; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; }; $as_echo "#define HAVE_SYSINFO_UPTIME 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysconf" >&5 $as_echo_n "checking for sysconf... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/src/config.h.in b/src/config.h.in index 5d01e2c4f7..fbf4b2449c 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -213,6 +213,7 @@ #undef HAVE_SYSCTL #undef HAVE_SYSINFO #undef HAVE_SYSINFO_MEM_UNIT +#undef HAVE_SYSINFO_UPTIME #undef HAVE_TGETENT #undef HAVE_TOWLOWER #undef HAVE_TOWUPPER diff --git a/src/configure.ac b/src/configure.ac index 798e9b8942..0bb5cc557c 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -4095,6 +4095,20 @@ AC_TRY_COMPILE( AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_MEM_UNIT), AC_MSG_RESULT(no)) +dnl struct sysinfo may have the uptime field or not +AC_MSG_CHECKING(for sysinfo.uptime) +AC_TRY_COMPILE( +[#include +#include ], +[ struct sysinfo sinfo; + long ut; + + (void)sysinfo(&sinfo); + ut = sinfo.uptime; + ], + AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_UPTIME), + AC_MSG_RESULT(no)) + dnl sysconf() may exist but not support what we want to use AC_MSG_CHECKING(for sysconf) AC_TRY_COMPILE( diff --git a/src/globals.h b/src/globals.h index 0fd08b6317..cb3b4f4b76 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1860,6 +1860,7 @@ EXTERN int nfa_fail_for_testing INIT(= FALSE); EXTERN int no_query_mouse_for_testing INIT(= FALSE); EXTERN int ui_delay_for_testing INIT(= 0); EXTERN int reset_term_props_on_termresponse INIT(= FALSE); +EXTERN long override_sysinfo_uptime INIT(= -1); EXTERN int in_free_unref_items INIT(= FALSE); #endif diff --git a/src/memline.c b/src/memline.c index c5303bb837..4da7b431fc 100644 --- a/src/memline.c +++ b/src/memline.c @@ -1080,6 +1080,32 @@ add_b0_fenc( } } +#if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO_UPTIME) +# include +#endif + +/* + * Return TRUE if the process with number "b0p->b0_pid" is still running. + * "swap_fname" is the name of the swap file, if it's from before a reboot then + * the result is FALSE; + */ + static int +swapfile_process_running(ZERO_BL *b0p, char_u *swap_fname UNUSED) +{ +#ifdef HAVE_SYSINFO_UPTIME + stat_T st; + struct sysinfo sinfo; + + // If the system rebooted after when the swap file was written then the + // process can't be running now. + if (mch_stat((char *)swap_fname, &st) != -1 + && sysinfo(&sinfo) == 0 + && st.st_mtime < time(NULL) - (override_sysinfo_uptime >= 0 + ? override_sysinfo_uptime : sinfo.uptime)) + return FALSE; +#endif + return mch_process_running(char_to_long(b0p->b0_pid)); +} /* * Try to recover curbuf from the .swp file. @@ -1692,7 +1718,7 @@ ml_recover(int checkext) msg(_("Recovery completed. Buffer contents equals file contents.")); msg_puts(_("\nYou may want to delete the .swp file now.")); #if defined(UNIX) || defined(MSWIN) - if (mch_process_running(char_to_long(b0p->b0_pid))) + if (swapfile_process_running(b0p, fname_used)) { // Warn there could be an active Vim on the same file, the user may // want to kill it. @@ -2170,7 +2196,7 @@ swapfile_info(char_u *fname) msg_puts(_("\n process ID: ")); msg_outnum(char_to_long(b0.b0_pid)); #if defined(UNIX) || defined(MSWIN) - if (mch_process_running(char_to_long(b0.b0_pid))) + if (swapfile_process_running(&b0, fname)) { msg_puts(_(" (STILL RUNNING)")); # ifdef HAVE_PROCESS_STILL_RUNNING @@ -2213,9 +2239,6 @@ swapfile_unchanged(char_u *fname) int fd; struct block0 b0; int ret = TRUE; -#if defined(UNIX) || defined(MSWIN) - long pid; -#endif // must be able to stat the swap file if (mch_stat((char *)fname, &st) == -1) @@ -2258,8 +2281,7 @@ swapfile_unchanged(char_u *fname) } // process must be known and not be running - pid = char_to_long(b0.b0_pid); - if (pid == 0L || mch_process_running(pid)) + if (char_to_long(b0.b0_pid) == 0L || swapfile_process_running(&b0, fname)) ret = FALSE; #endif diff --git a/src/testdir/test_recover.vim b/src/testdir/test_recover.vim index 8408ff3693..621e3152c7 100644 --- a/src/testdir/test_recover.vim +++ b/src/testdir/test_recover.vim @@ -1,5 +1,7 @@ " Test :recover +source check.vim + func Test_recover_root_dir() " This used to access invalid memory. split Xtest @@ -21,6 +23,21 @@ func Test_recover_root_dir() set dir& endfunc +" Make a copy of the current swap file to "Xswap". +" Return the name of the swap file. +func CopySwapfile() + preserve + " get the name of the swap file + let swname = split(execute("swapname"))[0] + let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '') + " make a copy of the swap file in Xswap + set binary + exe 'sp ' . swname + w! Xswap + set nobinary + return swname +endfunc + " Inserts 10000 lines with text to fill the swap file with two levels of pointer " blocks. Then recovers from the swap file and checks all text is restored. " @@ -37,15 +54,9 @@ func Test_swap_file() let i += 1 endwhile $delete - preserve - " get the name of the swap file - let swname = split(execute("swapname"))[0] - let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '') - " make a copy of the swap file in Xswap - set binary - exe 'sp ' . swname - w! Xswap - set nobinary + + let swname = CopySwapfile() + new only! bwipe! Xtest @@ -67,4 +78,52 @@ func Test_swap_file() enew! | only endfunc +func Test_nocatch_process_still_running() + " assume Unix means sysinfo.uptime can be used + CheckUnix + CheckNotGui + + " don't intercept existing swap file here + au! SwapExists + + " Edit a file and grab its swapfile. + edit Xswaptest + call setline(1, ['a', 'b', 'c']) + let swname = CopySwapfile() + + " Forget we edited this file + new + only! + bwipe! Xswaptest + + call rename('Xswap', swname) + call feedkeys('e', 'tL') + redir => editOutput + edit Xswaptest + redir END + call assert_match('E325: ATTENTION', editOutput) + call assert_match('file name: .*Xswaptest', editOutput) + call assert_match('process ID: \d* (STILL RUNNING)', editOutput) + + " Forget we edited this file + new + only! + bwipe! Xswaptest + + " pretend we rebooted + call test_override("uptime", 0) + sleep 1 + + call rename('Xswap', swname) + call feedkeys('e', 'tL') + redir => editOutput + edit Xswaptest + redir END + call assert_match('E325: ATTENTION', editOutput) + call assert_notmatch('(STILL RUNNING)', editOutput) + + call test_override("ALL", 0) + call delete(swname) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testing.c b/src/testing.c index 6d4f588f8d..df19b9eb49 100644 --- a/src/testing.c +++ b/src/testing.c @@ -970,6 +970,8 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED) ui_delay_for_testing = val; else if (STRCMP(name, (char_u *)"term_props") == 0) reset_term_props_on_termresponse = val; + else if (STRCMP(name, (char_u *)"uptime") == 0) + override_sysinfo_uptime = val; else if (STRCMP(name, (char_u *)"ALL") == 0) { disable_char_avail_for_testing = FALSE; @@ -979,6 +981,7 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED) no_query_mouse_for_testing = FALSE; ui_delay_for_testing = 0; reset_term_props_on_termresponse = FALSE; + override_sysinfo_uptime = -1; if (save_starting >= 0) { starting = save_starting; diff --git a/src/version.c b/src/version.c index b8ce28af88..b624a71e13 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2586, /**/ 2585, /**/ From 6635ae1437e6e343c0514524a8dfb19d9525b908 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 21:46:39 +0100 Subject: [PATCH 11/44] patch 8.2.2587: recover test fails on FreeBSD Problem: Recover test fails on FreeBSD. Solution: Check for Linux. --- src/testdir/check.vim | 10 +++++++++- src/testdir/test_recover.vim | 5 +++-- src/version.c | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/testdir/check.vim b/src/testdir/check.vim index e5298bc530..db16cfb7d9 100644 --- a/src/testdir/check.vim +++ b/src/testdir/check.vim @@ -84,8 +84,16 @@ func CheckUnix() endif endfunc +" Command to check for running on Linix +command CheckLinux call CheckLinux() +func CheckLinux() + if !has('linux') + throw 'Skipped: only works on Linux' + endif +endfunc + " Command to check for not running on a BSD system. -" TODO: using this checks should not be needed +" TODO: using this check should not be needed command CheckNotBSD call CheckNotBSD() func CheckNotBSD() if has('bsd') diff --git a/src/testdir/test_recover.vim b/src/testdir/test_recover.vim index 621e3152c7..28676632c5 100644 --- a/src/testdir/test_recover.vim +++ b/src/testdir/test_recover.vim @@ -79,8 +79,9 @@ func Test_swap_file() endfunc func Test_nocatch_process_still_running() - " assume Unix means sysinfo.uptime can be used - CheckUnix + " sysinfo.uptime probably only works on Linux + CheckLinux + " the GUI dialog can't be handled CheckNotGui " don't intercept existing swap file here diff --git a/src/version.c b/src/version.c index b624a71e13..df8d2f917b 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2587, /**/ 2586, /**/ From 23b32a8d6bd9ec83c0c6632b7a8bfa544ac0a2f1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 21:55:46 +0100 Subject: [PATCH 12/44] patch 8.2.2588: build failure with tiny features Problem: Build failure with tiny features. Solution: Add #ifdef. Run recover test separately. --- src/memline.c | 7 +++++-- src/testdir/Make_all.mak | 1 + src/testdir/test_alot.vim | 1 - src/version.c | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/memline.c b/src/memline.c index 4da7b431fc..4c4a1b24cb 100644 --- a/src/memline.c +++ b/src/memline.c @@ -1100,8 +1100,11 @@ swapfile_process_running(ZERO_BL *b0p, char_u *swap_fname UNUSED) // process can't be running now. if (mch_stat((char *)swap_fname, &st) != -1 && sysinfo(&sinfo) == 0 - && st.st_mtime < time(NULL) - (override_sysinfo_uptime >= 0 - ? override_sysinfo_uptime : sinfo.uptime)) + && st.st_mtime < time(NULL) - ( +# ifdef FEAT_EVAL + override_sysinfo_uptime >= 0 ? override_sysinfo_uptime : +# endif + sinfo.uptime)) return FALSE; #endif return mch_process_running(char_to_long(b0p->b0_pid)); diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index b769499328..108c52854d 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -459,6 +459,7 @@ NEW_TESTS_RES = \ test_quickfix.res \ test_quotestar.res \ test_random.res \ + test_recover.res \ test_regex_char_classes.res \ test_registers.res \ test_rename.res \ diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim index 83f2c1923c..f54e6f2c50 100644 --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -21,7 +21,6 @@ source test_jumps.vim source test_lispwords.vim source test_move.vim source test_put.vim -source test_recover.vim source test_reltime.vim source test_scroll_opt.vim source test_searchpos.vim diff --git a/src/version.c b/src/version.c index df8d2f917b..4d693c45f0 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2588, /**/ 2587, /**/ From 776b954622b45125dfdcb4a61243ca90956b0825 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 10 Mar 2021 22:27:48 +0100 Subject: [PATCH 13/44] patch 8.2.2589: recover test hangs in the GUI Problem: Recover test hangs in the GUI. Solution: Add g:skipped_reason to skip a _nocatch_ test. --- src/testdir/runtest.vim | 5 +++++ src/testdir/test_recover.vim | 10 ++++++++-- src/version.c | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index 369d931f16..4602051a73 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -196,7 +196,12 @@ func RunTheTest(test) if a:test =~ 'Test_nocatch_' " Function handles errors itself. This avoids skipping commands after the " error. + let g:skipped_reason = '' exe 'call ' . a:test + if g:skipped_reason != '' + call add(s:messages, ' Skipped') + call add(s:skipped, 'SKIPPED ' . a:test . ': ' . g:skipped_reason) + endif else try au VimLeavePre * call EarlyExit(g:testfunc) diff --git a/src/testdir/test_recover.vim b/src/testdir/test_recover.vim index 28676632c5..a1ff7d92af 100644 --- a/src/testdir/test_recover.vim +++ b/src/testdir/test_recover.vim @@ -80,9 +80,15 @@ endfunc func Test_nocatch_process_still_running() " sysinfo.uptime probably only works on Linux - CheckLinux + if !has('linux') + let g:skipped_reason = 'only works on Linux' + return + endif " the GUI dialog can't be handled - CheckNotGui + if has('gui_running') + let g:skipped_reason = 'only works in the terminal' + return + endif " don't intercept existing swap file here au! SwapExists diff --git a/src/version.c b/src/version.c index 4d693c45f0..87ac80f5be 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2589, /**/ 2588, /**/ From 12bce95887f7c5f07a7bdb7b4485b53d074ccc0a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 11 Mar 2021 20:04:04 +0100 Subject: [PATCH 14/44] patch 8.2.2590: Vim9: default argument value may cause internal error Problem: Vim9: default argument value may cause internal error. Solution: Hide later function arguments when compiling the expression. (closes #7948) --- src/testdir/test_vim9_func.vim | 8 ++++++++ src/version.c | 2 ++ src/vim9compile.c | 11 ++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 810b3a3cf0..6258b7d5d4 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -311,6 +311,14 @@ def Test_call_default_args() delfunc g:Func CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string') delfunc g:Func + + var lines =<< trim END + vim9script + def Func(a = b == 0 ? 1 : 2, b = 0) + enddef + defcompile + END + CheckScriptFailure(lines, 'E1001: Variable not found: b') enddef def FuncWithComment( # comment diff --git a/src/version.c b/src/version.c index 87ac80f5be..1eecf5d98a 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2590, /**/ 2589, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index d29c66b66b..c49c499841 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -8199,6 +8199,7 @@ compile_def_function( { int count = ufunc->uf_def_args.ga_len; int first_def_arg = ufunc->uf_args.ga_len - count; + int uf_args_len = ufunc->uf_args.ga_len; int i; char_u *arg; int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0); @@ -8211,16 +8212,24 @@ compile_def_function( ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1); if (ufunc->uf_def_arg_idx == NULL) goto erret; + SOURCING_LNUM = 0; // line number unknown for (i = 0; i < count; ++i) { garray_T *stack = &cctx.ctx_type_stack; type_T *val_type; int arg_idx = first_def_arg + i; where_T where; + int r; + + // Make sure later arguments are not found. + ufunc->uf_args.ga_len = i; ufunc->uf_def_arg_idx[i] = instr->ga_len; arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; - if (compile_expr0(&arg, &cctx) == FAIL) + r = compile_expr0(&arg, &cctx); + + ufunc->uf_args.ga_len = uf_args_len; + if (r == FAIL) goto erret; // If no type specified use the type of the default value. From c80f647512b001fb6952ed10d076d56c3d4b84e0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 12 Mar 2021 22:16:41 +0100 Subject: [PATCH 15/44] patch 8.2.2591: Poke files are not recognized Problem: Poke files are not recognized. Solution: Add a filetype entry. (Matt Ihlenfield) --- runtime/filetype.vim | 3 +++ src/testdir/test_filetype.vim | 1 + src/version.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 259e5eeb3c..311e6a81ec 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1334,6 +1334,9 @@ au BufNewFile,BufRead *.pml setf promela au BufNewFile,BufRead *.proto setf proto au BufNewFile,BufRead *.pbtxt setf pbtxt +" Poke +au BufNewFile,BufRead *.pk setf poke + " Protocols au BufNewFile,BufRead */etc/protocols setf protocols diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index ba8879c82d..11b6baeb83 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -374,6 +374,7 @@ let s:filename_checks = { \ 'po': ['file.po', 'file.pot'], \ 'pod': ['file.pod'], \ 'pod6': ['file.pod6'], + \ 'poke': ['file.pk'], \ 'postscr': ['file.ps', 'file.pfa', 'file.afm', 'file.eps', 'file.epsf', 'file.epsi', 'file.ai'], \ 'pov': ['file.pov'], \ 'povini': ['.povrayrc'], diff --git a/src/version.c b/src/version.c index 1eecf5d98a..76a95b9b6c 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2591, /**/ 2590, /**/ From 6fd367a97c8653a2d734a38252c7d68d4b2ebaa7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 13:14:04 +0100 Subject: [PATCH 16/44] patch 8.2.2592: code coverage could be improved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Code coverage could be improved. Solution: Add a few more tests. (Dominique Pellé, closes #7957) --- src/testdir/test_fileformat.vim | 9 +++++++++ src/testdir/test_normal.vim | 7 +++++++ src/testdir/test_sleep.vim | 1 + src/testdir/test_textformat.vim | 15 +++++++++++++++ src/testdir/test_viminfo.vim | 4 ++++ src/version.c | 2 ++ 6 files changed, 38 insertions(+) diff --git a/src/testdir/test_fileformat.vim b/src/testdir/test_fileformat.vim index 09be258221..07819dc2e6 100644 --- a/src/testdir/test_fileformat.vim +++ b/src/testdir/test_fileformat.vim @@ -33,6 +33,15 @@ func Test_fileformat_autocommand() bw! endfunc +func Test_fileformat_nomodifiable() + new + setlocal nomodifiable + + call assert_fails('set fileformat=latin1', 'E21:') + + bw +endfunc + " Convert the contents of a file into a literal string func s:file2str(fname) let b = readfile(a:fname, 'B') diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index 8aef41ddda..75b52bcb6e 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -3207,6 +3207,13 @@ func Test_normal_delete_cmd() " delete to a readonly register call setline(1, ['abcd']) call assert_beeps('normal ":d2l') + + " D and d with 'nomodifiable' + call setline(1, ['abcd']) + setlocal nomodifiable + call assert_fails('normal D', 'E21:') + call assert_fails('normal d$', 'E21:') + close! endfunc diff --git a/src/testdir/test_sleep.vim b/src/testdir/test_sleep.vim index f71855fd4b..a428f380b0 100644 --- a/src/testdir/test_sleep.vim +++ b/src/testdir/test_sleep.vim @@ -21,6 +21,7 @@ func! Test_sleep_bang() call s:assert_takes_longer('sl 50m', 50) call s:assert_takes_longer('sl! 50m', 50) call s:assert_takes_longer('1sleep', 1000) + call s:assert_takes_longer('normal 1gs', 1000) endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_textformat.vim b/src/testdir/test_textformat.vim index eac1c1980a..32ff3cc70b 100644 --- a/src/testdir/test_textformat.vim +++ b/src/testdir/test_textformat.vim @@ -858,6 +858,21 @@ func Test_mps_latin1() close! endfunc +func Test_mps_error() + let encoding_save = &encoding + + for e in ['utf-8', 'latin1'] + exe 'set encoding=' .. e + + call assert_fails('set mps=<:', 'E474:', e) + call assert_fails('set mps=:>', 'E474:', e) + call assert_fails('set mps=<>', 'E474:', e) + call assert_fails('set mps=<:>_', 'E474:', e) + endfor + + let &encoding = encoding_save +endfunc + " Test for ra on multi-byte characters func Test_ra_multibyte() new diff --git a/src/testdir/test_viminfo.vim b/src/testdir/test_viminfo.vim index cb090ce5ce..ef74e09dbd 100644 --- a/src/testdir/test_viminfo.vim +++ b/src/testdir/test_viminfo.vim @@ -906,6 +906,10 @@ func Test_viminfo_oldfiles_newfile() call delete('Xviminfofile') call delete('Xviminfotest') call delete('Xnew-file.txt') + + let v:oldfiles = test_null_list() + call assert_equal("\nNo old files", execute('oldfiles')) + let &viminfo = save_viminfo let &viminfofile = save_viminfofile endfunc diff --git a/src/version.c b/src/version.c index 76a95b9b6c..c6866a2973 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2592, /**/ 2591, /**/ From c8cdf0f80b3cfd88a4490d80572062c1fd1a96ca Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 13:28:13 +0100 Subject: [PATCH 17/44] Update runtime files. --- runtime/doc/change.txt | 18 +++-- runtime/doc/eval.txt | 24 +++--- runtime/doc/filetype.txt | 9 ++- runtime/doc/repeat.txt | 6 +- runtime/doc/sign.txt | 20 ++++- runtime/doc/syntax.txt | 8 +- runtime/doc/tags | 2 + runtime/doc/testing.txt | 3 +- runtime/doc/todo.txt | 55 ++++++++++---- runtime/doc/various.txt | 4 +- runtime/doc/vim9.txt | 6 +- runtime/filetype.vim | 2 +- runtime/ftplugin/poke.vim | 32 ++++++++ runtime/syntax/html.vim | 69 +++++++---------- runtime/syntax/poke.vim | 151 ++++++++++++++++++++++++++++++++++++++ src/INSTALL | 10 ++- 16 files changed, 327 insertions(+), 92 deletions(-) create mode 100644 runtime/ftplugin/poke.vim create mode 100644 runtime/syntax/poke.vim diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 7db3ffc41f..d0b50ca9a5 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 8.2. Last change: 2021 Jan 21 +*change.txt* For Vim version 8.2. Last change: 2021 Mar 01 VIM REFERENCE MANUAL by Bram Moolenaar @@ -649,6 +649,8 @@ For other systems the tmpnam() library function is used. The space between `:substitute` and the 'c', 'g', 'i', 'I' and 'r' flags isn't required, but in scripts it's a good idea to keep it to avoid confusion. + Also see the two and three letter commands to repeat + :substitute below |:substitute-repeat|. :[range]~[&][flags] [count] *:~* Repeat last substitute with same substitute string @@ -877,20 +879,26 @@ either the first or second pattern in parentheses did not match, so either *:sge* *:sgi* *:sgI* *:sgl* *:sgn* *:sgp* *:sgr* *:sI* *:si* *:sic* *:sIc* *:sie* *:sIe* *:sIg* *:sIl* *:sin* *:sIn* *:sIp* *:sip* *:sIr* *:sir* *:sr* *:src* *:srg* *:sri* *:srI* *:srl* - *:srn* *:srp* + *:srn* *:srp* *:substitute-repeat* 2-letter and 3-letter :substitute commands ~ +These commands repeat the previous `:substitute` command with the given flags. +The first letter is always "s", followed by one or two of the possible flag +characters. For example `:sce` works like `:s///ce`. The table lists the +possible combinations, not all flags are possible, because the command is +short for another command. + List of :substitute commands | c e g i I n p l r - | c :sc :sce :scg :sci :scI :scn :scp :scl --- + | c :sc :sce :scg :sci :scI :scn :scp :scl | e | g :sgc :sge :sg :sgi :sgI :sgn :sgp :sgl :sgr - | i :sic :sie --- :si :siI :sin :sip --- :sir + | i :sic :sie :si :siI :sin :sip :sir | I :sIc :sIe :sIg :sIi :sI :sIn :sIp :sIl :sIr | n | p | l - | r :src --- :srg :sri :srI :srn :srp :srl :sr + | r :src :srg :sri :srI :srn :srp :srl :sr Exceptions: :scr is `:scriptnames` diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 03fcb655d5..92f020689e 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.2. Last change: 2021 Feb 10 +*eval.txt* For Vim version 8.2. Last change: 2021 Mar 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -5300,6 +5300,9 @@ getcharpos({expr}) Get the position for {expr}. Same as |getpos()| but the column number in the returned List is a character index instead of a byte index. + If |getpos()| returns a very large column number, such as + 2147483647, then getcharpos() will return the character index + of the last character. Example: With the cursor on '세' in line 5 with text "여보세요": > @@ -5779,6 +5782,8 @@ getpos({expr}) Get the position for {expr}. For possible values of {expr} The column number in the returned List is the byte position within the line. To get the character position in the line, use |getcharpos()| + The column number can be very large, e.g. 2147483647, in which + case it means "after the end of the line". This can be used to save and restore the position of a mark: > let save_a_mark = getpos("'a") ... @@ -7450,7 +7455,8 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]]) to be used when fast match additions and deletions are required, for example to highlight matching parentheses. - The list {pos} can contain one of these items: + {pos} is a list of positions. Each position can be one of + these: - A number. This whole line will be highlighted. The first line has number 1. - A list with one number, e.g., [23]. The whole line with this @@ -7463,7 +7469,7 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]]) - A list with three numbers, e.g., [23, 11, 3]. As above, but the third number gives the length of the highlight in bytes. - The maximum number of positions is 8. + The maximum number of positions in {pos} is 8. Example: > :highlight MyGroup ctermbg=green guibg=green @@ -7472,8 +7478,7 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]]) :call matchdelete(m) < Matches added by |matchaddpos()| are returned by - |getmatches()| with an entry "pos1", "pos2", etc., with the - value a list like the {pos} item. + |getmatches()|. Can also be used as a |method|: > GetGroup()->matchaddpos([23, 11]) @@ -10273,7 +10278,8 @@ str2nr({expr} [, {base} [, {quoted}]]) *str2nr()* strcharpart({src}, {start} [, {len}]) *strcharpart()* Like |strpart()| but using character index and length instead - of byte index and length. + of byte index and length. Composing characters are counted + separately. When a character index is used where a character does not exist it is assumed to be one character. For example: > strcharpart('abc', -1, 2) @@ -13142,7 +13148,7 @@ text... Cannot be followed by a comment. Examples: > :execute "buffer" nextbuf - :execute "normal" count . "w" + :execute "normal" count .. "w" < ":execute" can be used to append a command to commands that don't accept a '|'. Example: > @@ -13158,8 +13164,8 @@ text... file names. The |fnameescape()| function can be used for Vim commands, |shellescape()| for |:!| commands. Examples: > - :execute "e " . fnameescape(filename) - :execute "!ls " . shellescape(filename, 1) + :execute "e " .. fnameescape(filename) + :execute "!ls " .. shellescape(filename, 1) < Note: The executed string may be any command-line, but starting or ending "if", "while" and "for" does not diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index 6a23b2fdb8..318507c16b 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -1,4 +1,4 @@ -*filetype.txt* For Vim version 8.2. Last change: 2021 Jan 21 +*filetype.txt* For Vim version 8.2. Last change: 2021 Mar 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -628,6 +628,13 @@ For fish, add to the config file set -x MANPAGER "vim -M +MANPAGER -" + +MARKDOWN *ft-markdown-plugin* + +To enable folding use this: > + let g:markdown_folding = 1 +< + PDF *ft-pdf-plugin* Two maps, and , are provided to simulate a tag stack for navigating diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index aa00dd3b54..71b4e10de4 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -677,9 +677,9 @@ Your directory layout would be like this: opt/fooextra/doc/tags " help tags This allows for the user to do: > - mkdir ~/.vim/pack/myfoobar - cd ~/.vim/pack/myfoobar - git clone https://github.com/you/foobar.git + mkdir ~/.vim/pack + cd ~/.vim/pack + git clone https://github.com/you/foobar.git myfoobar Here "myfoobar" is a name that the user can choose, the only condition is that it differs from other packages. diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 9c52587f42..66f8cc61bd 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -1,4 +1,4 @@ -*sign.txt* For Vim version 8.2. Last change: 2020 Oct 28 +*sign.txt* For Vim version 8.2. Last change: 2021 Mar 07 VIM REFERENCE MANUAL by Gordon Prieur @@ -146,6 +146,9 @@ See |sign_define()| for the equivalent Vim script function. texthl={group} Highlighting group used for the text item. + Example: > + :sign define MySign text=>> texthl=Search linehl=DiffText +< DELETING A SIGN *:sign-undefine* *E155* @@ -155,7 +158,9 @@ See |sign_undefine()| for the equivalent Vim script function. Deletes a previously defined sign. If signs with this {name} are still placed this will cause trouble. - + Example: > + :sign undefine MySign +< LISTING SIGNS *:sign-list* *E156* @@ -209,6 +214,10 @@ See |sign_place()| for the equivalent Vim script function. Same, but use buffer {nr}. If the buffer argument is not given, place the sign in the current buffer. + Example: > + :sign place 10 line=99 name=sign3 + :sign place 10 line=99 name=sign3 buffer=3 +< *E885* :sign place {id} name={name} file={fname} Change the placed sign {id} in file {fname} to use the defined @@ -221,10 +230,17 @@ See |sign_place()| for the equivalent Vim script function. "priority={prio}" attribute can be used to change the priority of an existing sign. + Example: > + :sign place 23 name=sign1 file=/path/to/edit.py +< :sign place {id} name={name} [buffer={nr}] Same, but use buffer {nr}. If the buffer argument is not given, use the current buffer. + Example: > + :sign place 23 name=sign1 + :sign place 23 name=sign1 buffer=7 +< REMOVING SIGNS *:sign-unplace* *E159* diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 6a94980671..bef8601313 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1,4 +1,4 @@ -*syntax.txt* For Vim version 8.2. Last change: 2021 Jan 21 +*syntax.txt* For Vim version 8.2. Last change: 2021 Mar 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1741,8 +1741,8 @@ The coloring scheme for tags in the HTML file works as follows. The <> of opening tags are colored differently than the of a closing tag. This is on purpose! For opening tags the 'Function' color is used, while for -closing tags the 'Type' color is used (See syntax.vim to check how those are -defined for you) +closing tags the 'Identifier' color is used (See syntax.vim to check how those +are defined for you) Known tag names are colored the same way as statements in C. Unknown tag names are colored with the same color as the <> or respectively which @@ -4676,7 +4676,7 @@ matches, nextgroup, etc. But there are a few differences: - A line continuation pattern can be given. It is used to decide which group of lines need to be searched like they were one line. This means that the search for a match with the specified items starts in the first of the - consecutive that contain the continuation pattern. + consecutive lines that contain the continuation pattern. - When using "nextgroup" or "contains", this only works within one line (or group of continued lines). - When using a region, it must start and end in the same line (or group of diff --git a/runtime/doc/tags b/runtime/doc/tags index 5f0b6c6518..27e8d754e1 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -3191,6 +3191,7 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX* :stselect tagsrch.txt /*:stselect* :su change.txt /*:su* :substitute change.txt /*:substitute* +:substitute-repeat change.txt /*:substitute-repeat* :sun windows.txt /*:sun* :sunhide windows.txt /*:sunhide* :sunm map.txt /*:sunm* @@ -6578,6 +6579,7 @@ ft-mail.vim syntax.txt /*ft-mail.vim* ft-make-syntax syntax.txt /*ft-make-syntax* ft-man-plugin filetype.txt /*ft-man-plugin* ft-maple-syntax syntax.txt /*ft-maple-syntax* +ft-markdown-plugin filetype.txt /*ft-markdown-plugin* ft-masm-syntax syntax.txt /*ft-masm-syntax* ft-mathematica-syntax syntax.txt /*ft-mathematica-syntax* ft-matlab-indent indent.txt /*ft-matlab-indent* diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index 5be1890df8..4e4cff0c27 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -1,4 +1,4 @@ -*testing.txt* For Vim version 8.2. Last change: 2020 Dec 12 +*testing.txt* For Vim version 8.2. Last change: 2021 Mar 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -168,6 +168,7 @@ test_override({name}, {val}) *test_override()* wait time of up to 3 seconds for messages term_props reset all terminal properties when the version string is detected + uptime overrules sysinfo.uptime ALL clear all overrides ({val} is not used) "starting" is to be used when a test should behave like diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 835a5ccca1..2486d9d50f 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 8.2. Last change: 2021 Feb 20 +*todo.txt* For Vim version 8.2. Last change: 2021 Mar 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -39,13 +39,25 @@ browser use: https://github.com/vim/vim/issues/1234 -------------------- Known bugs and current work ----------------------- Vim9 - Make everything work: -- Implement "export {one, two three}". +- Does this work now: Implement using imported items at script level from + "import * as X" in +- import of item that isn't exported: error should mention missing "export"? +- no error for using :import in legacy script? - Disallow :open ? +- Check: what if 'cpo' is intentionally changed in Vim9 script, does it get + restored at the end? - ISN_CHECKTYPE could use check_argtype() - Using a script variable inside a :def function doesn't work if the variable is inside a block, see Test_nested_function(). Should it work? - give error for variable name: var p = function('NoSuchFunc') +- When indexing a string, should we include composing characters? #6563 + string[0] - first character including its composing characters. + string[0 : 0] - same + If you don't want that use strcharpart(). + Also, add optional arg to strcharpart() to include composing chars, to + make it consistent with strchars(). + Add strcharlen(), like strchars() but like skipcc is always set - Make closures work better: - Create closure in a loop. Need to make a list of them. - If a :def function is called with a function reference, compile it to get @@ -74,13 +86,11 @@ Vim9 - Make everything work: - make 0 == 'string' fail on the script level, like inside :def. - Check that when using a user function name without prefix, it does not find a global function. Prefixing g: is required. -- Need the equivalent of get_lval() and set_var_lval() to implement assignment - to nested list and dict members. - - Assignment to dict doesn't work: - var ret: dict = #{} - ret[i] = string(i) - - Appending to dict item doesn't work: - var d[i] ..= value +- Appending to dict item doesn't work in a :def function: + var d: dict = {a: 'x'} + d['a'] ..= 'y' + d.a ..= 'y' + Test to be extended: Test_assign_dict_with_op() - Using ".." at script level doesn't convert arguments to a string. - Compile replacement of :s command: s/pat/\=expr/ - Compile redir to local variable: var_redir_start(). @@ -89,8 +99,6 @@ Vim9 - Make everything work: islocked() - When evaluating constants for script variables, some functions could work: has('asdf'), len('string') -- Implement "as Name" in "import Item as Name from ..." -- Implement using imported items at script level from "import * as X" in eval_variable(). Should pass the ".xxx" that follows and return that. - Make "++nr" work. "++g:count" doesn't work, thinks it is a range. - Reload: How to make sure type of script function hasn't changed? @@ -102,6 +110,11 @@ Vim9 - Make everything work: - give an error for "echo Func()" if Func() does not return anything. - Using "windo echo expr" does not accept a line break inside "expr" (in a :def function and at script level in a not executed block). #7681 +- "assert_fails()" cannot access local variables. Perhaps add this: + assertfails + ... cmd ... + endassertfails /E99:.*cmd/ + Similar to try/catch/endtry but without the boilerplate. Once Vim9 is stable: - Change the help to prefer Vim9 syntax where appropriate @@ -184,6 +197,7 @@ Text properties: - Popup attached to text property stays visible when text is deleted with "cc". (#7737) "C" works OK. "dd" also files in a buffer with a single line. +- Auto-indenting may cause highlighting to shift. (#7719) - "cc" does not call inserted_bytes(). (Axel Forsman, #5763) - Combining text property with 'cursorline' does not always work (Billie Cleek, #5533) @@ -263,7 +277,9 @@ Terminal emulator window: - When 'encoding' is not utf-8, or the job is using another encoding, setup conversions. -Valgrind reports memory leaks in test_options +Include patch #6290: recognize shell directory change. + +Valgrind reports memory leaks in test_options. test_arglist func Test_all_not_allowed_from_cmdwin() hangs on MS-Windows. @@ -277,6 +293,8 @@ Was originally written by Felipe Morales. Adding "10" to 'spellsuggest' causes spell suggestions to become very slow. (#4087) Did patch 8.2.2379 help? +Also, z= in German on a long word can take a very long time, but CTRL-C to +interrupt does not work. Where to add ui_breakcheck()? Remove SPACE_IN_FILENAME ? It is only used for completion. @@ -288,6 +306,8 @@ with 'termguicolors'. #1740 Patch for blockwise paste reporting changes: #6660. +Patch to make fillchars global-local. (#5206) + Missing filetype test for bashrc, PKGBUILD, etc. Add an option to not fetch terminal codes in xterm, to avoid flicker when t_Co @@ -306,6 +326,10 @@ Try setting a color then request the current color, like using t_u7. Regexp to search for duplicate lines does not work correctly: /\(^.*\n\)\1 (Chris Morgan, #6239) +MS-Windows: when writing undo file the infostreams are copied in +mch_copy_file_attribute(), that seems unnecessary. (#7925) +Add a flag to only copy attributes? + Changing a capturing group to non-capturing changes the result: #7607 :echo matchstr('aaa bbb', '\(.\{-1,}\>\)\|.*') aaa @@ -382,6 +406,10 @@ manager. Problem with Motif? Patch to add :argdedupe. (Nir Lichtman, #6235) +When editing a file with ":edit" the output of :swapname is relative, while +editing it with "vim file" it is absolute. (#355) +Which one should it be? + :map output does not clear the reset of the command line. (#5623, also see #5962) @@ -1156,9 +1184,6 @@ timer expires. Rule to use "^" for statusline does not work if a space is defined with highlighting for both stl and stlnc. Patch by Ken Hamada (itchyny, 2016 Dec 11) -8 "stl" and "stlnc" in 'fillchars' don't work for multibyte characters. - Patch by Christian Wellenbrock, 2013 Jul 5. - Using CTRL-G_U in InsertCharPre causes trouble for redo. (Israel Chauca Fuentes, 2017 Feb 12, #1470) diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index c60b1aa505..fd135c6252 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -1,4 +1,4 @@ -*various.txt* For Vim version 8.2. Last change: 2021 Jan 26 +*various.txt* For Vim version 8.2. Last change: 2021 Mar 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -572,7 +572,7 @@ N *+X11* Unix only: can restore window title |X11| it in / any non-ID character (see |'isident'|) can be used, so long as it does not appear in {pat}. Without the enclosing character the pattern cannot include the - bar character. + bar character. 'ignorecase' is not used. The pattern is matched against the relevant part of the output, not necessarily the whole line. Only some diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 016089a87c..20689ef58f 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1,4 +1,4 @@ -*vim9.txt* For Vim version 8.2. Last change: 2021 Feb 23 +*vim9.txt* For Vim version 8.2. Last change: 2021 Mar 03 VIM REFERENCE MANUAL by Bram Moolenaar @@ -800,6 +800,8 @@ Patterns are used like 'magic' is set, unless explicitly overruled. The 'edcompatible' option value is not used. The 'gdefault' option value is not used. +You may also find this wiki useful. It was written by an early adoptor of +Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md ============================================================================== @@ -1111,7 +1113,7 @@ Exporting an item can be written as: > export class MyClass ... As this suggests, only constants, variables, `:def` functions and classes can -be exported. {classes are not implemented yet} +be exported. {not implemented yet: export class} *E1042* `:export` can only be used in Vim9 script, at the script level. diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 311e6a81ec..1a18a651e0 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar -" Last Change: 2021 Jan 21 +" Last Change: 2021 Mar 12 " Listen very carefully, I will say this only once if exists("did_load_filetypes") diff --git a/runtime/ftplugin/poke.vim b/runtime/ftplugin/poke.vim new file mode 100644 index 0000000000..2be86695c8 --- /dev/null +++ b/runtime/ftplugin/poke.vim @@ -0,0 +1,32 @@ +" Vim filetype plugin file +" Language: GNU Poke +" Maintainer: Doug Kearns +" Last Change: 2021 March 11 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo&vim + +setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:// +setlocal commentstring=//\ %s +setlocal formatoptions-=t formatoptions+=croql + +setlocal include=load +setlocal suffixesadd=.pk + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Poke Files (*.pk)\t*.pk\n" . + \ "All Files (*.*)\t*.*\n" +endif + +let b:undo_ftplugin = "setl fo< com< cms< inc< sua<" . + \ " | unlet! b:browsefilter" + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: nowrap sw=2 sts=2 ts=8 diff --git a/runtime/syntax/html.vim b/runtime/syntax/html.vim index 36d3c25f3a..8ccb5574e7 100644 --- a/runtime/syntax/html.vim +++ b/runtime/syntax/html.vim @@ -3,8 +3,9 @@ " Previous Maintainer: Jorge Maldonado Ventura " Previous Maintainer: Claudio Fleiner " Repository: https://notabug.org/jorgesumle/vim-html-syntax -" Last Change: 2021 Feb 25 +" Last Change: 2021 Mar 02 " Included patch #7900 to fix comments +" Included patch #7916 to fix a few more things " " Please check :help html.vim for some comments and a description of the options @@ -79,26 +80,16 @@ syn keyword htmlArg contained usemap ismap valign value vlink vspace width wrap syn match htmlArg contained "\<\(http-equiv\|href\|title\)="me=e-1 " aria attributes -syn match htmlArg contained "\<\(aria-activedescendant\|aria-atomic\)\>" -syn match htmlArg contained "\<\(aria-autocomplete\|aria-busy\|aria-checked\)\>" -syn match htmlArg contained "\<\(aria-colcount\|aria-colindex\|aria-colspan\)\>" -syn match htmlArg contained "\<\(aria-controls\|aria-current\)\>" -syn match htmlArg contained "\<\(aria-describedby\|aria-details\)\>" -syn match htmlArg contained "\<\(aria-disabled\|aria-dropeffect\)\>" -syn match htmlArg contained "\<\(aria-errormessage\|aria-expanded\)\>" -syn match htmlArg contained "\<\(aria-flowto\|aria-grabbed\|aria-haspopup\)\>" -syn match htmlArg contained "\<\(aria-hidden\|aria-invalid\)\>" -syn match htmlArg contained "\<\(aria-keyshortcuts\|aria-label\)\>" -syn match htmlArg contained "\<\(aria-labelledby\|aria-level\|aria-live\)\>" -syn match htmlArg contained "\<\(aria-modal\|aria-multiline\)\>" -syn match htmlArg contained "\<\(aria-multiselectable\|aria-orientation\)\>" -syn match htmlArg contained "\<\(aria-owns\|aria-placeholder\|aria-posinset\)\>" -syn match htmlArg contained "\<\(aria-pressed\|aria-readonly\|aria-relevant\)\>" -syn match htmlArg contained "\<\(aria-required\|aria-roledescription\)\>" -syn match htmlArg contained "\<\(aria-rowcount\|aria-rowindex\|aria-rowspan\)\>" -syn match htmlArg contained "\<\(aria-selected\|aria-setsize\|aria-sort\)\>" -syn match htmlArg contained "\<\(aria-valuemax\|aria-valuemin\)\>" -syn match htmlArg contained "\<\(aria-valuenow\|aria-valuetext\)\>" +exe 'syn match htmlArg contained "\"' syn keyword htmlArg contained role " Netscape extensions @@ -139,25 +130,19 @@ syn match htmlSpecialChar "&#\=[0-9A-Za-z]\{1,8};" " Comments (the real ones or the old netscape ones) if exists("html_wrong_comments") - syn region htmlComment start=+ and are parser errors; browser treats as comments - syn match htmlComment " closes comment - " Idem 8.2.4.52: closing comment by dash-dash-bang (--!>) is error ignored by parser(!); closes comment - syn region htmlCommentPart contained start=+--+ end=+--!\?>+me=e-1 contains=htmlCommentNested,@htmlPreProc,@Spell - " Idem 8.2.4.49: opening nested comment is all right - syn match htmlCommentNested contained ""me=e-3 - syn match htmlCommentNested contained " + " Idem 8.2.4.43,44: Except and are parser errors + " Idem 8.2.4.52: dash-dash-bang (--!>) is error ignored by parser, also closes comment + syn region htmlComment matchgroup=htmlComment start=+ is all right + syn match htmlCommentNested contained "\@!" + syn match htmlCommentError contained "[^>+ +syn region htmlComment start=++ keepend " server-parsed commands syn region htmlPreProc start=++ contains=htmlPreStmt,htmlPreError,htmlPreAttr @@ -278,7 +263,7 @@ hi def link htmlEndTag Identifier hi def link htmlArg Type hi def link htmlTagName htmlStatement hi def link htmlSpecialTagName Exception -hi def link htmlValue String +hi def link htmlValue String hi def link htmlSpecialChar Special if !exists("html_no_rendering") @@ -322,14 +307,10 @@ hi def link htmlPreProc PreProc hi def link htmlPreAttr String hi def link htmlPreProcAttrName PreProc hi def link htmlPreProcAttrError Error -hi def link htmlSpecial Special -hi def link htmlSpecialChar Special hi def link htmlString String hi def link htmlStatement Statement hi def link htmlComment Comment -hi def link htmlCommentPart Comment -hi def link htmlValue String -hi def link htmlCommentNested htmlCommentError +hi def link htmlCommentNested htmlError hi def link htmlCommentError htmlError hi def link htmlTagError htmlError hi def link htmlEvent javaScript diff --git a/runtime/syntax/poke.vim b/runtime/syntax/poke.vim new file mode 100644 index 0000000000..4a07a77d6c --- /dev/null +++ b/runtime/syntax/poke.vim @@ -0,0 +1,151 @@ +" Copyright (C) 2021 Matthew T. Ihlenfield. +" +" This program is free software: you can redistribute it and/or modify +" it under the terms of the GNU General Public License as published by +" the Free Software Foundation, either version 3 of the License, or +" (at your option) any later version. +" +" This program is distributed in the hope that it will be useful, +" but WITHOUT ANY WARRANTY; without even the implied warranty of +" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +" GNU General Public License for more details. +" +" You should have received a copy of the GNU General Public License +" along with this program. If not, see . +" +" Vim syntax file +" Language: Poke +" Maintainer: Matt Ihlenfield +" Filenames: *.pk +" Latest Revision: 10 March 2021 + +if exists('b:current_syntax') + finish +endif + +" Poke statement +syn keyword pokeStatement assert break continue return +syn keyword pokeStatement type unit fun method nextgroup=pokeFunction skipwhite +syn keyword pokeStatement var nextgroup=pokeVar skipWhite + +" Identifiers +syn match pokeVar '\h\w*' display contained + +" User defined functions +syn match pokeFunction '\h\w*' display contained + +" Poke operators +syn keyword pokeOperator in sizeof as isa unmap + +" Conditionals +syn keyword pokeConditional if else where + +" Structures, unions, etc... +syn keyword pokeStructure struct union pinned + +" Loops +syn keyword pokeRepeat while for + +" Imports +syn keyword pokeLoad load + +" Exceptions +syn keyword pokeException try catch until raise + +" Exception types +syn keyword pokeExceptionType Exception E_generic E_out_of_bounds +syn keyword pokeExceptionType E_eof E_elem E_constraint +syn keyword pokeExceptionType E_conv E_map_bounds E_map +syn keyword pokeExceptionType E_div_by_zero E_no_ios E_no_return +syn keyword pokeExceptionType E_io E_io_flags E_assert E_overflow + +" Exception codes +syn keyword pokeExceptionCode EC_generic EC_out_of_bounds +syn keyword pokeExceptionCode EC_eof EC_elem EC_constraint +syn keyword pokeExceptionCode EC_conv EC_map_bounds EC_map +syn keyword pokeExceptionCode EC_div_by_zero EC_no_ios EC_no_return +syn keyword pokeExceptionCode EC_io EC_io_flags EC_assert EC_overflow + +" Poke builtin types +syn keyword pokeBuiltinType string void int uint bit nibble +syn keyword pokeBuiltinType byte char ushort short ulong long +syn keyword pokeBuiltinType uint8 uint16 uint32 uint64 +syn keyword pokeBuiltinType off64 uoff64 offset +syn keyword pokeBuiltinType Comparator POSIX_Time32 POSIX_Time64 +syn keyword pokeBuiltinType big little any + +" Poke constants +syn keyword pokeConstant ENDIAN_LITTLE ENDIAN_BIG +syn keyword pokeConstant IOS_F_READ IOS_F_WRITE IOS_F_TRUNCATE IOS_F_CREATE +syn keyword pokeConstant IOS_M_RDONLY IOS_M_WRONLY IOS_M_RDWR +syn keyword pokeConstant load_path NULL OFFSET + +" Poke std lib +syn keyword pokeBuiltinFunction print printf catos stoca atoi ltos reverse +syn keyword pokeBuiltinFunction ltrim rtrim strchr qsort crc32 alignto +syn keyword pokeBuiltinFunction open close flush get_ios set_ios iosize +syn keyword pokeBuiltinFunction rand get_endian set_endian strace exit +syn keyword pokeBuiltinFunction getenv + +" Formats + +" Special chars +syn match pokeSpecial "\\\([nt\\]\|\o\{1,3}\)" display contained + +" Chars +syn match pokeChar "'[^']*'" contains=pokeSpecial + +" Attributes +syn match pokeAttribute "\h\w*'\h\w" + +" Strings +syn region pokeString skip=+\\\\\|\\"+ start=+"+ end=+"+ contains=pokeSpecial + +" Integer literals +syn match pokeInteger "\<\d\+_*\d*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>" +syn match pokeInteger "\<0[Xx]\x\+_*\x*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>" +syn match pokeInteger "\<0[Oo]\o\+_*\o*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>" +syn match pokeInteger "\<0[Bb][01]\+_*[01]*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>" + +" Units +syn keyword pokeBuiltinUnit b M B +syn keyword pokeBuiltinUnit Kb KB Mb MB Gb GB +syn keyword pokeBuiltinUnit Kib KiB Mib MiB Gib GiB + +" Offsets +syn match pokeOffset "#\h\w*" contains=pokeBuiltinUnit + +" Comments +syn keyword pokeCommentTodo TODO FIXME XXX TBD contained +syn match pokeLineComment "\/\/.*" contains=pokeCommentTodo,@Spell extend +syn region pokeComment start="/\*" end="\*/" contains=pokeCommentTodo,@Spell fold extend + +" Allow folding of blocks +syn region pokeBlock start="{" end="}" transparent fold + +" Highlight groups +hi def link pokeBuiltinFunction Function +hi def link pokeBuiltinType Type +hi def link pokeBuiltinUnit Keyword +hi def link pokeChar Character +hi def link pokeComment Comment +hi def link pokeCommentTodo Todo +hi def link pokeConditional Conditional +hi def link pokeConstant Constant +hi def link pokeException Exception +hi def link pokeExceptionCode Constant +hi def link pokeExceptionType Type +hi def link pokeFunction Function +hi def link pokeInteger Number +hi def link pokeLineComment Comment +hi def link pokeLoad Include +hi def link pokeOffset StorageClass +hi def link pokeOperator Operator +hi def link pokeSpecial SpecialChar +hi def link pokeStatement Statement +hi def link pokeString String +hi def link pokeStructure Structure +hi def link pokeRepeat Repeat +hi def link pokeVar Identifier + +let b:current_syntax = 'poke' diff --git a/src/INSTALL b/src/INSTALL index 1ed4887c77..64958aa13f 100644 --- a/src/INSTALL +++ b/src/INSTALL @@ -60,8 +60,8 @@ To built Vim on Ubuntu from scratch on a clean system using git: % sudo apt install libxt-dev % make reconfig - Add GUI support (ignore compiler warnings): - % sudo apt install libgtk2.0-dev + Add GUI support: + % sudo apt install libgtk-3-dev % make reconfig Add Python 3 support: @@ -134,8 +134,12 @@ These configure arguments can be used to select which GUI to use: --disable-motif-check --disable-athena-check +This configure argument can be used to disable the GUI, even when the necessary +files are found: +--disable-gui + --enable-gui defaults to "auto", so it will automatically look for a GUI (in -the order of GTK, Motif, then Athena). If one is found, then is uses it and +the order of GTK, Motif, then Athena). If one is found, then it is used and does not proceed to check any of the remaining ones. Otherwise, it moves on to the next one. From 0de8e2d6a3fae61c4d9dfdd6f16fc5040d994f6c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 13:30:03 +0100 Subject: [PATCH 18/44] patch 8.2.2593: list of distributed files is incomplete Problem: List of distributed files is incomplete. Solution: Add a file and rename another. --- Filelist | 3 ++- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Filelist b/Filelist index 04a433291e..82fb376e1e 100644 --- a/Filelist +++ b/Filelist @@ -13,7 +13,8 @@ SRC_ALL = \ .hgignore \ .lgtm.yml \ .travis.yml \ - appveyor.yml \ + .appveyor.yml \ + .codecov.yml \ ci/appveyor.bat \ ci/build-snd-dummy.sh \ ci/config.mk*.sed \ diff --git a/src/version.c b/src/version.c index c6866a2973..45973eac26 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2593, /**/ 2592, /**/ From 0756f757edba755b75e0c9c612ab2f7e673def84 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 13:52:33 +0100 Subject: [PATCH 19/44] patch 8.2.2594: alternate buffer added to session file even when it's hidden Problem: Alternate buffer added to session file even when it's hidden. Solution: Check the 'buflisted' option. (closes #7951) --- src/session.c | 3 ++- src/testdir/test_mksession.vim | 14 ++++++++++++++ src/version.c | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/session.c b/src/session.c index a734656d54..6e73bb6766 100644 --- a/src/session.c +++ b/src/session.c @@ -401,11 +401,12 @@ put_view( { buf_T *alt = buflist_findnr(wp->w_alt_fnum); - // Set the alternate file. + // Set the alternate file if the buffer is listed. if ((flagp == &ssop_flags) && alt != NULL && alt->b_fname != NULL && *alt->b_fname != NUL + && alt->b_p_bl && (fputs("balt ", fd) < 0 || ses_fname(fd, alt, flagp, TRUE) == FAIL)) return FAIL; diff --git a/src/testdir/test_mksession.vim b/src/testdir/test_mksession.vim index eb8c6a5a46..6e36553733 100644 --- a/src/testdir/test_mksession.vim +++ b/src/testdir/test_mksession.vim @@ -544,6 +544,20 @@ func Test_mkview_no_balt() %bwipe endfunc +func Test_mksession_no_balt() + edit Xtestfile1 + edit Xtestfile2 + + bdelete Xtestfile1 + mksession! Xtestview + + source Xtestview + call assert_equal(0, buflisted('Xtestfile1')) + + call delete('Xtestview') + %bwipe +endfunc + " Test :mkview with a file argument. func Test_mkview_file() " Create a view with line number and a fold. diff --git a/src/version.c b/src/version.c index 45973eac26..f1b823226e 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2594, /**/ 2593, /**/ From 9e813b3dea94a8952b732a224fa31beba6e85973 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 14:29:05 +0100 Subject: [PATCH 20/44] patch 8.2.2595: setting 'winminheight' may cause 'lines' to change Problem: Setting 'winminheight' may cause 'lines' to change. Solution: Also take minimal height of other tabpages into account. (#7899) --- src/testdir/test_options.vim | 21 +++++++++++++++++++++ src/version.c | 2 ++ src/window.c | 4 ++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 2595392a03..54042d42f7 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -1035,6 +1035,27 @@ func Test_opt_winminheight_term() call delete('Xwinminheight') endfunc +func Test_opt_winminheight_term_tabs() + CheckRunVimInTerminal + + " The tabline should be taken into account. + let lines =<< trim END + set wmh=0 stal=2 + split + split + split + split + tabnew + END + call writefile(lines, 'Xwinminheight') + let buf = RunVimInTerminal('-S Xwinminheight', #{rows: 11}) + call term_sendkeys(buf, ":set wmh=1\n") + call WaitForAssert({-> assert_match('E36: Not enough room', term_getline(buf, 11))}) + + call StopVimInTerminal(buf) + call delete('Xwinminheight') +endfunc + " Test for the 'winminwidth' option func Test_opt_winminwidth() only! diff --git a/src/version.c b/src/version.c index f1b823226e..3981323f85 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2595, /**/ 2594, /**/ diff --git a/src/window.c b/src/window.c index a810a6af22..3e32b3759e 100644 --- a/src/window.c +++ b/src/window.c @@ -5860,8 +5860,8 @@ win_setminheight(void) // loop until there is a 'winminheight' that is possible while (p_wmh > 0) { - room = Rows - p_ch - tabline_height(); - needed = frame_minheight(topframe, NULL); + room = Rows - p_ch; + needed = min_rows() - 1; // 1 was added for the cmdline if (room >= needed) break; --p_wmh; From 41cd80335cf318c15c8b0139f53ab5e8a02561ef Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 15:47:56 +0100 Subject: [PATCH 21/44] patch 8.2.2596: :doautocmd may confuse scripts listening to WinEnter Problem: :doautocmd may confuse scripts listening to WinEnter. Solution: Do the current buffer last. (closes #7958) --- src/autocmd.c | 20 ++++++++++++++++---- src/testdir/test_autocmd.vim | 10 +++++++++- src/version.c | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/autocmd.c b/src/autocmd.c index 2f6001c267..ede8e7dbe0 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -1336,7 +1336,7 @@ do_doautocmd( void ex_doautoall(exarg_T *eap) { - int retval; + int retval = OK; aco_save_T aco; buf_T *buf; bufref_T bufref; @@ -1353,7 +1353,8 @@ ex_doautoall(exarg_T *eap) */ FOR_ALL_BUFFERS(buf) { - if (buf->b_ml.ml_mfp != NULL) + // Only do loaded buffers and skip the current buffer, it's done last. + if (buf->b_ml.ml_mfp != NULL && buf != curbuf) { // find a window for this buffer and save some values aucmd_prepbuf(&aco, buf); @@ -1363,22 +1364,31 @@ ex_doautoall(exarg_T *eap) retval = do_doautocmd(arg, FALSE, &did_aucmd); if (call_do_modelines && did_aucmd) - { // Execute the modeline settings, but don't set window-local // options if we are using the current window for another // buffer. do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0); - } // restore the current window aucmd_restbuf(&aco); // stop if there is some error or buffer was deleted if (retval == FAIL || !bufref_valid(&bufref)) + { + retval = FAIL; break; + } } } + // Execute autocommands for the current buffer last. + if (retval == OK) + { + do_doautocmd(arg, FALSE, &did_aucmd); + if (call_do_modelines && did_aucmd) + do_modelines(0); + } + check_cursor(); // just in case lines got deleted } @@ -2166,12 +2176,14 @@ apply_autocmds_group( while (au_pending_free_buf != NULL) { buf_T *b = au_pending_free_buf->b_next; + vim_free(au_pending_free_buf); au_pending_free_buf = b; } while (au_pending_free_win != NULL) { win_T *w = au_pending_free_win->w_next; + vim_free(au_pending_free_win); au_pending_free_win = w; } diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index e4f67f4fc6..8abf911fa8 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -2670,6 +2670,9 @@ func Test_autocmd_window() %bw! edit one.txt tabnew two.txt + vnew three.txt + tabnew four.txt + tabprevious let g:blist = [] augroup aucmd_win_test1 au! @@ -2678,7 +2681,12 @@ func Test_autocmd_window() augroup END doautoall BufEnter - call assert_equal([['one.txt', 'autocmd'], ['two.txt', '']], g:blist) + call assert_equal([ + \ ['one.txt', 'autocmd'], + \ ['two.txt', ''], + \ ['four.txt', 'autocmd'], + \ ['three.txt', ''], + \ ], g:blist) augroup aucmd_win_test1 au! diff --git a/src/version.c b/src/version.c index 3981323f85..fbcf57e364 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2596, /**/ 2595, /**/ From cb4e80fab9b1ee67249bde4f784526f900cda70c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 20:57:19 +0100 Subject: [PATCH 22/44] patch 8.2.2597: Vim9: "import * as" does not work at script level Problem: Vim9: "import * as" does not work at script level. Solution: Implement using an imported namespace. --- src/errors.h | 2 ++ src/eval.c | 62 ++++++++++++++++++++++++++++++-- src/evalvars.c | 40 ++++++++++++++------- src/proto/evalvars.pro | 2 +- src/proto/vim9script.pro | 2 +- src/testdir/test_vim9_script.vim | 24 +++++++++++-- src/version.c | 2 ++ src/vim.h | 5 +++ src/vim9execute.c | 2 +- src/vim9script.c | 11 +++--- 10 files changed, 129 insertions(+), 23 deletions(-) diff --git a/src/errors.h b/src/errors.h index db958e0541..c1dc547fbe 100644 --- a/src/errors.h +++ b/src/errors.h @@ -373,3 +373,5 @@ EXTERN char e_argument_name_shadows_existing_variable_str[] INIT(= N_("E1167: Argument name shadows existing variable: %s")); EXTERN char e_argument_already_declared_in_script_str[] INIT(= N_("E1168: Argument already declared in the script: %s")); +EXTERN char e_import_as_name_not_supported_here[] + INIT(= N_("E1169: 'import * as {name}' not supported here")); diff --git a/src/eval.c b/src/eval.c index 1ad6339659..8e964de700 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1370,7 +1370,7 @@ set_var_lval( // handle +=, -=, *=, /=, %= and .= di = NULL; if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name), - &tv, &di, TRUE, FALSE) == OK) + &tv, &di, EVAL_VAR_VERBOSE) == OK) { if ((di == NULL || (!var_check_ro(di->di_flags, lp->ll_name, FALSE) @@ -3500,7 +3500,8 @@ eval7( ret = OK; } else - ret = eval_variable(s, len, rettv, NULL, TRUE, FALSE); + ret = eval_variable(s, len, rettv, NULL, + EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT); } else { @@ -5760,6 +5761,63 @@ handle_subscript( check_white = FALSE; } + if (rettv->v_type == VAR_ANY) + { + char_u *exp_name; + int cc; + int idx; + ufunc_T *ufunc; + type_T *type; + + // Found script from "import * as {name}", script item name must + // follow. + if (**arg != '.') + { + if (verbose) + semsg(_(e_expected_str_but_got_str), "'.'", *arg); + ret = FAIL; + break; + } + ++*arg; + if (IS_WHITE_OR_NUL(**arg)) + { + if (verbose) + emsg(_(e_no_white_space_allowed_after_dot)); + ret = FAIL; + break; + } + + // isolate the name + exp_name = *arg; + while (eval_isnamec(**arg)) + ++*arg; + cc = **arg; + **arg = NUL; + + idx = find_exported(rettv->vval.v_number, exp_name, &ufunc, &type, + evalarg->eval_cctx, verbose); + **arg = cc; + *arg = skipwhite(*arg); + + if (idx < 0 && ufunc == NULL) + { + ret = FAIL; + break; + } + if (idx >= 0) + { + scriptitem_T *si = SCRIPT_ITEM(rettv->vval.v_number); + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; + + copy_tv(sv->sv_tv, rettv); + } + else + { + rettv->v_type = VAR_FUNC; + rettv->vval.v_string = vim_strsave(ufunc->uf_name); + } + } + if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC || rettv->v_type == VAR_PARTIAL)) && (!check_white || !VIM_ISWHITE(*(*arg - 1)))) diff --git a/src/evalvars.c b/src/evalvars.c index eac66b2b92..eefd05f367 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1219,7 +1219,8 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first) arg = skipwhite(arg); if (tofree != NULL) name = tofree; - if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL) + if (eval_variable(name, len, &tv, NULL, + EVAL_VAR_VERBOSE) == FAIL) error = TRUE; else { @@ -2539,6 +2540,8 @@ set_cmdarg(exarg_T *eap, char_u *oldarg) /* * Get the value of internal variable "name". + * If "flags" has EVAL_VAR_IMPORT may return a VAR_ANY with v_number set to the + * imported script ID. * Return OK or FAIL. If OK is returned "rettv" must be cleared. */ int @@ -2547,12 +2550,11 @@ eval_variable( int len, // length of "name" typval_T *rettv, // NULL when only checking existence dictitem_T **dip, // non-NULL when typval's dict item is needed - int verbose, // may give error message - int no_autoload) // do not use script autoloading + int flags) // EVAL_VAR_ flags { int ret = OK; typval_T *tv = NULL; - int foundFunc = FALSE; + int found = FALSE; dictitem_T *v; int cc; @@ -2561,7 +2563,7 @@ eval_variable( name[len] = NUL; // Check for user-defined variables. - v = find_var(name, NULL, no_autoload); + v = find_var(name, NULL, flags & EVAL_VAR_NOAUTOLOAD); if (v != NULL) { tv = &v->di_tv; @@ -2581,7 +2583,7 @@ eval_variable( { if (import->imp_funcname != NULL) { - foundFunc = TRUE; + found = TRUE; if (rettv != NULL) { rettv->v_type = VAR_FUNC; @@ -2590,8 +2592,21 @@ eval_variable( } else if (import->imp_flags & IMP_FLAGS_STAR) { - emsg("Sorry, 'import * as X' not implemented yet"); - ret = FAIL; + if ((flags & EVAL_VAR_IMPORT) == 0) + { + if (flags & EVAL_VAR_VERBOSE) + emsg(_(e_import_as_name_not_supported_here)); + ret = FAIL; + } + else + { + if (rettv != NULL) + { + rettv->v_type = VAR_ANY; + rettv->vval.v_number = import->imp_sid; + } + found = TRUE; + } } else { @@ -2607,7 +2622,7 @@ eval_variable( if (ufunc != NULL) { - foundFunc = TRUE; + found = TRUE; if (rettv != NULL) { rettv->v_type = VAR_FUNC; @@ -2617,11 +2632,11 @@ eval_variable( } } - if (!foundFunc) + if (!found) { if (tv == NULL) { - if (rettv != NULL && verbose) + if (rettv != NULL && (flags & EVAL_VAR_VERBOSE)) semsg(_(e_undefined_variable_str), name); ret = FAIL; } @@ -3695,7 +3710,8 @@ var_exists(char_u *var) { if (tofree != NULL) name = tofree; - n = (eval_variable(name, len, &tv, NULL, FALSE, TRUE) == OK); + n = (eval_variable(name, len, &tv, NULL, + EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK); if (n) { // handle d.key, l[idx], f(expr) diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index bd2c6879ff..1094d45630 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -56,7 +56,7 @@ void set_reg_var(int c); char_u *v_exception(char_u *oldval); char_u *v_throwpoint(char_u *oldval); char_u *set_cmdarg(exarg_T *eap, char_u *oldarg); -int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload); +int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int flags); void check_vars(char_u *name, int len); dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro index c6493519cf..c80618f750 100644 --- a/src/proto/vim9script.pro +++ b/src/proto/vim9script.pro @@ -7,7 +7,7 @@ void ex_export(exarg_T *eap); void free_imports_and_script_vars(int sid); void mark_imports_for_reload(int sid); void ex_import(exarg_T *eap); -int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx); +int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx, int verbose); char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx); char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg); void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, type_T **type); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 95c6a5b10b..d2f5febb97 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1031,13 +1031,17 @@ def Test_vim9_import_export() vim9script import * as Export from './Xexport.vim' def UseExport() - g:imported = Export.exported + g:imported_def = Export.exported enddef + g:imported_script = Export.exported + assert_equal(1, exists('Export.exported')) + assert_equal(0, exists('Export.notexported')) UseExport() END writefile(import_star_as_lines, 'Ximport.vim') source Ximport.vim - assert_equal(9883, g:imported) + assert_equal(9883, g:imported_def) + assert_equal(9883, g:imported_script) var import_star_as_lines_no_dot =<< trim END vim9script @@ -1072,6 +1076,22 @@ def Test_vim9_import_export() writefile(import_star_as_duplicated, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim') + var import_star_as_lines_script_no_dot =<< trim END + vim9script + import * as Export from './Xexport.vim' + g:imported_script = Export exported + END + writefile(import_star_as_lines_script_no_dot, 'Ximport.vim') + assert_fails('source Ximport.vim', 'E1029:') + + var import_star_as_lines_script_space_after_dot =<< trim END + vim9script + import * as Export from './Xexport.vim' + g:imported_script = Export. exported + END + writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim') + assert_fails('source Ximport.vim', 'E1074:') + var import_star_as_lines_missing_name =<< trim END vim9script import * as Export from './Xexport.vim' diff --git a/src/version.c b/src/version.c index fbcf57e364..f35f8b0b03 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2597, /**/ 2596, /**/ diff --git a/src/vim.h b/src/vim.h index 5dd69f6ee7..7f4c99ad36 100644 --- a/src/vim.h +++ b/src/vim.h @@ -2702,4 +2702,9 @@ long elapsed(DWORD start_tick); #define MCH_DELAY_IGNOREINPUT 1 #define MCH_DELAY_SETTMODE 2 +// Flags for eval_variable(). +#define EVAL_VAR_VERBOSE 1 // may give error message +#define EVAL_VAR_NOAUTOLOAD 2 // do not use script autoloading +#define EVAL_VAR_IMPORT 4 // may return special variable for import + #endif // VIM__H diff --git a/src/vim9execute.c b/src/vim9execute.c index d4435c4c5f..f8470f5c77 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1765,7 +1765,7 @@ call_def_function( goto failed; SOURCING_LNUM = iptr->isn_lnum; if (eval_variable(name, (int)STRLEN(name), - STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL) + STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL) goto on_error; ++ectx.ec_stack.ga_len; } diff --git a/src/vim9script.c b/src/vim9script.c index cd60b250f9..faee1316c4 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -257,7 +257,8 @@ find_exported( char_u *name, ufunc_T **ufunc, type_T **type, - cctx_T *cctx) + cctx_T *cctx, + int verbose) { int idx = -1; svar_T *sv; @@ -271,7 +272,8 @@ find_exported( sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; if (!sv->sv_export) { - semsg(_(e_item_not_exported_in_script_str), name); + if (verbose) + semsg(_(e_item_not_exported_in_script_str), name); return -1; } *type = sv->sv_type; @@ -301,7 +303,8 @@ find_exported( if (*ufunc == NULL) { - semsg(_(e_item_not_found_in_script_str), name); + if (verbose) + semsg(_(e_item_not_found_in_script_str), name); return -1; } } @@ -532,7 +535,7 @@ handle_import( ufunc_T *ufunc = NULL; type_T *type; - idx = find_exported(sid, name, &ufunc, &type, cctx); + idx = find_exported(sid, name, &ufunc, &type, cctx, TRUE); if (idx < 0 && ufunc == NULL) goto erret; From 6508880d6ca98486efb9ab947c651a2b73a6e795 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 21:07:21 +0100 Subject: [PATCH 23/44] patch 8.2.2598: Vim9: :open does not need to be supported Problem: Vim9: :open does not need to be supported. Solution: Do not support :open in Vim9 script. --- src/ex_docmd.c | 4 ++++ src/testdir/test_vim9_script.vim | 2 ++ src/version.c | 2 ++ src/vim9script.c | 1 + 4 files changed, 9 insertions(+) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 40e70c32b9..c7b57ba992 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -6609,6 +6609,10 @@ ex_open(exarg_T *eap) regmatch_T regmatch; char_u *p; +#ifdef FEAT_EVAL + if (not_in_vim9(eap) == FAIL) + return; +#endif curwin->w_cursor.lnum = eap->line2; beginline(BL_SOL | BL_FIX); if (*eap->arg == '/') diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index d2f5febb97..78ff44b936 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1880,6 +1880,8 @@ def Test_no_insert_xit() CheckScriptFailure(['vim9script', 'c'], 'E1100:') CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') CheckScriptFailure(['vim9script', 'i'], 'E1100:') + CheckScriptFailure(['vim9script', 'o = 1'], 'E1100:') + CheckScriptFailure(['vim9script', 'o'], 'E1100:') CheckScriptFailure(['vim9script', 't'], 'E1100:') CheckScriptFailure(['vim9script', 't = 1'], 'E1100:') CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') diff --git a/src/version.c b/src/version.c index f35f8b0b03..78eb6341d6 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2598, /**/ 2597, /**/ diff --git a/src/vim9script.c b/src/vim9script.c index faee1316c4..05977b641c 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -102,6 +102,7 @@ not_in_vim9(exarg_T *eap) case CMD_append: case CMD_change: case CMD_insert: + case CMD_open: case CMD_t: case CMD_xit: semsg(_(e_command_not_supported_in_vim9_script_missing_var_str), eap->cmd); From edba70703b6eaee3365ddfd82e4ba56ee08486f8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 21:14:18 +0100 Subject: [PATCH 24/44] patch 8.2.2599: build failure Problem: Build failure. Solution: Add missing change. --- src/version.c | 2 ++ src/vim9compile.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/version.c b/src/version.c index 78eb6341d6..9a4fa46808 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2599, /**/ 2598, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index c49c499841..1bb30ca0cf 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2645,7 +2645,8 @@ compile_load_scriptvar( cc = *p; *p = NUL; - idx = find_exported(import->imp_sid, exp_name, &ufunc, &type, cctx); + idx = find_exported(import->imp_sid, exp_name, &ufunc, &type, + cctx, TRUE); *p = cc; p = skipwhite(p); From 93e1cae739c32baf28954b64718bab009c6ee2ac Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 21:24:56 +0100 Subject: [PATCH 25/44] patch 8.2.2600: Vim9: crash when putting an unknown type in a dictionary Problem: Vim9: crash when putting an unknown type in a dictionary. (Yegappan Lakshmanan) Solution: Handle a NULL type pointer. --- src/testdir/test_vim9_builtin.vim | 20 ++++++++++++++++++++ src/version.c | 2 ++ src/vim9type.c | 6 ++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 8ec3db1482..75bbc0c506 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -340,6 +340,26 @@ def Test_extend_list_item_type() CheckScriptFailure(['vim9script'] + lines, 'E1012:', 1) enddef +def Test_extend_with_error_function() + var lines =<< trim END + vim9script + def F() + { + var m = 10 + } + echo m + enddef + + def Test() + var d: dict = {} + d->extend({A: 10, Func: function('F', [])}) + enddef + + Test() + END + CheckScriptFailure(lines, 'E1001: Variable not found: m') +enddef + def Test_job_info_return_type() if has('job') job_start(&shell) diff --git a/src/version.c b/src/version.c index 9a4fa46808..72d38783d4 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2600, /**/ 2599, /**/ diff --git a/src/vim9type.c b/src/vim9type.c index d1ada8e96b..9eda30d6e6 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -919,6 +919,8 @@ equal_type(type_T *type1, type_T *type2) { int i; + if (type1 == NULL || type2 == NULL) + return FALSE; if (type1->tt_type != type2->tt_type) return FALSE; switch (type1->tt_type) @@ -969,12 +971,12 @@ common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap) // If either is VAR_UNKNOWN use the other type. An empty list/dict has no // specific type. - if (type1->tt_type == VAR_UNKNOWN) + if (type1 == NULL || type1->tt_type == VAR_UNKNOWN) { *dest = type2; return; } - if (type2->tt_type == VAR_UNKNOWN) + if (type2 == NULL || type2->tt_type == VAR_UNKNOWN) { *dest = type1; return; From 6bce5856b5fc4d4eb8f75298382251ecda659ac3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 13 Mar 2021 22:11:51 +0100 Subject: [PATCH 26/44] patch 8.2.2601: memory usage test often fails on FreeBSD Problem: Memory usage test often fails on FreeBSD. Solution: Increase multiplier for upper limit. --- src/testdir/test_memory_usage.vim | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_memory_usage.vim b/src/testdir/test_memory_usage.vim index 4f78d9a094..3b7b37247f 100644 --- a/src/testdir/test_memory_usage.vim +++ b/src/testdir/test_memory_usage.vim @@ -147,9 +147,9 @@ func Test_memory_func_capture_lvars() " The usage may be a bit less than the last value, use 80%. " Allow for 20% tolerance at the upper limit. That's very permissive, but " otherwise the test fails sometimes. On Cirrus CI with FreeBSD we need to - " be even more permissive. + " be even much more permissive. if has('bsd') - let multiplier = 15 + let multiplier = 19 else let multiplier = 12 endif diff --git a/src/version.c b/src/version.c index 72d38783d4..0b9337240c 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2601, /**/ 2600, /**/ From 2e34c34be1393027a761ecbccd8f267d52ca7bc1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 14 Mar 2021 12:13:33 +0100 Subject: [PATCH 27/44] patch 8.2.2602: Vim9: continue doesn't work if :while is very first command Problem: Vim9: continue doesn't work if :while is very first command. (Yegappan Lakshmanan) Solution: Add one to the continue instruction index. --- src/testdir/test_vim9_script.vim | 25 +++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 8 +++++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 78ff44b936..c476acf896 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -592,6 +592,31 @@ def Test_try_catch_throw() assert_equal(4, ReturnInFinally()) enddef +" :while at the very start of a function that :continue jumps to +def TryContinueFunc() + while g:Count < 2 + g:sequence ..= 't' + try + echoerr 'Test' + catch + g:Count += 1 + g:sequence ..= 'c' + continue + endtry + g:sequence ..= 'e' + g:Count += 1 + endwhile +enddef + +def Test_continue_in_try_in_while() + g:Count = 0 + g:sequence = '' + TryContinueFunc() + assert_equal('tctc', g:sequence) + unlet g:Count + unlet g:sequence +enddef + def Test_nocatch_return_in_try() # return in try block returns normally def ReturnInTry(): string diff --git a/src/version.c b/src/version.c index 0b9337240c..5f950831b7 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2602, /**/ 2601, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index f8470f5c77..b2c28a31bc 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -30,7 +30,7 @@ typedef struct { int tcd_finally_idx; // instruction of the :finally block or zero int tcd_endtry_idx; // instruction of the :endtry int tcd_caught; // catch block entered - int tcd_cont; // :continue encountered, jump here + int tcd_cont; // :continue encountered, jump here (minus one) int tcd_return; // when TRUE return from end of :finally } trycmd_T; @@ -2757,7 +2757,9 @@ call_def_function( { trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - i; - trycmd->tcd_cont = iidx; + // Add one to tcd_cont to be able to jump to + // instruction with index zero. + trycmd->tcd_cont = iidx + 1; iidx = trycmd->tcd_finally_idx == 0 ? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx; } @@ -2811,7 +2813,7 @@ call_def_function( if (trycmd->tcd_cont != 0) // handling :continue: jump to outer try block or // start of the loop - ectx.ec_iidx = trycmd->tcd_cont; + ectx.ec_iidx = trycmd->tcd_cont - 1; } } break; From 77b10ffad4ebad15022614be4db2745f6a90f405 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 14 Mar 2021 13:21:35 +0100 Subject: [PATCH 28/44] patch 8.2.2603: Vim9: no effect if user command is also a function Problem: Vim9: no effect if user command is also a function. Solution: Check for paren following. (closes #7960) --- src/evalvars.c | 30 ++++++++++++++++++++---------- src/ex_docmd.c | 6 +++--- src/proto/evalvars.pro | 2 +- src/proto/ex_docmd.pro | 2 +- src/testdir/test_vim9_cmd.vim | 35 ++++++++++++++++++++++++++++++----- src/version.c | 2 ++ src/vim9compile.c | 28 +++++++++++++++++++--------- 7 files changed, 76 insertions(+), 29 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index eefd05f367..79c7a9c8c4 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2805,12 +2805,15 @@ get_script_local_ht(void) /* * Look for "name[len]" in script-local variables and functions. + * When "cmd" is TRUE it must look like a command, a function must be followed + * by "(" or "->". * Return OK when found, FAIL when not found. */ int lookup_scriptitem( char_u *name, size_t len, + int cmd, cctx_T *dummy UNUSED) { hashtab_T *ht = get_script_local_ht(); @@ -2845,19 +2848,26 @@ lookup_scriptitem( if (p != buffer) vim_free(p); + // Find a function, so that a following "->" works. + // When used as a command require "(" or "->" to follow, "Cmd" is a user + // command while "Cmd()" is a function call. if (res != OK) { - // Find a function, so that a following "->" works. Skip "g:" before a - // function name. - // Do not check for an internal function, since it might also be a - // valid command, such as ":split" versuse "split()". - if (name[0] == 'g' && name[1] == ':') + p = skipwhite(name + len); + + if (!cmd || name[len] == '(' || (p[0] == '-' && p[1] == '>')) { - is_global = TRUE; - fname = name + 2; + // Do not check for an internal function, since it might also be a + // valid command, such as ":split" versus "split()". + // Skip "g:" before a function name. + if (name[0] == 'g' && name[1] == ':') + { + is_global = TRUE; + fname = name + 2; + } + if (find_func(fname, is_global, NULL) != NULL) + res = OK; } - if (find_func(fname, is_global, NULL) != NULL) - res = OK; } return res; @@ -3288,7 +3298,7 @@ set_var_const( { // Item not found, check if a function already exists. if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0 - && lookup_scriptitem(name, STRLEN(name), NULL) == OK) + && lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK) { semsg(_(e_redefining_script_item_str), name); goto failed; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index c7b57ba992..477d140bde 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3311,7 +3311,7 @@ skip_option_env_lead(char_u *start) find_ex_command( exarg_T *eap, int *full UNUSED, - int (*lookup)(char_u *, size_t, cctx_T *) UNUSED, + int (*lookup)(char_u *, size_t, int cmd, cctx_T *) UNUSED, cctx_T *cctx UNUSED) { int len; @@ -3430,7 +3430,7 @@ find_ex_command( || *eap->cmd == '&' || *eap->cmd == '$' || *eap->cmd == '@' - || lookup(eap->cmd, p - eap->cmd, cctx) == OK) + || lookup(eap->cmd, p - eap->cmd, TRUE, cctx) == OK) { eap->cmdidx = CMD_var; return eap->cmd; @@ -3449,7 +3449,7 @@ find_ex_command( // If it is an ID it might be a variable with an operator on the next // line, if the variable exists it can't be an Ex command. if (p > eap->cmd && ends_excmd(*skipwhite(p)) - && (lookup(eap->cmd, p - eap->cmd, cctx) == OK + && (lookup(eap->cmd, p - eap->cmd, TRUE, cctx) == OK || (ASCII_ISALPHA(eap->cmd[0]) && eap->cmd[1] == ':'))) { eap->cmdidx = CMD_eval; diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 1094d45630..c75f80a863 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -61,7 +61,7 @@ void check_vars(char_u *name, int len); dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); hashtab_T *get_script_local_ht(void); -int lookup_scriptitem(char_u *name, size_t len, cctx_T *dummy); +int lookup_scriptitem(char_u *name, size_t len, int cmd, cctx_T *dummy); hashtab_T *find_var_ht(char_u *name, char_u **varname); char_u *get_var_value(char_u *name); void new_script_vars(scid_T id); diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro index dcd9f3940c..9ac8eaf527 100644 --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -13,7 +13,7 @@ void undo_cmdmod(cmdmod_T *cmod); int parse_cmd_address(exarg_T *eap, char **errormsg, int silent); int checkforcmd(char_u **pp, char *cmd, int len); char_u *skip_option_env_lead(char_u *start); -char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, cctx_T *), cctx_T *cctx); +char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, int cmd, cctx_T *), cctx_T *cctx); int modifier_len(char_u *cmd); int cmd_exists(char_u *name); void f_fullcommand(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index dd6e966de1..c21e55a477 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -364,9 +364,8 @@ def Test_method_call_linebreak() return F() enddef def Test() - Foo - ->Bar() - ->setline(1) + Foo ->Bar() + ->setline(1) enddef Test() assert_equal('the text', getline(1)) @@ -401,8 +400,7 @@ def Test_method_call_linebreak() return F() enddef - Foo - ->Bar() + Foo->Bar() ->setline(1) END CheckScriptSuccess(lines) @@ -424,6 +422,33 @@ def Test_method_call_whitespace() CheckDefAndScriptSuccess(lines) enddef +def Test_method_and_user_command() + var lines =<< trim END + vim9script + def Cmd() + g:didFunc = 1 + enddef + command Cmd g:didCmd = 1 + Cmd + assert_equal(1, g:didCmd) + Cmd() + assert_equal(1, g:didFunc) + unlet g:didFunc + unlet g:didCmd + + def InDefFunc() + Cmd + assert_equal(1, g:didCmd) + Cmd() + assert_equal(1, g:didFunc) + unlet g:didFunc + unlet g:didCmd + enddef + InDefFunc() + END + CheckScriptSuccess(lines) +enddef + def Test_skipped_expr_linebreak() if 0 var x = [] diff --git a/src/version.c b/src/version.c index 5f950831b7..14bf96bba0 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2603, /**/ 2602, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 1bb30ca0cf..3fef9bd6b0 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -391,19 +391,29 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx) * imported or function. */ static int -item_exists(char_u *name, size_t len, cctx_T *cctx) +item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx) { int is_global; + char_u *p; if (variable_exists(name, len, cctx)) return TRUE; - // Find a function, so that a following "->" works. Skip "g:" before a - // function name. - // Do not check for an internal function, since it might also be a - // valid command, such as ":split" versuse "split()". - is_global = (name[0] == 'g' && name[1] == ':'); - return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL; + // This is similar to what is in lookup_scriptitem(): + // Find a function, so that a following "->" works. + // Require "(" or "->" to follow, "Cmd" is a user command while "Cmd()" is + // a function call. + p = skipwhite(name + len); + + if (name[len] == '(' || (p[0] == '-' && p[1] == '>')) + { + // Do not check for an internal function, since it might also be a + // valid command, such as ":split" versuse "split()". + // Skip "g:" before a function name. + is_global = (name[0] == 'g' && name[1] == ':'); + return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL; + } + return FALSE; } /* @@ -8429,8 +8439,8 @@ compile_def_function( } } } - p = find_ex_command(&ea, NULL, starts_with_colon ? NULL - : (int (*)(char_u *, size_t, cctx_T *))item_exists, &cctx); + p = find_ex_command(&ea, NULL, starts_with_colon + ? NULL : item_exists, &cctx); if (p == NULL) { From 240309c9bfa8a0d2f154712f8e0dd33589f181d3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 14 Mar 2021 16:20:37 +0100 Subject: [PATCH 29/44] patch 8.2.2604: GUI-specific command line arguments not tested MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: GUI-specific command line arguments not tested. Solution: Add tests for several arguments. (Dominique Pellé, closes #7962) --- src/testdir/test_startup.vim | 158 +++++++++++++++++++++++++++++++---- src/version.c | 2 + 2 files changed, 146 insertions(+), 14 deletions(-) diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index 261cb5ef78..e8be19120b 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -109,9 +109,8 @@ func Test_pack_in_rtp_when_plugins_run() endfunc func Test_help_arg() - if !has('unix') && has('gui_running') - throw 'Skipped: does not work with gvim on MS-Windows' - endif + CheckNotMSWindows + if RunVim([], [], '--help >Xtestout') let lines = readfile('Xtestout') call assert_true(len(lines) > 20) @@ -408,6 +407,134 @@ func Test_A_F_H_arg() call delete('Xtestout') endfunc +" Test the --echo-wid argument (for GTK GUI only). +func Test_echo_wid() + CheckCanRunGui + CheckFeature gui_gtk + + if RunVim([], [], '-g --echo-wid -cq >Xtest_echo_wid') + let lines = readfile('Xtest_echo_wid') + call assert_equal(1, len(lines)) + call assert_match('^WID: \d\+$', lines[0]) + endif + + call delete('Xtest_echo_wid') +endfunction + +" Test the -reverse and +reverse arguments (for GUI only). +func Test_reverse() + CheckCanRunGui + CheckNotMSWindows + + let after =<< trim [CODE] + call writefile([&background], "Xtest_reverse") + qall + [CODE] + if RunVim([], after, '-f -g -reverse') + let lines = readfile('Xtest_reverse') + call assert_equal(['dark'], lines) + endif + if RunVim([], after, '-f -g +reverse') + let lines = readfile('Xtest_reverse') + call assert_equal(['light'], lines) + endif + + call delete('Xtest_reverse') +endfunc + +" Test the -background and -foreground arguments (for GUI only). +func Test_background_foreground() + CheckCanRunGui + CheckNotMSWindows + + " Is there a better way to check the effect of -background & -foreground + " other than merely looking at &background (dark or light)? + let after =<< trim [CODE] + call writefile([&background], "Xtest_fg_bg") + qall + [CODE] + if RunVim([], after, '-f -g -background darkred -foreground yellow') + let lines = readfile('Xtest_fg_bg') + call assert_equal(['dark'], lines) + endif + if RunVim([], after, '-f -g -background ivory -foreground darkgreen') + let lines = readfile('Xtest_fg_bg') + call assert_equal(['light'], lines) + endif + + call delete('Xtest_fg_bg') +endfunc + +" Test the -font argument (for GUI only). +func Test_font() + CheckCanRunGui + CheckNotMSWindows + + if has('gui_gtk') + let font = 'Courier 14' + elseif has('gui_motif') || has('gui_athena') + let font = '-misc-fixed-bold-*' + else + throw 'Skipped: test does not set a valid font for this GUI' + endif + + let after =<< trim [CODE] + call writefile([&guifont], "Xtest_font") + qall + [CODE] + + if RunVim([], after, '--nofork -g -font "' .. font .. '"') + let lines = readfile('Xtest_font') + call assert_equal([font], lines) + endif + + call delete('Xtest_font') +endfunc + +" Test the -geometry argument (for GUI only). +func Test_geometry() + CheckCanRunGui + CheckNotMSWindows + + if has('gui_motif') || has('gui_athena') + " FIXME: With GUI Athena or Motif, the value of getwinposx(), + " getwinposy() and getwinpos() do not match exactly the + " value given in -geometry. Why? + " So only check &columns and &lines for those GUIs. + let after =<< trim [CODE] + call writefile([&columns, &lines], "Xtest_geometry") + qall + [CODE] + if RunVim([], after, '-f -g -geometry 31x13+41+43') + let lines = readfile('Xtest_geometry') + call assert_equal(['31', '13'], lines) + endif + else + let after =<< trim [CODE] + call writefile([&columns, &lines, getwinposx(), getwinposy(), string(getwinpos())], "Xtest_geometry") + qall + [CODE] + if RunVim([], after, '-f -g -geometry 31x13+41+43') + let lines = readfile('Xtest_geometry') + call assert_equal(['31', '13', '41', '43', '[41, 43]'], lines) + endif + endif + + call delete('Xtest_geometry') +endfunc + +" Test the -iconic argument (for GUI only). +func Test_iconic() + CheckCanRunGui + CheckNotMSWindows + + call RunVim([], [], '-f -g -iconic -cq') + + " TODO: currently only start vim iconified, but does not + " check that vim is iconified. How could this be checked? +endfunc + + func Test_invalid_args() " must be able to get the output of Vim. CheckUnix @@ -1042,16 +1169,11 @@ func Test_progname() \ 'vimdiff', 'gvimdiff'] for progname in prognames - if empty($DISPLAY) - if progname =~# 'g' - " Can't run gvim, gview (etc.) if $DISPLAY is not setup. - continue - endif - if has('gui') && (progname ==# 'evim' || progname ==# 'eview') - " evim or eview will start the GUI if there is gui support. - " So don't try to start them either if $DISPLAY is not setup. - continue - endif + let run_with_gui = (progname =~# 'g') || (has('gui') && (progname ==# 'evim' || progname ==# 'eview')) + + if empty($DISPLAY) && run_with_gui + " Can't run gvim, gview (etc.) if $DISPLAY is not setup. + continue endif exe 'silent !ln -s -f ' ..exepath(GetVimProg()) .. ' Xprogname/' .. progname @@ -1066,7 +1188,15 @@ func Test_progname() if progname =~# 'g' && !has('gui') call assert_equal("E25: GUI cannot be used: Not enabled at compile time\n", stdout_stderr, progname) else - call assert_equal('', stdout_stderr, progname) + " GUI motif can output some warnings like this: + " Warning: + " Name: subMenu + " Class: XmCascadeButton + " Illegal mnemonic character; Could not convert X KEYSYM to a keycode + " So don't check that stderr is empty with GUI Motif. + if run_with_gui && !has('gui_motif') + call assert_equal('', stdout_stderr, progname) + endif call assert_equal(expectations[progname], readfile('Xprogname_out'), progname) endif diff --git a/src/version.c b/src/version.c index 14bf96bba0..b4307fbd34 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2604, /**/ 2603, /**/ From 0289a093a4d65c6280a3be118d1d3696d1aa74da Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 14 Mar 2021 18:40:19 +0100 Subject: [PATCH 30/44] patch 8.2.2605: Vim9: string index and slice does not include composing chars Problem: Vim9: string index and slice does not include composing chars. Solution: Include composing characters. (issue #6563) --- runtime/doc/vim9.txt | 14 +++++++++----- src/testdir/test_vim9_expr.vim | 29 +++++++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 25 ++++++++++++++----------- 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 20689ef58f..34048ece8e 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -96,8 +96,8 @@ script and `:def` functions; details are below: def CallMe(count: number, message: string): bool - Call functions without `:call`: > writefile(['done'], 'file.txt') -- You cannot use `:xit`, `:t`, `:k`, `:append`, `:change`, `:insert` or - curly-braces names. +- You cannot use `:xit`, `:t`, `:k`, `:append`, `:change`, `:insert`, `:open` + or curly-braces names. - A range before a command must be prefixed with a colon: > :%s/this/that - Unless mentioned specifically, the highest |scriptversion| is used. @@ -341,7 +341,8 @@ Functions can be called without `:call`: > Using `:call` is still possible, but this is discouraged. A method call without `eval` is possible, so long as the start is an -identifier or can't be an Ex command. Examples: > +identifier or can't be an Ex command. For a function either "(" or "->" must +be following, without a line break. Examples: > myList->add(123) g:myList->add(123) [1, 2, 3]->Process() @@ -696,8 +697,9 @@ for v:null. When converting a boolean to a string "false" and "true" are used, not "v:false" and "v:true" like in legacy script. "v:none" is not changed, it is only used in JSON and has no equivalent in other languages. -Indexing a string with [idx] or [idx : idx] uses character indexes instead of -byte indexes. Example: > +Indexing a string with [idx] or taking a slice with [idx : idx] uses character +indexes instead of byte indexes. Composing characters are included. +Example: > echo 'bár'[1] In legacy script this results in the character 0xc3 (an illegal byte), in Vim9 script this results in the string 'á'. @@ -845,6 +847,8 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE :enddef End of a function defined with `:def`. It should be on a line by its own. +You may also find this wiki useful. It was written by an early adoptor of +Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md If the script the function is defined in is Vim9 script, then script-local variables can be accessed without the "s:" prefix. They must be defined diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index a78cf1983f..9829d88007 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -2367,6 +2367,35 @@ def Test_expr7_any_index_slice() assert_equal('abcd', g:teststring[: -3]) assert_equal('', g:teststring[: -9]) + # composing characters are included + g:teststring = 'àéû' + assert_equal('à', g:teststring[0]) + assert_equal('é', g:teststring[1]) + assert_equal('û', g:teststring[2]) + assert_equal('', g:teststring[3]) + assert_equal('', g:teststring[4]) + + assert_equal('û', g:teststring[-1]) + assert_equal('é', g:teststring[-2]) + assert_equal('à', g:teststring[-3]) + assert_equal('', g:teststring[-4]) + assert_equal('', g:teststring[-5]) + + assert_equal('à', g:teststring[0 : 0]) + assert_equal('é', g:teststring[1 : 1]) + assert_equal('àé', g:teststring[0 : 1]) + assert_equal('àéû', g:teststring[0 : -1]) + assert_equal('àé', g:teststring[0 : -2]) + assert_equal('à', g:teststring[0 : -3]) + assert_equal('', g:teststring[0 : -4]) + assert_equal('', g:teststring[0 : -5]) + assert_equal('àéû', g:teststring[ : ]) + assert_equal('àéû', g:teststring[0 : ]) + assert_equal('éû', g:teststring[1 : ]) + assert_equal('û', g:teststring[2 : ]) + assert_equal('', g:teststring[3 : ]) + assert_equal('', g:teststring[4 : ]) + # blob index cannot be out of range g:testblob = 0z01ab assert_equal(0x01, g:testblob[0]) diff --git a/src/version.c b/src/version.c index b4307fbd34..c5797c32b9 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2605, /**/ 2604, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index b2c28a31bc..c0a4874022 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -985,8 +985,9 @@ allocate_if_null(typval_T *tv) } /* - * Return the character "str[index]" where "index" is the character index. If - * "index" is out of range NULL is returned. + * Return the character "str[index]" where "index" is the character index, + * including composing characters. + * If "index" is out of range NULL is returned. */ char_u * char_from_string(char_u *str, varnumber_T index) @@ -1005,7 +1006,7 @@ char_from_string(char_u *str, varnumber_T index) int clen = 0; for (nbyte = 0; nbyte < slen; ++clen) - nbyte += MB_CPTR2LEN(str + nbyte); + nbyte += mb_ptr2len(str + nbyte); nchar = clen + index; if (nchar < 0) // unlike list: index out of range results in empty string @@ -1013,15 +1014,15 @@ char_from_string(char_u *str, varnumber_T index) } for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar) - nbyte += MB_CPTR2LEN(str + nbyte); + nbyte += mb_ptr2len(str + nbyte); if (nbyte >= slen) return NULL; - return vim_strnsave(str + nbyte, MB_CPTR2LEN(str + nbyte)); + return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte)); } /* * Get the byte index for character index "idx" in string "str" with length - * "str_len". + * "str_len". Composing characters are included. * If going over the end return "str_len". * If "idx" is negative count from the end, -1 is the last character. * When going over the start return -1. @@ -1036,7 +1037,7 @@ char_idx2byte(char_u *str, size_t str_len, varnumber_T idx) { while (nchar > 0 && nbyte < str_len) { - nbyte += MB_CPTR2LEN(str + nbyte); + nbyte += mb_ptr2len(str + nbyte); --nchar; } } @@ -1056,7 +1057,8 @@ char_idx2byte(char_u *str, size_t str_len, varnumber_T idx) } /* - * Return the slice "str[first:last]" using character indexes. + * Return the slice "str[first : last]" using character indexes. Composing + * characters are included. * "exclusive" is TRUE for slice(). * Return NULL when the result is empty. */ @@ -1079,7 +1081,7 @@ string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive) end_byte = char_idx2byte(str, slen, last); if (!exclusive && end_byte >= 0 && end_byte < (long)slen) // end index is inclusive - end_byte += MB_CPTR2LEN(str + end_byte); + end_byte += mb_ptr2len(str + end_byte); } if (start_byte >= (long)slen || end_byte <= start_byte) @@ -3249,8 +3251,9 @@ call_def_function( res = string_slice(tv->vval.v_string, n1, n2, FALSE); else // Index: The resulting variable is a string of a - // single character. If the index is too big or - // negative the result is empty. + // single character (including composing characters). + // If the index is too big or negative the result is + // empty. res = char_from_string(tv->vval.v_string, n2); vim_free(tv->vval.v_string); tv->vval.v_string = res; From 70ce8a1561c5396e4c4381f76a005cbb97646f80 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 14 Mar 2021 19:02:09 +0100 Subject: [PATCH 31/44] patch 8.2.2606: strchars() defaults to counting composing characters Problem: strchars() defaults to counting composing characters. Solution: Add strcharlen() which ignores composing characters. --- runtime/doc/eval.txt | 19 +++++++++++++++++- runtime/doc/usr_41.txt | 3 ++- src/evalfunc.c | 41 +++++++++++++++++++++++++++------------ src/testdir/test_utf8.vim | 9 ++++++++- src/version.c | 2 ++ 5 files changed, 59 insertions(+), 15 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 92f020689e..3e5c6ee44b 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2923,10 +2923,11 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to ASCII/UTF8 value str2nr({expr} [, {base} [, {quoted}]]) Number convert String to Number +strcharlen({expr}) Number character length of the String {expr} strcharpart({str}, {start} [, {len}]) String {len} characters of {str} at character {start} -strchars({expr} [, {skipcc}]) Number character length of the String {expr} +strchars({expr} [, {skipcc}]) Number character count of the String {expr} strdisplaywidth({expr} [, {col}]) Number display length of the String {expr} strftime({format} [, {time}]) String format time with a specified format strgetchar({str}, {index}) Number get char {index} from {str} @@ -10276,6 +10277,19 @@ str2nr({expr} [, {base} [, {quoted}]]) *str2nr()* Can also be used as a |method|: > GetText()->str2nr() + +strcharlen({expr}) *strcharlen()* + The result is a Number, which is the number of characters + in String {expr}. Composing characters are ignored. + |strchars()| can count the number of characters, counting + composing characters separately. + + Also see |strlen()|, |strdisplaywidth()| and |strwidth()|. + + Can also be used as a |method|: > + GetText()->strcharlen() + + strcharpart({src}, {start} [, {len}]) *strcharpart()* Like |strpart()| but using character index and length instead of byte index and length. Composing characters are counted @@ -10288,12 +10302,15 @@ strcharpart({src}, {start} [, {len}]) *strcharpart()* Can also be used as a |method|: > GetText()->strcharpart(5) + strchars({expr} [, {skipcc}]) *strchars()* The result is a Number, which is the number of characters in String {expr}. When {skipcc} is omitted or zero, composing characters are counted separately. When {skipcc} set to 1, Composing characters are ignored. + |strcharlen()| does the same. + Also see |strlen()|, |strdisplaywidth()| and |strwidth()|. {skipcc} is only available after 7.4.755. For backward diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 8113bef8e5..0d17298fb0 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -611,7 +611,8 @@ String manipulation: *string-functions* stridx() first index of a short string in a long string strridx() last index of a short string in a long string strlen() length of a string in bytes - strchars() length of a string in characters + strcharlen() length of a string in characters + strchars() number of characters in a string strwidth() size of string when displayed strdisplaywidth() size of string when displayed, deals with tabs setcellwidths() set character cell width overrides diff --git a/src/evalfunc.c b/src/evalfunc.c index 29bbe8ab87..34369d77ad 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -223,6 +223,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv); #endif static void f_str2list(typval_T *argvars, typval_T *rettv); static void f_str2nr(typval_T *argvars, typval_T *rettv); +static void f_strcharlen(typval_T *argvars, typval_T *rettv); static void f_strchars(typval_T *argvars, typval_T *rettv); static void f_strgetchar(typval_T *argvars, typval_T *rettv); static void f_stridx(typval_T *argvars, typval_T *rettv); @@ -1572,6 +1573,8 @@ static funcentry_T global_functions[] = ret_list_number, f_str2list}, {"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_str2nr}, + {"strcharlen", 1, 1, FEARG_1, NULL, + ret_number, f_strcharlen}, {"strcharpart", 2, 3, FEARG_1, NULL, ret_string, f_strcharpart}, {"strchars", 1, 2, FEARG_1, NULL, @@ -9236,31 +9239,45 @@ f_strlen(typval_T *argvars, typval_T *rettv) tv_get_string(&argvars[0]))); } + static void +strchar_common(typval_T *argvars, typval_T *rettv, int skipcc) +{ + char_u *s = tv_get_string(&argvars[0]); + varnumber_T len = 0; + int (*func_mb_ptr2char_adv)(char_u **pp); + + func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; + while (*s != NUL) + { + func_mb_ptr2char_adv(&s); + ++len; + } + rettv->vval.v_number = len; +} + +/* + * "strcharlen()" function + */ + static void +f_strcharlen(typval_T *argvars, typval_T *rettv) +{ + strchar_common(argvars, rettv, TRUE); +} + /* * "strchars()" function */ static void f_strchars(typval_T *argvars, typval_T *rettv) { - char_u *s = tv_get_string(&argvars[0]); varnumber_T skipcc = FALSE; - varnumber_T len = 0; - int (*func_mb_ptr2char_adv)(char_u **pp); if (argvars[1].v_type != VAR_UNKNOWN) skipcc = tv_get_bool(&argvars[1]); if (skipcc < 0 || skipcc > 1) semsg(_(e_using_number_as_bool_nr), skipcc); else - { - func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; - while (*s != NUL) - { - func_mb_ptr2char_adv(&s); - ++len; - } - rettv->vval.v_number = len; - } + strchar_common(argvars, rettv, skipcc); } /* diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index a5fd4fb89a..5454e430ad 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -11,7 +11,7 @@ func Test_visual_block_insert() bwipeout! endfunc -" Test for built-in function strchars() +" Test for built-in functions strchars() and strcharlen() func Test_strchars() let inp = ["a", "あいa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"] let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]] @@ -20,6 +20,13 @@ func Test_strchars() call assert_equal(exp[i][1], inp[i]->strchars(0)) call assert_equal(exp[i][2], strchars(inp[i], 1)) endfor + + let exp = [1, 3, 1, 1, 1] + for i in range(len(inp)) + call assert_equal(exp[i], inp[i]->strcharlen()) + call assert_equal(exp[i], strcharlen(inp[i])) + endfor + call assert_fails("let v=strchars('abc', [])", 'E745:') call assert_fails("let v=strchars('abc', 2)", 'E1023:') endfunc diff --git a/src/version.c b/src/version.c index c5797c32b9..918a34c98f 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2606, /**/ 2605, /**/ From 02b4d9b18a03549b68e364e428392b7a62766c74 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 14 Mar 2021 19:46:45 +0100 Subject: [PATCH 32/44] patch 8.2.2607: strcharpart() cannot include composing characters Problem: strcharpart() cannot include composing characters. Solution: Add the {skipcc} argument. --- runtime/doc/eval.txt | 26 ++++++++++++++++---------- src/evalfunc.c | 26 +++++++++++++++++++++++--- src/testdir/test_expr_utf8.vim | 8 ++++++++ src/version.c | 2 ++ 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 3e5c6ee44b..723a7329b3 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1187,7 +1187,8 @@ byte under the cursor: > In Vim9 script: If expr8 is a String this results in a String that contains the expr1'th -single character from expr8. To use byte indexes use |strpart()|. +single character (including any composing characters) from expr8. To use byte +indexes use |strpart()|. Index zero gives the first byte or character. Careful: text column numbers start with one! @@ -1217,8 +1218,9 @@ In legacy Vim script the indexes are byte indexes. This doesn't recognize multibyte encodings, see |byteidx()| for computing the indexes. If expr8 is a Number it is first converted to a String. -In Vim9 script the indexes are character indexes. To use byte indexes use -|strpart()|. +In Vim9 script the indexes are character indexes and include composing +characters. To use byte indexes use |strpart()|. To use character indexes +without including composing characters use |strcharpart()|. The item at index expr1b is included, it is inclusive. For an exclusive index use the |slice()| function. @@ -2924,7 +2926,7 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to str2nr({expr} [, {base} [, {quoted}]]) Number convert String to Number strcharlen({expr}) Number character length of the String {expr} -strcharpart({str}, {start} [, {len}]) +strcharpart({str}, {start} [, {len} [, {skipcc}]]) String {len} characters of {str} at character {start} strchars({expr} [, {skipcc}]) Number character count of the String {expr} @@ -9919,7 +9921,7 @@ slice({expr}, {start} [, {end}]) *slice()* Similar to using a |slice| "expr[start : end]", but "end" is used exclusive. And for a string the indexes are used as character indexes instead of byte indexes, like in - |vim9script|. + |vim9script|. Also, composing characters are not counted. When {end} is omitted the slice continues to the last item. When {end} is -1 the last item is omitted. @@ -10290,12 +10292,16 @@ strcharlen({expr}) *strcharlen()* GetText()->strcharlen() -strcharpart({src}, {start} [, {len}]) *strcharpart()* +strcharpart({src}, {start} [, {len} [, {skipcc}]]) *strcharpart()* Like |strpart()| but using character index and length instead - of byte index and length. Composing characters are counted - separately. + of byte index and length. + When {skipcc} is omitted or zero, composing characters are + counted separately. + When {skipcc} set to 1, Composing characters are ignored, + similar to |slice()|. When a character index is used where a character does not - exist it is assumed to be one character. For example: > + exist it is omitted and counted as one character. For + example: > strcharpart('abc', -1, 2) < results in 'a'. @@ -10309,7 +10315,7 @@ strchars({expr} [, {skipcc}]) *strchars()* When {skipcc} is omitted or zero, composing characters are counted separately. When {skipcc} set to 1, Composing characters are ignored. - |strcharlen()| does the same. + |strcharlen()| always does this. Also see |strlen()|, |strdisplaywidth()| and |strwidth()|. diff --git a/src/evalfunc.c b/src/evalfunc.c index 34369d77ad..8fcdedbc00 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1575,7 +1575,7 @@ static funcentry_T global_functions[] = ret_number, f_str2nr}, {"strcharlen", 1, 1, FEARG_1, NULL, ret_number, f_strcharlen}, - {"strcharpart", 2, 3, FEARG_1, NULL, + {"strcharpart", 2, 4, FEARG_1, NULL, ret_string, f_strcharpart}, {"strchars", 1, 2, FEARG_1, NULL, ret_number, f_strchars}, @@ -9316,6 +9316,7 @@ f_strcharpart(typval_T *argvars, typval_T *rettv) int nchar; int nbyte = 0; int charlen; + int skipcc = FALSE; int len = 0; int slen; int error = FALSE; @@ -9326,10 +9327,24 @@ f_strcharpart(typval_T *argvars, typval_T *rettv) nchar = (int)tv_get_number_chk(&argvars[1], &error); if (!error) { + if (argvars[2].v_type != VAR_UNKNOWN + && argvars[3].v_type != VAR_UNKNOWN) + { + skipcc = tv_get_bool(&argvars[3]); + if (skipcc < 0 || skipcc > 1) + { + semsg(_(e_using_number_as_bool_nr), skipcc); + return; + } + } + if (nchar > 0) while (nchar > 0 && nbyte < slen) { - nbyte += MB_CPTR2LEN(p + nbyte); + if (skipcc) + nbyte += mb_ptr2len(p + nbyte); + else + nbyte += MB_CPTR2LEN(p + nbyte); --nchar; } else @@ -9344,7 +9359,12 @@ f_strcharpart(typval_T *argvars, typval_T *rettv) if (off < 0) len += 1; else - len += MB_CPTR2LEN(p + off); + { + if (skipcc) + len += mb_ptr2len(p + off); + else + len += MB_CPTR2LEN(p + off); + } --charlen; } } diff --git a/src/testdir/test_expr_utf8.vim b/src/testdir/test_expr_utf8.vim index b5937b2087..c6d2e4ed7e 100644 --- a/src/testdir/test_expr_utf8.vim +++ b/src/testdir/test_expr_utf8.vim @@ -31,6 +31,14 @@ func Test_strcharpart() call assert_equal('a', strcharpart('àxb', 0, 1)) call assert_equal('̀', strcharpart('àxb', 1, 1)) call assert_equal('x', strcharpart('àxb', 2, 1)) + + + call assert_equal('a', strcharpart('àxb', 0, 1, 0)) + call assert_equal('à', strcharpart('àxb', 0, 1, 1)) + call assert_equal('x', strcharpart('àxb', 1, 1, 1)) + + call assert_fails("let v = strcharpart('abc', 0, 0, [])", 'E745:') + call assert_fails("let v = strcharpart('abc', 0, 0, 2)", 'E1023:') endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 918a34c98f..0b1ece6a64 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2607, /**/ 2606, /**/ From f4fcedc59d4cc5ae6b5270a933e8377030283c1c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 15 Mar 2021 18:36:20 +0100 Subject: [PATCH 33/44] patch 8.2.2608: character input not fully tested Problem: Character input not fully tested. Solution: Add more tests. (Yegappan Lakshmanan, closes #7963) --- src/testdir/test_functions.vim | 8 ++++++++ src/testdir/test_messages.vim | 11 +++++++++++ src/testdir/test_paste.vim | 14 ++++++++++++++ src/testdir/test_registers.vim | 10 ++++++++++ src/testdir/test_undo.vim | 14 ++++++++++++++ src/version.c | 2 ++ 6 files changed, 59 insertions(+) diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 64afe54817..ca57c3086b 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -1430,6 +1430,14 @@ func Test_input_func() delfunc Tcomplete call assert_equal('item1 item2 item3', c) + " Test for using special characters as default input + call feedkeys(":let c = input('name? ', \"x\y\")\\", 'xt') + call assert_equal('y', c) + + " Test for using as default input + call feedkeys(":let c = input('name? ', \"\\\")\x\", 'xt') + call assert_equal(' x', c) + call assert_fails("call input('F:', '', 'invalid')", 'E180:') call assert_fails("call input('F:', '', [])", 'E730:') endfunc diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim index 4f8c75112f..375cb01461 100644 --- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -259,6 +259,17 @@ func Test_message_more() call term_sendkeys(buf, 'q') call WaitForAssert({-> assert_equal('100', term_getline(buf, 5))}) + " Execute a : command from the more prompt + call term_sendkeys(buf, ":%p#\n") + call term_wait(buf) + call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))}) + call term_sendkeys(buf, ":") + call term_wait(buf) + call WaitForAssert({-> assert_equal(':', term_getline(buf, 6))}) + call term_sendkeys(buf, "echo 'Hello'\n") + call term_wait(buf) + call WaitForAssert({-> assert_equal('Hello ', term_getline(buf, 5))}) + call StopVimInTerminal(buf) endfunc diff --git a/src/testdir/test_paste.vim b/src/testdir/test_paste.vim index 8995b971ac..df732f156f 100644 --- a/src/testdir/test_paste.vim +++ b/src/testdir/test_paste.vim @@ -149,4 +149,18 @@ func Test_xrestore() bwipe! endfunc +" Test for 'pastetoggle' +func Test_pastetoggle() + new + set pastetoggle= + set nopaste + call feedkeys("iHello\", 'xt') + call assert_true(&paste) + call feedkeys("i\", 'xt') + call assert_false(&paste) + call assert_equal('Hello', getline(1)) + set pastetoggle& + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim index b2916f4d06..c10af29466 100644 --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -709,4 +709,14 @@ func Test_insert_small_delete() bwipe! endfunc +" Record in insert mode using CTRL-O +func Test_record_in_insert_mode() + new + let @r = '' + call setline(1, ['foo']) + call feedkeys("i\qrbaz\q", 'xt') + call assert_equal('baz', @r) + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim index dd4b902b93..f12e1525c4 100644 --- a/src/testdir/test_undo.vim +++ b/src/testdir/test_undo.vim @@ -733,4 +733,18 @@ func Test_undofile_cryptmethod_blowfish2() set undofile& undolevels& cryptmethod& endfunc +" Test for redoing with incrementing numbered registers +func Test_redo_repeat_numbered_register() + new + for [i, v] in [[1, 'one'], [2, 'two'], [3, 'three'], + \ [4, 'four'], [5, 'five'], [6, 'six'], + \ [7, 'seven'], [8, 'eight'], [9, 'nine']] + exe 'let @' .. i .. '="' .. v .. '\n"' + endfor + call feedkeys('"1p.........', 'xt') + call assert_equal(['', 'one', 'two', 'three', 'four', 'five', 'six', + \ 'seven', 'eight', 'nine', 'nine'], getline(1, '$')) + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 0b1ece6a64..9d46da68cc 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2608, /**/ 2607, /**/ From 321481299757cdd43baeed33f4c5ba543fdfc7f7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 16 Mar 2021 13:23:30 +0100 Subject: [PATCH 34/44] patch 8.2.2609: test disabled on MS-Windows even though it should work Problem: Test disabled on MS-Windows even though it should work. Solution: Restore the condition for skipping the test. (Ken Takata, closes #7970) --- src/testdir/test_startup.vim | 4 +++- src/version.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index e8be19120b..169c21350e 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -109,7 +109,9 @@ func Test_pack_in_rtp_when_plugins_run() endfunc func Test_help_arg() - CheckNotMSWindows + if !has('unix') && has('gui_running') + throw 'Skipped: does not work with gvim on MS-Windows' + endif if RunVim([], [], '--help >Xtestout') let lines = readfile('Xtestout') diff --git a/src/version.c b/src/version.c index 9d46da68cc..ef2f0cb31e 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2609, /**/ 2608, /**/ From 1e448465e1281eeb379f75fe848cbb47fe1be1d9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 16 Mar 2021 21:17:16 +0100 Subject: [PATCH 35/44] patch 8.2.2610: mouse click test fails when using remote connection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Mouse click test fails when using remote connection. Solution: Use a larger 'mousetime'. (Dominique Pellé, closes #7968) --- src/testdir/test_selectmode.vim | 5 ++++- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_selectmode.vim b/src/testdir/test_selectmode.vim index 3adb843cb8..3296f7e702 100644 --- a/src/testdir/test_selectmode.vim +++ b/src/testdir/test_selectmode.vim @@ -165,7 +165,10 @@ func Test_term_mouse_multiple_clicks_to_select_mode() let save_term = &term let save_ttymouse = &ttymouse call test_override('no_query_mouse', 1) - set mouse=a term=xterm mousetime=200 + + " 'mousetime' must be sufficiently large, or else the test is flaky when + " using a ssh connection with X forwarding; i.e. ssh -X. + set mouse=a term=xterm mousetime=1000 set selectmode=mouse new diff --git a/src/version.c b/src/version.c index ef2f0cb31e..7b0771e7f0 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2610, /**/ 2609, /**/ From f8c52e8d08de3fdf48db877d7d53d2d68c6ceb7b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 12:27:23 +0100 Subject: [PATCH 36/44] patch 8.2.2611: conditions for startup tests are not exactly right Problem: Conditions for startup tests are not exactly right. Solution: Check for type of GUI instead of MS-Windows. (Ozaki Kiichi, closes #7976) --- src/main.c | 3 +++ src/testdir/check.vim | 25 +++++++++++++++++++++++++ src/testdir/test_startup.vim | 13 ++++++------- src/version.c | 2 ++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index 76252c7d1f..369741abad 100644 --- a/src/main.c +++ b/src/main.c @@ -3542,8 +3542,11 @@ usage(void) #endif // FEAT_GUI_X11 #ifdef FEAT_GUI_GTK mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n")); + main_msg(_("-background \tUse for the background (also: -bg)")); + main_msg(_("-foreground \tUse for normal text (also: -fg)")); main_msg(_("-font \t\tUse for normal text (also: -fn)")); main_msg(_("-geometry \tUse for initial geometry (also: -geom)")); + main_msg(_("-iconic\t\tStart Vim iconified")); main_msg(_("-reverse\t\tUse reverse video (also: -rv)")); main_msg(_("-display \tRun Vim on (also: --display)")); main_msg(_("--role \tSet a unique role to identify the main window")); diff --git a/src/testdir/check.vim b/src/testdir/check.vim index db16cfb7d9..4fe130b7bf 100644 --- a/src/testdir/check.vim +++ b/src/testdir/check.vim @@ -199,4 +199,29 @@ func CheckNotAsan() endif endfunc +" Command to check for satisfying any of the conditions. +" e.g. CheckAnyOf Feature:bsd Feature:sun Linux +command -nargs=+ CheckAnyOf call CheckAnyOf() +func CheckAnyOf(...) + let excp = [] + for arg in a:000 + try + exe 'Check' .. substitute(arg, ':', ' ', '') + return + catch /^Skipped:/ + let excp += [substitute(v:exception, '^Skipped:\s*', '', '')] + endtry + endfor + throw 'Skipped: ' .. join(excp, '; ') +endfunc + +" Command to check for satisfying all of the conditions. +" e.g. CheckAllOf Unix Gui Option:ballooneval +command -nargs=+ CheckAllOf call CheckAllOf() +func CheckAllOf(...) + for arg in a:000 + exe 'Check' .. substitute(arg, ':', ' ', '') + endfor +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index 169c21350e..17ac94d695 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -109,9 +109,8 @@ func Test_pack_in_rtp_when_plugins_run() endfunc func Test_help_arg() - if !has('unix') && has('gui_running') - throw 'Skipped: does not work with gvim on MS-Windows' - endif + " This does not work with a GUI-only binary, such as on MS-Windows. + CheckAnyOf Unix NotGui if RunVim([], [], '--help >Xtestout') let lines = readfile('Xtestout') @@ -426,7 +425,7 @@ endfunction " Test the -reverse and +reverse arguments (for GUI only). func Test_reverse() CheckCanRunGui - CheckNotMSWindows + CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena let after =<< trim [CODE] call writefile([&background], "Xtest_reverse") @@ -447,7 +446,7 @@ endfunc " Test the -background and -foreground arguments (for GUI only). func Test_background_foreground() CheckCanRunGui - CheckNotMSWindows + CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena " Is there a better way to check the effect of -background & -foreground " other than merely looking at &background (dark or light)? @@ -496,7 +495,7 @@ endfunc " Test the -geometry argument (for GUI only). func Test_geometry() CheckCanRunGui - CheckNotMSWindows + CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena if has('gui_motif') || has('gui_athena') " FIXME: With GUI Athena or Motif, the value of getwinposx(), @@ -528,7 +527,7 @@ endfunc " Test the -iconic argument (for GUI only). func Test_iconic() CheckCanRunGui - CheckNotMSWindows + CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena call RunVim([], [], '-f -g -iconic -cq') diff --git a/src/version.c b/src/version.c index 7b0771e7f0..dad20388df 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2611, /**/ 2610, /**/ From 18b7d86d7fa997bbb02a069dafacb32a0f73ca1e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 13:28:05 +0100 Subject: [PATCH 37/44] patch 8.2.2612: col('.') may get outdated column value Problem: col('.') may get outdated column value. Solution: Add a note to the help how to make this work and add a test for it. (closes #7971) --- runtime/doc/map.txt | 14 ++++++++++++++ src/testdir/test_mapping.vim | 24 ++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 40 insertions(+) diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index bf391305dc..873d5d6d7a 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -263,6 +263,20 @@ input. Example: > endfunc nnoremap OpenPopup() +Also, keep in mind that the expression may be evaluated when looking for +typeahead, before the previous command has been executed. For example: > + func StoreColumn() + let g:column = col('.') + return 'x' + endfunc + nnoremap x StoreColumn() + nmap ! f!x +You will notice that g:column has the value from before executing "fx", +because "z" is evaluated before "fx" is executed. +This can be solved by inserting before the character that is +expression-mapped: > + nmap ! f!x + Be very careful about side effects! The expression is evaluated while obtaining characters, you may very well make the command dysfunctional. For this reason the following is blocked: diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 1750f39d53..f76718fca1 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -485,6 +485,30 @@ func Test_list_mappings() nmapclear endfunc +func Test_expr_map_gets_cursor() + new + call setline(1, ['one', 'some w!rd']) + func StoreColumn() + let g:exprLine = line('.') + let g:exprCol = col('.') + return 'x' + endfunc + nnoremap x StoreColumn() + 2 + nmap ! f!x + call feedkeys("!", 'xt') + call assert_equal('some wrd', getline(2)) + call assert_equal(2, g:exprLine) + call assert_equal(7, g:exprCol) + + bwipe! + unlet g:exprLine + unlet g:exprCol + delfunc ExprMapped + nunmap x + nunmap ! +endfunc + func Test_expr_map_restore_cursor() CheckScreendump diff --git a/src/version.c b/src/version.c index dad20388df..815300cbfd 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2612, /**/ 2611, /**/ From 6ccfd99b923cc3452a6e6450dfdd7e31ea602dfd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 13:39:33 +0100 Subject: [PATCH 38/44] patch 8.2.2613: new test throws exception Problem: New test throws exception. Solution: Adjust the function cleanup. --- src/testdir/test_mapping.vim | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index f76718fca1..741e31520b 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -504,7 +504,7 @@ func Test_expr_map_gets_cursor() bwipe! unlet g:exprLine unlet g:exprCol - delfunc ExprMapped + delfunc StoreColumn nunmap x nunmap ! endfunc diff --git a/src/version.c b/src/version.c index 815300cbfd..37774a5f54 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2613, /**/ 2612, /**/ From c970e4225b68ff8650ff23df09e04246c147fca3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 15:03:04 +0100 Subject: [PATCH 39/44] patch 8.2.2614: Vim9: function is deleted while executing Problem: Vim9: function is deleted while executing. Solution: increment the call count, when more than zero do not delete the function but mark it as dead. (closes #7977) --- src/testdir/test_vim9_script.vim | 29 +++++++++++++++++++++++++++++ src/userfunc.c | 30 ++++++++++++++++++++++-------- src/version.c | 2 ++ src/vim9execute.c | 13 ++++++++++++- 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index c476acf896..418435bff2 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1561,6 +1561,35 @@ def Test_script_reload_change_type() delete('Xreload.vim') enddef +" Define CallFunc so that the test can be compiled +command CallFunc echo 'nop' + +def Test_script_reload_from_function() + var lines =<< trim END + vim9script + + if exists('g:loaded') + finish + endif + g:loaded = 1 + delcommand CallFunc + command CallFunc Func() + def Func() + so /tmp/test.vim + g:didTheFunc = 1 + enddef + END + writefile(lines, 'XreloadFunc.vim') + source XreloadFunc.vim + CallFunc + assert_equal(1, g:didTheFunc) + + delete('XreloadFunc.vim') + delcommand CallFunc + unlet g:loaded + unlet g:didTheFunc +enddef + def Test_script_var_shadows_function() var lines =<< trim END vim9script diff --git a/src/userfunc.c b/src/userfunc.c index e89b8858d3..4793ee5552 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1359,9 +1359,12 @@ func_remove(ufunc_T *fp) // function, so we can find the index when defining the function again. // Do remove it when it's a copy. if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0) + { fp->uf_flags |= FC_DEAD; - else - hash_remove(&func_hashtab, hi); + return FALSE; + } + hash_remove(&func_hashtab, hi); + fp->uf_flags |= FC_DELETED; return TRUE; } return FALSE; @@ -2134,11 +2137,23 @@ delete_script_functions(int sid) int changed = func_hashtab.ht_changed; fp->uf_flags |= FC_DEAD; - func_clear(fp, TRUE); - // When clearing a function another function can be cleared - // as a side effect. When that happens start over. - if (changed != func_hashtab.ht_changed) - break; + + if (fp->uf_calls > 0) + { + // Function is executing, don't free it but do remove + // it from the hashtable. + if (func_remove(fp)) + fp->uf_refcount--; + } + else + { + func_clear(fp, TRUE); + // When clearing a function another function can be + // cleared as a side effect. When that happens start + // over. + if (changed != func_hashtab.ht_changed) + break; + } } --todo; } @@ -4251,7 +4266,6 @@ ex_delfunction(exarg_T *eap) // do remove it from the hashtable. if (func_remove(fp)) fp->uf_refcount--; - fp->uf_flags |= FC_DELETED; } else func_clear_free(fp, FALSE); diff --git a/src/version.c b/src/version.c index 37774a5f54..49eed325b6 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2614, /**/ 2613, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index c0a4874022..6b8cd075c1 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -323,6 +323,8 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) else ectx->ec_outer = NULL; + ++ufunc->uf_calls; + // Set execution state to the start of the called function. ectx->ec_dfunc_idx = cdf_idx; ectx->ec_instr = INSTRUCTIONS(dfunc); @@ -556,6 +558,9 @@ func_return(ectx_T *ectx) } } #endif + // TODO: when is it safe to delete the function when it is no longer used? + --dfunc->df_ufunc->uf_calls; + // execution context goes one level up entry = estack_pop(); if (entry != NULL) @@ -1334,7 +1339,7 @@ call_def_function( ++ectx.ec_stack.ga_len; } if (ufunc->uf_va_name != NULL) - ++ectx.ec_stack.ga_len; + ++ectx.ec_stack.ga_len; // Frame pointer points to just after arguments. ectx.ec_frame_idx = ectx.ec_stack.ga_len; @@ -1407,6 +1412,9 @@ call_def_function( // Do turn errors into exceptions. suppress_errthrow = FALSE; + // Do not delete the function while executing it. + ++ufunc->uf_calls; + // When ":silent!" was used before calling then we still abort the // function. If ":silent!" is used in the function then we don't. emsg_silent_def = emsg_silent; @@ -3838,6 +3846,9 @@ failed: estack_pop(); current_sctx = save_current_sctx; + // TODO: when is it safe to delete the function if it is no longer used? + --ufunc->uf_calls; + if (*msg_list != NULL && saved_msg_list != NULL) { msglist_T **plist = saved_msg_list; From a4c81bea38d1f3e372a4191ab0bd7d664cba1428 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 15:23:16 +0100 Subject: [PATCH 40/44] patch 8.2.2615: test is sourcing the wrong file Problem: Test is sourcing the wrong file. Solution: Correct the file name. --- src/testdir/test_vim9_script.vim | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 418435bff2..956de369e1 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1575,7 +1575,7 @@ def Test_script_reload_from_function() delcommand CallFunc command CallFunc Func() def Func() - so /tmp/test.vim + so XreloadFunc.vim g:didTheFunc = 1 enddef END diff --git a/src/version.c b/src/version.c index 49eed325b6..425dfaacfd 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2615, /**/ 2614, /**/ From 3e1916947d5b29f67af554ce3b874b03a84c9093 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 17:46:00 +0100 Subject: [PATCH 41/44] patch 8.2.2616: Vim9: if 'cpo' is change in Vim9 script it may be restored Problem: Vim9: if 'cpo' is change in Vim9 script it may be restored. Solution: Apply the changes to 'cpo' to the restored value. --- runtime/doc/vim9.txt | 4 +++- src/scriptfile.c | 27 +++++++++++++++++++++++++++ src/testdir/test_vim9_script.vim | 12 +++++++++--- src/version.c | 2 ++ 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 34048ece8e..4e8016c9db 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1082,7 +1082,9 @@ A side effect of `:vim9script` is that the 'cpoptions' option is set to the Vim default value, like with: > :set cpo&vim One of the effects is that |line-continuation| is always enabled. -The original value of 'cpoptions' is restored at the end of the script. +The original value of 'cpoptions' is restored at the end of the script, while +flags added or removed in the script are also added to or removed from the +original value to get the same effect. The order of flags may change. *vim9-mix* There is one way to use both legacy and Vim9 syntax in one script file: > diff --git a/src/scriptfile.c b/src/scriptfile.c index 1e4b5ccf7e..203cad09fd 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1459,6 +1459,33 @@ almosttheend: si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_save_cpo != NULL) { + if (STRCMP(p_cpo, CPO_VIM) != 0) + { + char_u *f; + char_u *t; + + // 'cpo' was changed in the script. Apply the same change to the + // saved value, if possible. + for (f = (char_u *)CPO_VIM; *f != NUL; ++f) + if (vim_strchr(p_cpo, *f) == NULL + && (t = vim_strchr(si->sn_save_cpo, *f)) != NULL) + // flag was removed, also remove it from the saved 'cpo' + mch_memmove(t, t + 1, STRLEN(t)); + for (f = p_cpo; *f != NUL; ++f) + if (vim_strchr((char_u *)CPO_VIM, *f) == NULL + && vim_strchr(si->sn_save_cpo, *f) == NULL) + { + // flag was added, also add it to the saved 'cpo' + t = alloc(STRLEN(si->sn_save_cpo) + 2); + if (t != NULL) + { + *t = *f; + STRCPY(t + 1, si->sn_save_cpo); + vim_free(si->sn_save_cpo); + si->sn_save_cpo = t; + } + } + } set_option_value((char_u *)"cpo", 0L, si->sn_save_cpo, OPT_NO_REDRAW); VIM_CLEAR(si->sn_save_cpo); } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 956de369e1..38d0b0abcd 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1250,17 +1250,23 @@ def Test_vim9_import_export() delete('Xexport.vim') # Check that in a Vim9 script 'cpo' is set to the Vim default. - set cpo&vi - var cpo_before = &cpo + # Flags added or removed are also applied to the restored value. + set cpo=abcd var lines =<< trim END vim9script g:cpo_in_vim9script = &cpo + set cpo+=f + set cpo-=c + g:cpo_after_vim9script = &cpo END writefile(lines, 'Xvim9_script') source Xvim9_script - assert_equal(cpo_before, &cpo) + assert_equal('fabd', &cpo) set cpo&vim assert_equal(&cpo, g:cpo_in_vim9script) + var newcpo = substitute(&cpo, 'c', '', '') .. 'f' + assert_equal(newcpo, g:cpo_after_vim9script) + delete('Xvim9_script') enddef diff --git a/src/version.c b/src/version.c index 425dfaacfd..a92db82f34 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2616, /**/ 2615, /**/ From 8863bda25df821fc79bebf9dc73c79776ae5f675 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 18:42:08 +0100 Subject: [PATCH 42/44] patch 8.2.2617: Vim9: script variable in block not found by function Problem: Vim9: script variable in a block scope not found by a nested function. Solution: Copy the block scope IDs before compiling the function. --- src/testdir/test_vim9_disassemble.vim | 4 ++-- src/testdir/test_vim9_func.vim | 20 ++++++++++++++++++- src/version.c | 2 ++ src/vim9compile.c | 28 ++++++++++++++------------- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 9d05bbfd22..7470ac3ce7 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -947,7 +947,7 @@ def NestedOuter() enddef enddef -def Test_nested_func() +def Test_disassemble_nested_func() var instr = execute('disassemble NestedOuter') assert_match('NestedOuter\_s*' .. 'def g:Inner()\_s*' .. @@ -965,7 +965,7 @@ def NestedDefList() def /Info/ enddef -def Test_nested_def_list() +def Test_disassemble_nested_def_list() var instr = execute('disassemble NestedDefList') assert_match('NestedDefList\_s*' .. 'def\_s*' .. diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 6258b7d5d4..73d8e37aa7 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -393,7 +393,6 @@ def Test_nested_function() CheckDefFailure(lines, 'E1117:') # nested function inside conditional - # TODO: should it work when "thecount" is inside the "if"? lines =<< trim END vim9script var thecount = 0 @@ -411,6 +410,25 @@ def Test_nested_function() assert_equal(2, Test()) END CheckScriptSuccess(lines) + + # also works when "thecount" is inside the "if" block + lines =<< trim END + vim9script + if true + var thecount = 0 + def Test(): number + def TheFunc(): number + thecount += 1 + return thecount + enddef + return TheFunc() + enddef + endif + defcompile + assert_equal(1, Test()) + assert_equal(2, Test()) + END + CheckScriptSuccess(lines) enddef def Test_not_nested_function() diff --git a/src/version.c b/src/version.c index a92db82f34..3bb4eceb74 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2617, /**/ 2616, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 3fef9bd6b0..93ded08577 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5183,6 +5183,21 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) r = eap->skip ? OK : FAIL; goto theend; } + + // copy over the block scope IDs before compiling + if (!is_global && cctx->ctx_ufunc->uf_block_depth > 0) + { + int block_depth = cctx->ctx_ufunc->uf_block_depth; + + ufunc->uf_block_ids = ALLOC_MULT(int, block_depth); + if (ufunc->uf_block_ids != NULL) + { + mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids, + sizeof(int) * block_depth); + ufunc->uf_block_depth = block_depth; + } + } + if (func_needs_compiling(ufunc, PROFILING(ufunc)) && compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx) == FAIL) @@ -5209,25 +5224,12 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) // Define a local variable for the function reference. lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start, TRUE, ufunc->uf_func_type); - int block_depth = cctx->ctx_ufunc->uf_block_depth; if (lvar == NULL) goto theend; if (generate_FUNCREF(cctx, ufunc) == FAIL) goto theend; r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); - - // copy over the block scope IDs - if (block_depth > 0) - { - ufunc->uf_block_ids = ALLOC_MULT(int, block_depth); - if (ufunc->uf_block_ids != NULL) - { - mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids, - sizeof(int) * block_depth); - ufunc->uf_block_depth = block_depth; - } - } } // TODO: warning for trailing text? From 3f32788000258aabe078b426e3d71962bee9d2d1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 20:56:38 +0100 Subject: [PATCH 43/44] patch 8.2.2618: Vim9: cannot use a normal list name to store function refs Problem: Vim9: cannot use a normal list name to store function refs. Solution: Allow a lower case name if it is indexed. --- src/testdir/test_vim9_assign.vim | 7 +++++++ src/version.c | 2 ++ src/vim9compile.c | 7 +++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 23c0a89c85..f71226e1bd 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -72,6 +72,13 @@ def Test_assignment() CheckDefFailure(['var lambda = () => "lambda"'], 'E704:') CheckScriptFailure(['var x = "x"'], 'E1124:') + # lower case name is OK for a list + var lambdaLines =<< trim END + var lambdaList: list = [Test_syntax] + lambdaList[0] = () => "lambda" + END + CheckDefAndScriptSuccess(lambdaLines) + var nr: number = 1234 CheckDefFailure(['var nr: number = "asdf"'], 'E1012:') diff --git a/src/version.c b/src/version.c index 3bb4eceb74..6ac96acbda 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2618, /**/ 2617, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 93ded08577..458b4a1a34 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5832,11 +5832,13 @@ compile_lhs( return FAIL; } - // new local variable + // Check the name is valid for a funcref. if ((lhs->lhs_type->tt_type == VAR_FUNC || lhs->lhs_type->tt_type == VAR_PARTIAL) - && var_wrong_func_name(lhs->lhs_name, TRUE)) + && var_wrong_func_name(lhs->lhs_name, TRUE)) return FAIL; + + // New local variable. lhs->lhs_lvar = reserve_local(cctx, var_start, lhs->lhs_varlen, cmdidx == CMD_final || cmdidx == CMD_const, lhs->lhs_type); if (lhs->lhs_lvar == NULL) @@ -6275,6 +6277,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) { if ((rhs_type->tt_type == VAR_FUNC || rhs_type->tt_type == VAR_PARTIAL) + && !lhs.lhs_has_index && var_wrong_func_name(lhs.lhs_name, TRUE)) goto theend; From 5f91e74bf968c9033474086b2d9cb457281c8aa6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 17 Mar 2021 21:29:29 +0100 Subject: [PATCH 44/44] patch 8.2.2619: Vim9: no test for return type of lambda Problem: Vim9: no test for return type of lambda. Solution: Add a test. --- src/testdir/test_vim9_func.vim | 15 +++++++++++++++ src/version.c | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 73d8e37aa7..2697c29e44 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -752,11 +752,26 @@ def Test_call_lambda_args() CheckDefFailure(lines, 'E1167:') enddef +def FilterWithCond(x: string, Cond: func(string): bool): bool + return Cond(x) +enddef + def Test_lambda_return_type() var lines =<< trim END var Ref = (): => 123 END CheckDefAndScriptFailure(lines, 'E1157:', 1) + + # this works + for x in ['foo', 'boo'] + echo FilterWithCond(x, (v) => v =~ '^b') + endfor + + # this fails + lines =<< trim END + echo FilterWithCond('foo', (v) => v .. '^b') + END + CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1) enddef def Test_lambda_uses_assigned_var() diff --git a/src/version.c b/src/version.c index 6ac96acbda..74eec468a5 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2619, /**/ 2618, /**/