From 239f8d932672bcf5be6d32fc7c0bf95a2e69f5eb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 13:21:20 +0100 Subject: [PATCH 01/47] patch 8.2.2367: test failures on some less often used systems Problem: Test failures on some less often used systems. Solution: Adjust printf formats and types. (James McCoy, closes #7691) --- src/errors.h | 2 +- src/evalfunc.c | 12 ++++++------ src/list.c | 6 +++--- src/version.c | 2 ++ src/vim9execute.c | 6 +++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/errors.h b/src/errors.h index 47e9876f68..eb5ee1de2e 100644 --- a/src/errors.h +++ b/src/errors.h @@ -84,7 +84,7 @@ EXTERN char e_const_requires_a_value[] EXTERN char e_type_or_initialization_required[] INIT(= N_("E1022: Type or initialization required")); EXTERN char e_using_number_as_bool_nr[] - INIT(= N_("E1023: Using a Number as a Bool: %d")); + INIT(= N_("E1023: Using a Number as a Bool: %lld")); EXTERN char e_using_number_as_string[] INIT(= N_("E1024: Using a Number as a String")); EXTERN char e_using_rcurly_outside_if_block_scope[] diff --git a/src/evalfunc.c b/src/evalfunc.c index c9acd4136b..9c3e9f56fc 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2567,7 +2567,7 @@ f_charidx(typval_T *argvars, typval_T *rettv) { char_u *str; varnumber_T idx; - int countcc = FALSE; + varnumber_T countcc = FALSE; char_u *p; int len; int (*ptr2len)(char_u *); @@ -2588,7 +2588,7 @@ f_charidx(typval_T *argvars, typval_T *rettv) return; if (argvars[2].v_type != VAR_UNKNOWN) - countcc = (int)tv_get_bool(&argvars[2]); + countcc = tv_get_bool(&argvars[2]); if (countcc < 0 || countcc > 1) { semsg(_(e_using_number_as_bool_nr), countcc); @@ -2848,11 +2848,11 @@ f_debugbreak(typval_T *argvars, typval_T *rettv) static void f_deepcopy(typval_T *argvars, typval_T *rettv) { - int noref = 0; + varnumber_T noref = 0; int copyID; if (argvars[1].v_type != VAR_UNKNOWN) - noref = (int)tv_get_bool_chk(&argvars[1], NULL); + noref = tv_get_bool_chk(&argvars[1], NULL); if (noref < 0 || noref > 1) semsg(_(e_using_number_as_bool_nr), noref); else @@ -9185,12 +9185,12 @@ f_strlen(typval_T *argvars, typval_T *rettv) f_strchars(typval_T *argvars, typval_T *rettv) { char_u *s = tv_get_string(&argvars[0]); - int skipcc = FALSE; + varnumber_T skipcc = FALSE; varnumber_T len = 0; int (*func_mb_ptr2char_adv)(char_u **pp); if (argvars[1].v_type != VAR_UNKNOWN) - skipcc = (int)tv_get_bool(&argvars[1]); + skipcc = tv_get_bool(&argvars[1]); if (skipcc < 0 || skipcc > 1) semsg(_(e_using_number_as_bool_nr), skipcc); else diff --git a/src/list.c b/src/list.c index d6357f789c..77dd2a3074 100644 --- a/src/list.c +++ b/src/list.c @@ -925,7 +925,7 @@ list_slice_or_index( if (!range) { if (verbose) - semsg(_(e_listidx), n1_arg); + semsg(_(e_listidx), (long)n1_arg); return FAIL; } n1 = n1 < 0 ? 0 : len; @@ -1452,7 +1452,7 @@ list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg) listitem_T *item, *item2; listitem_T *li; int error = FALSE; - int idx; + long idx; if ((l = argvars[0].vval.v_list) == NULL || value_check_lock(l->lv_lock, arg_errmsg, TRUE)) @@ -1475,7 +1475,7 @@ list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg) else { // Remove range of items, return list with values. - int end = (long)tv_get_number_chk(&argvars[2], &error); + long end = (long)tv_get_number_chk(&argvars[2], &error); if (error) ; // type error: do nothing diff --git a/src/version.c b/src/version.c index 0367430ffe..e29ae78129 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 */ +/**/ + 2367, /**/ 2366, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 87a9218ae4..b24475ecfe 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1935,8 +1935,8 @@ call_def_function( if (status == OK && dest_type == VAR_LIST) { - varnumber_T lidx = tv_idx->vval.v_number; - list_T *list = tv_dest->vval.v_list; + long lidx = (long)tv_idx->vval.v_number; + list_T *list = tv_dest->vval.v_list; if (list == NULL) { @@ -2121,7 +2121,7 @@ call_def_function( else { list_T *l = tv_dest->vval.v_list; - varnumber_T n = tv_idx->vval.v_number; + long n = (long)tv_idx->vval.v_number; listitem_T *li = NULL; li = list_find(l, n); From 85773bf32b51cbe7e971c5ac11cb9c743bb7a38a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 13:48:03 +0100 Subject: [PATCH 02/47] patch 8.2.2368: insufficient tests for setting options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Insufficient tests for setting options. Solution: Add a few tests. (Dominique Pellé, closes #7695) --- src/testdir/test_options.vim | 19 ++++++++++++++++++- src/version.c | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 281c20c1f1..cc02c5c7ca 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -371,8 +371,14 @@ func Test_set_errors() call assert_fails('set foldmarker=x', 'E536:') call assert_fails('set commentstring=x', 'E537:') call assert_fails('set complete=x', 'E539:') + call assert_fails('set rulerformat=%-', 'E539:') + call assert_fails('set rulerformat=%(', 'E542:') + call assert_fails('set rulerformat=%15(%%', 'E542:') + call assert_fails('set statusline=%$', 'E539:') call assert_fails('set statusline=%{', 'E540:') call assert_fails('set statusline=%(', 'E542:') + call assert_fails('set statusline=%)', 'E542:') + if has('cursorshape') " This invalid value for 'guicursor' used to cause Vim to crash. call assert_fails('set guicursor=i-ci,r-cr:h', 'E545:') @@ -406,11 +412,22 @@ func Test_set_errors() call assert_fails('set wildchar=', 'E474:') call assert_fails('set cmdheight=1a', 'E521:') call assert_fails('set invcmdheight', 'E474:') - if has('python') && has('python3') + if has('python') || has('python3') call assert_fails('set pyxversion=6', 'E474:') endif call assert_fails("let &tabstop='ab'", 'E521:') call assert_fails('set spellcapcheck=%\\(', 'E54:') + call assert_fails('set sessionoptions=curdir,sesdir', 'E474:') + call assert_fails('set foldmarker={{{,', 'E474:') + call assert_fails('set sessionoptions=sesdir,curdir', 'E474:') + call assert_fails('set listchars=trail:· ambiwidth=double', 'E834:') + set listchars& + call assert_fails('set fillchars=stl:· ambiwidth=double', 'E835:') + set fillchars& + call assert_fails('set fileencoding=latin1,utf-8', 'E474:') + set nomodifiable + call assert_fails('set fileencoding=latin1', 'E21:') + set modifiable& endfunc func CheckWasSet(name) diff --git a/src/version.c b/src/version.c index e29ae78129..4d36419caf 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 */ +/**/ + 2368, /**/ 2367, /**/ From 3af15ab7888033fdfae0ae7085172aab794339a2 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 16:16:23 +0100 Subject: [PATCH 03/47] patch 8.2.2369: Vim9: functions return true/false but can't be used as bool Problem: Vim9: functions return true/false but can't be used as bool. Solution: Add ret_number_bool(). (closes #7693) --- src/evalfunc.c | 143 +++++++++++++------------- src/testdir/test_vim9_builtin.vim | 20 ++++ src/testdir/test_vim9_disassemble.vim | 2 +- src/version.c | 2 + 4 files changed, 97 insertions(+), 70 deletions(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index 9c3e9f56fc..7f703f60b5 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -449,6 +449,11 @@ ret_bool(int argcount UNUSED, type_T **argtypes UNUSED) return &t_bool; } static type_T * +ret_number_bool(int argcount UNUSED, type_T **argtypes UNUSED) +{ + return &t_number_bool; +} + static type_T * ret_number(int argcount UNUSED, type_T **argtypes UNUSED) { return &t_number; @@ -690,9 +695,9 @@ static funcentry_T global_functions[] = {"and", 2, 2, FEARG_1, NULL, ret_number, f_and}, {"append", 2, 2, FEARG_2, NULL, - ret_number, f_append}, + ret_number_bool, f_append}, {"appendbufline", 3, 3, FEARG_3, NULL, - ret_number, f_appendbufline}, + ret_number_bool, f_appendbufline}, {"argc", 0, 1, 0, NULL, ret_number, f_argc}, {"argidx", 0, 0, 0, NULL, @@ -704,29 +709,29 @@ static funcentry_T global_functions[] = {"asin", 1, 1, FEARG_1, NULL, ret_float, FLOAT_FUNC(f_asin)}, {"assert_beeps", 1, 2, FEARG_1, NULL, - ret_number, f_assert_beeps}, + ret_number_bool, f_assert_beeps}, {"assert_equal", 2, 3, FEARG_2, NULL, - ret_number, f_assert_equal}, + ret_number_bool, f_assert_equal}, {"assert_equalfile", 2, 3, FEARG_1, NULL, - ret_number, f_assert_equalfile}, + ret_number_bool, f_assert_equalfile}, {"assert_exception", 1, 2, 0, NULL, - ret_number, f_assert_exception}, + ret_number_bool, f_assert_exception}, {"assert_fails", 1, 5, FEARG_1, NULL, - ret_number, f_assert_fails}, + ret_number_bool, f_assert_fails}, {"assert_false", 1, 2, FEARG_1, NULL, - ret_number, f_assert_false}, + ret_number_bool, f_assert_false}, {"assert_inrange", 3, 4, FEARG_3, NULL, - ret_number, f_assert_inrange}, + ret_number_bool, f_assert_inrange}, {"assert_match", 2, 3, FEARG_2, NULL, - ret_number, f_assert_match}, + ret_number_bool, f_assert_match}, {"assert_notequal", 2, 3, FEARG_2, NULL, - ret_number, f_assert_notequal}, + ret_number_bool, f_assert_notequal}, {"assert_notmatch", 2, 3, FEARG_2, NULL, - ret_number, f_assert_notmatch}, + ret_number_bool, f_assert_notmatch}, {"assert_report", 1, 1, FEARG_1, NULL, - ret_number, f_assert_report}, + ret_number_bool, f_assert_report}, {"assert_true", 1, 2, FEARG_1, NULL, - ret_number, f_assert_true}, + ret_number_bool, f_assert_true}, {"atan", 1, 1, FEARG_1, NULL, ret_float, FLOAT_FUNC(f_atan)}, {"atan2", 2, 2, FEARG_1, NULL, @@ -762,19 +767,19 @@ static funcentry_T global_functions[] = {"bufadd", 1, 1, FEARG_1, NULL, ret_number, f_bufadd}, {"bufexists", 1, 1, FEARG_1, NULL, - ret_number, f_bufexists}, + ret_number_bool, f_bufexists}, {"buffer_exists", 1, 1, FEARG_1, NULL, // obsolete - ret_number, f_bufexists}, + ret_number_bool, f_bufexists}, {"buffer_name", 0, 1, FEARG_1, NULL, // obsolete ret_string, f_bufname}, {"buffer_number", 0, 1, FEARG_1, NULL, // obsolete ret_number, f_bufnr}, {"buflisted", 1, 1, FEARG_1, NULL, - ret_number, f_buflisted}, + ret_number_bool, f_buflisted}, {"bufload", 1, 1, FEARG_1, NULL, ret_void, f_bufload}, {"bufloaded", 1, 1, FEARG_1, NULL, - ret_number, f_bufloaded}, + ret_number_bool, f_bufloaded}, {"bufname", 0, 1, FEARG_1, NULL, ret_string, f_bufname}, {"bufnr", 0, 2, FEARG_1, NULL, @@ -794,7 +799,7 @@ static funcentry_T global_functions[] = {"ceil", 1, 1, FEARG_1, NULL, ret_float, FLOAT_FUNC(f_ceil)}, {"ch_canread", 1, 1, FEARG_1, NULL, - ret_number, JOB_FUNC(f_ch_canread)}, + ret_number_bool, JOB_FUNC(f_ch_canread)}, {"ch_close", 1, 1, FEARG_1, NULL, ret_void, JOB_FUNC(f_ch_close)}, {"ch_close_in", 1, 1, FEARG_1, NULL, @@ -852,7 +857,7 @@ static funcentry_T global_functions[] = {"complete_add", 1, 1, FEARG_1, NULL, ret_number, f_complete_add}, {"complete_check", 0, 0, 0, NULL, - ret_number, f_complete_check}, + ret_number_bool, f_complete_check}, {"complete_info", 0, 1, FEARG_1, NULL, ret_dict_any, f_complete_info}, {"confirm", 1, 4, FEARG_1, NULL, @@ -880,19 +885,19 @@ static funcentry_T global_functions[] = {"deepcopy", 1, 2, FEARG_1, NULL, ret_first_arg, f_deepcopy}, {"delete", 1, 2, FEARG_1, NULL, - ret_number, f_delete}, + ret_number_bool, f_delete}, {"deletebufline", 2, 3, FEARG_1, NULL, - ret_number, f_deletebufline}, + ret_number_bool, f_deletebufline}, {"did_filetype", 0, 0, 0, NULL, - ret_number, f_did_filetype}, + ret_number_bool, f_did_filetype}, {"diff_filler", 1, 1, FEARG_1, NULL, ret_number, f_diff_filler}, {"diff_hlID", 2, 2, FEARG_1, NULL, ret_number, f_diff_hlID}, {"echoraw", 1, 1, FEARG_1, NULL, - ret_number, f_echoraw}, + ret_void, f_echoraw}, {"empty", 1, 1, FEARG_1, NULL, - ret_number, f_empty}, + ret_number_bool, f_empty}, {"environ", 0, 0, 0, NULL, ret_dict_string, f_environ}, {"escape", 2, 2, FEARG_1, NULL, @@ -900,7 +905,7 @@ static funcentry_T global_functions[] = {"eval", 1, 1, FEARG_1, NULL, ret_any, f_eval}, {"eventhandler", 0, 0, 0, NULL, - ret_number, f_eventhandler}, + ret_number_bool, f_eventhandler}, {"executable", 1, 1, FEARG_1, NULL, ret_number, f_executable}, {"execute", 1, 2, FEARG_1, NULL, @@ -908,7 +913,7 @@ static funcentry_T global_functions[] = {"exepath", 1, 1, FEARG_1, NULL, ret_string, f_exepath}, {"exists", 1, 1, FEARG_1, NULL, - ret_number, f_exists}, + ret_number_bool, f_exists}, {"exp", 1, 1, FEARG_1, NULL, ret_float, FLOAT_FUNC(f_exp)}, {"expand", 1, 3, FEARG_1, NULL, @@ -922,9 +927,9 @@ static funcentry_T global_functions[] = {"feedkeys", 1, 2, FEARG_1, NULL, ret_void, f_feedkeys}, {"file_readable", 1, 1, FEARG_1, NULL, // obsolete - ret_number, f_filereadable}, + ret_number_bool, f_filereadable}, {"filereadable", 1, 1, FEARG_1, NULL, - ret_number, f_filereadable}, + ret_number_bool, f_filereadable}, {"filewritable", 1, 1, FEARG_1, NULL, ret_number, f_filewritable}, {"filter", 2, 2, FEARG_1, NULL, @@ -1010,7 +1015,7 @@ static funcentry_T global_functions[] = {"getftype", 1, 1, FEARG_1, NULL, ret_string, f_getftype}, {"getimstatus", 0, 0, 0, NULL, - ret_number, f_getimstatus}, + ret_number_bool, f_getimstatus}, {"getjumplist", 0, 2, FEARG_1, NULL, ret_list_any, f_getjumplist}, {"getline", 1, 2, FEARG_1, NULL, @@ -1062,21 +1067,21 @@ static funcentry_T global_functions[] = {"globpath", 2, 5, FEARG_2, NULL, ret_any, f_globpath}, {"has", 1, 2, 0, NULL, - ret_number, f_has}, + ret_number_bool, f_has}, {"has_key", 2, 2, FEARG_1, NULL, - ret_number, f_has_key}, + ret_number_bool, f_has_key}, {"haslocaldir", 0, 2, FEARG_1, NULL, ret_number, f_haslocaldir}, {"hasmapto", 1, 3, FEARG_1, NULL, - ret_number, f_hasmapto}, + ret_number_bool, f_hasmapto}, {"highlightID", 1, 1, FEARG_1, NULL, // obsolete ret_number, f_hlID}, {"highlight_exists",1, 1, FEARG_1, NULL, // obsolete - ret_number, f_hlexists}, + ret_number_bool, f_hlexists}, {"histadd", 2, 2, FEARG_2, NULL, - ret_number, f_histadd}, + ret_number_bool, f_histadd}, {"histdel", 1, 2, FEARG_1, NULL, - ret_number, f_histdel}, + ret_number_bool, f_histdel}, {"histget", 1, 2, FEARG_1, NULL, ret_string, f_histget}, {"histnr", 1, 1, FEARG_1, NULL, @@ -1084,7 +1089,7 @@ static funcentry_T global_functions[] = {"hlID", 1, 1, FEARG_1, NULL, ret_number, f_hlID}, {"hlexists", 1, 1, FEARG_1, NULL, - ret_number, f_hlexists}, + ret_number_bool, f_hlexists}, {"hostname", 0, 0, 0, NULL, ret_string, f_hostname}, {"iconv", 3, 3, FEARG_1, NULL, @@ -1100,9 +1105,9 @@ static funcentry_T global_functions[] = {"inputlist", 1, 1, FEARG_1, NULL, ret_number, f_inputlist}, {"inputrestore", 0, 0, 0, NULL, - ret_number, f_inputrestore}, + ret_number_bool, f_inputrestore}, {"inputsave", 0, 0, 0, NULL, - ret_number, f_inputsave}, + ret_number_bool, f_inputsave}, {"inputsecret", 1, 2, FEARG_1, NULL, ret_string, f_inputsecret}, {"insert", 2, 3, FEARG_1, arg3_insert, @@ -1112,13 +1117,13 @@ static funcentry_T global_functions[] = {"invert", 1, 1, FEARG_1, NULL, ret_number, f_invert}, {"isdirectory", 1, 1, FEARG_1, NULL, - ret_number, f_isdirectory}, + ret_number_bool, f_isdirectory}, {"isinf", 1, 1, FEARG_1, NULL, ret_number, MATH_FUNC(f_isinf)}, {"islocked", 1, 1, FEARG_1, NULL, - ret_number, f_islocked}, + ret_number_bool, f_islocked}, {"isnan", 1, 1, FEARG_1, NULL, - ret_number, MATH_FUNC(f_isnan)}, + ret_number_bool, MATH_FUNC(f_isnan)}, {"items", 1, 1, FEARG_1, NULL, ret_list_any, f_items}, {"job_getchannel", 1, 1, FEARG_1, NULL, @@ -1132,7 +1137,7 @@ static funcentry_T global_functions[] = {"job_status", 1, 1, FEARG_1, NULL, ret_string, JOB_FUNC(f_job_status)}, {"job_stop", 1, 2, FEARG_1, NULL, - ret_number, JOB_FUNC(f_job_stop)}, + ret_number_bool, JOB_FUNC(f_job_stop)}, {"join", 1, 2, FEARG_1, NULL, ret_string, f_join}, {"js_decode", 1, 1, FEARG_1, NULL, @@ -1166,7 +1171,7 @@ static funcentry_T global_functions[] = {"listener_flush", 0, 1, FEARG_1, NULL, ret_void, f_listener_flush}, {"listener_remove", 1, 1, FEARG_1, NULL, - ret_number, f_listener_remove}, + ret_number_bool, f_listener_remove}, {"localtime", 0, 0, 0, NULL, ret_number, f_localtime}, {"log", 1, 1, FEARG_1, NULL, @@ -1200,7 +1205,7 @@ static funcentry_T global_functions[] = {"matcharg", 1, 1, FEARG_1, NULL, ret_list_string, f_matcharg}, {"matchdelete", 1, 2, FEARG_1, NULL, - ret_number, f_matchdelete}, + ret_number_bool, f_matchdelete}, {"matchend", 2, 4, FEARG_1, NULL, ret_number, f_matchend}, {"matchfuzzy", 2, 3, FEARG_1, NULL, @@ -1226,7 +1231,7 @@ static funcentry_T global_functions[] = {"min", 1, 1, FEARG_1, NULL, ret_any, f_min}, {"mkdir", 1, 3, FEARG_1, NULL, - ret_number, f_mkdir}, + ret_number_bool, f_mkdir}, {"mode", 0, 1, FEARG_1, NULL, ret_string, f_mode}, {"mzeval", 1, 1, FEARG_1, NULL, @@ -1332,7 +1337,7 @@ static funcentry_T global_functions[] = {"pum_getpos", 0, 0, 0, NULL, ret_dict_number, f_pum_getpos}, {"pumvisible", 0, 0, 0, NULL, - ret_number, f_pumvisible}, + ret_number_bool, f_pumvisible}, {"py3eval", 1, 1, FEARG_1, NULL, ret_any, #ifdef FEAT_PYTHON3 @@ -1396,7 +1401,7 @@ static funcentry_T global_functions[] = {"remove", 2, 3, FEARG_1, NULL, ret_remove, f_remove}, {"rename", 2, 2, FEARG_1, NULL, - ret_number, f_rename}, + ret_number_bool, f_rename}, {"repeat", 2, 2, FEARG_1, NULL, ret_first_arg, f_repeat}, {"resolve", 1, 1, FEARG_1, NULL, @@ -1432,7 +1437,7 @@ static funcentry_T global_functions[] = {"searchcount", 0, 1, FEARG_1, NULL, ret_dict_any, f_searchcount}, {"searchdecl", 1, 3, FEARG_1, NULL, - ret_number, f_searchdecl}, + ret_number_bool, f_searchdecl}, {"searchpair", 3, 7, 0, NULL, ret_number, f_searchpair}, {"searchpairpos", 3, 7, 0, NULL, @@ -1440,45 +1445,45 @@ static funcentry_T global_functions[] = {"searchpos", 1, 5, FEARG_1, NULL, ret_list_number, f_searchpos}, {"server2client", 2, 2, FEARG_1, NULL, - ret_number, f_server2client}, + ret_number_bool, f_server2client}, {"serverlist", 0, 0, 0, NULL, ret_string, f_serverlist}, {"setbufline", 3, 3, FEARG_3, NULL, - ret_number, f_setbufline}, + ret_number_bool, f_setbufline}, {"setbufvar", 3, 3, FEARG_3, NULL, ret_void, f_setbufvar}, {"setcellwidths", 1, 1, FEARG_1, NULL, ret_void, f_setcellwidths}, {"setcharpos", 2, 2, FEARG_2, NULL, - ret_number, f_setcharpos}, + ret_number_bool, f_setcharpos}, {"setcharsearch", 1, 1, FEARG_1, NULL, ret_void, f_setcharsearch}, {"setcmdpos", 1, 1, FEARG_1, NULL, - ret_number, f_setcmdpos}, - {"setcursorcharpos", 1, 3, FEARG_1, NULL, - ret_number, f_setcursorcharpos}, + ret_number_bool, f_setcmdpos}, + {"setcursorcharpos", 1, 3, FEARG_1, NULL, + ret_number_bool, f_setcursorcharpos}, {"setenv", 2, 2, FEARG_2, NULL, ret_void, f_setenv}, {"setfperm", 2, 2, FEARG_1, NULL, - ret_number, f_setfperm}, + ret_number_bool, f_setfperm}, {"setline", 2, 2, FEARG_2, NULL, - ret_number, f_setline}, + ret_number_bool, f_setline}, {"setloclist", 2, 4, FEARG_2, NULL, - ret_number, f_setloclist}, + ret_number_bool, f_setloclist}, {"setmatches", 1, 2, FEARG_1, NULL, - ret_number, f_setmatches}, + ret_number_bool, f_setmatches}, {"setpos", 2, 2, FEARG_2, NULL, - ret_number, f_setpos}, + ret_number_bool, f_setpos}, {"setqflist", 1, 3, FEARG_1, NULL, - ret_number, f_setqflist}, + ret_number_bool, f_setqflist}, {"setreg", 2, 3, FEARG_2, NULL, - ret_number, f_setreg}, + ret_number_bool, f_setreg}, {"settabvar", 3, 3, FEARG_3, NULL, ret_void, f_settabvar}, {"settabwinvar", 4, 4, FEARG_4, NULL, ret_void, f_settabwinvar}, {"settagstack", 2, 3, FEARG_2, NULL, - ret_number, f_settagstack}, + ret_number_bool, f_settagstack}, {"setwinvar", 3, 3, FEARG_3, NULL, ret_void, f_setwinvar}, {"sha256", 1, 1, FEARG_1, NULL, @@ -1506,9 +1511,9 @@ static funcentry_T global_functions[] = {"sign_placelist", 1, 1, FEARG_1, NULL, ret_list_number, SIGN_FUNC(f_sign_placelist)}, {"sign_undefine", 0, 1, FEARG_1, NULL, - ret_number, SIGN_FUNC(f_sign_undefine)}, + ret_number_bool, SIGN_FUNC(f_sign_undefine)}, {"sign_unplace", 1, 2, FEARG_1, NULL, - ret_number, SIGN_FUNC(f_sign_unplace)}, + ret_number_bool, SIGN_FUNC(f_sign_unplace)}, {"sign_unplacelist", 1, 2, FEARG_1, NULL, ret_list_number, SIGN_FUNC(f_sign_unplacelist)}, {"simplify", 1, 1, FEARG_1, NULL, @@ -1788,7 +1793,7 @@ static funcentry_T global_functions[] = {"win_gettype", 0, 1, FEARG_1, NULL, ret_string, f_win_gettype}, {"win_gotoid", 1, 1, FEARG_1, NULL, - ret_number, f_win_gotoid}, + ret_number_bool, f_win_gotoid}, {"win_id2tabwin", 1, 1, FEARG_1, NULL, ret_list_number, f_win_id2tabwin}, {"win_id2win", 1, 1, FEARG_1, NULL, @@ -1796,7 +1801,7 @@ static funcentry_T global_functions[] = {"win_screenpos", 1, 1, FEARG_1, NULL, ret_list_number, f_win_screenpos}, {"win_splitmove", 2, 3, FEARG_1, NULL, - ret_number, f_win_splitmove}, + ret_number_bool, f_win_splitmove}, {"winbufnr", 1, 1, FEARG_1, NULL, ret_number, f_winbufnr}, {"wincol", 0, 0, 0, NULL, @@ -1822,7 +1827,7 @@ static funcentry_T global_functions[] = {"wordcount", 0, 0, 0, NULL, ret_dict_number, f_wordcount}, {"writefile", 2, 3, FEARG_1, NULL, - ret_number, f_writefile}, + ret_number_bool, f_writefile}, {"xor", 2, 2, FEARG_1, NULL, ret_number, f_xor}, }; @@ -8310,7 +8315,7 @@ f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED) * "setcursorcharpos" function */ static void -f_setcursorcharpos(typval_T *argvars, typval_T *rettv UNUSED) +f_setcursorcharpos(typval_T *argvars, typval_T *rettv) { set_cursorpos(argvars, rettv, TRUE); } diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 61d129ec23..50dc2a0735 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -115,6 +115,21 @@ def Test_add_blob() CheckDefExecFailure(lines, 'E1131:', 2) enddef +def Test_append() + new + setline(1, range(3)) + var res1: number = append(1, 'one') + assert_equal(0, res1) + var res2: bool = append(3, 'two') + assert_equal(false, res2) + assert_equal(['0', 'one', '1', 'two', '2'], getline(1, 6)) +enddef + +def Test_buflisted() + var res: bool = buflisted('asdf') + assert_equal(false, res) +enddef + def Test_bufname() split SomeFile bufname('%')->assert_equal('SomeFile') @@ -199,6 +214,11 @@ def Test_cursor() CheckDefExecAndScriptFailure(lines, 'E475:') enddef +def Test_delete() + var res: bool = delete('doesnotexist') + assert_equal(true, res) +enddef + def Test_executable() assert_false(executable("")) assert_false(executable(test_null_string())) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 83dcda0854..1aab9d5b38 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -762,7 +762,7 @@ def Test_disassemble_const_expr() 'if has("gui_running")\_s*' .. '\d PUSHS "gui_running"\_s*' .. '\d BCALL has(argc 1)\_s*' .. - '\d COND2BOOL\_s*' .. + '\d 2BOOL (!!val)\_s*' .. '\d JUMP_IF_FALSE -> \d\_s*' .. ' echo "yes"\_s*' .. '\d PUSHS "yes"\_s*' .. diff --git a/src/version.c b/src/version.c index 4d36419caf..3ac6cfae81 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 */ +/**/ + 2369, /**/ 2368, /**/ From 1430ceeb2d4185a8d60fa81007fbc8b74fd68c46 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 19:20:32 +0100 Subject: [PATCH 04/47] patch 8.2.2370: Vim9: command fails in catch block Problem: Vim9: command fails in catch block. Solution: Reset force_abort and need_rethrow. (closes #7692) --- src/testdir/test_vim9_script.vim | 37 ++++++++++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 1 + 3 files changed, 40 insertions(+) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 158c64c27c..478c394603 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -558,6 +558,43 @@ def Test_try_catch_throw() assert_equal(411, n) enddef +def Test_cnext_works_in_catch() + var lines =<< trim END + vim9script + au BufEnter * eval 0 + writefile(['text'], 'Xfile1') + writefile(['text'], 'Xfile2') + var items = [ + {lnum: 1, filename: 'Xfile1', valid: true}, + {lnum: 1, filename: 'Xfile2', valid: true} + ] + setqflist([], ' ', {items: items}) + cwindow + + def CnextOrCfirst() + # if cnext fails, cfirst is used + try + cnext + catch + cfirst + endtry + enddef + + CnextOrCfirst() + CnextOrCfirst() + writefile([getqflist({idx: 0}).idx], 'Xresult') + qall + END + writefile(lines, 'XCatchCnext') + RunVim([], [], '--clean -S XCatchCnext') + assert_equal(['1'], readfile('Xresult')) + + delete('Xfile1') + delete('Xfile2') + delete('XCatchCnext') + delete('Xresult') +enddef + def Test_throw_skipped() if 0 throw dontgethere diff --git a/src/version.c b/src/version.c index 3ac6cfae81..ecb0c4355e 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 */ +/**/ + 2370, /**/ 2369, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index b24475ecfe..fdc49eb05d 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2572,6 +2572,7 @@ call_def_function( trycmd->tcd_caught = TRUE; } did_emsg = got_int = did_throw = FALSE; + force_abort = need_rethrow = FALSE; catch_exception(current_exception); } break; From 036d07144efe213199b1ed8de998e6f12a056499 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 20:23:38 +0100 Subject: [PATCH 05/47] patch 8.2.2371: Vim9: crash when using types in :for with unpack Problem: Vim9: crash when using types in :for with unpack. Solution: Check for skip_var_list() failing. Pass include_type to skip_var_one(). Skip type when compiling. (closes #7694) --- src/evalvars.c | 11 +++++++---- src/testdir/test_vim9_script.vim | 6 ++++++ src/version.c | 2 ++ src/vim9compile.c | 4 ++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index 155f603b50..d98d9e4708 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1019,7 +1019,7 @@ skip_var_list( for (;;) { p = skipwhite(p + 1); // skip whites after '[', ';' or ',' - s = skip_var_one(p, FALSE); + s = skip_var_one(p, include_type); if (s == p) { if (!silent) @@ -1067,11 +1067,14 @@ skip_var_one(char_u *arg, int include_type) return arg + 2; end = find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START); + + // "a: type" is declaring variable "a" with a type, not "a:". + // Same for "s: type". + if (end == arg + 2 && end[-1] == ':') + --end; + if (include_type && in_vim9script()) { - // "a: type" is declaring variable "a" with a type, not "a:". - if (end == arg + 2 && end[-1] == ':') - --end; if (*end == ':') end = skip_type(skipwhite(end + 1), FALSE); } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 478c394603..957671c53b 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2060,6 +2060,12 @@ def Test_for_loop() total += nr endfor assert_equal(6, total) + + var res = "" + for [n: number, s: string] in [[1, 'a'], [2, 'b']] + res ..= n .. s + endfor + assert_equal('1a2b', res) enddef def Test_for_loop_fails() diff --git a/src/version.c b/src/version.c index ecb0c4355e..289854e89e 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 */ +/**/ + 2371, /**/ 2370, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index fb7aeddd49..01bf2c19a8 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6884,6 +6884,8 @@ compile_for(char_u *arg_start, cctx_T *cctx) int idx; p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE); + if (p == NULL) + return NULL; if (var_count == 0) var_count = 1; @@ -7018,6 +7020,8 @@ compile_for(char_u *arg_start, cctx_T *cctx) generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL); } + if (*p == ':') + p = skip_type(skipwhite(p + 1), FALSE); if (*p == ',' || *p == ';') ++p; arg = skipwhite(p); From 585587dadbc2558520c33969098db9ff49598785 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 20:52:13 +0100 Subject: [PATCH 06/47] patch 8.2.2372: confusing error message for wrong :let command Problem: Confusing error message for wrong :let command. Solution: Only check for type in Vim9 script. --- src/evalvars.c | 7 ++++--- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index d98d9e4708..200fb8f12c 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1061,7 +1061,8 @@ skip_var_list( char_u * skip_var_one(char_u *arg, int include_type) { - char_u *end; + char_u *end; + int vim9 = in_vim9script(); if (*arg == '@' && arg[1] != NUL) return arg + 2; @@ -1070,10 +1071,10 @@ skip_var_one(char_u *arg, int include_type) // "a: type" is declaring variable "a" with a type, not "a:". // Same for "s: type". - if (end == arg + 2 && end[-1] == ':') + if (vim9 && end == arg + 2 && end[-1] == ':') --end; - if (include_type && in_vim9script()) + if (include_type && vim9) { if (*end == ':') end = skip_type(skipwhite(end + 1), FALSE); diff --git a/src/version.c b/src/version.c index 289854e89e..3a88080e0d 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 */ +/**/ + 2372, /**/ 2371, /**/ From f30a14db3b26e510f193f50ee0dd8a41303e4740 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 21:51:24 +0100 Subject: [PATCH 07/47] patch 8.2.2373: Vim9: list assignment only accepts a number index Problem: Vim9: list assignment only accepts a number index. Solution: Accept "any" and do a runtime type check. (closes #7694) --- src/testdir/test_vim9_assign.vim | 13 +++++++++++-- src/version.c | 2 ++ src/vim9compile.c | 7 ++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index c035558803..20bdb91380 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -350,7 +350,7 @@ def Test_assign_index() var lines: list lines['a'] = 'asdf' END - CheckDefFailure(lines, 'E39:', 2) + CheckDefFailure(lines, 'E1012:', 2) lines =<< trim END var lines: string @@ -561,6 +561,15 @@ def Test_assignment_list() CheckDefExecFailure(lines, 'E1147:', 2) enddef +def Test_assignment_list_any_index() + var l: list = [1, 2] + for [x, y, _] + in [[0, 1, ''], [1, 3, '']] + l[x] = l[x] + y + endfor + assert_equal([2, 5], l) +enddef + def Test_assignment_list_vim9script() var lines =<< trim END vim9script @@ -1405,7 +1414,7 @@ def Test_unlet() CheckDefExecFailure([ 'var ll = [1]', 'unlet ll[g:astring]', - ], 'E39:', 2) + ], 'E1012:', 2) CheckDefExecFailure([ 'var dd = test_null_dict()', 'unlet dd["a"]', diff --git a/src/version.c b/src/version.c index 3a88080e0d..f1b728048a 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 */ +/**/ + 2373, /**/ 2372, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 01bf2c19a8..d1df00821c 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5802,12 +5802,9 @@ compile_assign_unlet( if (dest_type == VAR_DICT && may_generate_2STRING(-1, cctx) == FAIL) return FAIL; if (dest_type == VAR_LIST - && ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type - != VAR_NUMBER) - { - emsg(_(e_number_exp)); + && need_type(((type_T **)stack->ga_data)[stack->ga_len - 1], + &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL) return FAIL; - } } // Load the dict or list. On the stack we then have: From 82aa6e09e02b138ab7ee6b79ecac487813f117e5 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 17 Jan 2021 22:04:02 +0100 Subject: [PATCH 08/47] patch 8.2.2374: accessing uninitialized memory in test_undo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Accessing uninitialized memory in test_undo. Solution: Do not look in typebuf.tb_buf if it is empty. (Dominique Pellé, closes #7697) --- src/edit.c | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/edit.c b/src/edit.c index a152d84499..35e4bc2c4b 100644 --- a/src/edit.c +++ b/src/edit.c @@ -1586,7 +1586,7 @@ decodeModifyOtherKeys(int c) // Recognize: // form 0: {lead}{key};{modifier}u // form 1: {lead}27;{modifier};{key}~ - if ((c == CSI || (c == ESC && *p == '[')) && typebuf.tb_len >= 4) + if (typebuf.tb_len >= 4 && (c == CSI || (c == ESC && *p == '['))) { idx = (*p == '['); if (p[idx] == '2' && p[idx + 1] == '7' && p[idx + 2] == ';') diff --git a/src/version.c b/src/version.c index f1b728048a..98f120b2e2 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 */ +/**/ + 2374, /**/ 2373, /**/ From 98a29d00a48e15a50e2850e1a29b7d475c531b0c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 18 Jan 2021 19:55:44 +0100 Subject: [PATCH 09/47] Update runtime files. --- runtime/doc/eval.txt | 52 ++++++++++---------- runtime/doc/filetype.txt | 1 + runtime/doc/index.txt | 2 +- runtime/doc/options.txt | 4 +- runtime/doc/popup.txt | 2 - runtime/doc/syntax.txt | 9 ++-- runtime/doc/tags | 15 ++++-- runtime/doc/term.txt | 6 +-- runtime/doc/todo.txt | 28 +++-------- runtime/doc/usr_41.txt | 2 +- runtime/doc/various.txt | 7 ++- runtime/doc/version6.txt | 2 +- runtime/doc/vi_diff.txt | 2 +- runtime/doc/vim9.txt | 100 +++++++++++++++++++++++++-------------- runtime/ftplugin/vim.vim | 10 ++-- runtime/syntax/c.vim | 19 ++++---- runtime/syntax/cpp.vim | 5 +- 17 files changed, 150 insertions(+), 116 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 4bab6ef6f8..217e69dc08 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 Jan 13 +*eval.txt* For Vim version 8.2. Last change: 2021 Jan 17 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4084,8 +4084,9 @@ delete({fname} [, {flags}]) *delete()* A symbolic link itself is deleted, not what it points to. - The result is a Number, which is 0 if the delete operation was - successful and -1 when the deletion failed or partly failed. + The result is a Number, which is 0/false if the delete + operation was successful and -1/true when the deletion failed + or partly failed. Use |remove()| to delete an item from a |List|. To delete a line from the buffer use |:delete| or @@ -6222,8 +6223,8 @@ has({feature} [, {check}]) has_key({dict}, {key}) *has_key()* - The result is a Number, which is 1 if |Dictionary| {dict} has - an entry with key {key}. Zero otherwise. + The result is a Number, which is TRUE if |Dictionary| {dict} + has an entry with key {key}. FALSE otherwise. Can also be used as a |method|: > mydict->has_key(key) @@ -6266,16 +6267,16 @@ haslocaldir([{winnr} [, {tabnr}]]) *haslocaldir()* GetWinnr()->haslocaldir() hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()* - The result is a Number, which is 1 if there is a mapping that - contains {what} in somewhere in the rhs (what it is mapped to) - and this mapping exists in one of the modes indicated by - {mode}. + The result is a Number, which is TRUE if there is a mapping + that contains {what} in somewhere in the rhs (what it is + mapped to) and this mapping exists in one of the modes + indicated by {mode}. When {abbr} is there and it is |TRUE| use abbreviations instead of mappings. Don't forget to specify Insert and/or Command-line mode. Both the global mappings and the mappings local to the current buffer are checked for a match. - If no matching mapping is found 0 is returned. + If no matching mapping is found FALSE is returned. The following characters are recognized in {mode}: n Normal mode v Visual and Select mode @@ -6311,8 +6312,8 @@ histadd({history}, {item}) *histadd()* character is sufficient. If {item} does already exist in the history, it will be shifted to become the newest entry. - The result is a Number: 1 if the operation was successful, - otherwise 0 is returned. + The result is a Number: TRUE if the operation was successful, + otherwise FALSE is returned. Example: > :call histadd("input", strftime("%Y %b %d")) @@ -6335,8 +6336,8 @@ histdel({history} [, {item}]) *histdel()* an index, see |:history-indexing|. The respective entry will be removed if it exists. - The result is a Number: 1 for a successful operation, - otherwise 0 is returned. + The result is TRUE for a successful operation, otherwise FALSE + is returned. Examples: Clear expression register history: > @@ -6388,7 +6389,7 @@ histnr({history}) *histnr()* GetHistory()->histnr() < hlexists({name}) *hlexists()* - The result is a Number, which is non-zero if a highlight group + The result is a Number, which is TRUE if a highlight group called {name} exists. This is when the group has been defined in some way. Not necessarily when highlighting has been defined for it, it may also have been used for a syntax @@ -6561,7 +6562,7 @@ inputrestore() *inputrestore()* Restore typeahead that was saved with a previous |inputsave()|. Should be called the same number of times inputsave() is called. Calling it more often is harmless though. - Returns 1 when there is nothing to restore, 0 otherwise. + Returns TRUE when there is nothing to restore, FALSE otherwise. inputsave() *inputsave()* Preserve typeahead (also from mappings) and clear it, so that @@ -6569,7 +6570,7 @@ inputsave() *inputsave()* followed by a matching inputrestore() after the prompt. Can be used several times, in which case there must be just as many inputrestore() calls. - Returns 1 when out of memory, 0 otherwise. + Returns TRUE when out of memory, FALSE otherwise. inputsecret({prompt} [, {text}]) *inputsecret()* This function acts much like the |input()| function with but @@ -7045,7 +7046,7 @@ listener_flush([{buf}]) *listener_flush()* listener_remove({id}) *listener_remove()* Remove a listener previously added with listener_add(). - Returns zero when {id} could not be found, one when {id} was + Returns FALSE when {id} could not be found, TRUE when {id} was removed. Can also be used as a |method|: > @@ -7728,8 +7729,8 @@ mkdir({name} [, {path} [, {prot}]]) flag is passed (since patch 8.0.1708). However, without the "p" option the call will fail. - The function result is a Number, which is 1 if the call was - successful or 0 if the directory creation failed or partly + The function result is a Number, which is TRUE if the call was + successful or FALSE if the directory creation failed or partly failed. Not available on all systems. To check use: > @@ -9205,6 +9206,7 @@ server2client({clientid}, {string}) *server2client()* Send a reply string to {clientid}. The most recent {clientid} that sent a string can be retrieved with expand(""). {only available when compiled with the |+clientserver| feature} + Returns zero for success, -1 for failure. Note: This id has to be stored before the next command can be received. I.e. before returning from the received command and @@ -9342,8 +9344,8 @@ setcmdpos({pos}) *setcmdpos()* before inserting the resulting text. When the number is too big the cursor is put at the end of the line. A number smaller than one has undefined results. - Returns 0 when successful, 1 when not editing the command - line. + Returns FALSE when successful, TRUE when not editing the + command line. Can also be used as a |method|: > GetPos()->setcmdpos() @@ -9402,8 +9404,8 @@ setline({lnum}, {text}) *setline()* When {lnum} is just below the last line the {text} will be added below the last line. - If this succeeds, 0 is returned. If this fails (most likely - because {lnum} is invalid) 1 is returned. + If this succeeds, FALSE is returned. If this fails (most likely + because {lnum} is invalid) TRUE is returned. Example: > :call setline(5, strftime("%c")) @@ -11378,7 +11380,7 @@ win_gettype([{nr}]) *win_gettype()* win_gotoid({expr}) *win_gotoid()* Go to window with ID {expr}. This may also change the current tabpage. - Return 1 if successful, 0 if the window cannot be found. + Return TRUE if successful, FALSE if the window cannot be found. Can also be used as a |method|: > GetWinid()->win_gotoid() diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index 19720e1841..d3a4bde8b0 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -147,6 +147,7 @@ can be used to overrule the filetype used for certain extensions: *.w g:filetype_w |ft-cweb-syntax| *.i g:filetype_i |ft-progress-syntax| *.p g:filetype_p |ft-pascal-syntax| + *.pp g:filetype_pp |ft-pascal-syntax| *.sh g:bash_is_sh |ft-sh-syntax| *.tex g:tex_flavor |ft-tex-plugin| diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index aec4ca04af..e5d29ad20b 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -1,4 +1,4 @@ -*index.txt* For Vim version 8.2. Last change: 2020 Oct 05 +*index.txt* For Vim version 8.2. Last change: 2021 Jan 15 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 2963193a00..8b655dc600 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3273,7 +3273,7 @@ A jump table for the options with a short description can be found at |Q_op|. See the 'endofline' option. *'fkmap'* *'fk'* *'nofkmap'* *'nofk'* -'fkmap' 'fk' boolean (default off) *E198* +'fkmap' 'fk' boolean (default off) global {only available when compiled with the |+rightleft| feature} @@ -5221,7 +5221,7 @@ A jump table for the options with a short description can be found at |Q_op|. NOTE: This option is set to the Vi default value when 'compatible' is set and to the Vim default value when 'compatible' is reset. - *'mouse'* *E538* + *'mouse'* 'mouse' string (default "", "a" for GUI and Win32, set to "a" or "nvi" in |defaults.vim|) global diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt index 54302a95d8..005b57f0d0 100644 --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -588,8 +588,6 @@ properties. It is in one of four forms: If you want to create a new buffer yourself use |bufadd()| and pass the buffer number to popup_create(). -It is not possible to use the buffer of a terminal window. *E278* You CAN -create a hidden terminal buffer and use that one in a popup window. The second argument of |popup_create()| is a dictionary with options: line Screen line where to position the popup. Can use a diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index c171a20acf..a2a12b0cf0 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -2335,11 +2335,12 @@ http://papp.plan9.de. PASCAL *pascal.vim* *ft-pascal-syntax* -Files matching "*.p" could be Progress or Pascal. If the automatic detection -doesn't work for you, or you don't edit Progress at all, use this in your -startup vimrc: > +Files matching "*.p" could be Progress or Pascal and those matching "*.pp" +could be Puppet or Pascal. If the automatic detection doesn't work for you, +or you only edit Pascal files, use this in your startup vimrc: > - :let filetype_p = "pascal" + :let filetype_p = "pascal" + :let filetype_pp = "pascal" The Pascal syntax file has been extended to take into account some extensions provided by Turbo Pascal, Free Pascal Compiler and GNU Pascal Compiler. diff --git a/runtime/doc/tags b/runtime/doc/tags index 1b36eb2984..24cdded5aa 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -1045,6 +1045,8 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX* 't_da' term.txt /*'t_da'* 't_db' term.txt /*'t_db'* 't_dl' term.txt /*'t_dl'* +'t_fd' term.txt /*'t_fd'* +'t_fe' term.txt /*'t_fe'* 't_fs' term.txt /*'t_fs'* 't_k1' term.txt /*'t_k1'* 't_k2' term.txt /*'t_k2'* @@ -3112,9 +3114,11 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX* :sip change.txt /*:sip* :sir change.txt /*:sir* :sl various.txt /*:sl* +:sl! various.txt /*:sl!* :sla windows.txt /*:sla* :slast windows.txt /*:slast* :sleep various.txt /*:sleep* +:sleep! various.txt /*:sleep!* :sm change.txt /*:sm* :smagic change.txt /*:smagic* :smap map.txt /*:smap* @@ -4028,7 +4032,6 @@ E194 message.txt /*E194* E195 starting.txt /*E195* E196 various.txt /*E196* E197 mlang.txt /*E197* -E198 options.txt /*E198* E199 cmdline.txt /*E199* E20 motion.txt /*E20* E200 autocmd.txt /*E200* @@ -4114,7 +4117,6 @@ E274 eval.txt /*E274* E275 textprop.txt /*E275* E276 eval.txt /*E276* E277 remote.txt /*E277* -E278 popup.txt /*E278* E279 terminal.txt /*E279* E28 syntax.txt /*E28* E280 if_tcl.txt /*E280* @@ -4180,7 +4182,6 @@ E337 gui.txt /*E337* E338 editing.txt /*E338* E339 message.txt /*E339* E34 various.txt /*E34* -E340 vi_diff.txt /*E340* E341 message.txt /*E341* E342 message.txt /*E342* E343 options.txt /*E343* @@ -4388,7 +4389,6 @@ E534 options.txt /*E534* E535 options.txt /*E535* E536 options.txt /*E536* E537 options.txt /*E537* -E538 options.txt /*E538* E539 options.txt /*E539* E54 pattern.txt /*E54* E540 options.txt /*E540* @@ -6351,6 +6351,7 @@ expression-commands eval.txt /*expression-commands* expression-syntax eval.txt /*expression-syntax* exrc starting.txt /*exrc* extend() eval.txt /*extend()* +extendnew() eval.txt /*extendnew()* extension-removal cmdline.txt /*extension-removal* extensions-improvements todo.txt /*extensions-improvements* f motion.txt /*f* @@ -8680,6 +8681,7 @@ read-in-close-cb channel.txt /*read-in-close-cb* read-messages insert.txt /*read-messages* read-only-share editing.txt /*read-only-share* read-stdin version5.txt /*read-stdin* +readblob() eval.txt /*readblob()* readdir() eval.txt /*readdir()* readdirex() eval.txt /*readdirex()* readfile() eval.txt /*readfile()* @@ -8945,6 +8947,7 @@ sinh() eval.txt /*sinh()* skeleton autocmd.txt /*skeleton* skip_defaults_vim starting.txt /*skip_defaults_vim* slice eval.txt /*slice* +slice() eval.txt /*slice()* slow-fast-terminal term.txt /*slow-fast-terminal* slow-start starting.txt /*slow-start* slow-terminal term.txt /*slow-terminal* @@ -9340,6 +9343,8 @@ t_f6 version4.txt /*t_f6* t_f7 version4.txt /*t_f7* t_f8 version4.txt /*t_f8* t_f9 version4.txt /*t_f9* +t_fd term.txt /*t_fd* +t_fe term.txt /*t_fe* t_float-variable eval.txt /*t_float-variable* t_fs term.txt /*t_fs* t_func-variable eval.txt /*t_func-variable* @@ -9714,6 +9719,7 @@ type-inference vim9.txt /*type-inference* type-mistakes tips.txt /*type-mistakes* typecorr-settings usr_41.txt /*typecorr-settings* typecorr.txt usr_41.txt /*typecorr.txt* +typename() eval.txt /*typename()* u undo.txt /*u* uganda uganda.txt /*uganda* uganda.txt uganda.txt /*uganda.txt* @@ -10314,6 +10320,7 @@ xterm-command-server term.txt /*xterm-command-server* xterm-copy-paste term.txt /*xterm-copy-paste* xterm-cursor-keys term.txt /*xterm-cursor-keys* xterm-end-home-keys term.txt /*xterm-end-home-keys* +xterm-focus-event term.txt /*xterm-focus-event* xterm-function-keys term.txt /*xterm-function-keys* xterm-modifier-keys term.txt /*xterm-modifier-keys* xterm-mouse options.txt /*xterm-mouse* diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt index 0456a8b89b..8eea4a59e7 100644 --- a/runtime/doc/term.txt +++ b/runtime/doc/term.txt @@ -1,4 +1,4 @@ -*term.txt* For Vim version 8.2. Last change: 2020 Dec 29 +*term.txt* For Vim version 8.2. Last change: 2021 Jan 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -373,9 +373,9 @@ Added by Vim (there are no standard codes for these): t_Ri restore icon text from stack *t_Ri* *'t_Ri'* t_TE end of "raw" mode *t_TE* *'t_TE'* t_TI put terminal into "raw" mode *t_TI* *'t_TI'* - t_fd disable focus-event tracking *t_TI* *'t_TI'* + t_fd disable focus-event tracking *t_fd* *'t_fd'* |xterm-focus-event| - t_fe enable focus-event tracking *t_TI* *'t_TI'* + t_fe enable focus-event tracking *t_fe* *'t_fe'* |xterm-focus-event| Some codes have a start, middle and end part. The start and end are defined diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 6e5fe4cc09..75133f78bc 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 Jan 11 +*todo.txt* For Vim version 8.2. Last change: 2021 Jan 17 VIM REFERENCE MANUAL by Bram Moolenaar @@ -38,15 +38,7 @@ browser use: https://github.com/vim/vim/issues/1234 *known-bugs* -------------------- Known bugs and current work ----------------------- -no error for: - echo extend([0], ['a', true]) -like it does for: - echo extend([0], ['a']) -At script level this does not give an error: - echo map([0], (_, v) => []) -Or: - var l: list = [0] - echo map(l, (_, v) => []) +test_autocmd failure in Windows: Something wrong with system()? Vim9 - Make everything work: - Expand `=expr` in :next, :argedit, :argadd, :argdelete, :drop @@ -117,6 +109,8 @@ Vim9 - Make everything work: - compile "skip" argument of searchpair() - compile "expr" and "call" expression of a channel in channel_exe_cmd()? - 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 Once Vim9 is stable: - Change the help to prefer Vim9 syntax where appropriate @@ -287,6 +281,9 @@ Have another look at the implementation. Patch to implement the vimtutor with a plugin: #6414 Was originally written by Felipe Morales. +Adding "10" to 'spellsuggest' causes spell suggestions to become very slow. +(#4087) + Patch to find Python dll using registry key. (#7540) Remove SPACE_IN_FILENAME ? It is only used for completion. @@ -479,9 +476,6 @@ Help for ":argadd fname" says that if "fname" is already in the argument list that entry is used. But instead it's always added. (#6210) Add flag AL_FIND_ADD, if there is one argument find it in the list. -Adding "10" to 'spellsuggest' causes spell suggestions to become very slow. -(#4087) - behavior of i_CTRl-R_CTRL-R differs from documentation. (Paul Desmond Parker, #5771) @@ -556,14 +550,6 @@ when "qq" is mapped and after the first "q" the mouse is moved outside of the gvim window (with focus follows mouse), then the K_FOCUSLOST key is put in the input buffer. (#5302) -xterm should be able to pass focus changes to Vim, so that Vim can check for -buffers that changed. Perhaps in misc.c, function selectwindow(). -Xterm 224 supports it! -Patch to make FocusGained and FocusLost work in modern terminals. (Hayaki -Saito, 2013 Apr 24) Update 2016 Aug 12. -Also see issue #609. -We could add the enable/disable sequences to t_ti/t_te or t_ks/t_ke. - :buffer completion does not escape "+" properly and results in a regexp error. (#5467) diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 5d4686ae04..965a97732d 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1,4 +1,4 @@ -*usr_41.txt* For Vim version 8.2. Last change: 2021 Jan 08 +*usr_41.txt* For Vim version 8.2. Last change: 2021 Jan 13 VIM USER MANUAL - by Bram Moolenaar diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index c116d69f2c..729cde334c 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -1,4 +1,4 @@ -*various.txt* For Vim version 8.2. Last change: 2020 Nov 16 +*various.txt* For Vim version 8.2. Last change: 2021 Jan 16 VIM REFERENCE MANUAL by Bram Moolenaar @@ -411,7 +411,7 @@ N *+mouse_sysmouse* Unix only: *BSD console mouse handling |sysmouse| B *+mouse_sgr* Unix only: sgr mouse handling |sgr-mouse| B *+mouse_urxvt* Unix only: urxvt mouse handling |urxvt-mouse| N *+mouse_xterm* Unix only: xterm mouse handling |xterm-mouse| -N *+multi_byte* 16 and 32 bit characters |multibyte| +T *+multi_byte* Unicode support, 16 and 32 bit characters |multibyte| *+multi_byte_ime* Win32 input method for multibyte chars |multibyte-ime| N *+multi_lang* non-English language support |multi-lang| m *+mzscheme* Mzscheme interface |mzscheme| @@ -722,6 +722,9 @@ K Run a program to lookup the keyword under the available when compiled with the |+netbeans_intg| feature} + *:sl!* *:sleep!* +:[N]sl[eep]! [N] [m] Same as above, but hide the cursor + *:xrestore* *:xr* :xr[estore] [display] Reinitializes the connection to the X11 server. Useful after the X server restarts, e.g. when running Vim for diff --git a/runtime/doc/version6.txt b/runtime/doc/version6.txt index 82405e7f5f..6b9f1d9343 100644 --- a/runtime/doc/version6.txt +++ b/runtime/doc/version6.txt @@ -9661,7 +9661,7 @@ Solution: Check for tcsetattr() to return an error, retry when it does. Files: src/os_unix.c Patch 6.2f.018 -Problem: Mac OS X 10.2: OK is defined to zero in cursus.h while Vim uses +Problem: Mac OS X 10.2: OK is defined to zero in curses.h while Vim uses one. Redefining it causes a warning message. Solution: Undefine OK before defining it to one. (Taro Muraoka) Files: src/vim.h diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt index c7c7f7e38c..0fb29e4946 100644 --- a/runtime/doc/vi_diff.txt +++ b/runtime/doc/vi_diff.txt @@ -73,7 +73,7 @@ edit the termcap entry and try again. Vim has the |terminal-options|. Vim has only a few limits for the files that can be edited {Vi: can not handle characters and characters above 128, has limited line length, many other limits}. - *E340* + Maximum line length 2147483647 characters. Longer lines are split. Maximum number of lines 2147483647 lines. Maximum file size 2147483647 bytes (2 Gbyte) when a long integer is diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index a7b91db0a4..93c3ddd2f9 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 Jan 10 +*vim9.txt* For Vim version 8.2. Last change: 2021 Jan 15 VIM REFERENCE MANUAL by Bram Moolenaar @@ -487,6 +487,9 @@ Now "exit_cb: Func})" is actually a valid command: save any changes to the file "_cb: Func})" and exit. To avoid this kind of mistake in Vim9 script there must be white space between most command names and the argument. +However, the argument of a command that is a command won't be recognized. For +example, after "windo echo expr" a line break inside "expr" will not be seen. + Notes: - "enddef" cannot be used at the start of a continuation line, it ends the @@ -527,17 +530,17 @@ that using a literal key is much more common than using an expression, and considering that JavaScript uses this syntax, using the {} form for dictionary literals is considered a much more useful syntax. In Vim9 script the {} form uses literal keys: > - let dict = {key: value} + var dict = {key: value} This works for alphanumeric characters, underscore and dash. If you want to use another character, use a single or double quoted string: > - let dict = {'key with space': value} - let dict = {"key\twith\ttabs": value} - let dict = {'': value} # empty key + var dict = {'key with space': value} + var dict = {"key\twith\ttabs": value} + var dict = {'': value} # empty key In case the key needs to be an expression, square brackets can be used, just like in JavaScript: > - let dict = {["key" .. nr]: value} + var dict = {["key" .. nr]: value} No :xit, :t, :append, :change or :insert ~ @@ -552,6 +555,29 @@ Comparators ~ The 'ignorecase' option is not used for comparators that use strings. +For loop ~ + +Legacy Vim script has some tricks to make a for loop over a list handle +deleting items at the current or previous item. In Vim9 script it just uses +the index, if items are deleted then items in the list will be skipped. +Example legacy script: > + let l = [1, 2, 3, 4] + for i in l + echo i + call remove(l, index(l, i)) + endfor +Would echo: + 1 + 2 + 3 + 4 +In compiled Vim9 script you get: + 1 + 3 +Generally, you should not change the list that is iterated over. Make a copy +first if needed. + + White space ~ Vim9 script enforces proper use of white space. This is no longer allowed: > @@ -576,15 +602,17 @@ the start and end: > White space is not allowed: - Between a function name and the "(": > - call Func (arg) # Error! - call Func + Func (arg) # Error! + Func \ (arg) # Error! - call Func(arg) # OK - call Func( - \ arg) # OK - call Func( - \ arg # OK - \ ) + Func + (arg) # Error! + Func(arg) # OK + Func( + arg) # OK + Func( + arg # OK + ) Conditions and expressions ~ @@ -648,12 +676,13 @@ 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 +Indexing a string with [idx] or [idx : idx] uses character indexes instead of byte indexes. 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 'á'. A negative index is counting from the end, "[-1]" is the last character. +To exclude the last character use |slice()|. If the index is out of range then an empty string results. In legacy script "++var" and "--var" would be silently accepted and have no @@ -670,21 +699,22 @@ same time tries to support the legacy Vim commands. Some compromises had to be made. Here is a summary of what might be unexpected. Ex command ranges need to be prefixed with a colon. > - -> # legacy Vim: shifts the previous line to the right - ->func() # Vim9: method call in continuation line - :-> # Vim9: shifts the previous line to the right + -> legacy Vim: shifts the previous line to the right + ->func() Vim9: method call in a continuation line + :-> Vim9: shifts the previous line to the right - %s/a/b # legacy Vim: substitute on all lines + %s/a/b legacy Vim: substitute on all lines x = alongname - % another # Vim9: line continuation without a backslash - :%s/a/b # Vim9: substitute on all lines - 'text'->func() # Vim9: method call - :'t # legacy Vim: jump to mark m + % another Vim9: modulo operator in a continuation line + :%s/a/b Vim9: substitute on all lines + 't legacy Vim: jump to mark t + 'text'->func() Vim9: method call + :'t Vim9: jump to mark t Some Ex commands can be confused with assignments in Vim9 script: > - g:name = value # assignment - g:pattern:cmd # invalid command - ERROR - :g:pattern:cmd # :global command + g:name = value # assignment + g:pattern:cmd # invalid command - ERROR + :g:pattern:cmd # :global command Functions defined with `:def` compile the whole function. Legacy functions can bail out, and the following lines are not parsed: > @@ -704,7 +734,7 @@ Vim9 functions are compiled as a whole: > For a workaround, split it in two functions: > func Maybe() if has('feature') - call MaybyInner() + call MaybeInner() endif endfunc if has('feature') @@ -720,7 +750,7 @@ evaluates to false: > endif enddef < *vim9-user-command* -Another side effect of compiling a function is that the precense of a user +Another side effect of compiling a function is that the presence of a user command is checked at compile time. If the user command is defined later an error will result. This works: > command -nargs=1 MyCommand echom @@ -1090,7 +1120,7 @@ actually needed. A recommended mechanism: 1. In the plugin define user commands, functions and/or mappings that refer to an autoload script. > - command -nargs=1 SearchForStuff call searchfor#Stuff() + command -nargs=1 SearchForStuff searchfor#Stuff() < This goes in .../plugin/anyname.vim. "anyname.vim" can be freely chosen. @@ -1183,12 +1213,12 @@ When compiling lines of Vim commands into instructions as much as possible should be done at compile time. Postponing it to runtime makes the execution slower and means mistakes are found only later. For example, when encountering the "+" character and compiling this into a generic add -instruction, at execution time the instruction would have to inspect the type -of the arguments and decide what kind of addition to do. And when the -type is dictionary throw an error. If the types are known to be numbers then -an "add number" instruction can be used, which is faster. The error can be -given at compile time, no error handling is needed at runtime, since adding -two numbers cannot fail. +instruction, at runtime the instruction would have to inspect the type of the +arguments and decide what kind of addition to do. And when the type is +dictionary throw an error. If the types are known to be numbers then an "add +number" instruction can be used, which is faster. The error can be given at +compile time, no error handling is needed at runtime, since adding two numbers +cannot fail. The syntax for types, using for compound types, is similar to Java. It is easy to understand and widely used. The type names are what were used in diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index 3307de5410..6adadbda94 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Vim " Maintainer: Bram Moolenaar -" Last Change: 2021 Jan 05 +" Last Change: 2021 Jan 12 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -51,12 +51,12 @@ setlocal keywordprg=:help if "\n" .. getline(1, 10)->join("\n") =~# '\n\s*vim9\%[script]\>' " Set 'comments' to format dashed lists in comments setlocal com=sO:#\ -,mO:#\ \ ,eO:##,:# - " Comments start with a double quote in a legacy script; - " with # in a Vim9 script - setlocal commentstring=\"%s + " Comments starts with # in Vim9 script + setlocal commentstring=#%s else setlocal com=sO:\"\ -,mO:\"\ \ ,:\" - setlocal commentstring=#%s + " Comments starts with a double quote in legacy script + setlocal commentstring=\"%s endif diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim index 7925e88aa5..d07aaf2658 100644 --- a/runtime/syntax/c.vim +++ b/runtime/syntax/c.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: C " Maintainer: Bram Moolenaar -" Last Change: 2020 Aug 28 +" Last Change: 2021 Jan 11 " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") @@ -13,6 +13,9 @@ set cpo&vim let s:ft = matchstr(&ft, '^\([^.]\)\+') +" check if this was included from cpp.vim +let s:in_cpp_family = exists("b:filetype_in_cpp_family") + " Optional embedded Autodoc parsing " To enable it add: let g:c_autodoc = 1 " to your .vimrc @@ -55,7 +58,7 @@ if !exists("c_no_cformat") endif " cCppString: same as cString, but ends at end of line -if s:ft ==# "cpp" && !exists("cpp_no_cpp11") && !exists("c_no_cformat") +if s:in_cpp_family && !exists("cpp_no_cpp11") && !exists("c_no_cformat") " ISO C++11 syn region cString start=+\(L\|u\|u8\|U\|R\|LR\|u8R\|uR\|UR\)\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell extend syn region cCppString start=+\(L\|u\|u8\|U\|R\|LR\|u8R\|uR\|UR\)\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat,@Spell @@ -87,7 +90,7 @@ syn match cSpecialCharacter display "L\='\\\o\{1,3}'" syn match cSpecialCharacter display "'\\x\x\{1,2}'" syn match cSpecialCharacter display "L'\\x\x\+'" -if (s:ft ==# "c" && !exists("c_no_c11")) || (s:ft ==# "cpp" && !exists("cpp_no_cpp11")) +if (s:ft ==# "c" && !exists("c_no_c11")) || (s:in_cpp_family && !exists("cpp_no_cpp11")) " ISO C11 or ISO C++ 11 if exists("c_no_cformat") syn region cString start=+\%(U\|u8\=\)"+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,@Spell extend @@ -130,7 +133,7 @@ endif " But avoid matching <::. syn cluster cParenGroup contains=cParenError,cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserLabel,cBitField,cOctalZero,@cCppOutInGroup,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom if exists("c_no_curly_error") - if s:ft ==# 'cpp' && !exists("cpp_no_cpp11") + if s:in_cpp_family && !exists("cpp_no_cpp11") syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,@cStringGroup,@Spell " cCppParen: same as cParen but ends at end-of-line; used in cDefine syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell @@ -144,7 +147,7 @@ if exists("c_no_curly_error") syn match cErrInParen display contained "^[{}]\|^<%\|^%>" endif elseif exists("c_no_bracket_error") - if s:ft ==# 'cpp' && !exists("cpp_no_cpp11") + if s:in_cpp_family && !exists("cpp_no_cpp11") syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,@cStringGroup,@Spell " cCppParen: same as cParen but ends at end-of-line; used in cDefine syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell @@ -158,7 +161,7 @@ elseif exists("c_no_bracket_error") syn match cErrInParen display contained "[{}]\|<%\|%>" endif else - if s:ft ==# 'cpp' && !exists("cpp_no_cpp11") + if s:in_cpp_family && !exists("cpp_no_cpp11") syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cErrInBracket,cCppBracket,@cStringGroup,@Spell " cCppParen: same as cParen but ends at end-of-line; used in cDefine syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cErrInBracket,cParen,cBracket,cString,@Spell @@ -278,7 +281,7 @@ syn keyword cStorageClass static register auto volatile extern const if exists("c_gnu") syn keyword cStorageClass inline __attribute__ endif -if !exists("c_no_c99") && s:ft !=# 'cpp' +if !exists("c_no_c99") && !s:in_cpp_family syn keyword cStorageClass inline restrict endif if !exists("c_no_c11") @@ -420,7 +423,7 @@ endif syn cluster cLabelGroup contains=cUserLabel syn match cUserCont display "^\s*\zs\I\i*\s*:$" contains=@cLabelGroup syn match cUserCont display ";\s*\zs\I\i*\s*:$" contains=@cLabelGroup -if s:ft ==# 'cpp' +if s:in_cpp_family syn match cUserCont display "^\s*\zs\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup syn match cUserCont display ";\s*\zs\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup else diff --git a/runtime/syntax/cpp.vim b/runtime/syntax/cpp.vim index 53b6a513f2..ed38913f29 100644 --- a/runtime/syntax/cpp.vim +++ b/runtime/syntax/cpp.vim @@ -2,13 +2,16 @@ " Language: C++ " Current Maintainer: vim-jp (https://github.com/vim-jp/vim-cpp) " Previous Maintainer: Ken Shan -" Last Change: 2019 Dec 18 +" Last Change: 2021 Jan 12 " quit when a syntax file was already loaded if exists("b:current_syntax") finish endif +" inform C syntax that the file was included from cpp.vim +let b:filetype_in_cpp_family = 1 + " Read the C syntax to start with runtime! syntax/c.vim unlet b:current_syntax From 09fbedc8dc3adc0a7adf2093916911e633cfa626 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 19 Jan 2021 17:22:58 +0100 Subject: [PATCH 10/47] patch 8.2.2375: test for RGB color skipped in the terminal Problem: Test for RGB color skipped in the terminal. Solution: Run the GUI if possible. --- src/testdir/test_highlight.vim | 5 +++-- src/version.c | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim index 8bd03e2da1..a4c7a72591 100644 --- a/src/testdir/test_highlight.vim +++ b/src/testdir/test_highlight.vim @@ -781,8 +781,9 @@ func Test_highlight_User() endfunc " Test for using RGB color values in a highlight group -func Test_highlight_RGB_color() - CheckGui +func Test_xxlast_highlight_RGB_color() + CheckCanRunGui + gui -f hi MySearch guifg=#110000 guibg=#001100 guisp=#000011 call assert_equal('#110000', synIDattr(synIDtrans(hlID('MySearch')), 'fg#')) call assert_equal('#001100', synIDattr(synIDtrans(hlID('MySearch')), 'bg#')) diff --git a/src/version.c b/src/version.c index 98f120b2e2..452fa2d22f 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 */ +/**/ + 2375, /**/ 2374, /**/ From e64f83cc6aba05baa61ba4a4cb8d4447b8091e5b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 19 Jan 2021 22:16:41 +0100 Subject: [PATCH 11/47] patch 8.2.2376: Vim9: crash when dividing by zero in compiled code Problem: Vim9: crash when dividing by zero in compiled code using constants. Solution: Call num_divide() and num_modulus(). (closes #7704) --- src/testdir/test_vim9_expr.vim | 2 ++ src/version.c | 2 ++ src/vim9compile.c | 6 ++++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index a45d0eae6e..c81468cb36 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1376,6 +1376,7 @@ def Test_expr6() assert_equal(1, g:anint / 6) assert_equal(2, g:anint / g:thefour) + assert_true(1 / 0 > 99999) assert_equal(5, 11 % 6) assert_equal(4, g:anint % 6) @@ -1383,6 +1384,7 @@ def Test_expr6() g:anint) assert_equal(2, g:anint % g:thefour) + assert_equal(0, 1 % 0) assert_equal(4, 6 * 4 / 6) diff --git a/src/version.c b/src/version.c index 452fa2d22f..b809cb2b7e 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 */ +/**/ + 2376, /**/ 2375, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index d1df00821c..36fd2534c3 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4300,9 +4300,11 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) { case '*': res = tv1->vval.v_number * tv2->vval.v_number; break; - case '/': res = tv1->vval.v_number / tv2->vval.v_number; + case '/': res = num_divide(tv1->vval.v_number, + tv2->vval.v_number); break; - case '%': res = tv1->vval.v_number % tv2->vval.v_number; + case '%': res = num_modulus(tv1->vval.v_number, + tv2->vval.v_number); break; } tv1->vval.v_number = res; From a28639e71198238d5c09c43445dc448d7f3fb29b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 19 Jan 2021 22:48:09 +0100 Subject: [PATCH 12/47] patch 8.2.2377: Vim9: crash when using a range after another expression Problem: Vim9: crash when using a range after another expression. Solution: Set the variable type to number. Fix using :put with a range and the "=" register. (closes #7706) --- src/testdir/test_vim9_cmd.vim | 4 ++++ src/version.c | 2 ++ src/vim9execute.c | 36 +++++++++++++++++++---------------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 098cded98a..12b9bf191b 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -750,6 +750,10 @@ def Test_put_command() :+2put! a assert_equal('aaa', getline(4)) + []->mapnew(() => 0) + :$put ='end' + assert_equal('end', getline('$')) + bwipe! CheckDefFailure(['put =xxx'], 'E1001:') diff --git a/src/version.c b/src/version.c index b809cb2b7e..57b1a0c474 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 */ +/**/ + 2377, /**/ 2376, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index fdc49eb05d..907a52f18f 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -3326,10 +3326,6 @@ call_def_function( exarg_T ea; char *errormsg; - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; - ++ectx.ec_stack.ga_len; - tv = STACK_TV_BOT(-1); ea.line2 = 0; ea.addr_count = 0; ea.addr_type = ADDR_LINES; @@ -3337,6 +3333,13 @@ call_def_function( ea.skip = FALSE; if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL) goto on_error; + + if (GA_GROW(&ectx.ec_stack, 1) == FAIL) + goto failed; + ++ectx.ec_stack.ga_len; + tv = STACK_TV_BOT(-1); + tv->v_type = VAR_NUMBER; + tv->v_lock = 0; if (ea.addr_count == 0) tv->vval.v_number = curwin->w_cursor.lnum; else @@ -3351,18 +3354,6 @@ call_def_function( char_u *expr = NULL; int dir = FORWARD; - if (regname == '=') - { - tv = STACK_TV_BOT(-1); - if (tv->v_type == VAR_STRING) - expr = tv->vval.v_string; - else - { - expr = typval2string(tv, TRUE); // allocates value - clear_tv(tv); - } - --ectx.ec_stack.ga_len; - } if (lnum < -2) { // line number was put on the stack by ISN_RANGE @@ -3377,6 +3368,19 @@ call_def_function( dir = BACKWARD; else if (lnum >= 0) curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum; + + if (regname == '=') + { + tv = STACK_TV_BOT(-1); + if (tv->v_type == VAR_STRING) + expr = tv->vval.v_string; + else + { + expr = typval2string(tv, TRUE); // allocates value + clear_tv(tv); + } + --ectx.ec_stack.ga_len; + } check_cursor(); do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE); vim_free(expr); From 99880f96cf444014d589fc1d99bb164deaba71ce Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 20 Jan 2021 21:23:14 +0100 Subject: [PATCH 13/47] patch 8.2.2378: Vim9: no error message for dividing by zero Problem: Vim9: no error message for dividing by zero. Solution: Give an error message. (issue #7704) --- src/errors.h | 2 ++ src/eval.c | 7 +++++-- src/testdir/test_vim9_expr.vim | 5 +++-- src/version.c | 2 ++ src/vim9execute.c | 10 ++++++++-- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/errors.h b/src/errors.h index eb5ee1de2e..4bd4efea69 100644 --- a/src/errors.h +++ b/src/errors.h @@ -343,3 +343,5 @@ EXTERN char e_mismatched_enddef[] INIT(= N_("E1152: Mismatched enddef")); EXTERN char e_invalid_operation_for_bool[] INIT(= N_("E1153: Invalid operation for bool")); +EXTERN char e_divide_by_zero[] + INIT(= N_("E1154: Divide by zero")); diff --git a/src/eval.c b/src/eval.c index 13ee49aac4..40c6feb706 100644 --- a/src/eval.c +++ b/src/eval.c @@ -63,8 +63,10 @@ num_divide(varnumber_T n1, varnumber_T n2) { varnumber_T result; - if (n2 == 0) // give an error message? + if (n2 == 0) { + if (in_vim9script()) + emsg(_(e_divide_by_zero)); if (n1 == 0) result = VARNUM_MIN; // similar to NaN else if (n1 < 0) @@ -84,7 +86,8 @@ num_divide(varnumber_T n1, varnumber_T n2) varnumber_T num_modulus(varnumber_T n1, varnumber_T n2) { - // Give an error when n2 is 0? + if (n2 == 0 && in_vim9script()) + emsg(_(e_divide_by_zero)); return (n2 == 0) ? 0 : (n1 % n2); } diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index c81468cb36..2239e76df9 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1376,7 +1376,6 @@ def Test_expr6() assert_equal(1, g:anint / 6) assert_equal(2, g:anint / g:thefour) - assert_true(1 / 0 > 99999) assert_equal(5, 11 % 6) assert_equal(4, g:anint % 6) @@ -1384,7 +1383,6 @@ def Test_expr6() g:anint) assert_equal(2, g:anint % g:thefour) - assert_equal(0, 1 % 0) assert_equal(4, 6 * 4 / 6) @@ -1405,6 +1403,9 @@ def Test_expr6() CheckDefFailure(["var x = 6 * xxx"], 'E1001:', 1) CheckDefFailure(["var d = 6 * "], 'E1097:', 3) + + CheckDefExecAndScriptFailure(['echo 1 / 0'], 'E1154', 1) + CheckDefExecAndScriptFailure(['echo 1 % 0'], 'E1154', 1) enddef def Test_expr6_vim9script() diff --git a/src/version.c b/src/version.c index 57b1a0c474..5668f75546 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 */ +/**/ + 2378, /**/ 2377, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 907a52f18f..b1bc282636 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2954,10 +2954,16 @@ call_def_function( switch (iptr->isn_arg.op.op_type) { case EXPR_MULT: n1 = n1 * n2; break; - case EXPR_DIV: n1 = num_divide(n1, n2); break; + case EXPR_DIV: n1 = num_divide(n1, n2); + if (n2 == 0) + goto on_error; + break; case EXPR_SUB: n1 = n1 - n2; break; case EXPR_ADD: n1 = n1 + n2; break; - default: n1 = num_modulus(n1, n2); break; + default: n1 = num_modulus(n1, n2); + if (n2 == 0) + goto on_error; + break; } clear_tv(tv1); clear_tv(tv2); From 77a849c4b3d73c228013a047913c90834a93b4f6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 20 Jan 2021 21:42:33 +0100 Subject: [PATCH 14/47] patch 8.2.2379: do spell suggestions twice if 'spellsuggest' contains number Problem: Finding spell suggestions twice if 'spellsuggest' contains number. Solution: Only do internal suggestions once. (closes #7713) --- src/spellsuggest.c | 6 ++++-- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/spellsuggest.c b/src/spellsuggest.c index e2423cd98a..3de9ff2112 100644 --- a/src/spellsuggest.c +++ b/src/spellsuggest.c @@ -770,6 +770,7 @@ spell_find_suggest( int c; int i; langp_T *lp; + int did_intern = FALSE; // Set the info in "*su". CLEAR_POINTER(su); @@ -863,12 +864,13 @@ spell_find_suggest( else if (STRNCMP(buf, "file:", 5) == 0) // Use list of suggestions in a file. spell_suggest_file(su, buf + 5); - else + else if (!did_intern) { - // Use internal method. + // Use internal method once. spell_suggest_intern(su, interactive); if (sps_flags & SPS_DOUBLE) do_combine = TRUE; + did_intern = TRUE; } } diff --git a/src/version.c b/src/version.c index 5668f75546..2e67f32aee 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 */ +/**/ + 2379, /**/ 2378, /**/ From a0f7f73ebb3ab032af08699c24c465403512b7d8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 20 Jan 2021 22:22:49 +0100 Subject: [PATCH 15/47] patch 8.2.2380: Vim9: occasional crash when using try/catch and a timer Problem: Vim9: occasional crash when using try/catch and a timer. Solution: Save and restore "need_rethrow" when invoking a timer callback. (closes #7708) --- src/time.c | 3 +++ src/version.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/time.c b/src/time.c index d1cf21b6bc..c5ab693050 100644 --- a/src/time.c +++ b/src/time.c @@ -478,6 +478,7 @@ check_due_timer(void) int save_must_redraw = must_redraw; int save_trylevel = trylevel; int save_did_throw = did_throw; + int save_need_rethrow = need_rethrow; int save_ex_pressedreturn = get_pressedreturn(); int save_may_garbage_collect = may_garbage_collect; except_T *save_current_exception = current_exception; @@ -493,6 +494,7 @@ check_due_timer(void) must_redraw = 0; trylevel = 0; did_throw = FALSE; + need_rethrow = FALSE; current_exception = NULL; may_garbage_collect = FALSE; save_vimvars(&vvsave); @@ -513,6 +515,7 @@ check_due_timer(void) called_emsg = save_called_emsg; trylevel = save_trylevel; did_throw = save_did_throw; + need_rethrow = save_need_rethrow; current_exception = save_current_exception; restore_vimvars(&vvsave); if (must_redraw != 0) diff --git a/src/version.c b/src/version.c index 2e67f32aee..0e4a97b956 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 */ +/**/ + 2380, /**/ 2379, /**/ From c5f59fab23820454f060562927ddc1397f9d479a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 12:34:14 +0100 Subject: [PATCH 16/47] patch 8.2.2381: Vim9: divide by zero does not abort expression execution Problem: Vim9: divide by zero does not abort expression execution. Solution: Use a "failed" flag. (issue #7704) --- src/eval.c | 31 ++++++++++++++++++++++++------- src/evalvars.c | 6 ++++-- src/proto/eval.pro | 4 ++-- src/testdir/test_vim9_assign.vim | 24 ++++++++++++++++++++++++ src/testdir/vim9.vim | 13 +++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 13 ++++++++----- 7 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/eval.c b/src/eval.c index 40c6feb706..3e316bdb10 100644 --- a/src/eval.c +++ b/src/eval.c @@ -57,16 +57,21 @@ static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u * /* * Return "n1" divided by "n2", taking care of dividing by zero. + * If "failed" is not NULL set it to TRUE when dividing by zero fails. */ varnumber_T -num_divide(varnumber_T n1, varnumber_T n2) +num_divide(varnumber_T n1, varnumber_T n2, int *failed) { varnumber_T result; if (n2 == 0) { if (in_vim9script()) + { emsg(_(e_divide_by_zero)); + if (failed != NULL) + *failed = TRUE; + } if (n1 == 0) result = VARNUM_MIN; // similar to NaN else if (n1 < 0) @@ -82,12 +87,17 @@ num_divide(varnumber_T n1, varnumber_T n2) /* * Return "n1" modulus "n2", taking care of dividing by zero. + * If "failed" is not NULL set it to TRUE when dividing by zero fails. */ varnumber_T -num_modulus(varnumber_T n1, varnumber_T n2) +num_modulus(varnumber_T n1, varnumber_T n2, int *failed) { if (n2 == 0 && in_vim9script()) + { emsg(_(e_divide_by_zero)); + if (failed != NULL) + *failed = TRUE; + } return (n2 == 0) ? 0 : (n1 % n2); } @@ -1516,6 +1526,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op) varnumber_T n; char_u numbuf[NUMBUFLEN]; char_u *s; + int failed = FALSE; // Can't do anything with a Funcref, Dict, v:true on the right. if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT @@ -1599,8 +1610,10 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op) case '+': n += tv_get_number(tv2); break; case '-': n -= tv_get_number(tv2); break; case '*': n *= tv_get_number(tv2); break; - case '/': n = num_divide(n, tv_get_number(tv2)); break; - case '%': n = num_modulus(n, tv_get_number(tv2)); break; + case '/': n = num_divide(n, tv_get_number(tv2), + &failed); break; + case '%': n = num_modulus(n, tv_get_number(tv2), + &failed); break; } clear_tv(tv1); tv1->v_type = VAR_NUMBER; @@ -1619,7 +1632,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op) tv1->v_type = VAR_STRING; tv1->vval.v_string = s; } - return OK; + return failed ? FAIL : OK; case VAR_FLOAT: #ifdef FEAT_FLOAT @@ -3196,12 +3209,16 @@ eval6( else #endif { + int failed = FALSE; + if (op == '*') n1 = n1 * n2; else if (op == '/') - n1 = num_divide(n1, n2); + n1 = num_divide(n1, n2, &failed); else - n1 = num_modulus(n1, n2); + n1 = num_modulus(n1, n2, &failed); + if (failed) + return FAIL; rettv->v_type = VAR_NUMBER; rettv->vval.v_number = n1; diff --git a/src/evalvars.c b/src/evalvars.c index 200fb8f12c..1799531786 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1410,8 +1410,10 @@ ex_let_one( case '+': n = numval + n; break; case '-': n = numval - n; break; case '*': n = numval * n; break; - case '/': n = (long)num_divide(numval, n); break; - case '%': n = (long)num_modulus(numval, n); break; + case '/': n = (long)num_divide(numval, n, + &failed); break; + case '%': n = (long)num_modulus(numval, n, + &failed); break; } } else if (opt_type == gov_string diff --git a/src/proto/eval.pro b/src/proto/eval.pro index fbae530306..07b11b25a5 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -1,6 +1,6 @@ /* eval.c */ -varnumber_T num_divide(varnumber_T n1, varnumber_T n2); -varnumber_T num_modulus(varnumber_T n1, varnumber_T n2); +varnumber_T num_divide(varnumber_T n1, varnumber_T n2, int *failed); +varnumber_T num_modulus(varnumber_T n1, varnumber_T n2, int *failed); void eval_init(void); void eval_clear(void); void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip); diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 20bdb91380..992eeaa655 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -1489,6 +1489,30 @@ def Test_unlet() assert_equal('', $ENVVAR) enddef +def Test_expr_error_no_assign() + var lines =<< trim END + vim9script + var x = invalid + echo x + END + CheckScriptFailureList(lines, ['E121:', 'E121:']) + + lines =<< trim END + vim9script + var x = 1 / 0 + echo x + END + CheckScriptFailureList(lines, ['E1154:', 'E121:']) + + lines =<< trim END + vim9script + var x = 1 % 0 + echo x + END + CheckScriptFailureList(lines, ['E1154:', 'E121:']) +enddef + + def Test_assign_command_modifier() var lines =<< trim END var verbose = 0 diff --git a/src/testdir/vim9.vim b/src/testdir/vim9.vim index bb522df151..cc0510fe91 100644 --- a/src/testdir/vim9.vim +++ b/src/testdir/vim9.vim @@ -69,6 +69,19 @@ def CheckScriptFailure(lines: list, error: string, lnum = -3) endtry enddef +def CheckScriptFailureList(lines: list, errors: list, lnum = -3) + var cwd = getcwd() + var fname = 'XScriptFailure' .. s:sequence + s:sequence += 1 + writefile(lines, fname) + try + assert_fails('so ' .. fname, errors, lines, lnum) + finally + chdir(cwd) + delete(fname) + endtry +enddef + def CheckScriptSuccess(lines: list) var cwd = getcwd() var fname = 'XScriptSuccess' .. s:sequence diff --git a/src/version.c b/src/version.c index 0e4a97b956..c220a409ec 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 */ +/**/ + 2381, /**/ 2380, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 36fd2534c3..e972033f0b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4291,9 +4291,10 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER) { - typval_T *tv1 = &ppconst->pp_tv[ppconst_used]; - typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1]; - varnumber_T res = 0; + typval_T *tv1 = &ppconst->pp_tv[ppconst_used]; + typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1]; + varnumber_T res = 0; + int failed = FALSE; // both are numbers: compute the result switch (*op) @@ -4301,12 +4302,14 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) case '*': res = tv1->vval.v_number * tv2->vval.v_number; break; case '/': res = num_divide(tv1->vval.v_number, - tv2->vval.v_number); + tv2->vval.v_number, &failed); break; case '%': res = num_modulus(tv1->vval.v_number, - tv2->vval.v_number); + tv2->vval.v_number, &failed); break; } + if (failed) + return FAIL; tv1->vval.v_number = res; --ppconst->pp_used; } From b1f2857096aabe9a11e576005d08fc4e53781698 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 13:03:20 +0100 Subject: [PATCH 17/47] patch 8.2.2382: build failure Problem: Build failure. Solution: Add missing changes. --- src/version.c | 2 ++ src/vim9execute.c | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/version.c b/src/version.c index c220a409ec..2b6f6a88e3 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 */ +/**/ + 2382, /**/ 2381, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index b1bc282636..59a0982b3f 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2951,17 +2951,19 @@ call_def_function( else #endif { + int failed = FALSE; + switch (iptr->isn_arg.op.op_type) { case EXPR_MULT: n1 = n1 * n2; break; - case EXPR_DIV: n1 = num_divide(n1, n2); - if (n2 == 0) + case EXPR_DIV: n1 = num_divide(n1, n2, &failed); + if (failed) goto on_error; break; case EXPR_SUB: n1 = n1 - n2; break; case EXPR_ADD: n1 = n1 + n2; break; - default: n1 = num_modulus(n1, n2); - if (n2 == 0) + default: n1 = num_modulus(n1, n2, &failed); + if (failed) goto on_error; break; } From ccb47a2899d9f8076dad0f8348c057450febf32b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 13:36:43 +0100 Subject: [PATCH 18/47] patch 8.2.2383: focus escape sequences are not named Problem: Focus escape sequences are not named in ":set termcap" output. Solution: Add the names to the list. (closes #7718) --- src/misc2.c | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/misc2.c b/src/misc2.c index 52e0499bc8..5a6d863521 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -2531,6 +2531,8 @@ static struct key_name_entry {K_CURSORHOLD, (char_u *)"CursorHold"}, {K_IGNORE, (char_u *)"Ignore"}, {K_COMMAND, (char_u *)"Cmd"}, + {K_FOCUSGAINED, (char_u *)"FocusGained"}, + {K_FOCUSLOST, (char_u *)"FocusLost"}, {0, NULL} // NOTE: When adding a long name update MAX_KEY_NAME_LEN. }; diff --git a/src/version.c b/src/version.c index 2b6f6a88e3..361ae36fc7 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 */ +/**/ + 2383, /**/ 2382, /**/ From 5e6a7aa2b26077775906eb8411952dc6259694de Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 14:45:13 +0100 Subject: [PATCH 19/47] patch 8.2.2384: turtle filetype not recognized Problem: Turtle filetype not recognized. Solution: Add a rule to detect turtle files. (closes #7722) --- runtime/filetype.vim | 9 +++++++-- src/testdir/test_filetype.vim | 17 +++++++++++++++++ src/version.c | 2 ++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 4c419ed060..c9c9fdf715 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1731,8 +1731,13 @@ au BufNewFile,BufRead *.tli setf tli " Telix Salt au BufNewFile,BufRead *.slt setf tsalt -" Tera Term Language -au BufRead,BufNewFile *.ttl setf teraterm +" Tera Term Language or Turtle +au BufRead,BufNewFile *.ttl + \ if getline(1) =~ '^@\?\(prefix\|base\)' | + \ setf turtle | + \ else | + \ setf teraterm | + \ endif " Terminfo au BufNewFile,BufRead *.ti setf terminfo diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index b05c152dc6..4e6d4331a3 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -733,6 +733,23 @@ func Test_ts_file() filetype off endfunc +func Test_ttl_file() + filetype on + + call writefile(['@base .'], 'Xfile.ttl') + split Xfile.ttl + call assert_equal('turtle', &filetype) + bwipe! + + call writefile(['looks like Tera Term Language'], 'Xfile.ttl') + split Xfile.ttl + call assert_equal('teraterm', &filetype) + bwipe! + + call delete('Xfile.ttl') + filetype off +endfunc + func Test_pp_file() filetype on diff --git a/src/version.c b/src/version.c index 361ae36fc7..a90c645382 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 */ +/**/ + 2384, /**/ 2383, /**/ From e71996bd0865659bde5450f466bc3e53e83431b2 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 17:03:07 +0100 Subject: [PATCH 20/47] patch 8.2.2385: "gj" and "gk" do not work correctly when inside a fold Problem: "gj" and "gk" do not work correctly when inside a fold. Solution: Move check for folding. (closes #7724, closes #4095) --- src/normal.c | 31 +++++++++++-------------------- src/testdir/test_fold.vim | 35 +++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/normal.c b/src/normal.c index a5f5794c52..c70971f8e9 100644 --- a/src/normal.c +++ b/src/normal.c @@ -2570,12 +2570,6 @@ nv_screengo(oparg_T *oap, int dir, long dist) else { // to previous line - if (curwin->w_cursor.lnum == 1) - { - retval = FAIL; - break; - } - --curwin->w_cursor.lnum; #ifdef FEAT_FOLDING // Move to the start of a closed fold. Don't do that when // 'foldopen' contains "all": it will open in a moment. @@ -2583,6 +2577,13 @@ nv_screengo(oparg_T *oap, int dir, long dist) (void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL); #endif + if (curwin->w_cursor.lnum == 1) + { + retval = FAIL; + break; + } + --curwin->w_cursor.lnum; + linelen = linetabsize(ml_get_curline()); if (linelen > width1) curwin->w_curswant += (((linelen - width1 - 1) / width2) @@ -5957,13 +5958,8 @@ nv_g_cmd(cmdarg_T *cap) */ case 'j': case K_DOWN: - // with 'nowrap' it works just like the normal "j" command; also when - // in a closed fold - if (!curwin->w_p_wrap -#ifdef FEAT_FOLDING - || hasFolding(curwin->w_cursor.lnum, NULL, NULL) -#endif - ) + // with 'nowrap' it works just like the normal "j" command. + if (!curwin->w_p_wrap) { oap->motion_type = MLINE; i = cursor_down(cap->count1, oap->op_type == OP_NOP); @@ -5976,13 +5972,8 @@ nv_g_cmd(cmdarg_T *cap) case 'k': case K_UP: - // with 'nowrap' it works just like the normal "k" command; also when - // in a closed fold - if (!curwin->w_p_wrap -#ifdef FEAT_FOLDING - || hasFolding(curwin->w_cursor.lnum, NULL, NULL) -#endif - ) + // with 'nowrap' it works just like the normal "k" command. + if (!curwin->w_p_wrap) { oap->motion_type = MLINE; i = cursor_up(cap->count1, oap->op_type == OP_NOP); diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim index b978fc080f..895a96b127 100644 --- a/src/testdir/test_fold.vim +++ b/src/testdir/test_fold.vim @@ -859,4 +859,39 @@ func Test_fold_create_delete() bwipe! endfunc +func Test_fold_relative_move() + enew! + set fdm=indent sw=2 wrap tw=80 + + let content = [ ' foo', ' bar', ' baz', + \ repeat('x', 100), + \ ' foo', ' bar', ' baz' + \ ] + call append(0, content) + + normal zM + + call cursor(3, 1) + call assert_true(foldclosed(line('.'))) + normal gj + call assert_equal(2, winline()) + + call cursor(2, 1) + call assert_true(foldclosed(line('.'))) + normal 2gj + call assert_equal(3, winline()) + + call cursor(5, 1) + call assert_true(foldclosed(line('.'))) + normal gk + call assert_equal(3, winline()) + + call cursor(6, 1) + call assert_true(foldclosed(line('.'))) + normal 2gk + call assert_equal(2, winline()) + + set fdm& sw& wrap& tw& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index a90c645382..faa2777434 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 */ +/**/ + 2385, /**/ 2384, /**/ From f904133e1a5ea84a124d3ece12b1f0a7392f1ca7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 19:41:16 +0100 Subject: [PATCH 21/47] patch 8.2.2386: Vim9: crash when using ":silent! put" Problem: Vim9: crash when using ":silent! put". Solution: When ignoring an error for ":silent!" rewind the stack and skip ahead to restoring the cmdmod. (closes #7717) --- src/testdir/test_vim9_func.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 17 +++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 1ea8ac9fc9..da0a0e6432 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -2184,6 +2184,24 @@ def Test_dict_member_with_silent() CheckScriptSuccess(lines) enddef +def Test_skip_cmds_with_silent() + var lines =<< trim END + vim9script + + def Func(b: bool) + Crash() + enddef + + def Crash() + sil! :/not found/d _ + sil! :/not found/put _ + enddef + + Func(true) + END + CheckScriptSuccess(lines) +enddef + def Test_opfunc() nnoremap set opfunc=Opfuncg@ def g:Opfunc(_: any): string diff --git a/src/version.c b/src/version.c index faa2777434..a73927045c 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 */ +/**/ + 2386, /**/ 2385, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 59a0982b3f..b533617fc7 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1124,6 +1124,7 @@ call_def_function( msglist_T *private_msg_list = NULL; cmdmod_T save_cmdmod; int restore_cmdmod = FALSE; + int restore_cmdmod_stacklen = 0; int save_emsg_silent_def = emsg_silent_def; int save_did_emsg_def = did_emsg_def; int trylevel_at_start = trylevel; @@ -3398,6 +3399,7 @@ call_def_function( case ISN_CMDMOD: save_cmdmod = cmdmod; restore_cmdmod = TRUE; + restore_cmdmod_stacklen = ectx.ec_stack.ga_len; cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod; apply_cmdmod(&cmdmod); break; @@ -3523,7 +3525,22 @@ on_error: // when calling the function. if (did_emsg_cumul + did_emsg == did_emsg_before && emsg_silent && did_emsg_def == 0) + { + // If a sequence of instructions causes an error while ":silent!" + // was used, restore the stack length and jump ahead to restoring + // the cmdmod. + if (restore_cmdmod) + { + while (ectx.ec_stack.ga_len > restore_cmdmod_stacklen) + { + --ectx.ec_stack.ga_len; + clear_tv(STACK_TV_BOT(0)); + } + while (ectx.ec_instr[ectx.ec_iidx].isn_type != ISN_CMDMOD_REV) + ++ectx.ec_iidx; + } continue; + } on_fatal_error: // Jump here for an error that messes up the stack. // If we are not inside a try-catch started here, abort execution. From e32e516dfa46e9c5965d278f96aaf57573de8ac4 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 20:21:29 +0100 Subject: [PATCH 22/47] patch 8.2.2387: runtime type check does not mention argument index Problem: Runtime type check does not mention argument index. Solution: Add ct_arg_idx. (closes #7720) --- src/testdir/test_vim9_builtin.vim | 2 +- src/testdir/test_vim9_disassemble.vim | 2 +- src/testdir/test_vim9_func.vim | 16 ++++++++++++++++ src/version.c | 2 ++ src/vim9.h | 3 ++- src/vim9compile.c | 12 +++++++----- src/vim9execute.c | 16 ++++++++++++---- 7 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 50dc2a0735..06b5ecdba5 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -263,7 +263,7 @@ def Test_extend_arg_types() CheckDefFailure(['extend({a: 1}, {b: 2}, 1)'], 'E1013: Argument 3: type mismatch, expected string but got number') CheckDefFailure(['extend([1], ["b"])'], 'E1013: Argument 2: type mismatch, expected list but got list') - CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1012: Type mismatch; expected list but got list') + CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1013: Argument 2: type mismatch, expected list but got list') enddef def Test_extendnew() diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 1aab9d5b38..f40bcf0ae0 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -934,7 +934,7 @@ def Test_disassemble_lambda_with_type() 'return Ref(g:value)\_s*' .. '\d LOADG g:value\_s*' .. '\d LOAD $0\_s*' .. - '\d CHECKTYPE number stack\[-2\]\_s*' .. + '\d CHECKTYPE number stack\[-2\] arg 1\_s*' .. '\d PCALL (argc 1)\_s*' .. '\d RETURN', instr) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index da0a0e6432..fc1ed2120a 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -144,6 +144,22 @@ def Test_return_something() assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal') enddef +def Test_check_argument_type() + var lines =<< trim END + vim9script + def Val(a: number, b: number): number + return 0 + enddef + def Func() + var x: any = true + Val(0, x) + enddef + disass Func + Func() + END + CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got bool', 2) +enddef + def Test_missing_return() CheckDefFailure(['def Missing(): number', ' if g:cond', diff --git a/src/version.c b/src/version.c index a73927045c..c911ed4608 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 */ +/**/ + 2387, /**/ 2386, /**/ diff --git a/src/vim9.h b/src/vim9.h index b0c465deb2..c51be8ef62 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -224,7 +224,8 @@ typedef struct { // arguments to ISN_CHECKTYPE typedef struct { type_T *ct_type; - int ct_off; // offset in stack, -1 is bottom + char ct_off; // offset in stack, -1 is bottom + char ct_arg_idx; // argument index or zero } checktype_T; // arguments to ISN_STORENR diff --git a/src/vim9compile.c b/src/vim9compile.c index e972033f0b..ead971feba 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -816,7 +816,8 @@ generate_COND2BOOL(cctx_T *cctx) generate_TYPECHECK( cctx_T *cctx, type_T *expected, - int offset) + int offset, + int argidx) { isn_T *isn; garray_T *stack = &cctx->ctx_type_stack; @@ -826,6 +827,7 @@ generate_TYPECHECK( return FAIL; isn->isn_arg.type.ct_type = alloc_type(expected); isn->isn_arg.type.ct_off = offset; + isn->isn_arg.type.ct_arg_idx = argidx; // type becomes expected ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected; @@ -904,7 +906,7 @@ need_type( // If it's a constant a runtime check makes no sense. if (!actual_is_const && use_typecheck(actual, expected)) { - generate_TYPECHECK(cctx, expected, offset); + generate_TYPECHECK(cctx, expected, offset, arg_idx); return OK; } @@ -1637,7 +1639,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call) if (maptype != NULL && maptype->tt_member != NULL && maptype->tt_member != &t_any) // Check that map() didn't change the item types. - generate_TYPECHECK(cctx, maptype, -1); + generate_TYPECHECK(cctx, maptype, -1, 1); return OK; } @@ -1735,7 +1737,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) else expected = ufunc->uf_va_type->tt_member; actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i]; - if (need_type(actual, expected, -argcount + i, 0, cctx, + if (need_type(actual, expected, -argcount + i, i + 1, cctx, TRUE, FALSE) == FAIL) { arg_type_mismatch(expected, actual, i + 1); @@ -1852,7 +1854,7 @@ generate_PCALL( type->tt_argcount - 1]->tt_member; else expected = type->tt_args[i]; - if (need_type(actual, expected, offset, 0, + if (need_type(actual, expected, offset, i + 1, cctx, TRUE, FALSE) == FAIL) { arg_type_mismatch(expected, actual, i + 1); diff --git a/src/vim9execute.c b/src/vim9execute.c index b533617fc7..7d1d079bb1 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -3242,7 +3242,8 @@ call_def_function( tv = STACK_TV_BOT(ct->ct_off); SOURCING_LNUM = iptr->isn_lnum; - if (check_typval_type(ct->ct_type, tv, 0) == FAIL) + if (check_typval_type(ct->ct_type, tv, ct->ct_arg_idx) + == FAIL) goto on_error; // number 0 is FALSE, number 1 is TRUE @@ -4235,11 +4236,18 @@ ex_disassemble(exarg_T *eap) case ISN_CHECKNR: smsg("%4d CHECKNR", current); break; case ISN_CHECKTYPE: { + checktype_T *ct = &iptr->isn_arg.type; char *tofree; - smsg("%4d CHECKTYPE %s stack[%d]", current, - type_name(iptr->isn_arg.type.ct_type, &tofree), - iptr->isn_arg.type.ct_off); + if (ct->ct_arg_idx == 0) + smsg("%4d CHECKTYPE %s stack[%d]", current, + type_name(ct->ct_type, &tofree), + (int)ct->ct_off); + else + smsg("%4d CHECKTYPE %s stack[%d] arg %d", current, + type_name(ct->ct_type, &tofree), + (int)ct->ct_off, + (int)ct->ct_arg_idx); vim_free(tofree); break; } From 57d5a01cb45d6edb16c3835a49b42d6d8fc0163e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 21:42:31 +0100 Subject: [PATCH 23/47] patch 8.2.2388: no easy way to get the maximum or mininum number value Problem: No easy way to get the maximum or mininum number value. Solution: Add v:numbermax and v:numbermin. --- runtime/doc/eval.txt | 8 ++++- src/evalvars.c | 4 +++ src/testdir/test_eval_stuff.vim | 9 ++++-- src/version.c | 2 ++ src/vim.h | 54 +++++++++++++++++---------------- 5 files changed, 47 insertions(+), 30 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 217e69dc08..dd5bc939d3 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 Jan 17 +*eval.txt* For Vim version 8.2. Last change: 2021 Jan 21 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2082,6 +2082,12 @@ v:null An empty String. Used to put "null" in JSON. See That is so that eval() can parse the string back to the same value. Read-only. + *v:numbermax* *numbermax-variable* +v:numbermax Maximum value of a number. + + *v:numbermix* *numbermix-variable* +v:numbermin Minimum value of a number (negative) + *v:numbersize* *numbersize-variable* v:numbersize Number of bits in a Number. This is normally 64, but on some systems it may be 32. diff --git a/src/evalvars.c b/src/evalvars.c index 1799531786..dfc8e63f5a 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -122,6 +122,8 @@ static struct vimvar {VV_NAME("true", VAR_BOOL), VV_RO}, {VV_NAME("none", VAR_SPECIAL), VV_RO}, {VV_NAME("null", VAR_SPECIAL), VV_RO}, + {VV_NAME("numbermax", VAR_NUMBER), VV_RO}, + {VV_NAME("numbermin", VAR_NUMBER), VV_RO}, {VV_NAME("numbersize", VAR_NUMBER), VV_RO}, {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, {VV_NAME("testing", VAR_NUMBER), 0}, @@ -228,6 +230,8 @@ evalvars_init(void) set_vim_var_nr(VV_TRUE, VVAL_TRUE); set_vim_var_nr(VV_NONE, VVAL_NONE); set_vim_var_nr(VV_NULL, VVAL_NULL); + set_vim_var_nr(VV_NUMBERMAX, VARNUM_MAX); + set_vim_var_nr(VV_NUMBERMIN, VARNUM_MIN); set_vim_var_nr(VV_NUMBERSIZE, sizeof(varnumber_T) * 8); set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER); diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim index e5f521c85c..52e8df9242 100644 --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -256,10 +256,13 @@ func Test_execute_cmd_with_null() endif endfunc -func Test_numbersize() - " This will fail on systems without 64 bit int support or when not configured - " correctly. +func Test_number_max_min_size() + " This will fail on systems without 64 bit number support or when not + " configured correctly. call assert_equal(64, v:numbersize) + + call assert_true(v:numbermin < -9999999) + call assert_true(v:numbermax > 9999999) endfunc func Assert_reg(name, type, value, valuestr, expr, exprstr) diff --git a/src/version.c b/src/version.c index c911ed4608..6d99990cd3 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 */ +/**/ + 2388, /**/ 2387, /**/ diff --git a/src/vim.h b/src/vim.h index 7ba728a370..de2482e8b8 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1975,32 +1975,34 @@ typedef int sock_T; #define VV_TRUE 69 #define VV_NONE 70 #define VV_NULL 71 -#define VV_NUMBERSIZE 72 -#define VV_VIM_DID_ENTER 73 -#define VV_TESTING 74 -#define VV_TYPE_NUMBER 75 -#define VV_TYPE_STRING 76 -#define VV_TYPE_FUNC 77 -#define VV_TYPE_LIST 78 -#define VV_TYPE_DICT 79 -#define VV_TYPE_FLOAT 80 -#define VV_TYPE_BOOL 81 -#define VV_TYPE_NONE 82 -#define VV_TYPE_JOB 83 -#define VV_TYPE_CHANNEL 84 -#define VV_TYPE_BLOB 85 -#define VV_TERMRFGRESP 86 -#define VV_TERMRBGRESP 87 -#define VV_TERMU7RESP 88 -#define VV_TERMSTYLERESP 89 -#define VV_TERMBLINKRESP 90 -#define VV_EVENT 91 -#define VV_VERSIONLONG 92 -#define VV_ECHOSPACE 93 -#define VV_ARGV 94 -#define VV_COLLATE 95 -#define VV_EXITING 96 -#define VV_LEN 97 // number of v: vars +#define VV_NUMBERMAX 72 +#define VV_NUMBERMIN 73 +#define VV_NUMBERSIZE 74 +#define VV_VIM_DID_ENTER 75 +#define VV_TESTING 76 +#define VV_TYPE_NUMBER 77 +#define VV_TYPE_STRING 78 +#define VV_TYPE_FUNC 79 +#define VV_TYPE_LIST 80 +#define VV_TYPE_DICT 81 +#define VV_TYPE_FLOAT 82 +#define VV_TYPE_BOOL 83 +#define VV_TYPE_NONE 84 +#define VV_TYPE_JOB 85 +#define VV_TYPE_CHANNEL 86 +#define VV_TYPE_BLOB 87 +#define VV_TERMRFGRESP 88 +#define VV_TERMRBGRESP 89 +#define VV_TERMU7RESP 90 +#define VV_TERMSTYLERESP 91 +#define VV_TERMBLINKRESP 92 +#define VV_EVENT 93 +#define VV_VERSIONLONG 94 +#define VV_ECHOSPACE 95 +#define VV_ARGV 96 +#define VV_COLLATE 97 +#define VV_EXITING 98 +#define VV_LEN 99 // number of v: vars // used for v_number in VAR_BOOL and VAR_SPECIAL #define VVAL_FALSE 0L // VAR_BOOL From 9b6344613eecfcf77c510d7b63fcc4b7b51aefbc Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 21 Jan 2021 22:53:38 +0100 Subject: [PATCH 24/47] patch 8.2.2389: test failure on a few systems Problem: Test failure on a few systems. Solution: Avoid that "char" value is negative. --- src/version.c | 2 ++ src/vim9.h | 2 +- src/vim9compile.c | 4 +++- src/vim9execute.c | 6 +++--- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/version.c b/src/version.c index 6d99990cd3..568756b85f 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 */ +/**/ + 2389, /**/ 2388, /**/ diff --git a/src/vim9.h b/src/vim9.h index c51be8ef62..e6c4087c61 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -224,7 +224,7 @@ typedef struct { // arguments to ISN_CHECKTYPE typedef struct { type_T *ct_type; - char ct_off; // offset in stack, -1 is bottom + char ct_off; // offset in stack (positive), 1 is bottom char ct_arg_idx; // argument index or zero } checktype_T; diff --git a/src/vim9compile.c b/src/vim9compile.c index ead971feba..2fad4ac34b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -826,7 +826,9 @@ generate_TYPECHECK( if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL) return FAIL; isn->isn_arg.type.ct_type = alloc_type(expected); - isn->isn_arg.type.ct_off = offset; + // Use the negated offset so that it's always positive. Some systems don't + // support negative numbers for "char". + isn->isn_arg.type.ct_off = (char)-offset; isn->isn_arg.type.ct_arg_idx = argidx; // type becomes expected diff --git a/src/vim9execute.c b/src/vim9execute.c index 7d1d079bb1..b5f4be34e3 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -3240,7 +3240,7 @@ call_def_function( { checktype_T *ct = &iptr->isn_arg.type; - tv = STACK_TV_BOT(ct->ct_off); + tv = STACK_TV_BOT(-(int)ct->ct_off); SOURCING_LNUM = iptr->isn_lnum; if (check_typval_type(ct->ct_type, tv, ct->ct_arg_idx) == FAIL) @@ -4242,11 +4242,11 @@ ex_disassemble(exarg_T *eap) if (ct->ct_arg_idx == 0) smsg("%4d CHECKTYPE %s stack[%d]", current, type_name(ct->ct_type, &tofree), - (int)ct->ct_off); + -(int)ct->ct_off); else smsg("%4d CHECKTYPE %s stack[%d] arg %d", current, type_name(ct->ct_type, &tofree), - (int)ct->ct_off, + -(int)ct->ct_off, (int)ct->ct_arg_idx); vim_free(tofree); break; From b3005ce191d27fd2f234df4969d5b58fda9c1940 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 22 Jan 2021 17:51:06 +0100 Subject: [PATCH 25/47] patch 8.2.2390: Vim9: using positive offset is unexpected Problem: Vim9: using positive offset is unexpected. Solution: Use int8_T instead of char. (James McCoy) --- src/version.c | 2 ++ src/vim9.h | 4 ++-- src/vim9compile.c | 6 ++---- src/vim9execute.c | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/version.c b/src/version.c index 568756b85f..722c8332fc 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 */ +/**/ + 2390, /**/ 2389, /**/ diff --git a/src/vim9.h b/src/vim9.h index e6c4087c61..8d4faa3d11 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -224,8 +224,8 @@ typedef struct { // arguments to ISN_CHECKTYPE typedef struct { type_T *ct_type; - char ct_off; // offset in stack (positive), 1 is bottom - char ct_arg_idx; // argument index or zero + int8_T ct_off; // offset in stack, -1 is bottom + int8_T ct_arg_idx; // argument index or zero } checktype_T; // arguments to ISN_STORENR diff --git a/src/vim9compile.c b/src/vim9compile.c index 2fad4ac34b..ae5cb12f3f 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -826,10 +826,8 @@ generate_TYPECHECK( if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL) return FAIL; isn->isn_arg.type.ct_type = alloc_type(expected); - // Use the negated offset so that it's always positive. Some systems don't - // support negative numbers for "char". - isn->isn_arg.type.ct_off = (char)-offset; - isn->isn_arg.type.ct_arg_idx = argidx; + isn->isn_arg.type.ct_off = (int8_T)offset; + isn->isn_arg.type.ct_arg_idx = (int8_T)argidx; // type becomes expected ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected; diff --git a/src/vim9execute.c b/src/vim9execute.c index b5f4be34e3..21f7bb24ff 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -3240,7 +3240,7 @@ call_def_function( { checktype_T *ct = &iptr->isn_arg.type; - tv = STACK_TV_BOT(-(int)ct->ct_off); + tv = STACK_TV_BOT((int)ct->ct_off); SOURCING_LNUM = iptr->isn_lnum; if (check_typval_type(ct->ct_type, tv, ct->ct_arg_idx) == FAIL) @@ -4242,11 +4242,11 @@ ex_disassemble(exarg_T *eap) if (ct->ct_arg_idx == 0) smsg("%4d CHECKTYPE %s stack[%d]", current, type_name(ct->ct_type, &tofree), - -(int)ct->ct_off); + (int)ct->ct_off); else smsg("%4d CHECKTYPE %s stack[%d] arg %d", current, type_name(ct->ct_type, &tofree), - -(int)ct->ct_off, + (int)ct->ct_off, (int)ct->ct_arg_idx); vim_free(tofree); break; From 0d3de8cb590aed90be71d96eb3dbc6addf80bb11 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 22 Jan 2021 20:46:27 +0100 Subject: [PATCH 26/47] patch 8.2.2391: memory leak when creating a global function with closure Problem: Memory leak when creating a global function with closure. Solution: Create a separate partial for every instantiated function. --- src/userfunc.c | 36 +++++++++++++++++++----------------- src/version.c | 2 ++ src/vim9execute.c | 39 ++++++++++++++++++++++++--------------- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/userfunc.c b/src/userfunc.c index bf701b42eb..5372260d6d 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1352,8 +1352,13 @@ func_clear_items(ufunc_T *fp) VIM_CLEAR(fp->uf_block_ids); VIM_CLEAR(fp->uf_va_name); clear_type_list(&fp->uf_type_list); + + // Increment the refcount of this function to avoid it being freed + // recursively when the partial is freed. + fp->uf_refcount += 3; partial_unref(fp->uf_partial); fp->uf_partial = NULL; + fp->uf_refcount -= 3; #ifdef FEAT_LUA if (fp->uf_cb_free != NULL) @@ -1446,10 +1451,10 @@ copy_func(char_u *lambda, char_u *global, ectx_T *ectx) return FAIL; } - // TODO: handle ! to overwrite fp = find_func(global, TRUE, NULL); if (fp != NULL) { + // TODO: handle ! to overwrite semsg(_(e_funcexts), global); return FAIL; } @@ -1501,8 +1506,9 @@ copy_func(char_u *lambda, char_u *global, ectx_T *ectx) // the referenced dfunc_T is now used one more time link_def_function(fp); - // Create a partial to store the context of the function, if not done - // already. + // Create a partial to store the context of the function where it was + // instantiated. Only needs to be done once. Do this on the original + // function, "dfunc->df_ufunc" will point to it. if ((ufunc->uf_flags & FC_CLOSURE) && ufunc->uf_partial == NULL) { partial_T *pt = ALLOC_CLEAR_ONE(partial_T); @@ -1510,14 +1516,12 @@ copy_func(char_u *lambda, char_u *global, ectx_T *ectx) if (pt == NULL) goto failed; if (fill_partial_and_closure(pt, ufunc, ectx) == FAIL) + { + vim_free(pt); goto failed; + } ufunc->uf_partial = pt; - --pt->pt_refcount; // not referenced here yet - } - if (ufunc->uf_partial != NULL) - { - fp->uf_partial = ufunc->uf_partial; - ++fp->uf_partial->pt_refcount; + --pt->pt_refcount; // not actually referenced here } return OK; @@ -4243,23 +4247,21 @@ func_unref(char_u *name) #endif internal_error("func_unref()"); } - if (fp != NULL && --fp->uf_refcount <= 0) - { - // Only delete it when it's not being used. Otherwise it's done - // when "uf_calls" becomes zero. - if (fp->uf_calls == 0) - func_clear_free(fp, FALSE); - } + func_ptr_unref(fp); } /* * Unreference a Function: decrement the reference count and free it when it * becomes zero. + * Also when it becomes one and uf_partial points to the function. */ void func_ptr_unref(ufunc_T *fp) { - if (fp != NULL && --fp->uf_refcount <= 0) + if (fp != NULL && (--fp->uf_refcount <= 0 + || (fp->uf_refcount == 1 && fp->uf_partial != NULL + && fp->uf_partial->pt_refcount <= 1 + && fp->uf_partial->pt_func == fp))) { // Only delete it when it's not being used. Otherwise it's done // when "uf_calls" becomes zero. diff --git a/src/version.c b/src/version.c index 722c8332fc..6bcd0747de 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 */ +/**/ + 2391, /**/ 2390, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 21f7bb24ff..232c84ed7d 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -263,7 +263,8 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) } ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount; - if (pt != NULL || ufunc->uf_partial != NULL || ufunc->uf_flags & FC_CLOSURE) + if (pt != NULL || ufunc->uf_partial != NULL + || (ufunc->uf_flags & FC_CLOSURE)) { outer_T *outer = ALLOC_CLEAR_ONE(outer_T); @@ -1062,7 +1063,7 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx) pt->pt_func = ufunc; pt->pt_refcount = 1; - if (pt->pt_func->uf_flags & FC_CLOSURE) + if (ufunc->uf_flags & FC_CLOSURE) { dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; @@ -1093,7 +1094,7 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx) ++pt->pt_refcount; ++ectx->ec_funcrefs.ga_len; } - ++pt->pt_func->uf_refcount; + ++ufunc->uf_refcount; return OK; } @@ -1243,24 +1244,32 @@ call_def_function( ectx.ec_frame_idx = ectx.ec_stack.ga_len; initial_frame_idx = ectx.ec_frame_idx; - if (partial != NULL || ufunc->uf_partial != NULL) { - ectx.ec_outer = ALLOC_CLEAR_ONE(outer_T); - if (ectx.ec_outer == NULL) - goto failed_early; - if (partial != NULL) + dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + + ufunc->uf_dfunc_idx; + ufunc_T *base_ufunc = dfunc->df_ufunc; + + // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done + // by copy_func(). + if (partial != NULL || base_ufunc->uf_partial != NULL) { - if (partial->pt_outer.out_stack == NULL && current_ectx != NULL) + ectx.ec_outer = ALLOC_CLEAR_ONE(outer_T); + if (ectx.ec_outer == NULL) + goto failed_early; + if (partial != NULL) { - if (current_ectx->ec_outer != NULL) - *ectx.ec_outer = *current_ectx->ec_outer; + if (partial->pt_outer.out_stack == NULL && current_ectx != NULL) + { + if (current_ectx->ec_outer != NULL) + *ectx.ec_outer = *current_ectx->ec_outer; + } + else + *ectx.ec_outer = partial->pt_outer; } else - *ectx.ec_outer = partial->pt_outer; + *ectx.ec_outer = base_ufunc->uf_partial->pt_outer; + ectx.ec_outer->out_up_is_copy = TRUE; } - else - *ectx.ec_outer = ufunc->uf_partial->pt_outer; - ectx.ec_outer->out_up_is_copy = TRUE; } // dummy frame entries From 402115f1c2b4d0704a822206f2e6e931e721c129 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 22 Jan 2021 20:55:04 +0100 Subject: [PATCH 27/47] patch 8.2.2392: fennel filetype not recognized Problem: Fennel filetype not recognized. Solution: Detect with pattern and hashbang. (Chinmay Dalal, closes #7729) --- runtime/filetype.vim | 3 +++ runtime/scripts.vim | 4 ++++ src/testdir/test_filetype.vim | 2 ++ src/version.c | 2 ++ 4 files changed, 11 insertions(+) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index c9c9fdf715..1e365ec081 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -589,6 +589,9 @@ au BufNewFile,BufRead *.fan,*.fwt setf fan " Factor au BufNewFile,BufRead *.factor setf factor +" Fennel +autocmd BufRead,BufNewFile *.fnl setf fennel + " Fetchmail RC file au BufNewFile,BufRead .fetchmailrc setf fetchmail diff --git a/runtime/scripts.vim b/runtime/scripts.vim index 9217b4416a..6448c542cb 100644 --- a/runtime/scripts.vim +++ b/runtime/scripts.vim @@ -186,6 +186,10 @@ if s:line1 =~# "^#!" elseif s:name =~# 'instantfpc\>' set ft=pascal + " Fennel + elseif s:name =~# 'fennel\>' + set ft=fennel + endif unlet s:name diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 4e6d4331a3..2d667a297a 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -174,6 +174,7 @@ let s:filename_checks = { \ 'factor': ['file.factor'], \ 'falcon': ['file.fal'], \ 'fan': ['file.fan', 'file.fwt'], + \ 'fennel': ['file.fnl'], \ 'fetchmail': ['.fetchmailrc'], \ 'fgl': ['file.4gl', 'file.4gh', 'file.m4gl'], \ 'focexec': ['file.fex', 'file.focexec'], @@ -639,6 +640,7 @@ let s:script_checks = { \ ['// -*- C++ -*-']], \ 'yaml': [['%YAML 1.2']], \ 'pascal': [['#!/path/instantfpc']], + \ 'fennel': [['#!/path/fennel']], \ } " Various forms of "env" optional arguments. diff --git a/src/version.c b/src/version.c index 6bcd0747de..c5fdf85855 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 */ +/**/ + 2392, /**/ 2391, /**/ From 4bce26bb70144633713e7e8f149ba99cac511336 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 22 Jan 2021 22:06:56 +0100 Subject: [PATCH 28/47] patch 8.2.2393: Vim9: error message when script line starts with "[{" Problem: Vim9: error message when script line starts with "[{". Solution: Do not give an error for checking for end of list. --- src/dict.c | 3 ++- src/testdir/test_vim9_script.vim | 6 ++++++ src/version.c | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/dict.c b/src/dict.c index fc8756c57b..b267e240db 100644 --- a/src/dict.c +++ b/src/dict.c @@ -1032,7 +1032,8 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) if (**arg != '}') { - semsg(_(e_missing_dict_end), *arg); + if (evalarg != NULL) + semsg(_(e_missing_dict_end), *arg); failret: if (d != NULL) dict_free(d); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 957671c53b..9dadf1edaa 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -815,6 +815,12 @@ def Test_list_vimscript() # comment 6 END assert_equal(['# comment 1', 'two', '# comment 3', '', 'five', '# comment 6'], lines) + + lines =<< trim END + [{ + a: 0}]->string()->assert_equal("[{'a': 0}]") + END + CheckDefAndScriptSuccess(lines) enddef if has('channel') diff --git a/src/version.c b/src/version.c index c5fdf85855..02fd3fa49f 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 */ +/**/ + 2393, /**/ 2392, /**/ From 9ae3705b6ebd45086ca13c0f93a93f943559bd15 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 22 Jan 2021 22:31:10 +0100 Subject: [PATCH 29/47] patch 8.2.2394: Vim9: min() and max() return type is "any" Problem: Vim9: min() and max() return type is "any". Solution: Use return type "number". (closes #7728) --- src/evalfunc.c | 4 ++-- src/testdir/test_vim9_builtin.vim | 28 ++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index 7f703f60b5..cc812ce336 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1219,7 +1219,7 @@ static funcentry_T global_functions[] = {"matchstrpos", 2, 4, FEARG_1, NULL, ret_list_any, f_matchstrpos}, {"max", 1, 1, FEARG_1, NULL, - ret_any, f_max}, + ret_number, f_max}, {"menu_info", 1, 2, FEARG_1, NULL, ret_dict_any, #ifdef FEAT_MENU @@ -1229,7 +1229,7 @@ static funcentry_T global_functions[] = #endif }, {"min", 1, 1, FEARG_1, NULL, - ret_any, f_min}, + ret_number, f_min}, {"mkdir", 1, 3, FEARG_1, NULL, ret_number_bool, f_mkdir}, {"mode", 0, 1, FEARG_1, NULL, diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 06b5ecdba5..776aec0bde 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -655,6 +655,34 @@ def Test_maparg_mapset() nunmap enddef +def Test_max() + g:flag = true + var l1: list = g:flag + ? [1, max([2, 3])] + : [4, 5] + assert_equal([1, 3], l1) + + g:flag = false + var l2: list = g:flag + ? [1, max([2, 3])] + : [4, 5] + assert_equal([4, 5], l2) +enddef + +def Test_min() + g:flag = true + var l1: list = g:flag + ? [1, min([2, 3])] + : [4, 5] + assert_equal([1, 2], l1) + + g:flag = false + var l2: list = g:flag + ? [1, min([2, 3])] + : [4, 5] + assert_equal([4, 5], l2) +enddef + def Test_nr2char() nr2char(97, true)->assert_equal('a') enddef diff --git a/src/version.c b/src/version.c index 02fd3fa49f..63fc0b33bc 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 */ +/**/ + 2394, /**/ 2393, /**/ From 9a562c184d98d82bb7506caf2071cfe15a92fa43 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 23 Jan 2021 13:39:14 +0100 Subject: [PATCH 30/47] patch 8.2.2395: Vim9: error for wrong type may report wrong line number Problem: Vim9: error for wrong type may report wrong line number. Solution: Save and restore the line number when evaluating the expression. (closes #7727) --- src/evalvars.c | 7 +++++++ src/testdir/test_vim9_assign.vim | 2 ++ src/version.c | 2 ++ 3 files changed, 11 insertions(+) diff --git a/src/evalvars.c b/src/evalvars.c index dfc8e63f5a..b6a6927d60 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -838,6 +838,8 @@ ex_let(exarg_T *eap) i = FAIL; if (has_assign || concat) { + int cur_lnum; + op[0] = '='; op[1] = NUL; if (*expr != '=') @@ -882,10 +884,15 @@ ex_let(exarg_T *eap) evalarg.eval_cookie = eap->cookie; } expr = skipwhite_and_linebreak(expr, &evalarg); + cur_lnum = SOURCING_LNUM; i = eval0(expr, &rettv, eap, &evalarg); if (eap->skip) --emsg_skip; clear_evalarg(&evalarg, eap); + + // Restore the line number so that any type error is given for the + // declaration, not the expression. + SOURCING_LNUM = cur_lnum; } if (eap->skip) { diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 992eeaa655..55beffa958 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -55,6 +55,8 @@ def Test_assignment_bool() CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:') CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:') CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:') + + CheckDefAndScriptFailure(['var x: bool = "x"', '', 'eval 0'], 'E1012:', 1) enddef def Test_syntax() diff --git a/src/version.c b/src/version.c index 63fc0b33bc..7942e743f2 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 */ +/**/ + 2395, /**/ 2394, /**/ From 7cebe8ba7dd9a3a955e2da74014f11c42e1c6ac3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 23 Jan 2021 14:22:16 +0100 Subject: [PATCH 31/47] patch 8.2.2396: Vim9: no white space allowed before "->" Problem: Vim9: no white space allowed before "->". Solution: Allow for white space. (closes #7725) --- src/eval.c | 12 ++++-------- src/ex_docmd.c | 7 ++++--- src/testdir/test_vim9_cmd.vim | 14 ++++++++++++++ src/version.c | 2 ++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/eval.c b/src/eval.c index 3e316bdb10..ebd25077c3 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3671,7 +3671,7 @@ call_func_rettv( /* * Evaluate "->method()". - * "*arg" points to the '-'. + * "*arg" points to "method". * Returns FAIL or OK. "*arg" is advanced to after the ')'. */ static int @@ -3686,8 +3686,6 @@ eval_lambda( typval_T base = *rettv; int ret; - // Skip over the ->. - *arg += 2; rettv->v_type = VAR_UNKNOWN; if (**arg == '{') @@ -3735,7 +3733,7 @@ eval_lambda( /* * Evaluate "->method()". - * "*arg" points to the '-'. + * "*arg" points to "method". * Returns FAIL or OK. "*arg" is advanced to after the ')'. */ static int @@ -3753,8 +3751,6 @@ eval_method( int evaluate = evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE); - // Skip over the ->. - *arg += 2; rettv->v_type = VAR_UNKNOWN; name = *arg; @@ -5765,10 +5761,10 @@ handle_subscript( } else if (p[0] == '-' && p[1] == '>') { - *arg = p; + *arg = skipwhite(p + 2); if (ret == OK) { - if (((*arg)[2] == '{' && !in_vim9script()) || (*arg)[2] == '(') + if ((**arg == '{' && !in_vim9script()) || **arg == '(') // expr->{lambda}() or expr->(lambda)() ret = eval_lambda(arg, rettv, evalarg, verbose); else diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 9562e6be3a..b9ae13d0a8 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3313,8 +3313,9 @@ find_ex_command( if (vim_strchr((char_u *)"{('[\"@", *p) != NULL || ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL)) { - int oplen; - int heredoc; + int oplen; + int heredoc; + char_u *swp = skipwhite(p); if ( // "(..." is an expression. @@ -3332,7 +3333,7 @@ find_ex_command( || eap->cmd[1] == ':' ) // "varname->func()" is an expression. - : (*p == '-' && p[1] == '>'))) + : (*swp == '-' && swp[1] == '>'))) { if (*eap->cmd == '{' && ends_excmd(*skipwhite(eap->cmd + 1))) { diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 12b9bf191b..735f48807d 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -319,6 +319,20 @@ def Test_method_call_linebreak() CheckScriptSuccess(lines) enddef +def Test_method_call_whitespace() + var lines =<< trim END + new + var yank = 'text' + yank->setline(1) + yank ->setline(2) + yank-> setline(3) + yank -> setline(4) + assert_equal(['text', 'text', 'text', 'text'], getline(1, 4)) + bwipe! + END + CheckDefAndScriptSuccess(lines) +enddef + def Test_skipped_expr_linebreak() if 0 var x = [] diff --git a/src/version.c b/src/version.c index 7942e743f2..af1f7d2959 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 */ +/**/ + 2396, /**/ 2395, /**/ From dfbc5fd879d92c2a79ced1e1d16dc89f4d55772d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 23 Jan 2021 15:15:01 +0100 Subject: [PATCH 32/47] patch 8.2.2397: Vim9: "%%" not seen as alternate file name for ":bdel" Problem: Vim9: "%%" not seen as alternate file name for commands with a buffer name argument. Solution: Recognize "%%" like "#". (closes #7732) --- src/buffer.c | 11 +++++++---- src/testdir/test_vim9_cmd.vim | 11 +++++++++++ src/version.c | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index c347ef9a64..f9bffbf3d8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2564,12 +2564,15 @@ buflist_findpat( char_u *p; int toggledollar; - if (pattern_end == pattern + 1 && (*pattern == '%' || *pattern == '#')) + // "%" is current file, "%%" or "#" is alternate file + if ((pattern_end == pattern + 1 && (*pattern == '%' || *pattern == '#')) + || (in_vim9script() && pattern_end == pattern + 2 + && pattern[0] == '%' && pattern[1] == '%')) { - if (*pattern == '%') - match = curbuf->b_fnum; - else + if (*pattern == '#' || pattern_end == pattern + 2) match = curwin->w_alt_fnum; + else + match = curbuf->b_fnum; #ifdef FEAT_DIFF if (diffmode && !diff_mode_buf(buflist_findnr(match))) match = -1; diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 735f48807d..2f8fd71e95 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -68,6 +68,17 @@ def Test_expand_alternate_file() edit Xfiletwo edit %%:r assert_equal('Xfileone', bufname()) + + assert_false(bufexists('altfoo')) + edit altfoo + edit bar + assert_true(bufexists('altfoo')) + assert_true(buflisted('altfoo')) + bdel %% + assert_true(bufexists('altfoo')) + assert_false(buflisted('altfoo')) + bwipe! altfoo + bwipe! bar END CheckDefAndScriptSuccess(lines) enddef diff --git a/src/version.c b/src/version.c index af1f7d2959..f63f999e1e 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 */ +/**/ + 2397, /**/ 2396, /**/ From 40be52ba71b9d6a7f586b1e77db8e827ff4c0c42 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 23 Jan 2021 15:27:09 +0100 Subject: [PATCH 33/47] patch 8.2.2398: method test fails Problem: Method test fails. Solution: Adjust test for allowed white space. --- src/testdir/test_method.vim | 6 ++++-- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_method.vim b/src/testdir/test_method.vim index 0d55f2a894..262c08c79b 100644 --- a/src/testdir/test_method.vim +++ b/src/testdir/test_method.vim @@ -131,9 +131,11 @@ func Test_method_syntax() eval [1, 2, 3] \ ->sort( \ ) - call assert_fails('eval [1, 2, 3]-> sort()', 'E15:') + eval [1, 2, 3]-> sort() + call assert_fails('eval [1, 2, 3]->sort ()', 'E274:') - call assert_fails('eval [1, 2, 3]-> sort ()', 'E15:') + call assert_fails('eval [1, 2, 3] ->sort ()', 'E274:') + call assert_fails('eval [1, 2, 3]-> sort ()', 'E274:') endfunc func Test_method_lambda() diff --git a/src/version.c b/src/version.c index f63f999e1e..568756b397 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 */ +/**/ + 2398, /**/ 2397, /**/ From 7cf0c114d690c91ac88c92a1a6f1b1935cb6410f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 12:00:01 +0100 Subject: [PATCH 34/47] patch 8.2.2399: fold test fails in wide terminal Problem: Fold test fails in wide terminal. Solution: Adjust the test. (Dominique Pelle, closes #7731, closes #7739) --- src/testdir/test_fold.vim | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim index 895a96b127..8206193c4a 100644 --- a/src/testdir/test_fold.vim +++ b/src/testdir/test_fold.vim @@ -864,7 +864,7 @@ func Test_fold_relative_move() set fdm=indent sw=2 wrap tw=80 let content = [ ' foo', ' bar', ' baz', - \ repeat('x', 100), + \ repeat('x', &columns + 1), \ ' foo', ' bar', ' baz' \ ] call append(0, content) diff --git a/src/version.c b/src/version.c index 568756b397..55ce7133b6 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 */ +/**/ + 2399, /**/ 2398, /**/ From b204990346ca857802b174afe8a7fbb05e4f318e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 12:53:53 +0100 Subject: [PATCH 35/47] patch 8.2.2400: Vim9: compiled functions are not profiled Problem: Vim9: compiled functions are not profiled. Solution: Add initial changes to profile compiled functions. Fix that a script-local function was hard to debug. --- runtime/doc/repeat.txt | 20 +++-- src/debugger.c | 28 ++++--- src/ex_cmds.h | 2 +- src/ex_docmd.c | 2 +- src/profiler.c | 52 +++++++++++- src/proto/profiler.pro | 4 +- src/proto/vim9compile.pro | 3 +- src/structs.h | 9 +- src/testdir/test_profile.vim | 39 +++++---- src/testdir/test_vim9_disassemble.vim | 21 +++++ src/userfunc.c | 56 +++++-------- src/version.c | 2 + src/vim9.h | 9 +- src/vim9compile.c | 114 ++++++++++++++++++++++---- src/vim9execute.c | 56 ++++++++++--- src/vim9type.c | 3 +- 16 files changed, 311 insertions(+), 109 deletions(-) diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index fc699a1d78..195a2025a5 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -1,4 +1,4 @@ -*repeat.txt* For Vim version 8.2. Last change: 2021 Jan 02 +*repeat.txt* For Vim version 8.2. Last change: 2021 Jan 23 VIM REFERENCE MANUAL by Bram Moolenaar @@ -354,7 +354,7 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. Vim version, or update Vim to a newer version. See |vimscript-version| for what changed between versions. -:vim9script [noclear] *:vim9* *:vim9script* +:vim9[script] [noclear] *:vim9* *:vim9script* Marks a script file as containing |Vim9-script| commands. Also see |vim9-namespace|. Must be the first command in the file. @@ -899,8 +899,9 @@ matches ".../plugin/explorer.vim", ".../plugin/iexplorer.vim", etc. > matches ".../plugin/explorer.vim" and "explorer.vim" in any other directory. The match for functions is done against the name as it's shown in the output -of ":function". For local functions this means that something like "99_" -is prepended. +of ":function". However, for local functions the script-specific prefix such +as "99_" is ignored to make it easier to match script-local functions +without knowing the ID of the script. Note that functions are first loaded and later executed. When they are loaded the "file" breakpoints are checked, when they are executed the "func" @@ -955,10 +956,10 @@ OBSCURE Profiling means that Vim measures the time that is spent on executing functions and/or scripts. The |+profile| feature is required for this. -It is only included when Vim was compiled with "huge" features. +It is included when Vim was compiled with "huge" features. You can also use the |reltime()| function to measure time. This only requires -the |+reltime| feature, which is present more often. +the |+reltime| feature, which is present in more builds. For profiling syntax highlighting see |:syntime|. @@ -1005,7 +1006,12 @@ For example, to profile the one_script.vim script file: > You must always start with a ":profile start fname" command. The resulting -file is written when Vim exits. Here is an example of the output, with line +file is written when Vim exits. For example, to profile one specific +function: > + profile start /tmp/vimprofile + profile func MyFunc + +Here is an example of the output, with line numbers prepended for the explanation: 1 FUNCTION Test2() ~ diff --git a/src/debugger.c b/src/debugger.c index f745761f10..4e8a173186 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -864,7 +864,7 @@ has_profiling( */ static linenr_T debuggy_find( - int file, // TRUE for a file, FALSE for a function + int is_file, // TRUE for a file, FALSE for a function char_u *fname, // file or function name linenr_T after, // after this line number garray_T *gap, // either &dbg_breakp or &prof_ga @@ -873,20 +873,25 @@ debuggy_find( struct debuggy *bp; int i; linenr_T lnum = 0; - char_u *name = fname; + char_u *name = NULL; + char_u *short_name = fname; int prev_got_int; // Return quickly when there are no breakpoints. if (gap->ga_len == 0) return (linenr_T)0; - // Replace K_SNR in function name with "". - if (!file && fname[0] == K_SPECIAL) + // For a script-local function remove the prefix, so that + // "profile func Func" matches "Func" in any script. Otherwise it's very + // difficult to profile/debug a script-local function. It may match a + // function in the wrong script, but that is much better than not being + // able to profile/debug a function in a script with unknown ID. + // Also match a script-specific name. + if (!is_file && fname[0] == K_SPECIAL) { + short_name = vim_strchr(fname, '_') + 1; name = alloc(STRLEN(fname) + 3); - if (name == NULL) - name = fname; - else + if (name != NULL) { STRCPY(name, ""); STRCPY(name + 5, fname + 3); @@ -898,8 +903,8 @@ debuggy_find( // Skip entries that are not useful or are for a line that is beyond // an already found breakpoint. bp = &DEBUGGY(gap, i); - if (((bp->dbg_type == DBG_FILE) == file && - bp->dbg_type != DBG_EXPR && ( + if (((bp->dbg_type == DBG_FILE) == is_file + && bp->dbg_type != DBG_EXPR && ( #ifdef FEAT_PROFILE gap == &prof_ga || #endif @@ -910,7 +915,10 @@ debuggy_find( // while matching should abort it. prev_got_int = got_int; got_int = FALSE; - if (vim_regexec_prog(&bp->dbg_prog, FALSE, name, (colnr_T)0)) + if ((name != NULL + && vim_regexec_prog(&bp->dbg_prog, FALSE, name, (colnr_T)0)) + || vim_regexec_prog(&bp->dbg_prog, FALSE, + short_name, (colnr_T)0)) { lnum = bp->dbg_lnum; if (fp != NULL) diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 30f5221400..01c6156147 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -489,7 +489,7 @@ EXCMD(CMD_digraphs, "digraphs", ex_digraphs, EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_disassemble, "disassemble", ex_disassemble, - EX_EXTRA|EX_NEEDARG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, + EX_BANG|EX_EXTRA|EX_NEEDARG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_djump, "djump", ex_findpat, EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA, diff --git a/src/ex_docmd.c b/src/ex_docmd.c index b9ae13d0a8..3dec65e88f 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -866,7 +866,7 @@ do_cmdline( if (do_profiling == PROF_YES) { if (getline_is_func) - func_line_start(real_cookie); + func_line_start(real_cookie, SOURCING_LNUM); else if (getline_equal(fgetline, cookie, getsourceline)) script_line_start(); } diff --git a/src/profiler.c b/src/profiler.c index 7896897a44..46ab3e3059 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -554,6 +554,51 @@ func_do_profile(ufunc_T *fp) fp->uf_profiling = TRUE; } +/* + * When calling a function: may initialize for profiling. + */ + void +profile_may_start_func(profinfo_T *info, ufunc_T *fp, funccall_T *fc) +{ + if (do_profiling == PROF_YES) + { + if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL)) + { + info->pi_started_profiling = TRUE; + func_do_profile(fp); + } + if (fp->uf_profiling + || (fc->caller != NULL && fc->caller->func->uf_profiling)) + { + ++fp->uf_tm_count; + profile_start(&info->pi_call_start); + profile_zero(&fp->uf_tm_children); + } + script_prof_save(&info->pi_wait_start); + } +} + +/* + * After calling a function: may handle profiling. profile_may_start_func() + * must have been called previously. + */ + void +profile_may_end_func(profinfo_T *info, ufunc_T *fp, funccall_T *fc) +{ + profile_end(&info->pi_call_start); + profile_sub_wait(&info->pi_wait_start, &info->pi_call_start); + profile_add(&fp->uf_tm_total, &info->pi_call_start); + profile_self(&fp->uf_tm_self, &info->pi_call_start, &fp->uf_tm_children); + if (fc->caller != NULL && fc->caller->func->uf_profiling) + { + profile_add(&fc->caller->func->uf_tm_children, &info->pi_call_start); + profile_add(&fc->caller->func->uf_tml_children, &info->pi_call_start); + } + if (info->pi_started_profiling) + // make a ":profdel func" stop profiling the function + fp->uf_profiling = FALSE; +} + /* * Prepare profiling for entering a child or something else that is not * counted for the script/function itself. @@ -597,15 +642,14 @@ prof_child_exit( * until later and we need to store the time now. */ void -func_line_start(void *cookie) +func_line_start(void *cookie, long lnum) { funccall_T *fcp = (funccall_T *)cookie; ufunc_T *fp = fcp->func; - if (fp->uf_profiling && SOURCING_LNUM >= 1 - && SOURCING_LNUM <= fp->uf_lines.ga_len) + if (fp->uf_profiling && lnum >= 1 && lnum <= fp->uf_lines.ga_len) { - fp->uf_tml_idx = SOURCING_LNUM - 1; + fp->uf_tml_idx = lnum - 1; // Skip continuation lines. while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL) --fp->uf_tml_idx; diff --git a/src/proto/profiler.pro b/src/proto/profiler.pro index 5e0b6a2144..b2070df132 100644 --- a/src/proto/profiler.pro +++ b/src/proto/profiler.pro @@ -19,9 +19,11 @@ void prof_inchar_enter(void); void prof_inchar_exit(void); int prof_def_func(void); void func_do_profile(ufunc_T *fp); +void profile_may_start_func(profinfo_T *info, ufunc_T *fp, funccall_T *fc); +void profile_may_end_func(profinfo_T *info, ufunc_T *fp, funccall_T *fc); void prof_child_enter(proftime_T *tm); void prof_child_exit(proftime_T *tm); -void func_line_start(void *cookie); +void func_line_start(void *cookie, long lnum); void func_line_exec(void *cookie); void func_line_end(void *cookie); void script_do_profile(scriptitem_T *si); diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index d1d1b0c7d0..04c3c5efda 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -3,6 +3,7 @@ int check_defined(char_u *p, size_t len, cctx_T *cctx); int check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2); int use_typecheck(type_T *actual, type_T *expected); int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const); +int func_needs_compiling(ufunc_T *ufunc, int profile); int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx); imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx); imported_T *find_imported_in_script(char_u *name, size_t len, int sid); @@ -15,7 +16,7 @@ void error_white_both(char_u *op, int len); int assignment_len(char_u *p, int *heredoc); void vim9_declare_error(char_u *name); int check_vim9_unlet(char_u *name); -int compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx); +int compile_def_function(ufunc_T *ufunc, int check_return_type, int profiling, cctx_T *outer_cctx); void set_function_type(ufunc_T *ufunc); void delete_instr(isn_T *isn); void unlink_def_function(ufunc_T *ufunc); diff --git a/src/structs.h b/src/structs.h index d6bf6672aa..b092b45bb0 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1577,7 +1577,7 @@ typedef struct svar_S svar_T; #if defined(FEAT_EVAL) || defined(PROTO) typedef struct funccall_S funccall_T; -// values used for "uf_dfunc_idx" +// values used for "uf_def_status" typedef enum { UF_NOT_COMPILED, UF_TO_BE_COMPILED, @@ -1899,6 +1899,13 @@ typedef struct sn_prl_S } sn_prl_T; # define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)]) + +typedef struct { + int pi_started_profiling; + proftime_T pi_wait_start; + proftime_T pi_call_start; +} profinfo_T; + # endif #else // dummy typedefs for use in function prototypes diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index 7bac118aef..9c7cb5cde6 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -7,22 +7,27 @@ source shared.vim source screendump.vim func Test_profile_func() + call RunProfileFunc('func', 'let', 'let') + call RunProfileFunc('def', 'var', '') +endfunc + +func RunProfileFunc(command, declare, assign) let lines =<< trim [CODE] profile start Xprofile_func.log profile func Foo* - func! Foo1() - endfunc - func! Foo2() - let l:count = 100 - while l:count > 0 - let l:count = l:count - 1 + XXX Foo1() + endXXX + XXX Foo2() + DDD counter = 100 + while counter > 0 + AAA counter = counter - 1 endwhile sleep 1m - endfunc - func! Foo3() - endfunc - func! Bar() - endfunc + endXXX + XXX Foo3() + endXXX + XXX Bar() + endXXX call Foo1() call Foo1() profile pause @@ -37,6 +42,10 @@ func Test_profile_func() delfunc Foo3 [CODE] + call map(lines, {k, v -> substitute(v, 'XXX', a:command, '') }) + call map(lines, {k, v -> substitute(v, 'DDD', a:declare, '') }) + call map(lines, {k, v -> substitute(v, 'AAA', a:assign, '') }) + call writefile(lines, 'Xprofile_func.vim') call system(GetVimCommand() \ . ' -es --clean' @@ -69,10 +78,10 @@ func Test_profile_func() call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[12]) call assert_equal('', lines[13]) call assert_equal('count total (s) self (s)', lines[14]) - call assert_match('^\s*1\s\+.*\slet l:count = 100$', lines[15]) - call assert_match('^\s*101\s\+.*\swhile l:count > 0$', lines[16]) - call assert_match('^\s*100\s\+.*\s let l:count = l:count - 1$', lines[17]) - call assert_match('^\s*101\s\+.*\sendwhile$', lines[18]) + call assert_match('^\s*1\s\+.*\s\(let\|var\) counter = 100$', lines[15]) + call assert_match('^\s*101\s\+.*\swhile counter > 0$', lines[16]) + call assert_match('^\s*100\s\+.*\s \(let\)\= counter = counter - 1$', lines[17]) + call assert_match('^\s*10[01]\s\+.*\sendwhile$', lines[18]) call assert_match('^\s*1\s\+.\+sleep 1m$', lines[19]) call assert_equal('', lines[20]) call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[21]) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index f40bcf0ae0..9a3401fc32 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1842,6 +1842,27 @@ def Test_silent() res) enddef +def s:Profiled(): string + echo "profiled" + return "done" +enddef + +def Test_profiled() + var res = execute('disass! s:Profiled') + assert_match('\d*_Profiled\_s*' .. + 'echo "profiled"\_s*' .. + '\d PROFILE START line 1\_s*' .. + '\d PUSHS "profiled"\_s*' .. + '\d ECHO 1\_s*' .. + '\d PROFILE END\_s*' .. + 'return "done"\_s*' .. + '\d PROFILE START line 2\_s*' .. + '\d PUSHS "done"\_s*' .. + '\d RETURN\_s*' .. + '\d PROFILE END', + res) +enddef + def s:SilentReturn(): string silent return "done" enddef diff --git a/src/userfunc.c b/src/userfunc.c index 5372260d6d..9216685823 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1601,12 +1601,14 @@ call_user_func( char_u numbuf[NUMBUFLEN]; char_u *name; #ifdef FEAT_PROFILE - proftime_T wait_start; - proftime_T call_start; - int started_profiling = FALSE; + profinfo_T profile_info; #endif ESTACK_CHECK_DECLARATION +#ifdef FEAT_PROFILE + CLEAR_FIELD(profile_info); +#endif + // If depth of calling is getting too high, don't execute the function. if (funcdepth_increment() == FAIL) { @@ -1635,8 +1637,16 @@ call_user_func( if (fp->uf_def_status != UF_NOT_COMPILED) { // Execute the function, possibly compiling it first. +#ifdef FEAT_PROFILE + profile_may_start_func(&profile_info, fp, fc); +#endif call_def_function(fp, argcount, argvars, funcexe->partial, rettv); funcdepth_decrement(); +#ifdef FEAT_PROFILE + if (do_profiling == PROF_YES && (fp->uf_profiling + || (fc->caller != NULL && fc->caller->func->uf_profiling))) + profile_may_end_func(&profile_info, fp, fc); +#endif current_funccal = fc->caller; free_funccal(fc); return; @@ -1849,22 +1859,7 @@ call_user_func( --no_wait_return; } #ifdef FEAT_PROFILE - if (do_profiling == PROF_YES) - { - if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL)) - { - started_profiling = TRUE; - func_do_profile(fp); - } - if (fp->uf_profiling - || (fc->caller != NULL && fc->caller->func->uf_profiling)) - { - ++fp->uf_tm_count; - profile_start(&call_start); - profile_zero(&fp->uf_tm_children); - } - script_prof_save(&wait_start); - } + profile_may_start_func(&profile_info, fp, fc); #endif save_current_sctx = current_sctx; @@ -1902,20 +1897,7 @@ call_user_func( #ifdef FEAT_PROFILE if (do_profiling == PROF_YES && (fp->uf_profiling || (fc->caller != NULL && fc->caller->func->uf_profiling))) - { - profile_end(&call_start); - profile_sub_wait(&wait_start, &call_start); - profile_add(&fp->uf_tm_total, &call_start); - profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children); - if (fc->caller != NULL && fc->caller->func->uf_profiling) - { - profile_add(&fc->caller->func->uf_tm_children, &call_start); - profile_add(&fc->caller->func->uf_tml_children, &call_start); - } - if (started_profiling) - // make a ":profdel func" stop profiling the function - fp->uf_profiling = FALSE; - } + profile_may_end_func(&profile_info, fp, fc); #endif // when being verbose, mention the return value @@ -1964,7 +1946,7 @@ call_user_func( current_sctx = save_current_sctx; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) - script_prof_restore(&wait_start); + script_prof_restore(&profile_info.pi_wait_start); #endif if (using_sandbox) --sandbox; @@ -3982,7 +3964,7 @@ ex_function(exarg_T *eap) /* * :defcompile - compile all :def functions in the current script that need to - * be compiled. Except dead functions. + * be compiled. Except dead functions. Doesn't do profiling. */ void ex_defcompile(exarg_T *eap UNUSED) @@ -4002,7 +3984,7 @@ ex_defcompile(exarg_T *eap UNUSED) && ufunc->uf_def_status == UF_TO_BE_COMPILED && (ufunc->uf_flags & FC_DEAD) == 0) { - compile_def_function(ufunc, FALSE, NULL); + compile_def_function(ufunc, FALSE, FALSE, NULL); if (func_hashtab.ht_changed != changed) { @@ -4698,7 +4680,7 @@ get_func_line( SOURCING_LNUM = fcp->linenr; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) - func_line_start(cookie); + func_line_start(cookie, SOURCING_LNUM); #endif } } diff --git a/src/version.c b/src/version.c index 55ce7133b6..41858baacf 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 */ +/**/ + 2400, /**/ 2399, /**/ diff --git a/src/vim9.h b/src/vim9.h index 8d4faa3d11..9446c15bf3 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -152,6 +152,9 @@ typedef enum { ISN_CMDMOD, // set cmdmod ISN_CMDMOD_REV, // undo ISN_CMDMOD + ISN_PROF_START, // start a line for profiling + ISN_PROF_END, // end a line for profiling + ISN_UNPACK, // unpack list into items, uses isn_arg.unpack ISN_SHUFFLE, // move item on stack up or down ISN_DROP // pop stack and discard value @@ -366,8 +369,12 @@ struct dfunc_S { // was compiled. garray_T df_def_args_isn; // default argument instructions + + // After compiling "df_instr" and/or "df_instr_prof" is not NULL. isn_T *df_instr; // function body to be executed - int df_instr_count; + int df_instr_count; // size of "df_instr" + isn_T *df_instr_prof; // like "df_instr" with profiling + int df_instr_prof_count; // size of "df_instr_prof" int df_varcount; // number of local variables int df_has_closure; // one if a closure was created diff --git a/src/vim9compile.c b/src/vim9compile.c index ae5cb12f3f..5a7da1247a 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -123,6 +123,8 @@ struct cctx_S { char_u *ctx_line_start; // start of current line or NULL garray_T ctx_instr; // generated instructions + int ctx_profiling; // when TRUE generate ISN_PROF_START + garray_T ctx_locals; // currently visible local variables int ctx_locals_count; // total number of local variables @@ -1692,6 +1694,29 @@ generate_BLOBAPPEND(cctx_T *cctx) return OK; } +/* + * Return TRUE if "ufunc" should be compiled, taking into account whether + * "profile" indicates profiling is to be done. + */ + int +func_needs_compiling(ufunc_T *ufunc, int profile) +{ + switch (ufunc->uf_def_status) + { + case UF_NOT_COMPILED: return FALSE; + case UF_TO_BE_COMPILED: return TRUE; + case UF_COMPILED: + { + dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + + ufunc->uf_dfunc_idx; + + return profile ? dfunc->df_instr_prof == NULL + : dfunc->df_instr == NULL; + } + case UF_COMPILING: return FALSE; + } +} + /* * Generate an ISN_DCALL or ISN_UCALL instruction. * Return FAIL if the number of arguments is wrong. @@ -1744,10 +1769,10 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) return FAIL; } } - if (ufunc->uf_def_status == UF_TO_BE_COMPILED) - if (compile_def_function(ufunc, ufunc->uf_ret_type == NULL, NULL) - == FAIL) - return FAIL; + if (func_needs_compiling(ufunc, cctx->ctx_profiling) + && compile_def_function(ufunc, ufunc->uf_ret_type == NULL, + cctx->ctx_profiling, NULL) == FAIL) + return FAIL; } if ((isn = generate_instr(cctx, @@ -2063,6 +2088,19 @@ generate_undo_cmdmods(cctx_T *cctx) return OK; } + static void +may_generate_prof_end(cctx_T *cctx, int prof_lnum) +{ + if (cctx->ctx_profiling && prof_lnum >= 0) + { + int save_lnum = cctx->ctx_lnum; + + cctx->ctx_lnum = prof_lnum; + generate_instr(cctx, ISN_PROF_END); + cctx->ctx_lnum = save_lnum; + } +} + /* * Reserve space for a local variable. * Return the variable or NULL if it failed. @@ -2575,9 +2613,10 @@ generate_funcref(cctx_T *cctx, char_u *name) return FAIL; // Need to compile any default values to get the argument types. - if (ufunc->uf_def_status == UF_TO_BE_COMPILED) - if (compile_def_function(ufunc, TRUE, NULL) == FAIL) - return FAIL; + if (func_needs_compiling(ufunc, cctx->ctx_profiling) + && compile_def_function(ufunc, TRUE, cctx->ctx_profiling, NULL) + == FAIL) + return FAIL; return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type); } @@ -3070,7 +3109,7 @@ compile_lambda(char_u **arg, cctx_T *cctx) clear_tv(&rettv); // Compile the function into instructions. - compile_def_function(ufunc, TRUE, cctx); + compile_def_function(ufunc, TRUE, cctx->ctx_profiling, cctx); clear_evalarg(&evalarg, NULL); @@ -5047,8 +5086,9 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) r = eap->skip ? OK : FAIL; goto theend; } - if (ufunc->uf_def_status == UF_TO_BE_COMPILED - && compile_def_function(ufunc, TRUE, cctx) == FAIL) + if (func_needs_compiling(ufunc, cctx->ctx_profiling) + && compile_def_function(ufunc, TRUE, cctx->ctx_profiling, cctx) + == FAIL) { func_ptr_unref(ufunc); goto theend; @@ -7101,7 +7141,11 @@ compile_while(char_u *arg, cctx_T *cctx) if (scope == NULL) return NULL; + // "endwhile" jumps back here, one before when profiling scope->se_u.se_while.ws_top_label = instr->ga_len; + if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + --scope->se_u.se_while.ws_top_label; // compile "expr" if (compile_expr0(&p, cctx) == FAIL) @@ -7134,6 +7178,9 @@ compile_endwhile(char_u *arg, cctx_T *cctx) cctx->ctx_scope = scope->se_outer; unwind_locals(cctx, scope->se_local_count); + // count the endwhile before jumping + may_generate_prof_end(cctx, cctx->ctx_lnum); + // At end of ":for" scope jump back to the FOR instruction. generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label); @@ -7794,13 +7841,18 @@ add_def_function(ufunc_T *ufunc) * When "check_return_type" is set then set ufunc->uf_ret_type to the type of * the return statement (used for lambda). When uf_ret_type is already set * then check that it matches. + * When "profiling" is true add ISN_PROF_START instructions. * "outer_cctx" is set for a nested function. * This can be used recursively through compile_lambda(), which may reallocate * "def_functions". * Returns OK or FAIL. */ int -compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx) +compile_def_function( + ufunc_T *ufunc, + int check_return_type, + int profiling, + cctx_T *outer_cctx) { char_u *line = NULL; char_u *p; @@ -7813,6 +7865,7 @@ compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx) int save_estack_compiling = estack_compiling; int do_estack_push; int new_def_function = FALSE; + int prof_lnum = -1; // When using a function that was compiled before: Free old instructions. // The index is reused. Otherwise add a new entry in "def_functions". @@ -7832,6 +7885,8 @@ compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx) ufunc->uf_def_status = UF_COMPILING; CLEAR_FIELD(cctx); + + cctx.ctx_profiling = profiling; cctx.ctx_ufunc = ufunc; cctx.ctx_lnum = -1; cctx.ctx_outer = outer_cctx; @@ -7932,22 +7987,35 @@ compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx) { line = next_line_from_context(&cctx, FALSE); if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len) + { // beyond the last line + may_generate_prof_end(&cctx, prof_lnum); break; + } } CLEAR_FIELD(ea); ea.cmdlinep = &line; ea.cmd = skipwhite(line); + if (*ea.cmd == '#') + { + // "#" starts a comment + line = (char_u *)""; + continue; + } + + if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum) + { + may_generate_prof_end(&cctx, prof_lnum); + + prof_lnum = cctx.ctx_lnum; + generate_instr(&cctx, ISN_PROF_START); + } + // Some things can be recognized by the first character. switch (*ea.cmd) { - case '#': - // "#" starts a comment - line = (char_u *)""; - continue; - case '}': { // "}" ends a block scope @@ -8308,8 +8376,16 @@ nextline: + ufunc->uf_dfunc_idx; dfunc->df_deleted = FALSE; dfunc->df_script_seq = current_sctx.sc_seq; - dfunc->df_instr = instr->ga_data; - dfunc->df_instr_count = instr->ga_len; + if (cctx.ctx_profiling) + { + dfunc->df_instr_prof = instr->ga_data; + dfunc->df_instr_prof_count = instr->ga_len; + } + else + { + dfunc->df_instr = instr->ga_data; + dfunc->df_instr_count = instr->ga_len; + } dfunc->df_varcount = cctx.ctx_locals_count; dfunc->df_has_closure = cctx.ctx_has_closure; if (cctx.ctx_outer_used) @@ -8586,6 +8662,8 @@ delete_instr(isn_T *isn) case ISN_OPNR: case ISN_PCALL: case ISN_PCALL_END: + case ISN_PROF_END: + case ISN_PROF_START: case ISN_PUSHBOOL: case ISN_PUSHF: case ISN_PUSHNR: diff --git a/src/vim9execute.c b/src/vim9execute.c index 232c84ed7d..e4948859f9 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -294,7 +294,7 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) // Set execution state to the start of the called function. ectx->ec_dfunc_idx = cdf_idx; ectx->ec_instr = dfunc->df_instr; - entry = estack_push_ufunc(dfunc->df_ufunc, 1); + entry = estack_push_ufunc(ufunc, 1); if (entry != NULL) { // Set the script context to the script where the function was defined. @@ -645,9 +645,10 @@ call_ufunc( int error; int idx; int did_emsg_before = did_emsg; + int profiling = do_profiling == PROF_YES && ufunc->uf_profiling; - if (ufunc->uf_def_status == UF_TO_BE_COMPILED - && compile_def_function(ufunc, FALSE, NULL) == FAIL) + if (func_needs_compiling(ufunc, profiling) + && compile_def_function(ufunc, FALSE, profiling, NULL) == FAIL) return FAIL; if (ufunc->uf_def_status == UF_COMPILED) { @@ -1130,6 +1131,7 @@ call_def_function( int save_did_emsg_def = did_emsg_def; int trylevel_at_start = trylevel; int orig_funcdepth; + int profiling = do_profiling == PROF_YES && ufunc->uf_profiling; // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) @@ -1142,8 +1144,9 @@ call_def_function( #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) if (ufunc->uf_def_status == UF_NOT_COMPILED - || (ufunc->uf_def_status == UF_TO_BE_COMPILED - && compile_def_function(ufunc, FALSE, NULL) == FAIL)) + || (func_needs_compiling(ufunc, profiling) + && compile_def_function(ufunc, FALSE, profiling, NULL) + == FAIL)) { if (did_emsg_cumul + did_emsg == did_emsg_before) semsg(_(e_function_is_not_compiled_str), @@ -1155,7 +1158,7 @@ call_def_function( // Check the function was really compiled. dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; - if (dfunc->df_instr == NULL) + if ((profiling ? dfunc->df_instr_prof : dfunc->df_instr) == NULL) { iemsg("using call_def_function() on not compiled function"); return FAIL; @@ -1294,7 +1297,7 @@ call_def_function( ++ectx.ec_stack.ga_len; } - ectx.ec_instr = dfunc->df_instr; + ectx.ec_instr = profiling ? dfunc->df_instr_prof : dfunc->df_instr; } // Following errors are in the function, not the caller. @@ -3495,6 +3498,26 @@ call_def_function( } break; + case ISN_PROF_START: + case ISN_PROF_END: + { + funccall_T cookie; + ufunc_T *cur_ufunc = + (((dfunc_T *)def_functions.ga_data) + + ectx.ec_dfunc_idx)->df_ufunc; + + cookie.func = cur_ufunc; + if (iptr->isn_type == ISN_PROF_START) + { + func_line_start(&cookie, iptr->isn_lnum); + // if we get here the instruction is executed + func_line_exec(&cookie); + } + else + func_line_end(&cookie); + } + break; + case ISN_SHUFFLE: { typval_T tmp_tv; @@ -3642,6 +3665,7 @@ ex_disassemble(exarg_T *eap) ufunc_T *ufunc; dfunc_T *dfunc; isn_T *instr; + int instr_count; int current; int line_idx = 0; int prev_current = 0; @@ -3677,8 +3701,8 @@ ex_disassemble(exarg_T *eap) semsg(_(e_cannot_find_function_str), eap->arg); return; } - if (ufunc->uf_def_status == UF_TO_BE_COMPILED - && compile_def_function(ufunc, FALSE, NULL) == FAIL) + if (func_needs_compiling(ufunc, eap->forceit) + && compile_def_function(ufunc, FALSE, eap->forceit, NULL) == FAIL) return; if (ufunc->uf_def_status != UF_COMPILED) { @@ -3691,8 +3715,10 @@ ex_disassemble(exarg_T *eap) msg((char *)ufunc->uf_name); dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; - instr = dfunc->df_instr; - for (current = 0; current < dfunc->df_instr_count; ++current) + instr = eap->forceit ? dfunc->df_instr_prof : dfunc->df_instr; + instr_count = eap->forceit ? dfunc->df_instr_prof_count + : dfunc->df_instr_count; + for (current = 0; current < instr_count; ++current) { isn_T *iptr = &instr[current]; char *line; @@ -4319,6 +4345,14 @@ ex_disassemble(exarg_T *eap) } case ISN_CMDMOD_REV: smsg("%4d CMDMOD_REV", current); break; + case ISN_PROF_START: + smsg("%4d PROFILE START line %d", current, iptr->isn_lnum); + break; + + case ISN_PROF_END: + smsg("%4d PROFILE END", current); + break; + case ISN_UNPACK: smsg("%4d UNPACK %d%s", current, iptr->isn_arg.unpack.unp_count, iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : ""); diff --git a/src/vim9type.c b/src/vim9type.c index 81b0db22df..1374cee1b1 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -336,7 +336,8 @@ typval2type_int(typval_T *tv, garray_T *type_gap) // May need to get the argument types from default values by // compiling the function. if (ufunc->uf_def_status == UF_TO_BE_COMPILED - && compile_def_function(ufunc, TRUE, NULL) == FAIL) + && compile_def_function(ufunc, TRUE, FALSE, NULL) + == FAIL) return NULL; if (ufunc->uf_func_type == NULL) set_function_type(ufunc); From f002a41d127d49cfe5a59819d1498bc0ff8b594a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 13:34:18 +0100 Subject: [PATCH 36/47] patch 8.2.2401: build fails without +profiling feature Problem: Build fails without +profiling feature. Solution: Add #ifdefs. --- src/structs.h | 5 +++++ src/testdir/test_vim9_disassemble.vim | 3 +++ src/version.c | 2 ++ src/vim9.h | 6 ++++-- src/vim9compile.c | 29 +++++++++++++++++++++++---- src/vim9execute.c | 25 ++++++++++++++++++++++- 6 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/structs.h b/src/structs.h index b092b45bb0..bd59656b7c 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1906,6 +1906,11 @@ typedef struct { proftime_T pi_call_start; } profinfo_T; +# else +typedef struct +{ + int dummy; +} profinfo_T; # endif #else // dummy typedefs for use in function prototypes diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 9a3401fc32..97846a6f5f 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1848,6 +1848,9 @@ def s:Profiled(): string enddef def Test_profiled() + if !has('profile') + MissingFeature 'profile' + endif var res = execute('disass! s:Profiled') assert_match('\d*_Profiled\_s*' .. 'echo "profiled"\_s*' .. diff --git a/src/version.c b/src/version.c index 41858baacf..8786933fb2 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 */ +/**/ + 2401, /**/ 2400, /**/ diff --git a/src/vim9.h b/src/vim9.h index 9446c15bf3..f8d51c5028 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -373,8 +373,10 @@ struct dfunc_S { // After compiling "df_instr" and/or "df_instr_prof" is not NULL. isn_T *df_instr; // function body to be executed int df_instr_count; // size of "df_instr" - isn_T *df_instr_prof; // like "df_instr" with profiling - int df_instr_prof_count; // size of "df_instr_prof" +#ifdef FEAT_PROFILE + isn_T *df_instr_prof; // like "df_instr" with profiling + int df_instr_prof_count; // size of "df_instr_prof" +#endif int df_varcount; // number of local variables int df_has_closure; // one if a closure was created diff --git a/src/vim9compile.c b/src/vim9compile.c index 5a7da1247a..32d9dea1eb 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1699,22 +1699,27 @@ generate_BLOBAPPEND(cctx_T *cctx) * "profile" indicates profiling is to be done. */ int -func_needs_compiling(ufunc_T *ufunc, int profile) +func_needs_compiling(ufunc_T *ufunc, int profile UNUSED) { switch (ufunc->uf_def_status) { - case UF_NOT_COMPILED: return FALSE; + case UF_NOT_COMPILED: break; case UF_TO_BE_COMPILED: return TRUE; case UF_COMPILED: { +#ifdef FEAT_PROFILE dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; return profile ? dfunc->df_instr_prof == NULL : dfunc->df_instr == NULL; +#else + break; +#endif } - case UF_COMPILING: return FALSE; + case UF_COMPILING: break; } + return FALSE; } /* @@ -2088,6 +2093,7 @@ generate_undo_cmdmods(cctx_T *cctx) return OK; } +#ifdef FEAT_PROFILE static void may_generate_prof_end(cctx_T *cctx, int prof_lnum) { @@ -2100,6 +2106,7 @@ may_generate_prof_end(cctx_T *cctx, int prof_lnum) cctx->ctx_lnum = save_lnum; } } +#endif /* * Reserve space for a local variable. @@ -7143,9 +7150,11 @@ compile_while(char_u *arg, cctx_T *cctx) // "endwhile" jumps back here, one before when profiling scope->se_u.se_while.ws_top_label = instr->ga_len; +#ifdef FEAT_PROFILE if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1] .isn_type == ISN_PROF_START) --scope->se_u.se_while.ws_top_label; +#endif // compile "expr" if (compile_expr0(&p, cctx) == FAIL) @@ -7178,8 +7187,10 @@ compile_endwhile(char_u *arg, cctx_T *cctx) cctx->ctx_scope = scope->se_outer; unwind_locals(cctx, scope->se_local_count); +#ifdef FEAT_PROFILE // count the endwhile before jumping may_generate_prof_end(cctx, cctx->ctx_lnum); +#endif // At end of ":for" scope jump back to the FOR instruction. generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label); @@ -7851,7 +7862,7 @@ add_def_function(ufunc_T *ufunc) compile_def_function( ufunc_T *ufunc, int check_return_type, - int profiling, + int profiling UNUSED, cctx_T *outer_cctx) { char_u *line = NULL; @@ -7865,7 +7876,9 @@ compile_def_function( int save_estack_compiling = estack_compiling; int do_estack_push; int new_def_function = FALSE; +#ifdef FEAT_PROFILE int prof_lnum = -1; +#endif // When using a function that was compiled before: Free old instructions. // The index is reused. Otherwise add a new entry in "def_functions". @@ -7886,7 +7899,9 @@ compile_def_function( CLEAR_FIELD(cctx); +#ifdef FEAT_PROFILE cctx.ctx_profiling = profiling; +#endif cctx.ctx_ufunc = ufunc; cctx.ctx_lnum = -1; cctx.ctx_outer = outer_cctx; @@ -7989,7 +8004,9 @@ compile_def_function( if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len) { // beyond the last line +#ifdef FEAT_PROFILE may_generate_prof_end(&cctx, prof_lnum); +#endif break; } } @@ -8005,6 +8022,7 @@ compile_def_function( continue; } +#ifdef FEAT_PROFILE if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum) { may_generate_prof_end(&cctx, prof_lnum); @@ -8012,6 +8030,7 @@ compile_def_function( prof_lnum = cctx.ctx_lnum; generate_instr(&cctx, ISN_PROF_START); } +#endif // Some things can be recognized by the first character. switch (*ea.cmd) @@ -8376,12 +8395,14 @@ nextline: + ufunc->uf_dfunc_idx; dfunc->df_deleted = FALSE; dfunc->df_script_seq = current_sctx.sc_seq; +#ifdef FEAT_PROFILE if (cctx.ctx_profiling) { dfunc->df_instr_prof = instr->ga_data; dfunc->df_instr_prof_count = instr->ga_len; } else +#endif { dfunc->df_instr = instr->ga_data; dfunc->df_instr_count = instr->ga_len; diff --git a/src/vim9execute.c b/src/vim9execute.c index e4948859f9..f640684c6e 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -645,7 +645,11 @@ call_ufunc( int error; int idx; int did_emsg_before = did_emsg; +#ifdef FEAT_PROFILE int profiling = do_profiling == PROF_YES && ufunc->uf_profiling; +#else +# define profiling FALSE +#endif if (func_needs_compiling(ufunc, profiling) && compile_def_function(ufunc, FALSE, profiling, NULL) == FAIL) @@ -1131,7 +1135,11 @@ call_def_function( int save_did_emsg_def = did_emsg_def; int trylevel_at_start = trylevel; int orig_funcdepth; +#ifdef FEAT_PROFILE int profiling = do_profiling == PROF_YES && ufunc->uf_profiling; +#else +# define profiling FALSE +#endif // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) @@ -1158,7 +1166,11 @@ call_def_function( // Check the function was really compiled. dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; - if ((profiling ? dfunc->df_instr_prof : dfunc->df_instr) == NULL) + if (( +#ifdef FEAT_PROFILE + profiling ? dfunc->df_instr_prof : +#endif + dfunc->df_instr) == NULL) { iemsg("using call_def_function() on not compiled function"); return FAIL; @@ -1297,7 +1309,11 @@ call_def_function( ++ectx.ec_stack.ga_len; } +#ifdef FEAT_PROFILE ectx.ec_instr = profiling ? dfunc->df_instr_prof : dfunc->df_instr; +#else + ectx.ec_instr = dfunc->df_instr; +#endif } // Following errors are in the function, not the caller. @@ -3501,6 +3517,7 @@ call_def_function( case ISN_PROF_START: case ISN_PROF_END: { +#ifdef FEAT_PROFILE funccall_T cookie; ufunc_T *cur_ufunc = (((dfunc_T *)def_functions.ga_data) @@ -3515,6 +3532,7 @@ call_def_function( } else func_line_end(&cookie); +#endif } break; @@ -3715,9 +3733,14 @@ ex_disassemble(exarg_T *eap) msg((char *)ufunc->uf_name); dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; +#ifdef FEAT_PROFILE instr = eap->forceit ? dfunc->df_instr_prof : dfunc->df_instr; instr_count = eap->forceit ? dfunc->df_instr_prof_count : dfunc->df_instr_count; +#else + instr = dfunc->df_instr; + instr_count = dfunc->df_instr_count; +#endif for (current = 0; current < instr_count; ++current) { isn_T *iptr = &instr[current]; From 8323cab31c3120a7f80cf3271a506a30ec04d99e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 15:25:56 +0100 Subject: [PATCH 37/47] patch 8.2.2402: some filetypes not detected Problem: Some filetypes not detected. Solution: Detect Ruby Signature and Puppet related files. (Doug Kearns) --- runtime/filetype.vim | 22 ++++++++++++++++------ src/testdir/test_filetype.vim | 4 +++- src/version.c | 2 ++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 1e365ec081..897ac80ebc 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1176,9 +1176,10 @@ au BufNewFile,BufRead *.papp,*.pxml,*.pxsl setf papp " Password file au BufNewFile,BufRead */etc/passwd,*/etc/passwd-,*/etc/passwd.edit,*/etc/shadow,*/etc/shadow-,*/etc/shadow.edit,*/var/backups/passwd.bak,*/var/backups/shadow.bak setf passwd -" Pascal (also *.p) +" Pascal (also *.p, *.pp, *.inc) au BufNewFile,BufRead *.pas setf pascal +" Pascal or Puppet manifest au BufNewFile,BufRead *.pp call dist#ft#FTpp() " Delphi or Lazarus program file @@ -1269,7 +1270,7 @@ au BufNewFile,BufRead *.pov setf pov " Povray configuration au BufNewFile,BufRead .povrayrc setf povini -" Povray, PHP or assembly +" Povray, Pascal, PHP or assembly au BufNewFile,BufRead *.inc call dist#ft#FTinc() " Printcap and Termcap @@ -1278,13 +1279,19 @@ au BufNewFile,BufRead *printcap au BufNewFile,BufRead *termcap \ let b:ptcap_type = "term" | setf ptcap -" PCCTS / ANTRL -"au BufNewFile,BufRead *.g setf antrl +" PCCTS / ANTLR +"au BufNewFile,BufRead *.g setf antlr au BufNewFile,BufRead *.g setf pccts " PPWizard au BufNewFile,BufRead *.it,*.ih setf ppwiz +" Puppet +au BufNewFile,BufRead Puppetfile setf ruby + +" Embedded Puppet +au BufNewFile,BufRead *.epp setf epuppet + " Obj 3D file format " TODO: is there a way to avoid MS-Windows Object files? au BufNewFile,BufRead *.obj setf obj @@ -1427,8 +1434,8 @@ au BufNewFile,BufRead *.rb,*.rbw setf ruby " RubyGems au BufNewFile,BufRead *.gemspec setf ruby -" Rust -au BufNewFile,BufRead *.rs setf rust +" RBS (Ruby Signature) +au BufNewFile,BufRead *.rbs setf rbs " Rackup au BufNewFile,BufRead *.ru setf ruby @@ -1442,6 +1449,9 @@ au BufNewFile,BufRead *.builder,*.rxml,*.rjs setf ruby " Rantfile and Rakefile is like Ruby au BufNewFile,BufRead [rR]antfile,*.rant,[rR]akefile,*.rake setf ruby +" Rust +au BufNewFile,BufRead *.rs setf rust + " S-lang (or shader language, or SmallLisp) au BufNewFile,BufRead *.sl setf slang diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 2d667a297a..4104ec2b32 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -162,6 +162,7 @@ let s:filename_checks = { \ 'elinks': ['elinks.conf'], \ 'elm': ['file.elm'], \ 'elmfilt': ['filter-rules'], + \ 'epuppet': ['file.epp'], \ 'erlang': ['file.erl', 'file.hrl', 'file.yaws'], \ 'eruby': ['file.erb', 'file.rhtml'], \ 'esmtprc': ['anyesmtprc', 'esmtprc', 'some-esmtprc'], @@ -391,6 +392,7 @@ let s:filename_checks = { \ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg', 'baseq2/file.cfg', 'id1/file.cfg', 'quake1/file.cfg', 'some-baseq2/file.cfg', 'some-id1/file.cfg', 'some-quake1/file.cfg'], \ 'radiance': ['file.rad', 'file.mat'], \ 'ratpoison': ['.ratpoisonrc', 'ratpoisonrc'], + \ 'rbs': ['file.rbs'], \ 'rc': ['file.rc', 'file.rch'], \ 'rcs': ['file,v'], \ 'readline': ['.inputrc', 'inputrc'], @@ -407,7 +409,7 @@ let s:filename_checks = { \ 'rpl': ['file.rpl'], \ 'rst': ['file.rst'], \ 'rtf': ['file.rtf'], - \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file'], + \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file', 'Puppetfile'], \ 'rust': ['file.rs'], \ 'samba': ['smb.conf'], \ 'sas': ['file.sas'], diff --git a/src/version.c b/src/version.c index 8786933fb2..1a7994b9c8 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 */ +/**/ + 2402, /**/ 2401, /**/ From ced68a0070dac059fc978a1a99e2893edf158116 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 17:53:47 +0100 Subject: [PATCH 38/47] patch 8.2.2403: Vim9: profiling if/elseif/endif not correct Problem: Vim9: profiling if/elseif/endif not correct. Solution: Add profile instructions. Fix that "elseif" was wrong. --- src/testdir/test_profile.vim | 57 ++++++++++-------- src/testdir/test_vim9_disassemble.vim | 2 +- src/testdir/test_vim9_script.vim | 2 +- src/version.c | 2 + src/vim9compile.c | 87 ++++++++++++++++++++++++--- 5 files changed, 115 insertions(+), 35 deletions(-) diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index 9c7cb5cde6..d037c778e5 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -100,39 +100,48 @@ func RunProfileFunc(command, declare, assign) endfunc func Test_profile_func_with_ifelse() + call Run_profile_func_with_ifelse('func', 'let', 'let') + call Run_profile_func_with_ifelse('def', 'var', '') +endfunc + +func Run_profile_func_with_ifelse(command, declare, assign) let lines =<< trim [CODE] - func! Foo1() + XXX Foo1() if 1 - let x = 0 + DDD x = 0 elseif 1 - let x = 1 + DDD x = 1 else - let x = 2 + DDD x = 2 endif - endfunc - func! Foo2() + endXXX + XXX Foo2() if 0 - let x = 0 + DDD x = 0 elseif 1 - let x = 1 + DDD x = 1 else - let x = 2 + DDD x = 2 endif - endfunc - func! Foo3() + endXXX + XXX Foo3() if 0 - let x = 0 + DDD x = 0 elseif 0 - let x = 1 + DDD x = 1 else - let x = 2 + DDD x = 2 endif - endfunc + endXXX call Foo1() call Foo2() call Foo3() [CODE] + call map(lines, {k, v -> substitute(v, 'XXX', a:command, '') }) + call map(lines, {k, v -> substitute(v, 'DDD', a:declare, '') }) + call map(lines, {k, v -> substitute(v, 'AAA', a:assign, '') }) + call writefile(lines, 'Xprofile_func.vim') call system(GetVimCommand() \ . ' -es -i NONE --noplugin' @@ -157,11 +166,11 @@ func Test_profile_func_with_ifelse() call assert_equal('', lines[5]) call assert_equal('count total (s) self (s)', lines[6]) call assert_match('^\s*1\s\+.*\sif 1$', lines[7]) - call assert_match('^\s*1\s\+.*\s let x = 0$', lines[8]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 0$', lines[8]) call assert_match( '^\s\+elseif 1$', lines[9]) - call assert_match( '^\s\+let x = 1$', lines[10]) + call assert_match( '^\s\+\(let\|var\) x = 1$', lines[10]) call assert_match( '^\s\+else$', lines[11]) - call assert_match( '^\s\+let x = 2$', lines[12]) + call assert_match( '^\s\+\(let\|var\) x = 2$', lines[12]) call assert_match('^\s*1\s\+.*\sendif$', lines[13]) call assert_equal('', lines[14]) call assert_equal('FUNCTION Foo2()', lines[15]) @@ -171,11 +180,11 @@ func Test_profile_func_with_ifelse() call assert_equal('', lines[20]) call assert_equal('count total (s) self (s)', lines[21]) call assert_match('^\s*1\s\+.*\sif 0$', lines[22]) - call assert_match( '^\s\+let x = 0$', lines[23]) + call assert_match( '^\s\+\(let\|var\) x = 0$', lines[23]) call assert_match('^\s*1\s\+.*\selseif 1$', lines[24]) - call assert_match('^\s*1\s\+.*\s let x = 1$', lines[25]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 1$', lines[25]) call assert_match( '^\s\+else$', lines[26]) - call assert_match( '^\s\+let x = 2$', lines[27]) + call assert_match( '^\s\+\(let\|var\) x = 2$', lines[27]) call assert_match('^\s*1\s\+.*\sendif$', lines[28]) call assert_equal('', lines[29]) call assert_equal('FUNCTION Foo3()', lines[30]) @@ -185,11 +194,11 @@ func Test_profile_func_with_ifelse() call assert_equal('', lines[35]) call assert_equal('count total (s) self (s)', lines[36]) call assert_match('^\s*1\s\+.*\sif 0$', lines[37]) - call assert_match( '^\s\+let x = 0$', lines[38]) + call assert_match( '^\s\+\(let\|var\) x = 0$', lines[38]) call assert_match('^\s*1\s\+.*\selseif 0$', lines[39]) - call assert_match( '^\s\+let x = 1$', lines[40]) + call assert_match( '^\s\+\(let\|var\) x = 1$', lines[40]) call assert_match('^\s*1\s\+.*\selse$', lines[41]) - call assert_match('^\s*1\s\+.*\s let x = 2$', lines[42]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 2$', lines[42]) call assert_match('^\s*1\s\+.*\sendif$', lines[43]) call assert_equal('', lines[44]) call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[45]) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 97846a6f5f..1c57432485 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1857,8 +1857,8 @@ def Test_profiled() '\d PROFILE START line 1\_s*' .. '\d PUSHS "profiled"\_s*' .. '\d ECHO 1\_s*' .. - '\d PROFILE END\_s*' .. 'return "done"\_s*' .. + '\d PROFILE END\_s*' .. '\d PROFILE START line 2\_s*' .. '\d PUSHS "done"\_s*' .. '\d RETURN\_s*' .. diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 9dadf1edaa..0d9586d768 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1741,7 +1741,7 @@ def Test_if_elseif_else_fails() CheckDefFailure(['elseif true'], 'E582:') CheckDefFailure(['else'], 'E581:') CheckDefFailure(['endif'], 'E580:') - CheckDefFailure(['if true', 'elseif xxx'], 'E1001:') + CheckDefFailure(['if g:abool', 'elseif xxx'], 'E1001:') CheckDefFailure(['if true', 'echo 1'], 'E171:') enddef diff --git a/src/version.c b/src/version.c index 1a7994b9c8..554231fd00 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 */ +/**/ + 2403, /**/ 2402, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 32d9dea1eb..995083099c 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -44,6 +44,7 @@ struct endlabel_S { */ typedef struct { int is_seen_else; + int is_seen_skip_not; // a block was unconditionally executed int is_had_return; // every block ends in :return int is_if_label; // instruction idx at IF or ELSEIF endlabel_T *is_end_label; // instructions to set end label @@ -2098,13 +2099,7 @@ generate_undo_cmdmods(cctx_T *cctx) may_generate_prof_end(cctx_T *cctx, int prof_lnum) { if (cctx->ctx_profiling && prof_lnum >= 0) - { - int save_lnum = cctx->ctx_lnum; - - cctx->ctx_lnum = prof_lnum; generate_instr(cctx, ISN_PROF_END); - cctx->ctx_lnum = save_lnum; - } } #endif @@ -6735,6 +6730,18 @@ compile_if(char_u *arg, cctx_T *cctx) else scope->se_u.se_if.is_if_label = -1; +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES + && skip_save != SKIP_YES) + { + // generated a profile start, need to generate a profile end, since it + // won't be done after returning + cctx->ctx_skip = SKIP_NOT; + generate_instr(cctx, ISN_PROF_END); + cctx->ctx_skip = SKIP_YES; + } +#endif + return p; } @@ -6758,6 +6765,25 @@ compile_elseif(char_u *arg, cctx_T *cctx) if (!cctx->ctx_had_return) scope->se_u.se_if.is_had_return = FALSE; + if (cctx->ctx_skip == SKIP_NOT) + { + // previous block was executed, this one and following will not + cctx->ctx_skip = SKIP_YES; + scope->se_u.se_if.is_seen_skip_not = TRUE; + } + if (scope->se_u.se_if.is_seen_skip_not) + { + // A previous block was executed, skip over expression and bail out. + // Do not count the "elseif" for profiling. +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + --instr->ga_len; +#endif + skip_expr_cctx(&p, cctx); + return p; + } + if (cctx->ctx_skip == SKIP_UNKNOWN) { if (compile_jump_to_end(&scope->se_u.se_if.is_end_label, @@ -6771,7 +6797,17 @@ compile_elseif(char_u *arg, cctx_T *cctx) // compile "expr"; if we know it evaluates to FALSE skip the block CLEAR_FIELD(ppconst); if (cctx->ctx_skip == SKIP_YES) + { cctx->ctx_skip = SKIP_UNKNOWN; +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling) + { + // the previous block was skipped, need to profile this line + generate_instr(cctx, ISN_PROF_START); + instr_count = instr->ga_len; + } +#endif + } if (compile_expr1(&p, cctx, &ppconst) == FAIL) { clear_ppconst(&ppconst); @@ -6829,7 +6865,27 @@ compile_else(char_u *arg, cctx_T *cctx) scope->se_u.se_if.is_had_return = FALSE; scope->se_u.se_if.is_seen_else = TRUE; - if (scope->se_skip_save != SKIP_YES) +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling) + { + if (cctx->ctx_skip == SKIP_NOT + && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + // the previous block was executed, do not count "else" for profiling + --instr->ga_len; + if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not) + { + // the previous block was not executed, this one will, do count the + // "else" for profiling + cctx->ctx_skip = SKIP_NOT; + generate_instr(cctx, ISN_PROF_END); + generate_instr(cctx, ISN_PROF_START); + cctx->ctx_skip = SKIP_YES; + } + } +#endif + + if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES) { // jump from previous block to the end, unless the else block is empty if (cctx->ctx_skip == SKIP_UNKNOWN) @@ -6884,6 +6940,17 @@ compile_endif(char_u *arg, cctx_T *cctx) } // Fill in the "end" label in jumps at the end of the blocks. compile_fill_jump_to_end(&ifscope->is_end_label, cctx); + +#ifdef FEAT_PROFILE + // even when skipping we count the endif as executed, unless the block it's + // in is skipped + if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES + && scope->se_skip_save != SKIP_YES) + { + cctx->ctx_skip = SKIP_NOT; + generate_instr(cctx, ISN_PROF_START); + } +#endif cctx->ctx_skip = scope->se_skip_save; // If all the blocks end in :return and there is an :else then the @@ -8005,7 +8072,8 @@ compile_def_function( { // beyond the last line #ifdef FEAT_PROFILE - may_generate_prof_end(&cctx, prof_lnum); + if (cctx.ctx_skip != SKIP_YES) + may_generate_prof_end(&cctx, prof_lnum); #endif break; } @@ -8023,7 +8091,8 @@ compile_def_function( } #ifdef FEAT_PROFILE - if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum) + if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum && + cctx.ctx_skip != SKIP_YES) { may_generate_prof_end(&cctx, prof_lnum); From 107e9cecf72928b4aaaf08b73bf2d191924ab695 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 20:52:00 +0100 Subject: [PATCH 39/47] patch 8.2.2404: Vim9: profiling try/catch not correct Problem: Vim9: profiling try/catch not correct. Solution: Add profile instructions. Fix that "entry" did not rethrow an excpetion. --- src/testdir/test_profile.vim | 57 +++++++++++++++++----------- src/version.c | 2 + src/vim9compile.c | 60 +++++++++++++++++++++++++----- src/vim9execute.c | 72 +++++++++++++++++++++++------------- 4 files changed, 133 insertions(+), 58 deletions(-) diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index d037c778e5..8aaac90e89 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -100,11 +100,11 @@ func RunProfileFunc(command, declare, assign) endfunc func Test_profile_func_with_ifelse() - call Run_profile_func_with_ifelse('func', 'let', 'let') - call Run_profile_func_with_ifelse('def', 'var', '') + call Run_profile_func_with_ifelse('func', 'let') + call Run_profile_func_with_ifelse('def', 'var') endfunc -func Run_profile_func_with_ifelse(command, declare, assign) +func Run_profile_func_with_ifelse(command, declare) let lines =<< trim [CODE] XXX Foo1() if 1 @@ -140,7 +140,6 @@ func Run_profile_func_with_ifelse(command, declare, assign) call map(lines, {k, v -> substitute(v, 'XXX', a:command, '') }) call map(lines, {k, v -> substitute(v, 'DDD', a:declare, '') }) - call map(lines, {k, v -> substitute(v, 'AAA', a:assign, '') }) call writefile(lines, 'Xprofile_func.vim') call system(GetVimCommand() @@ -219,42 +218,56 @@ func Run_profile_func_with_ifelse(command, declare, assign) endfunc func Test_profile_func_with_trycatch() + call Run_profile_func_with_trycatch('func', 'let') + call Run_profile_func_with_trycatch('def', 'var') +endfunc + +func Run_profile_func_with_trycatch(command, declare) let lines =<< trim [CODE] - func! Foo1() + XXX Foo1() try - let x = 0 + DDD x = 0 catch - let x = 1 + DDD x = 1 finally - let x = 2 + DDD x = 2 endtry - endfunc - func! Foo2() + endXXX + XXX Foo2() try throw 0 catch - let x = 1 + DDD x = 1 finally - let x = 2 + DDD x = 2 endtry - endfunc - func! Foo3() + endXXX + XXX Foo3() try throw 0 catch throw 1 finally - let x = 2 + DDD x = 2 endtry - endfunc + endXXX call Foo1() call Foo2() + let rethrown = 0 try call Foo3() catch + let rethrown = 1 endtry + if rethrown != 1 + " call Foo1 again so that the test fails + call Foo1() + endif [CODE] + call map(lines, {k, v -> substitute(v, 'XXX', a:command, '') }) + call map(lines, {k, v -> substitute(v, 'DDD', a:declare, '') }) + call writefile(lines, 'Xprofile_func.vim') call system(GetVimCommand() \ . ' -es -i NONE --noplugin' @@ -279,11 +292,11 @@ func Test_profile_func_with_trycatch() call assert_equal('', lines[5]) call assert_equal('count total (s) self (s)', lines[6]) call assert_match('^\s*1\s\+.*\stry$', lines[7]) - call assert_match('^\s*1\s\+.*\s let x = 0$', lines[8]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 0$', lines[8]) call assert_match( '^\s\+catch$', lines[9]) - call assert_match( '^\s\+let x = 1$', lines[10]) + call assert_match( '^\s\+\(let\|var\) x = 1$', lines[10]) call assert_match('^\s*1\s\+.*\sfinally$', lines[11]) - call assert_match('^\s*1\s\+.*\s let x = 2$', lines[12]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 2$', lines[12]) call assert_match('^\s*1\s\+.*\sendtry$', lines[13]) call assert_equal('', lines[14]) call assert_equal('FUNCTION Foo2()', lines[15]) @@ -295,9 +308,9 @@ func Test_profile_func_with_trycatch() call assert_match('^\s*1\s\+.*\stry$', lines[22]) call assert_match('^\s*1\s\+.*\s throw 0$', lines[23]) call assert_match('^\s*1\s\+.*\scatch$', lines[24]) - call assert_match('^\s*1\s\+.*\s let x = 1$', lines[25]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 1$', lines[25]) call assert_match('^\s*1\s\+.*\sfinally$', lines[26]) - call assert_match('^\s*1\s\+.*\s let x = 2$', lines[27]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 2$', lines[27]) call assert_match('^\s*1\s\+.*\sendtry$', lines[28]) call assert_equal('', lines[29]) call assert_equal('FUNCTION Foo3()', lines[30]) @@ -311,7 +324,7 @@ func Test_profile_func_with_trycatch() call assert_match('^\s*1\s\+.*\scatch$', lines[39]) call assert_match('^\s*1\s\+.*\s throw 1$', lines[40]) call assert_match('^\s*1\s\+.*\sfinally$', lines[41]) - call assert_match('^\s*1\s\+.*\s let x = 2$', lines[42]) + call assert_match('^\s*1\s\+.*\s \(let\|var\) x = 2$', lines[42]) call assert_match( '^\s\+endtry$', lines[43]) call assert_equal('', lines[44]) call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[45]) diff --git a/src/version.c b/src/version.c index 554231fd00..43ad049da5 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 */ +/**/ + 2404, /**/ 2403, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 995083099c..9497782ff9 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6566,7 +6566,7 @@ compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx) } static void -compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx) +compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx) { garray_T *instr = &cctx->ctx_instr; @@ -6576,7 +6576,7 @@ compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx) isn_T *isn; isn = ((isn_T *)instr->ga_data) + cur->el_end_label; - isn->isn_arg.jump.jump_where = instr->ga_len; + isn->isn_arg.jump.jump_where = jump_where; *el = cur->el_next; vim_free(cur); } @@ -6939,7 +6939,7 @@ compile_endif(char_u *arg, cctx_T *cctx) isn->isn_arg.jump.jump_where = instr->ga_len; } // Fill in the "end" label in jumps at the end of the blocks. - compile_fill_jump_to_end(&ifscope->is_end_label, cctx); + compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx); #ifdef FEAT_PROFILE // even when skipping we count the endif as executed, unless the block it's @@ -7182,7 +7182,7 @@ compile_endfor(char_u *arg, cctx_T *cctx) isn->isn_arg.forloop.for_end = instr->ga_len; // Fill in the "end" label any BREAK statements - compile_fill_jump_to_end(&forscope->fs_end_label, cctx); + compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx); // Below the ":for" scope drop the "expr" list from the stack. if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL) @@ -7245,6 +7245,7 @@ compile_while(char_u *arg, cctx_T *cctx) compile_endwhile(char_u *arg, cctx_T *cctx) { scope_T *scope = cctx->ctx_scope; + garray_T *instr = &cctx->ctx_instr; if (scope == NULL || scope->se_type != WHILE_SCOPE) { @@ -7264,7 +7265,8 @@ compile_endwhile(char_u *arg, cctx_T *cctx) // Fill in the "end" label in the WHILE statement so it can jump here. // And in any jumps for ":break" - compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx); + compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, + instr->ga_len, cctx); vim_free(scope); @@ -7446,6 +7448,12 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED) if (cctx->ctx_skip != SKIP_YES) { +#ifdef FEAT_PROFILE + // the profile-start should be after the jump + if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + --instr->ga_len; +#endif // Jump from end of previous block to :finally or :endtry if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label, JUMP_ALWAYS, cctx) == FAIL) @@ -7461,6 +7469,15 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED) isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label; isn->isn_arg.jump.jump_where = instr->ga_len; } +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling) + { + // a "throw" that jumps here needs to be counted + generate_instr(cctx, ISN_PROF_END); + // the "catch" is also counted + generate_instr(cctx, ISN_PROF_START); + } +#endif } p = skipwhite(arg); @@ -7521,6 +7538,7 @@ compile_finally(char_u *arg, cctx_T *cctx) scope_T *scope = cctx->ctx_scope; garray_T *instr = &cctx->ctx_instr; isn_T *isn; + int this_instr; // end block scope from :try or :catch if (scope != NULL && scope->se_type == BLOCK_SCOPE) @@ -7542,15 +7560,24 @@ compile_finally(char_u *arg, cctx_T *cctx) return NULL; } - // Fill in the "end" label in jumps at the end of the blocks. - compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx); + this_instr = instr->ga_len; +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + // jump to the profile start of the "finally" + --this_instr; +#endif - isn->isn_arg.try.try_finally = instr->ga_len; + // Fill in the "end" label in jumps at the end of the blocks. + compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, + this_instr, cctx); + + isn->isn_arg.try.try_finally = this_instr; if (scope->se_u.se_try.ts_catch_label != 0) { // Previous catch without match jumps here isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label; - isn->isn_arg.jump.jump_where = instr->ga_len; + isn->isn_arg.jump.jump_where = this_instr; scope->se_u.se_try.ts_catch_label = 0; } @@ -7595,9 +7622,18 @@ compile_endtry(char_u *arg, cctx_T *cctx) return NULL; } +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_PROF_START) + // move the profile start after "endtry" so that it's not counted when + // the exception is rethrown. + --instr->ga_len; +#endif + // Fill in the "end" label in jumps at the end of the blocks, if not // done by ":finally". - compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx); + compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, + instr->ga_len, cctx); // End :catch or :finally scope: set value in ISN_TRY instruction if (isn->isn_arg.try.try_catch == 0) @@ -7617,6 +7653,10 @@ compile_endtry(char_u *arg, cctx_T *cctx) if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_ENDTRY) == NULL) return NULL; +#ifdef FEAT_PROFILE + if (cctx->ctx_profiling) + generate_instr(cctx, ISN_PROF_START); +#endif return arg; } diff --git a/src/vim9execute.c b/src/vim9execute.c index f640684c6e..4c144f67ae 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2613,7 +2613,7 @@ call_def_function( if (trystack->ga_len > 0) { - trycmd_T *trycmd = NULL; + trycmd_T *trycmd; --trystack->ga_len; --trylevel; @@ -2635,34 +2635,54 @@ call_def_function( break; case ISN_THROW: - if (ectx.ec_trystack.ga_len == 0 && trylevel == 0 - && emsg_silent) { - // throwing an exception while using "silent!" causes the - // function to abort but not display an error. - tv = STACK_TV_BOT(-1); - clear_tv(tv); - tv->v_type = VAR_NUMBER; - tv->vval.v_number = 0; - goto done; - } - --ectx.ec_stack.ga_len; - tv = STACK_TV_BOT(0); - if (tv->vval.v_string == NULL - || *skipwhite(tv->vval.v_string) == NUL) - { - vim_free(tv->vval.v_string); - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_throw_with_empty_string)); - goto failed; - } + garray_T *trystack = &ectx.ec_trystack; - if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL) - { - vim_free(tv->vval.v_string); - goto failed; + if (trystack->ga_len == 0 && trylevel == 0 && emsg_silent) + { + // throwing an exception while using "silent!" causes + // the function to abort but not display an error. + tv = STACK_TV_BOT(-1); + clear_tv(tv); + tv->v_type = VAR_NUMBER; + tv->vval.v_number = 0; + goto done; + } + --ectx.ec_stack.ga_len; + tv = STACK_TV_BOT(0); + if (tv->vval.v_string == NULL + || *skipwhite(tv->vval.v_string) == NUL) + { + vim_free(tv->vval.v_string); + SOURCING_LNUM = iptr->isn_lnum; + emsg(_(e_throw_with_empty_string)); + goto failed; + } + + // Inside a "catch" we need to first discard the caught + // exception. + if (trystack->ga_len > 0) + { + trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) + + trystack->ga_len - 1; + if (trycmd->tcd_caught && current_exception != NULL) + { + // discard the exception + if (caught_stack == current_exception) + caught_stack = caught_stack->caught; + discard_current_exception(); + trycmd->tcd_caught = FALSE; + } + } + + if (throw_exception(tv->vval.v_string, ET_USER, NULL) + == FAIL) + { + vim_free(tv->vval.v_string); + goto failed; + } + did_throw = TRUE; } - did_throw = TRUE; break; // compare with special values From 4efd9948291801bffebf36b4a9910d08ff981987 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 21:14:20 +0100 Subject: [PATCH 40/47] patch 8.2.2405: Vim9: no need to allow white space before "(" for :def Problem: Vim9: no need to allow white space before "(" for :def. Solution: Give an error for stray white space. (issue #7734) --- src/testdir/test_vim9_func.vim | 32 ++++++++++++++++++++++++++++++++ src/userfunc.c | 6 ++++++ src/version.c | 2 ++ 3 files changed, 40 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index fc1ed2120a..a5855adcbc 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -116,6 +116,38 @@ def Test_missing_endfunc_enddef() CheckScriptFailure(lines, 'E126:', 2) enddef +def Test_white_space_before_paren() + var lines =<< trim END + vim9script + def Test () + echo 'test' + enddef + END + CheckScriptFailure(lines, 'E1068:', 2) + + lines =<< trim END + vim9script + func Test () + echo 'test' + endfunc + END + CheckScriptFailure(lines, 'E1068:', 2) + + lines =<< trim END + def Test () + echo 'test' + enddef + END + CheckScriptFailure(lines, 'E1068:', 1) + + lines =<< trim END + func Test () + echo 'test' + endfunc + END + CheckScriptSuccess(lines) +enddef + def Test_enddef_dict_key() var d = { enddef: 'x', diff --git a/src/userfunc.c b/src/userfunc.c index 9216685823..0f28b028e7 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3199,6 +3199,12 @@ define_function(exarg_T *eap, char_u *name_arg) p = vim_strchr(p, '('); } + if ((vim9script || eap->cmdidx == CMD_def) && VIM_ISWHITE(p[-1])) + { + semsg(_(e_no_white_space_allowed_before_str), "("); + goto ret_free; + } + // In Vim9 script only global functions can be redefined. if (vim9script && eap->forceit && !is_global) { diff --git a/src/version.c b/src/version.c index 43ad049da5..136448a352 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 */ +/**/ + 2405, /**/ 2404, /**/ From c05fe07529f10fc32a2086cb44a708520c8d14ce Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 24 Jan 2021 21:30:48 +0100 Subject: [PATCH 41/47] patch 8.2.2406: Vim9: profiled :def function leaks memory Problem: Vim9: profiled :def function leaks memory. Solution: Delete the profiled instructions. --- src/version.c | 2 ++ src/vim9compile.c | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/version.c b/src/version.c index 136448a352..5153086b02 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 */ +/**/ + 2406, /**/ 2405, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 9497782ff9..2dd3a4ffec 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -8837,6 +8837,15 @@ delete_def_function_contents(dfunc_T *dfunc, int mark_deleted) VIM_CLEAR(dfunc->df_instr); dfunc->df_instr = NULL; } +#ifdef FEAT_PROFILE + if (dfunc->df_instr_prof != NULL) + { + for (idx = 0; idx < dfunc->df_instr_prof_count; ++idx) + delete_instr(dfunc->df_instr_prof + idx); + VIM_CLEAR(dfunc->df_instr_prof); + dfunc->df_instr_prof = NULL; + } +#endif if (mark_deleted) dfunc->df_deleted = TRUE; From ab55f11d9bc776d546794748bc62ac47d5340c2e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 25 Jan 2021 18:44:57 +0100 Subject: [PATCH 42/47] patch 8.2.2407: old jumplist code is never used Problem: Old jumplist code is never used. Solution: Delete the dead code. (Yegappan Lakshmanan, closes #7740) --- src/mark.c | 21 --------------------- src/version.c | 2 ++ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/mark.c b/src/mark.c index 5efda8e0eb..6107c9ac4e 100644 --- a/src/mark.c +++ b/src/mark.c @@ -140,9 +140,6 @@ setpcmark(void) int i; xfmark_T *fm; #endif -#ifdef JUMPLIST_ROTATE - xfmark_T tempmark; -#endif // for :global the mark is set only once if (global_busy || listcmd_busy || (cmdmod.cmod_flags & CMOD_KEEPJUMPS)) @@ -152,24 +149,6 @@ setpcmark(void) curwin->w_pcmark = curwin->w_cursor; #ifdef FEAT_JUMPLIST -# ifdef JUMPLIST_ROTATE - /* - * If last used entry is not at the top, put it at the top by rotating - * the stack until it is (the newer entries will be at the bottom). - * Keep one entry (the last used one) at the top. - */ - if (curwin->w_jumplistidx < curwin->w_jumplistlen) - ++curwin->w_jumplistidx; - while (curwin->w_jumplistidx < curwin->w_jumplistlen) - { - tempmark = curwin->w_jumplist[curwin->w_jumplistlen - 1]; - for (i = curwin->w_jumplistlen - 1; i > 0; --i) - curwin->w_jumplist[i] = curwin->w_jumplist[i - 1]; - curwin->w_jumplist[0] = tempmark; - ++curwin->w_jumplistidx; - } -# endif - // If jumplist is full: remove oldest entry if (++curwin->w_jumplistlen > JUMPLISTSIZE) { diff --git a/src/version.c b/src/version.c index 5153086b02..0602b9d876 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 */ +/**/ + 2407, /**/ 2406, /**/ From 5c829bf229de463657e4ba1de6c4ee91899de14e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 25 Jan 2021 19:18:02 +0100 Subject: [PATCH 43/47] patch 8.2.2408: MinGW: "--preprocessor" flag no longer supported Problem: MinGW: "--preprocessor" flag no longer supported. Solution: Remove the flag, use the defaults. (Christopher Wellons, closes #7741) --- src/GvimExt/Make_ming.mak | 4 ++-- src/Make_cyg_ming.mak | 4 ++-- src/version.c | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/GvimExt/Make_ming.mak b/src/GvimExt/Make_ming.mak index a6ab3ae10e..8d17142817 100644 --- a/src/GvimExt/Make_ming.mak +++ b/src/GvimExt/Make_ming.mak @@ -49,8 +49,8 @@ WINVER = 0x0501 endif CXX := $(CROSS_COMPILE)g++ WINDRES := $(CROSS_COMPILE)windres -WINDRES_CXX = $(CXX) -WINDRES_FLAGS = --preprocessor="$(WINDRES_CXX) -E -xc" -DRC_INVOKED +# this used to have --preprocessor, but it's no longer supported +WINDRES_FLAGS = LIBS := -luuid -lgdi32 RES := gvimext.res DEFFILE = gvimext_ming.def diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index b6dd928b12..8895d2797f 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -220,7 +220,6 @@ WINDRES := $(CROSS_COMPILE)windres else WINDRES := windres endif -WINDRES_CC = $(CC) # Get the default ARCH. ifndef ARCH @@ -514,7 +513,8 @@ endif CFLAGS = -I. -Iproto $(DEFINES) -pipe -march=$(ARCH) -Wall CXXFLAGS = -std=gnu++11 -WINDRES_FLAGS = --preprocessor="$(WINDRES_CC) -E -xc" -DRC_INVOKED +# This used to have --preprocessor, but it's no longer supported +WINDRES_FLAGS = EXTRA_LIBS = ifdef GETTEXT diff --git a/src/version.c b/src/version.c index 0602b9d876..dce32e7336 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 */ +/**/ + 2408, /**/ 2407, /**/ From e5ea346a07a7750c02a89996b67716b43c767d06 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 25 Jan 2021 21:01:48 +0100 Subject: [PATCH 44/47] patch 8.2.2409: Vim9: profiling only works for one function Problem: Vim9: profiling only works for one function. Solution: Select the right instructions when calling and returning. (closes #7743) --- src/testdir/test_profile.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ src/vim9.h | 10 ++++++++++ src/vim9compile.c | 14 +++++++------- src/vim9execute.c | 36 +++++++++++++++++------------------- 5 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index 8aaac90e89..3abe898052 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -5,6 +5,7 @@ CheckFeature profile source shared.vim source screendump.vim +source vim9.vim func Test_profile_func() call RunProfileFunc('func', 'let', 'let') @@ -583,4 +584,21 @@ func Test_profile_typed_func() call delete('XtestProfile') endfunc +func Test_vim9_profiling() + " only tests that compiling and calling functions doesn't crash + let lines =<< trim END + vim9script + def Func() + Crash() + enddef + def Crash() + enddef + prof start /tmp/profile.log + prof func Func + Func() + END + call CheckScriptSuccess(lines) +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index dce32e7336..279c49d0c1 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 */ +/**/ + 2409, /**/ 2408, /**/ diff --git a/src/vim9.h b/src/vim9.h index f8d51c5028..76ec40303d 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -408,3 +408,13 @@ extern garray_T def_functions; // Used for "lnum" when a range is to be taken from the stack and "!" is used. #define LNUM_VARIABLE_RANGE_ABOVE -888 + +#ifdef FEAT_PROFILE +# define PROFILING(ufunc) (do_profiling == PROF_YES && (ufunc)->uf_profiling) +# define INSTRUCTIONS(dfunc) \ + ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \ + ? (dfunc)->df_instr_prof : (dfunc)->df_instr) +#else +# define PROFILING FALSE +# define INSTRUCTIONS(dfunc) ((dfunc)->df_instr) +#endif diff --git a/src/vim9compile.c b/src/vim9compile.c index 2dd3a4ffec..5b9f7f5184 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1775,9 +1775,9 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) return FAIL; } } - if (func_needs_compiling(ufunc, cctx->ctx_profiling) + if (func_needs_compiling(ufunc, PROFILING(ufunc)) && compile_def_function(ufunc, ufunc->uf_ret_type == NULL, - cctx->ctx_profiling, NULL) == FAIL) + PROFILING(ufunc), NULL) == FAIL) return FAIL; } @@ -2615,8 +2615,8 @@ generate_funcref(cctx_T *cctx, char_u *name) return FAIL; // Need to compile any default values to get the argument types. - if (func_needs_compiling(ufunc, cctx->ctx_profiling) - && compile_def_function(ufunc, TRUE, cctx->ctx_profiling, NULL) + if (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, TRUE, PROFILING(ufunc), NULL) == FAIL) return FAIL; return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type); @@ -3111,7 +3111,7 @@ compile_lambda(char_u **arg, cctx_T *cctx) clear_tv(&rettv); // Compile the function into instructions. - compile_def_function(ufunc, TRUE, cctx->ctx_profiling, cctx); + compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx); clear_evalarg(&evalarg, NULL); @@ -5088,8 +5088,8 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) r = eap->skip ? OK : FAIL; goto theend; } - if (func_needs_compiling(ufunc, cctx->ctx_profiling) - && compile_def_function(ufunc, TRUE, cctx->ctx_profiling, cctx) + if (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx) == FAIL) { func_ptr_unref(ufunc); diff --git a/src/vim9execute.c b/src/vim9execute.c index 4c144f67ae..bcdc5d190a 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -181,6 +181,16 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) return FAIL; } +#ifdef FEAT_PROFILE + // Profiling might be enabled/disabled along the way. This should not + // fail, since the function was compiled before and toggling profiling + // doesn't change any errors. + if (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) + == FAIL) + return FAIL; +#endif + if (ufunc->uf_va_name != NULL) { // Need to make a list out of the vararg arguments. @@ -293,7 +303,7 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) // Set execution state to the start of the called function. ectx->ec_dfunc_idx = cdf_idx; - ectx->ec_instr = dfunc->df_instr; + ectx->ec_instr = INSTRUCTIONS(dfunc); entry = estack_push_ufunc(ufunc, 1); if (entry != NULL) { @@ -542,7 +552,7 @@ func_return(ectx_T *ectx) ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_IDX_OFF)->vval.v_number; dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; - ectx->ec_instr = dfunc->df_instr; + ectx->ec_instr = INSTRUCTIONS(dfunc); if (ret_idx > 0) { @@ -1103,6 +1113,7 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx) return OK; } + /* * Call a "def" function from old Vim script. * Return OK or FAIL. @@ -1135,11 +1146,6 @@ call_def_function( int save_did_emsg_def = did_emsg_def; int trylevel_at_start = trylevel; int orig_funcdepth; -#ifdef FEAT_PROFILE - int profiling = do_profiling == PROF_YES && ufunc->uf_profiling; -#else -# define profiling FALSE -#endif // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) @@ -1152,8 +1158,8 @@ call_def_function( #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) if (ufunc->uf_def_status == UF_NOT_COMPILED - || (func_needs_compiling(ufunc, profiling) - && compile_def_function(ufunc, FALSE, profiling, NULL) + || (func_needs_compiling(ufunc, PROFILING(ufunc)) + && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) == FAIL)) { if (did_emsg_cumul + did_emsg == did_emsg_before) @@ -1166,11 +1172,7 @@ call_def_function( // Check the function was really compiled. dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; - if (( -#ifdef FEAT_PROFILE - profiling ? dfunc->df_instr_prof : -#endif - dfunc->df_instr) == NULL) + if (INSTRUCTIONS(dfunc) == NULL) { iemsg("using call_def_function() on not compiled function"); return FAIL; @@ -1309,11 +1311,7 @@ call_def_function( ++ectx.ec_stack.ga_len; } -#ifdef FEAT_PROFILE - ectx.ec_instr = profiling ? dfunc->df_instr_prof : dfunc->df_instr; -#else - ectx.ec_instr = dfunc->df_instr; -#endif + ectx.ec_instr = INSTRUCTIONS(dfunc); } // Following errors are in the function, not the caller. From e0e3917554327f2524066f89fbbef9c83c1535da Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 25 Jan 2021 21:14:57 +0100 Subject: [PATCH 45/47] Update runtime files. --- .github/CODEOWNERS | 5 + runtime/compiler/fbc.vim | 27 +++++ runtime/compiler/tidy.vim | 17 ++- runtime/doc/change.txt | 22 +++- runtime/doc/eval.txt | 4 +- runtime/doc/filetype.txt | 2 +- runtime/doc/popup.txt | 2 +- runtime/doc/syntax.txt | 2 +- runtime/doc/tags | 24 ++++ runtime/doc/todo.txt | 24 ++-- runtime/doc/vi_diff.txt | 2 +- runtime/doc/vim9.txt | 11 +- runtime/filetype.vim | 2 +- runtime/ftplugin/ada.vim | 67 +++++------ runtime/ftplugin/basic.vim | 27 +++++ runtime/ftplugin/bzl.vim | 4 +- runtime/ftplugin/framescript.vim | 6 +- runtime/ftplugin/freebasic.vim | 13 +++ runtime/ftplugin/hamster.vim | 7 +- runtime/ftplugin/ocaml.vim | 4 +- runtime/ftplugin/tidy.vim | 32 +++++ runtime/ftplugin/vim.vim | 9 +- runtime/indent/fortran.vim | 6 +- runtime/indent/testdir/vim.in | 5 + runtime/indent/testdir/vim.ok | 5 + runtime/indent/vim.vim | 11 +- runtime/indent/yaml.vim | 8 +- runtime/syntax/basic.vim | 62 +++++----- runtime/syntax/tidy.vim | 193 ++++++++++++++++++++++++++----- runtime/tutor/tutor.ko | 2 +- runtime/tutor/tutor.ko.euc | 2 +- runtime/tutor/tutor.ko.utf-8 | 2 +- 32 files changed, 477 insertions(+), 132 deletions(-) create mode 100644 runtime/compiler/fbc.vim create mode 100644 runtime/ftplugin/basic.vim create mode 100644 runtime/ftplugin/freebasic.vim create mode 100644 runtime/ftplugin/tidy.vim diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 970cc942dc..02d6986289 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -31,6 +31,7 @@ runtime/compiler/dartdevc.vim @dkearns runtime/compiler/dartdoc.vim @dkearns runtime/compiler/dartfmt.vim @dkearns runtime/compiler/eruby.vim @dkearns +runtime/compiler/fbc.vim @dkearns runtime/compiler/gawk.vim @dkearns runtime/compiler/gjs.vim @dkearns runtime/compiler/haml.vim @tpope @@ -66,12 +67,14 @@ runtime/doc/pi_tar.txt @cecamp runtime/doc/pi_vimball.txt @cecamp runtime/doc/pi_zip.txt @cecamp runtime/ftplugin/awk.vim @dkearns +runtime/ftplugin/basic.vim @dkearns runtime/ftplugin/bst.vim @tpope runtime/ftplugin/cfg.vim @chrisbra runtime/ftplugin/css.vim @dkearns runtime/ftplugin/cucumber.vim @tpope runtime/ftplugin/eiffel.vim @dkearns runtime/ftplugin/eruby.vim @tpope @dkearns +runtime/ftplugin/freebasic.vim @dkearns runtime/ftplugin/git.vim @tpope runtime/ftplugin/gitcommit.vim @tpope runtime/ftplugin/gitconfig.vim @tpope @@ -93,6 +96,7 @@ runtime/ftplugin/ruby.vim @tpope @dkearns runtime/ftplugin/sass.vim @tpope runtime/ftplugin/scss.vim @tpope runtime/ftplugin/spec.vim @ignatenkobrain +runtime/ftplugin/tidy.vim @dkearns runtime/ftplugin/tmux.vim @ericpruitt runtime/ftplugin/typescript.vim @dkearns runtime/ftplugin/typescriptreact.vim @dkearns @@ -127,6 +131,7 @@ runtime/syntax/amiga.vim @cecamp runtime/syntax/asm.vim @dkearns runtime/syntax/asmh8300.vim @dkearns runtime/syntax/awk.vim @dkearns +runtime/syntax/basic.vim @dkearns runtime/syntax/bst.vim @tpope runtime/syntax/cabal.vim @coot runtime/syntax/cabalconfig.vim @coot diff --git a/runtime/compiler/fbc.vim b/runtime/compiler/fbc.vim new file mode 100644 index 0000000000..1c29392da8 --- /dev/null +++ b/runtime/compiler/fbc.vim @@ -0,0 +1,27 @@ +" Vim compiler file +" Compiler: FreeBASIC Compiler +" Maintainer: Doug Kearns +" Last Change: 2015 Jan 10 + +if exists("current_compiler") + finish +endif +let current_compiler = "fbc" + +if exists(":CompilerSet") != 2 " older Vim always used :setlocal + command -nargs=* CompilerSet setlocal +endif + +let s:cpo_save = &cpo +set cpo&vim + +CompilerSet makeprg=fbc +CompilerSet errorformat=%-G%.%#Too\ many\ errors\\,\ exiting, + \%f(%l)\ %tarning\ %n(%\\d%\\+):\ %m, + \%E%f(%l)\ error\ %n:\ %m, + \%-Z%p^, + \%-C%.%#, + \%-G%.%# + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/compiler/tidy.vim b/runtime/compiler/tidy.vim index 75be8b83d9..3f8e68ebf2 100644 --- a/runtime/compiler/tidy.vim +++ b/runtime/compiler/tidy.vim @@ -1,7 +1,7 @@ " Vim compiler file " Compiler: HTML Tidy " Maintainer: Doug Kearns -" Last Change: 2016 Apr 21 +" Last Change: 2020 Sep 4 if exists("current_compiler") finish @@ -12,8 +12,15 @@ if exists(":CompilerSet") != 2 " older Vim always used :setlocal command -nargs=* CompilerSet setlocal endif -CompilerSet makeprg=tidy\ -quiet\ -errors\ --gnu-emacs\ yes\ %:S +let s:cpo_save = &cpo +set cpo&vim -" foo.html:8:1: Warning: inserting missing 'foobar' element -" foo.html:9:2: Error: is not recognized! -CompilerSet errorformat=%f:%l:%c:\ %trror:%m,%f:%l:%c:\ %tarning:%m,%-G%.%# +CompilerSet makeprg=tidy\ -quiet\ -errors\ --gnu-emacs\ yes +CompilerSet errorformat=%f:%l:%c:\ %trror:\ %m, + \%f:%l:%c:\ %tarning:\ %m, + \%f:%l:%c:\ %tnfo:\ %m, + \%f:%l:%c:\ %m, + \%-G%.%# + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index bf425dda51..7db3ffc41f 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 8.2. Last change: 2020 Nov 21 +*change.txt* For Vim version 8.2. Last change: 2021 Jan 21 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1631,24 +1631,31 @@ default setting is "tcq". You can separate the option letters with commas for readability. letter meaning when present in 'formatoptions' ~ - + *fo-t* t Auto-wrap text using textwidth + *fo-c* c Auto-wrap comments using textwidth, inserting the current comment leader automatically. + *fo-r* r Automatically insert the current comment leader after hitting in Insert mode. + *fo-o* o Automatically insert the current comment leader after hitting 'o' or 'O' in Normal mode. + *fo-q* q Allow formatting of comments with "gq". Note that formatting will not change blank lines or lines containing only the comment leader. A new paragraph starts after such a line, or when the comment leader changes. + *fo-w* w Trailing white space indicates a paragraph continues in the next line. A line that ends in a non-white character ends a paragraph. + *fo-a* a Automatic formatting of paragraphs. Every time text is inserted or deleted the paragraph will be reformatted. See |auto-format|. When the 'c' flag is present this only happens for recognized comments. + *fo-n* n When formatting text, recognize numbered lists. This actually uses the 'formatlistpat' option, thus any kind of list can be used. The indent of the text after the number is used for the next line. The @@ -1659,6 +1666,7 @@ n When formatting text, recognize numbered lists. This actually uses 1. the first item wraps 2. the second item +< *fo-2* 2 When formatting text, use the indent of the second line of a paragraph for the rest of the paragraph, instead of the indent of the first line. This supports paragraphs in which the first line has a @@ -1668,36 +1676,46 @@ n When formatting text, recognize numbered lists. This actually uses second line of the same paragraph third line. < This also works inside comments, ignoring the comment leader. + *fo-v* v Vi-compatible auto-wrapping in insert mode: Only break a line at a blank that you have entered during the current insert command. (Note: this is not 100% Vi compatible. Vi has some "unexpected features" or bugs in this area. It uses the screen column instead of the line column.) + *fo-b* b Like 'v', but only auto-wrap if you enter a blank at or before the wrap margin. If the line was longer than 'textwidth' when you started the insert, or you do not enter a blank in the insert before reaching 'textwidth', Vim does not perform auto-wrapping. + *fo-l* l Long lines are not broken in insert mode: When a line was longer than 'textwidth' when the insert command started, Vim does not automatically format it. + *fo-m* m Also break at a multibyte character above 255. This is useful for Asian text where every character is a word on its own. + *fo-M* M When joining lines, don't insert a space before or after a multibyte character. Overrules the 'B' flag. + *fo-B* B When joining lines, don't insert a space between two multibyte characters. Overruled by the 'M' flag. + *fo-1* 1 Don't break a line after a one-letter word. It's broken before it instead (if possible). + *fo-]* ] Respect textwidth rigorously. With this flag set, no line can be longer than textwidth, unless line-break-prohibition rules make this impossible. Mainly for CJK scripts and works only if 'encoding' is "utf-8". + *fo-j* j Where it makes sense, remove a comment leader when joining lines. For example, joining: int i; // the index ~ // in the list ~ Becomes: int i; // the index in the list ~ + *fo-p* p Don't break lines at single spaces that follow periods. This is intended to complement 'joinspaces' and |cpo-J|, for prose with sentences separated by two spaces. For example, with 'textwidth' set diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index dd5bc939d3..edf5fc8cc3 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 Jan 21 +*eval.txt* For Vim version 8.2. Last change: 2021 Jan 22 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2085,7 +2085,7 @@ v:null An empty String. Used to put "null" in JSON. See *v:numbermax* *numbermax-variable* v:numbermax Maximum value of a number. - *v:numbermix* *numbermix-variable* + *v:numbermin* *numbermin-variable* v:numbermin Minimum value of a number (negative) *v:numbersize* *numbersize-variable* diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index d3a4bde8b0..6a23b2fdb8 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -1,4 +1,4 @@ -*filetype.txt* For Vim version 8.2. Last change: 2020 Sep 28 +*filetype.txt* For Vim version 8.2. Last change: 2021 Jan 21 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt index 005b57f0d0..6d70cecd54 100644 --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -1,4 +1,4 @@ -*popup.txt* For Vim version 8.2. Last change: 2020 Nov 07 +*popup.txt* For Vim version 8.2. Last change: 2021 Jan 21 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index a2a12b0cf0..6a94980671 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1,4 +1,4 @@ -*syntax.txt* For Vim version 8.2. Last change: 2020 Dec 17 +*syntax.txt* For Vim version 8.2. Last change: 2021 Jan 21 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/tags b/runtime/doc/tags index 24cdded5aa..83ccca299e 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -6431,7 +6431,26 @@ fname_new-variable eval.txt /*fname_new-variable* fname_out-variable eval.txt /*fname_out-variable* fnameescape() eval.txt /*fnameescape()* fnamemodify() eval.txt /*fnamemodify()* +fo-1 change.txt /*fo-1* +fo-2 change.txt /*fo-2* +fo-B change.txt /*fo-B* +fo-M change.txt /*fo-M* +fo-] change.txt /*fo-]* +fo-a change.txt /*fo-a* +fo-b change.txt /*fo-b* +fo-c change.txt /*fo-c* +fo-j change.txt /*fo-j* +fo-l change.txt /*fo-l* +fo-m change.txt /*fo-m* +fo-n change.txt /*fo-n* +fo-o change.txt /*fo-o* +fo-p change.txt /*fo-p* +fo-q change.txt /*fo-q* +fo-r change.txt /*fo-r* +fo-t change.txt /*fo-t* fo-table change.txt /*fo-table* +fo-v change.txt /*fo-v* +fo-w change.txt /*fo-w* fold-behavior fold.txt /*fold-behavior* fold-colors fold.txt /*fold-colors* fold-commands fold.txt /*fold-commands* @@ -8271,6 +8290,8 @@ null vim9.txt /*null* null-variable eval.txt /*null-variable* number_relativenumber options.txt /*number_relativenumber* numbered-function eval.txt /*numbered-function* +numbermax-variable eval.txt /*numbermax-variable* +numbermin-variable eval.txt /*numbermin-variable* numbersize-variable eval.txt /*numbersize-variable* o insert.txt /*o* o_CTRL-V motion.txt /*o_CTRL-V* @@ -9847,6 +9868,8 @@ v:mouse_win eval.txt /*v:mouse_win* v:mouse_winid eval.txt /*v:mouse_winid* v:none eval.txt /*v:none* v:null eval.txt /*v:null* +v:numbermax eval.txt /*v:numbermax* +v:numbermin eval.txt /*v:numbermin* v:numbersize eval.txt /*v:numbersize* v:oldfiles eval.txt /*v:oldfiles* v:operator eval.txt /*v:operator* @@ -10089,6 +10112,7 @@ vim8 version8.txt /*vim8* vim9 vim9.txt /*vim9* vim9-classes vim9.txt /*vim9-classes* vim9-const vim9.txt /*vim9-const* +vim9-curly vim9.txt /*vim9-curly* vim9-declaration vim9.txt /*vim9-declaration* vim9-declarations usr_46.txt /*vim9-declarations* vim9-differences vim9.txt /*vim9-differences* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 75133f78bc..efff0929d7 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 Jan 17 +*todo.txt* For Vim version 8.2. Last change: 2021 Jan 25 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41,6 +41,7 @@ browser use: https://github.com/vim/vim/issues/1234 test_autocmd failure in Windows: Something wrong with system()? Vim9 - Make everything work: +- Add a test for profiling with nested function calls and lambda. - Expand `=expr` in :next, :argedit, :argadd, :argdelete, :drop - Expand `=expr` in :vimgrep, :vimgrepadd, :lvimgrep, :lvimgrepadd - Expand `=expr` in :mkspell @@ -50,7 +51,7 @@ Vim9 - Make everything work: - 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: - let p = function('NoSuchFunc') + var p = function('NoSuchFunc') - 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 @@ -58,20 +59,16 @@ Vim9 - Make everything work: def Filter(x: string, Cond: func(string): bool) Filter(x, (v) => v =~ '^b') - Make inline function work, to be used as a funcref: - let Ref = (arg: type): type => { + var Ref = (arg: type): type => { statement return expr } - let Ref = (arg: type) => { + var Ref = (arg: type) => { statement statement } -- Does this work already: can use func as reference: - def SomeFunc() ... - map(list, SomeFunc) - For builtin functions using tv_get_string*() use check_for_string() to be more strict about the argument type. -- Possible memory leaks in test_vim9_func - Implement :lockvar and :unlockvar. How about local variables? Perhaps only allow this for global variables. Use :final or :const otherwise. - Allow function names that will be script-local to start with lower case @@ -86,10 +83,10 @@ Vim9 - Make everything work: - 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: - let ret: dict = #{} + var ret: dict = #{} ret[i] = string(i) - Appending to dict item doesn't work: - let d[i] ..= value + var d[i] ..= value - 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(). @@ -144,7 +141,6 @@ Also for Vim9: - Make debugging work - at least per function. Need to recompile a function to step through it line-by-line? Evaluate the stack and variables on the stack? -- Make profiling work - Add ISN_PROFILE instructions after every line? - List commands when 'verbose' is set or :verbose is used. Further Vim9 improvements, possibly after launch: @@ -187,6 +183,10 @@ Popup windows: - Figure out the size and position better if wrapping inserts indent Text properties: +- Popup attached to text property stays visible when text is no longer + visible. (#7736) +- Popup attached to text property stays visible when text is deleted with + "cc". (#7737) "C" works OK. - :goto does not go to the right place when text properties are present. (#5930) - "cc" does not call inserted_bytes(). (Axel Forsman, #5763) @@ -282,7 +282,7 @@ Patch to implement the vimtutor with a plugin: #6414 Was originally written by Felipe Morales. Adding "10" to 'spellsuggest' causes spell suggestions to become very slow. -(#4087) +(#4087) Did patch 8.2.2379 help? Patch to find Python dll using registry key. (#7540) diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt index 0fb29e4946..89ef4bb71e 100644 --- a/runtime/doc/vi_diff.txt +++ b/runtime/doc/vi_diff.txt @@ -1,4 +1,4 @@ -*vi_diff.txt* For Vim version 8.2. Last change: 2020 Aug 15 +*vi_diff.txt* For Vim version 8.2. Last change: 2021 Jan 21 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 93c3ddd2f9..7246ff87a6 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 Jan 15 +*vim9.txt* For Vim version 8.2. Last change: 2021 Jan 23 VIM REFERENCE MANUAL by Bram Moolenaar @@ -403,10 +403,16 @@ Additionally, a lambda can contain statements in {}: > } NOT IMPLEMENTED YET + *vim9-curly* To avoid the "{" of a dictionary literal to be recognized as a statement block wrap it in parenthesis: > var Lambda = (arg) => ({key: 42}) +Also when confused with the start of a command block: > + ({ + key: value + })->method() + Automatic line continuation ~ @@ -841,6 +847,9 @@ prefix and they do not need to exist (they can be deleted any time). Note that for command line completion of {func} you can prepend "s:" to find script-local functions. +:disa[ssemble]! {func} Like `:disassemble` but with the instructions used for + profiling. + Limitations ~ Local variables will not be visible to string evaluation. For example: > diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 897ac80ebc..e4910e3719 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: 2020 Dec 24 +" Last Change: 2021 Jan 21 " Listen very carefully, I will say this only once if exists("did_load_filetypes") diff --git a/runtime/ftplugin/ada.vim b/runtime/ftplugin/ada.vim index 0809e7b206..a0621e1d13 100644 --- a/runtime/ftplugin/ada.vim +++ b/runtime/ftplugin/ada.vim @@ -159,40 +159,41 @@ if exists("g:ada_abbrev") endif " Section: Commands, Mapping, Menus {{{1 -" -call ada#Map_Popup ( - \ 'Tag.List', - \ 'l', - \ 'call ada#List_Tag ()') -call ada#Map_Popup ( - \'Tag.Jump', - \'j', - \'call ada#Jump_Tag ()') -call ada#Map_Menu ( - \'Tag.Create File', - \':AdaTagFile', - \'call ada#Create_Tags (''file'')') -call ada#Map_Menu ( - \'Tag.Create Dir', - \':AdaTagDir', - \'call ada#Create_Tags (''dir'')') +if !exists(':AdaTagFile') + call ada#Map_Popup ( + \ 'Tag.List', + \ 'l', + \ 'call ada#List_Tag ()') + call ada#Map_Popup ( + \'Tag.Jump', + \'j', + \'call ada#Jump_Tag ()') + call ada#Map_Menu ( + \'Tag.Create File', + \':AdaTagFile', + \'call ada#Create_Tags (''file'')') + call ada#Map_Menu ( + \'Tag.Create Dir', + \':AdaTagDir', + \'call ada#Create_Tags (''dir'')') -call ada#Map_Menu ( - \'Highlight.Toggle Space Errors', - \ ':AdaSpaces', - \'call ada#Switch_Syntax_Option (''space_errors'')') -call ada#Map_Menu ( - \'Highlight.Toggle Lines Errors', - \ ':AdaLines', - \'call ada#Switch_Syntax_Option (''line_errors'')') -call ada#Map_Menu ( - \'Highlight.Toggle Rainbow Color', - \ ':AdaRainbow', - \'call ada#Switch_Syntax_Option (''rainbow_color'')') -call ada#Map_Menu ( - \'Highlight.Toggle Standard Types', - \ ':AdaTypes', - \'call ada#Switch_Syntax_Option (''standard_types'')') + call ada#Map_Menu ( + \'Highlight.Toggle Space Errors', + \ ':AdaSpaces', + \'call ada#Switch_Syntax_Option (''space_errors'')') + call ada#Map_Menu ( + \'Highlight.Toggle Lines Errors', + \ ':AdaLines', + \'call ada#Switch_Syntax_Option (''line_errors'')') + call ada#Map_Menu ( + \'Highlight.Toggle Rainbow Color', + \ ':AdaRainbow', + \'call ada#Switch_Syntax_Option (''rainbow_color'')') + call ada#Map_Menu ( + \'Highlight.Toggle Standard Types', + \ ':AdaTypes', + \'call ada#Switch_Syntax_Option (''standard_types'')') +endif " 1}}} " Reset cpoptions diff --git a/runtime/ftplugin/basic.vim b/runtime/ftplugin/basic.vim new file mode 100644 index 0000000000..c6ec254dfc --- /dev/null +++ b/runtime/ftplugin/basic.vim @@ -0,0 +1,27 @@ +" Vim filetype plugin file +" Language: BASIC +" Maintainer: Doug Kearns +" Last Change: 2015 Jan 10 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo&vim + +setlocal comments=:REM,:' +setlocal commentstring='\ %s +setlocal formatoptions-=t formatoptions+=croql + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "BASIC Source Files (*.bas)\t*.bas\n" . + \ "All Files (*.*)\t*.*\n" +endif + +let b:undo_ftplugin = "setl fo< com< cms< sua<" . + \ " | unlet! b:browsefilter" + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/ftplugin/bzl.vim b/runtime/ftplugin/bzl.vim index 0296b0c0b8..8ab876e9d6 100644 --- a/runtime/ftplugin/bzl.vim +++ b/runtime/ftplugin/bzl.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Bazel (http://bazel.io) " Maintainer: David Barnett (https://github.com/google/vim-ft-bzl) -" Last Change: 2015 Aug 11 +" Last Change: 2021 Jan 19 "" " @section Introduction, intro @@ -51,6 +51,8 @@ if get(g:, 'ft_bzl_fold', 0) endif if exists('*BzlFoldText') + let &cpo = s:save_cpo + unlet s:save_cpo finish endif diff --git a/runtime/ftplugin/framescript.vim b/runtime/ftplugin/framescript.vim index 48fe0ace7c..66802cad0d 100644 --- a/runtime/ftplugin/framescript.vim +++ b/runtime/ftplugin/framescript.vim @@ -3,14 +3,14 @@ " Previous Maintainer: Nikolai Weibull " Latest Revision: 2008-07-19 -let s:cpo_save = &cpo -set cpo&vim - if exists("b:did_ftplugin") finish endif let b:did_ftplugin = 1 +let s:cpo_save = &cpo +set cpo&vim + let b:undo_ftplugin = "setl com< cms< fo< inc< | unlet! b:matchwords" setlocal comments=s1:/*,mb:*,ex:*/,:// commentstring=/*\ %s\ */ diff --git a/runtime/ftplugin/freebasic.vim b/runtime/ftplugin/freebasic.vim new file mode 100644 index 0000000000..a2bb459f20 --- /dev/null +++ b/runtime/ftplugin/freebasic.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin file +" Language: FreeBasic +" Maintainer: Doug Kearns +" Last Change: 2015 Jan 10 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +runtime! ftplugin/basic.vim + +" vim: ts=8 diff --git a/runtime/ftplugin/hamster.vim b/runtime/ftplugin/hamster.vim index 6c0630fe04..5446e72286 100644 --- a/runtime/ftplugin/hamster.vim +++ b/runtime/ftplugin/hamster.vim @@ -2,7 +2,7 @@ " Language: Hamster Script " Version: 2.0.6.0 " Maintainer: David Fishburn -" Last Change: 2017 Mar 18 +" Last Change: 2021 Jan 19 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -57,6 +57,9 @@ if exists("loaded_matchit") endif setlocal ignorecase + let &cpo = s:cpo_save unlet s:cpo_save -setlocal cpo+=M " makes \%( match \) + +" Disabled, 'cpo' is a global option. +" setlocal cpo+=M " makes \%( match \) diff --git a/runtime/ftplugin/ocaml.vim b/runtime/ftplugin/ocaml.vim index 793b887afc..8a628604fa 100644 --- a/runtime/ftplugin/ocaml.vim +++ b/runtime/ftplugin/ocaml.vim @@ -159,6 +159,8 @@ let b:undo_ftplugin = "setlocal efm< foldmethod< foldexpr<" " - Only definitions below, executed once ------------------------------------- if exists("*OMLetFoldLevel") + let &cpoptions = s:cposet + unlet s:cposet finish endif @@ -635,7 +637,7 @@ endfunction nnoremap OCamlPrintType :call Ocaml_print_type("normal") xnoremap OCamlPrintType :call Ocaml_print_type("visual")`< -let &cpoptions=s:cposet +let &cpoptions = s:cposet unlet s:cposet " vim:sw=2 fdm=indent diff --git a/runtime/ftplugin/tidy.vim b/runtime/ftplugin/tidy.vim new file mode 100644 index 0000000000..470548d83a --- /dev/null +++ b/runtime/ftplugin/tidy.vim @@ -0,0 +1,32 @@ +" Vim filetype plugin file +" Language: HMTL Tidy Configuration +" Maintainer: Doug Kearns +" Last Change: 2020 Sep 4 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo&vim + +setlocal comments=:#,:// +setlocal commentstring=#\ %s +setlocal formatoptions-=t formatoptions+=croql + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "HTML Tidy Files (tidyrc, .tidyrc, tidy.conf)\ttidyrc;.tidyrc;tidy.conf\n" . + \ "HTML Files (*.html, *.htm)\t*.html;*.htm\n" . + \ "XHTML Files (*.xhtml, *.xhtm)\t*.xhtml;*.xhtm\n" . + \ "XML Files (*.xml)\t*.xml\n" . + \ "All Files (*.*)\t*.*\n" +endif + +let b:undo_ftplugin = "setl fo< com< cms<" . + \ " | unlet! b:browsefilter" + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: nowrap sw=2 sts=2 ts=8 diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index 6adadbda94..d39ad9579b 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Vim " Maintainer: Bram Moolenaar -" Last Change: 2021 Jan 12 +" Last Change: 2021 Jan 23 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -88,8 +88,13 @@ endif " Let the matchit plugin know what items can be matched. if exists("loaded_matchit") let b:match_ignorecase = 0 + " "func" can also be used as a type: + " var Ref: func + " or to list functions: + " func name + " require a parenthesis following, then there can be an "endfunc". let b:match_words = - \ '\<\%(fu\%[nction]\|def\)\>)\@!:\:\<\%(endf\%[unction]\|enddef\)\>,' . + \ '\<\%(fu\%[nction]\|def\)\s\+\S\+(:\:\<\%(endf\%[unction]\|enddef\)\>,' . \ '\<\(wh\%[ile]\|for\)\>:\:\:\,' . \ '\:\:\,' . \ '{:},' . diff --git a/runtime/indent/fortran.vim b/runtime/indent/fortran.vim index 696320288d..26ed33a54d 100644 --- a/runtime/indent/fortran.vim +++ b/runtime/indent/fortran.vim @@ -74,11 +74,15 @@ endif if (b:fortran_fixed_source == 1) setlocal indentexpr=FortranGetFixedIndent() if exists("*FortranGetFixedIndent") + let &cpoptions = s:cposet + unlet s:cposet finish endif else setlocal indentexpr=FortranGetFreeIndent() if exists("*FortranGetFreeIndent") + let &cpoptions = s:cposet + unlet s:cposet finish endif endif @@ -213,7 +217,7 @@ function FortranGetFixedIndent() return ind endfunction -let &cpoptions=s:cposet +let &cpoptions = s:cposet unlet s:cposet " vim:sw=2 tw=130 diff --git a/runtime/indent/testdir/vim.in b/runtime/indent/testdir/vim.in index 47e692975f..f652dbda79 100644 --- a/runtime/indent/testdir/vim.in +++ b/runtime/indent/testdir/vim.in @@ -10,6 +10,11 @@ let cmd = \ 'some ' \ 'string' +if 1 +let x = [ +\ ] +endif + " END_INDENT " START_INDENT diff --git a/runtime/indent/testdir/vim.ok b/runtime/indent/testdir/vim.ok index 3f53c5286c..b8592c18eb 100644 --- a/runtime/indent/testdir/vim.ok +++ b/runtime/indent/testdir/vim.ok @@ -10,6 +10,11 @@ let cmd = \ 'some ' \ 'string' +if 1 + let x = [ + \ ] +endif + " END_INDENT " START_INDENT diff --git a/runtime/indent/vim.vim b/runtime/indent/vim.vim index 3e502c9adb..b031d1f2ed 100644 --- a/runtime/indent/vim.vim +++ b/runtime/indent/vim.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Vim script " Maintainer: Bram Moolenaar -" Last Change: 2021 Jan 06 +" Last Change: 2021 Jan 21 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -38,6 +38,9 @@ function GetVimIndentIntern() " Find a non-blank line above the current line. let lnum = prevnonblank(v:lnum - 1) + " The previous line, ignoring line continuation + let prev_text_end = lnum > 0 ? getline(lnum) : '' + " If the current line doesn't start with '\' or '"\ ' and below a line that " starts with '\' or '"\ ', use the indent of the line above it. let cur_text = getline(v:lnum) @@ -51,6 +54,8 @@ function GetVimIndentIntern() if lnum == 0 return 0 endif + + " the start of the previous line, skipping over line continuation let prev_text = getline(lnum) let found_cont = 0 @@ -147,13 +152,13 @@ function GetVimIndentIntern() endif " Below a line starting with "]" we must be below the end of a list. - if prev_text =~ '^\s*]' + if prev_text_end =~ '^\s*]' let ind = ind - shiftwidth() endif " A line ending in "{"/"[} is most likely the start of a dict/list literal, " indent the next line more. Not for a continuation line. - if prev_text =~ '[{[]\s*$' && !found_cont + if prev_text_end =~ '[{[]\s*$' && !found_cont let ind = ind + shiftwidth() endif diff --git a/runtime/indent/yaml.vim b/runtime/indent/yaml.vim index 26e14effb2..8dca5cd763 100644 --- a/runtime/indent/yaml.vim +++ b/runtime/indent/yaml.vim @@ -2,16 +2,13 @@ " Language: YAML " Maintainer: Nikolai Pavlov " Last Update: Lukas Reineke -" Last Change: 2020 Jun 07 +" Last Change: 2021 Jan 19 " Only load this indent file when no other was loaded. if exists('b:did_indent') finish endif -let s:save_cpo = &cpo -set cpo&vim - let b:did_indent = 1 setlocal indentexpr=GetYAMLIndent(v:lnum) @@ -25,6 +22,9 @@ if exists('*GetYAMLIndent') finish endif +let s:save_cpo = &cpo +set cpo&vim + function s:FindPrevLessIndentedLine(lnum, ...) let prevlnum = prevnonblank(a:lnum-1) let curindent = a:0 ? a:1 : indent(a:lnum) diff --git a/runtime/syntax/basic.vim b/runtime/syntax/basic.vim index 488ddc0ec4..ad9450b3b8 100644 --- a/runtime/syntax/basic.vim +++ b/runtime/syntax/basic.vim @@ -1,14 +1,16 @@ " Vim syntax file -" Language: BASIC -" Maintainer: Allan Kelly -" Last Change: 2011 Dec 25 by Thilo Six +" Language: BASIC +" Maintainer: Doug Kearns +" Previous Maintainer: Allan Kelly +" Contributors: Thilo Six +" Last Change: 2015 Jan 10 " First version based on Micro$soft QBASIC circa 1989, as documented in " 'Learn BASIC Now' by Halvorson&Rygmyr. Microsoft Press 1989. " This syntax file not a complete implementation yet. Send suggestions to the " maintainer. -" quit when a syntax file was already loaded +" Prelude {{{1 if exists("b:current_syntax") finish endif @@ -16,7 +18,7 @@ endif let s:cpo_save = &cpo set cpo&vim -" A bunch of useful BASIC keywords +" Keywords {{{1 syn keyword basicStatement BEEP beep Beep BLOAD bload Bload BSAVE bsave Bsave syn keyword basicStatement CALL call Call ABSOLUTE absolute Absolute syn keyword basicStatement CHAIN chain Chain CHDIR chdir Chdir @@ -116,32 +118,39 @@ syn keyword basicFunction RIGHT$ right$ Right$ RTRIM$ rtrim$ Rtrim$ syn keyword basicFunction SPACE$ space$ Space$ STR$ str$ Str$ syn keyword basicFunction STRING$ string$ String$ TIME$ time$ Time$ syn keyword basicFunction UCASE$ ucase$ Ucase$ VARPTR$ varptr$ Varptr$ -syn keyword basicTodo contained TODO -"integer number, or floating point number without a dot. +" Numbers {{{1 +" Integer number, or floating point number without a dot. syn match basicNumber "\<\d\+\>" -"floating point number, with dot +" Floating point number, with dot syn match basicNumber "\<\d\+\.\d*\>" -"floating point number, starting with a dot +" Floating point number, starting with a dot syn match basicNumber "\.\d\+\>" -" String and Character contstants -syn match basicSpecial contained "\\\d\d\d\|\\." -syn region basicString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=basicSpecial +" String and Character constants {{{1 +syn match basicSpecial "\\\d\d\d\|\\." contained +syn region basicString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=basicSpecial -syn region basicComment start="REM" end="$" contains=basicTodo -syn region basicComment start="^[ \t]*'" end="$" contains=basicTodo +" Line numbers {{{1 syn region basicLineNumber start="^\d" end="\s" -syn match basicTypeSpecifier "[a-zA-Z0-9][\$%&!#]"ms=s+1 + +" Data-type suffixes {{{1 +syn match basicTypeSpecifier "[a-zA-Z0-9][$%&!#]"ms=s+1 " Used with OPEN statement syn match basicFilenumber "#\d\+" -"syn sync ccomment basicComment + +" Mathematical operators {{{1 " syn match basicMathsOperator "[<>+\*^/\\=-]" -syn match basicMathsOperator "-\|=\|[:<>+\*^/\\]\|AND\|OR" +syn match basicMathsOperator "-\|=\|[:<>+\*^/\\]\|AND\|OR" -" Define the default highlighting. -" Only when an item doesn't have highlighting yet +" Comments {{{1 +syn keyword basicTodo TODO FIXME XXX NOTE contained +syn region basicComment start="^\s*\zsREM\>" start="\%(:\s*\)\@<=REM\>" end="$" contains=basicTodo +syn region basicComment start="'" end="$" contains=basicTodo +"syn sync ccomment basicComment + +" Default Highlighting {{{1 hi def link basicLabel Label hi def link basicConditional Conditional hi def link basicRepeat Repeat @@ -150,17 +159,18 @@ hi def link basicNumber Number hi def link basicError Error hi def link basicStatement Statement hi def link basicString String -hi def link basicComment Comment -hi def link basicSpecial Special +hi def link basicComment Comment +hi def link basicSpecial Special hi def link basicTodo Todo -hi def link basicFunction Identifier -hi def link basicTypeSpecifier Type -hi def link basicFilenumber basicTypeSpecifier +hi def link basicFunction Identifier +hi def link basicTypeSpecifier Type +hi def link basicFilenumber basicTypeSpecifier "hi basicMathsOperator term=bold cterm=bold gui=bold - +" Postscript {{{1 let b:current_syntax = "basic" let &cpo = s:cpo_save unlet s:cpo_save -" vim: ts=8 + +" vim: nowrap sw=2 sts=2 ts=8 noet fdm=marker: diff --git a/runtime/syntax/tidy.vim b/runtime/syntax/tidy.vim index 6371cb5a86..7ffda90e55 100644 --- a/runtime/syntax/tidy.vim +++ b/runtime/syntax/tidy.vim @@ -1,8 +1,9 @@ " Vim syntax file -" Language: HMTL Tidy configuration file (/etc/tidyrc ~/.tidyrc) +" Language: HMTL Tidy Configuration " Maintainer: Doug Kearns -" Last Change: 2016 Apr 24 +" Last Change: 2020 Sep 4 +" Preamble {{{1 if exists("b:current_syntax") finish endif @@ -12,10 +13,15 @@ set cpo&vim syn iskeyword @,48-57,-,_ +" Values {{{1 +syn match tidyWordSeparator contained ",\|\s" nextgroup=tidyWord skipwhite skipnl +syn match tidyMuteIDSeparator contained ",\|\s" nextgroup=tidyMuteID skipwhite skipnl + syn case ignore syn keyword tidyBoolean contained t[rue] f[alse] y[es] n[o] 1 0 syn keyword tidyAutoBoolean contained t[rue] f[alse] y[es] n[o] 1 0 auto syn case match +syn keyword tidyCustomTags contained no blocklevel empty inline pre syn keyword tidyDoctype contained html5 omit auto strict loose transitional user syn keyword tidyEncoding contained raw ascii latin0 latin1 utf8 iso2022 mac win1252 ibm858 utf16le utf16be utf16 big5 shiftjis syn keyword tidyNewline contained LF CRLF CR @@ -24,36 +30,148 @@ syn keyword tidyRepeat contained keep-first keep-last syn keyword tidySorter contained alpha none syn region tidyString contained start=+"+ skip=+\\\\\|\\"+ end=+"+ oneline syn region tidyString contained start=+'+ skip=+\\\\\|\\'+ end=+'+ oneline -syn match tidyTags contained "\<\w\+\(\s*,\s*\w\+\)*\>" +" Tag and attribute lists +syn match tidyWord contained "\<\k\+\>:\@!" nextgroup=tidyWordSeparator skipwhite skipnl -syn keyword tidyBooleanOption add-xml-decl add-xml-pi add-xml-space - \ anchor-as-name ascii-chars assume-xml-procins bare break-before-br - \ clean coerce-endtags decorate-inferred-ul drop-empty-paras - \ drop-empty-elements drop-font-tags drop-proprietary-attributes - \ enclose-block-text enclose-text escape-cdata escape-scripts - \ fix-backslash fix-bad-comments fix-uri force-output gdoc gnu-emacs - \ hide-comments hide-endtags indent-attributes indent-cdata - \ indent-with-tabs input-xml join-classes join-styles keep-time - \ language literal-attributes logical-emphasis lower-literals markup - \ merge-emphasis ncr numeric-entities omit-optional-tags output-html - \ output-xhtml output-xml preserve-entities punctuation-wrap quiet - \ quote-ampersand quote-marks quote-nbsp raw replace-color show-info - \ show-warnings skip-nested split strict-tags-attributes tidy-mark - \ uppercase-attributes uppercase-tags word-2000 wrap-asp - \ wrap-attributes wrap-jste wrap-php wrap-script-literals - \ wrap-sections write-back +" Mute Message IDs {{{2 +syn keyword tidyMuteID ADDED_MISSING_CHARSET ANCHOR_DUPLICATED + \ ANCHOR_NOT_UNIQUE APOS_UNDEFINED APPLET_MISSING_ALT AREA_MISSING_ALT + \ ASCII_REQUIRES_DESCRIPTION ASSOCIATE_LABELS_EXPLICITLY + \ ASSOCIATE_LABELS_EXPLICITLY_FOR ASSOCIATE_LABELS_EXPLICITLY_ID + \ ATTRIBUTE_IS_NOT_ALLOWED ATTRIBUTE_VALUE_REPLACED + \ ATTR_VALUE_NOT_LCASE AUDIO_MISSING_TEXT_AIFF AUDIO_MISSING_TEXT_AU + \ AUDIO_MISSING_TEXT_RA AUDIO_MISSING_TEXT_RM AUDIO_MISSING_TEXT_SND + \ AUDIO_MISSING_TEXT_WAV BACKSLASH_IN_URI BAD_ATTRIBUTE_VALUE + \ BAD_ATTRIBUTE_VALUE_REPLACED BAD_CDATA_CONTENT BAD_SUMMARY_HTML5 + \ BAD_SURROGATE_LEAD BAD_SURROGATE_PAIR BAD_SURROGATE_TAIL + \ CANT_BE_NESTED COERCE_TO_ENDTAG COLOR_CONTRAST_ACTIVE_LINK + \ COLOR_CONTRAST_LINK COLOR_CONTRAST_TEXT COLOR_CONTRAST_VISITED_LINK + \ CONTENT_AFTER_BODY CUSTOM_TAG_DETECTED DATA_TABLE_MISSING_HEADERS + \ DATA_TABLE_MISSING_HEADERS_COLUMN DATA_TABLE_MISSING_HEADERS_ROW + \ DATA_TABLE_REQUIRE_MARKUP_COLUMN_HEADERS + \ DATA_TABLE_REQUIRE_MARKUP_ROW_HEADERS DISCARDING_UNEXPECTED + \ DOCTYPE_AFTER_TAGS DOCTYPE_MISSING DUPLICATE_FRAMESET + \ ELEMENT_NOT_EMPTY ELEMENT_VERS_MISMATCH_ERROR + \ ELEMENT_VERS_MISMATCH_WARN ENCODING_MISMATCH + \ ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_APPLET + \ ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_EMBED + \ ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_OBJECT + \ ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_SCRIPT ESCAPED_ILLEGAL_URI + \ FILE_CANT_OPEN FILE_CANT_OPEN_CFG FILE_NOT_FILE FIXED_BACKSLASH + \ FOUND_STYLE_IN_BODY FRAME_MISSING_LONGDESC FRAME_MISSING_NOFRAMES + \ FRAME_MISSING_TITLE FRAME_SRC_INVALID FRAME_TITLE_INVALID_NULL + \ FRAME_TITLE_INVALID_SPACES HEADERS_IMPROPERLY_NESTED + \ HEADER_USED_FORMAT_TEXT ID_NAME_MISMATCH ILLEGAL_NESTING + \ ILLEGAL_URI_CODEPOINT ILLEGAL_URI_REFERENCE + \ IMAGE_MAP_SERVER_SIDE_REQUIRES_CONVERSION + \ IMG_ALT_SUSPICIOUS_FILENAME IMG_ALT_SUSPICIOUS_FILE_SIZE + \ IMG_ALT_SUSPICIOUS_PLACEHOLDER IMG_ALT_SUSPICIOUS_TOO_LONG + \ IMG_BUTTON_MISSING_ALT IMG_MAP_CLIENT_MISSING_TEXT_LINKS + \ IMG_MAP_SERVER_REQUIRES_TEXT_LINKS IMG_MISSING_ALT IMG_MISSING_DLINK + \ IMG_MISSING_LONGDESC IMG_MISSING_LONGDESC_DLINK + \ INFORMATION_NOT_CONVEYED_APPLET INFORMATION_NOT_CONVEYED_IMAGE + \ INFORMATION_NOT_CONVEYED_INPUT INFORMATION_NOT_CONVEYED_OBJECT + \ INFORMATION_NOT_CONVEYED_SCRIPT INSERTING_AUTO_ATTRIBUTE + \ INSERTING_TAG INVALID_ATTRIBUTE INVALID_NCR INVALID_SGML_CHARS + \ INVALID_UTF16 INVALID_UTF8 INVALID_XML_ID JOINING_ATTRIBUTE + \ LANGUAGE_INVALID LANGUAGE_NOT_IDENTIFIED + \ LAYOUT_TABLES_LINEARIZE_PROPERLY LAYOUT_TABLE_INVALID_MARKUP + \ LINK_TEXT_MISSING LINK_TEXT_NOT_MEANINGFUL + \ LINK_TEXT_NOT_MEANINGFUL_CLICK_HERE LINK_TEXT_TOO_LONG + \ LIST_USAGE_INVALID_LI LIST_USAGE_INVALID_OL LIST_USAGE_INVALID_UL + \ MALFORMED_COMMENT MALFORMED_COMMENT_DROPPING MALFORMED_COMMENT_EOS + \ MALFORMED_COMMENT_WARN MALFORMED_DOCTYPE METADATA_MISSING + \ METADATA_MISSING_REDIRECT_AUTOREFRESH MISMATCHED_ATTRIBUTE_ERROR + \ MISMATCHED_ATTRIBUTE_WARN MISSING_ATTRIBUTE MISSING_ATTR_VALUE + \ MISSING_DOCTYPE MISSING_ENDTAG_BEFORE MISSING_ENDTAG_FOR + \ MISSING_ENDTAG_OPTIONAL MISSING_IMAGEMAP MISSING_QUOTEMARK + \ MISSING_QUOTEMARK_OPEN MISSING_SEMICOLON MISSING_SEMICOLON_NCR + \ MISSING_STARTTAG MISSING_TITLE_ELEMENT MOVED_STYLE_TO_HEAD + \ MULTIMEDIA_REQUIRES_TEXT NESTED_EMPHASIS NESTED_QUOTATION + \ NEWLINE_IN_URI NEW_WINDOWS_REQUIRE_WARNING_BLANK + \ NEW_WINDOWS_REQUIRE_WARNING_NEW NOFRAMES_CONTENT + \ NOFRAMES_INVALID_CONTENT NOFRAMES_INVALID_LINK + \ NOFRAMES_INVALID_NO_VALUE NON_MATCHING_ENDTAG OBJECT_MISSING_ALT + \ OBSOLETE_ELEMENT OPTION_REMOVED OPTION_REMOVED_APPLIED + \ OPTION_REMOVED_UNAPPLIED POTENTIAL_HEADER_BOLD + \ POTENTIAL_HEADER_ITALICS POTENTIAL_HEADER_UNDERLINE + \ PREVIOUS_LOCATION PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_APPLET + \ PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_EMBED + \ PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_OBJECT + \ PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_SCRIPT PROPRIETARY_ATTRIBUTE + \ PROPRIETARY_ATTR_VALUE PROPRIETARY_ELEMENT REMOVED_HTML5 + \ REMOVE_AUTO_REDIRECT REMOVE_AUTO_REFRESH REMOVE_BLINK_MARQUEE + \ REMOVE_FLICKER_ANIMATED_GIF REMOVE_FLICKER_APPLET + \ REMOVE_FLICKER_EMBED REMOVE_FLICKER_OBJECT REMOVE_FLICKER_SCRIPT + \ REPEATED_ATTRIBUTE REPLACE_DEPRECATED_HTML_APPLET + \ REPLACE_DEPRECATED_HTML_BASEFONT REPLACE_DEPRECATED_HTML_CENTER + \ REPLACE_DEPRECATED_HTML_DIR REPLACE_DEPRECATED_HTML_FONT + \ REPLACE_DEPRECATED_HTML_ISINDEX REPLACE_DEPRECATED_HTML_MENU + \ REPLACE_DEPRECATED_HTML_S REPLACE_DEPRECATED_HTML_STRIKE + \ REPLACE_DEPRECATED_HTML_U REPLACING_ELEMENT REPLACING_UNEX_ELEMENT + \ SCRIPT_MISSING_NOSCRIPT SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_CLICK + \ SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_DOWN + \ SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_MOVE + \ SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OUT + \ SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OVER + \ SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_UP SKIPOVER_ASCII_ART + \ SPACE_PRECEDING_XMLDECL STRING_ARGUMENT_BAD STRING_CONTENT_LOOKS + \ STRING_DOCTYPE_GIVEN STRING_MISSING_MALFORMED STRING_MUTING_TYPE + \ STRING_NO_SYSID STRING_UNKNOWN_OPTION + \ STYLESHEETS_REQUIRE_TESTING_LINK + \ STYLESHEETS_REQUIRE_TESTING_STYLE_ATTR + \ STYLESHEETS_REQUIRE_TESTING_STYLE_ELEMENT + \ STYLE_SHEET_CONTROL_PRESENTATION SUSPECTED_MISSING_QUOTE + \ TABLE_MAY_REQUIRE_HEADER_ABBR TABLE_MAY_REQUIRE_HEADER_ABBR_NULL + \ TABLE_MAY_REQUIRE_HEADER_ABBR_SPACES TABLE_MISSING_CAPTION + \ TABLE_MISSING_SUMMARY TABLE_SUMMARY_INVALID_NULL + \ TABLE_SUMMARY_INVALID_PLACEHOLDER TABLE_SUMMARY_INVALID_SPACES + \ TAG_NOT_ALLOWED_IN TEXT_EQUIVALENTS_REQUIRE_UPDATING_APPLET + \ TEXT_EQUIVALENTS_REQUIRE_UPDATING_OBJECT + \ TEXT_EQUIVALENTS_REQUIRE_UPDATING_SCRIPT TOO_MANY_ELEMENTS + \ TOO_MANY_ELEMENTS_IN TRIM_EMPTY_ELEMENT UNESCAPED_AMPERSAND + \ UNEXPECTED_ENDTAG UNEXPECTED_ENDTAG_ERR UNEXPECTED_ENDTAG_IN + \ UNEXPECTED_END_OF_FILE UNEXPECTED_END_OF_FILE_ATTR + \ UNEXPECTED_EQUALSIGN UNEXPECTED_GT UNEXPECTED_QUOTEMARK + \ UNKNOWN_ELEMENT UNKNOWN_ELEMENT_LOOKS_CUSTOM UNKNOWN_ENTITY + \ USING_BR_INPLACE_OF VENDOR_SPECIFIC_CHARS WHITE_IN_URI + \ XML_DECLARATION_DETECTED XML_ID_SYNTAX + \ contained nextgroup=tidyMuteIDSeparator skipwhite skipnl + +" Options {{{1 +syn keyword tidyCustomTagsOption custom-tags contained nextgroup=tidyCustomTagsDelimiter +syn match tidyCustomTagsDelimiter ":" nextgroup=tidyCustomTags contained skipwhite + +syn keyword tidyBooleanOption add-meta-charset add-xml-decl + \ add-xml-pi add-xml-space anchor-as-name ascii-chars + \ assume-xml-procins bare break-before-br clean coerce-endtags + \ decorate-inferred-ul drop-empty-paras drop-empty-elements + \ drop-font-tags drop-proprietary-attributes enclose-block-text + \ enclose-text escape-cdata escape-scripts fix-backslash + \ fix-style-tags fix-uri force-output gdoc gnu-emacs hide-comments + \ hide-endtags indent-attributes indent-cdata indent-with-tabs + \ input-xml join-classes join-styles keep-tabs keep-time language + \ literal-attributes logical-emphasis lower-literals markup + \ merge-emphasis mute-id ncr numeric-entities omit-optional-tags + \ output-html output-xhtml output-xml preserve-entities + \ punctuation-wrap quiet quote-ampersand quote-marks quote-nbsp raw + \ replace-color show-filename show-info show-meta-change show-warnings + \ skip-nested split strict-tags-attributes tidy-mark + \ uppercase-attributes uppercase-tags warn-proprietary-attributes + \ word-2000 wrap-asp wrap-attributes wrap-jste wrap-php + \ wrap-script-literals wrap-sections write-back \ contained nextgroup=tidyBooleanDelimiter syn match tidyBooleanDelimiter ":" nextgroup=tidyBoolean contained skipwhite -syn keyword tidyAutoBooleanOption indent merge-divs merge-spans output-bom show-body-only vertical-space contained nextgroup=tidyAutoBooleanDelimiter +syn keyword tidyAutoBooleanOption fix-bad-comments indent merge-divs merge-spans output-bom show-body-only vertical-space contained nextgroup=tidyAutoBooleanDelimiter syn match tidyAutoBooleanDelimiter ":" nextgroup=tidyAutoBoolean contained skipwhite syn keyword tidyCSSSelectorOption css-prefix contained nextgroup=tidyCSSSelectorDelimiter syn match tidyCSSSelectorDelimiter ":" nextgroup=tidyCSSSelector contained skipwhite syn keyword tidyDoctypeOption doctype contained nextgroup=tidyDoctypeDelimiter -syn match tidyDoctypeDelimiter ":" nextgroup=tidyDoctype contained skipwhite +syn match tidyDoctypeDelimiter ":" nextgroup=tidyDoctype,tidyString contained skipwhite syn keyword tidyEncodingOption char-encoding input-encoding output-encoding contained nextgroup=tidyEncodingDelimiter syn match tidyEncodingDelimiter ":" nextgroup=tidyEncoding contained skipwhite @@ -67,8 +185,11 @@ syn match tidyNameDelimiter ":" nextgroup=tidyName contained skipwhite syn keyword tidyNewlineOption newline contained nextgroup=tidyNewlineDelimiter syn match tidyNewlineDelimiter ":" nextgroup=tidyNewline contained skipwhite +syn keyword tidyAttributesOption priority-attributes contained nextgroup=tidyAttributesDelimiter +syn match tidyAttributesDelimiter ":" nextgroup=tidyWord contained skipwhite + syn keyword tidyTagsOption new-blocklevel-tags new-empty-tags new-inline-tags new-pre-tags contained nextgroup=tidyTagsDelimiter -syn match tidyTagsDelimiter ":" nextgroup=tidyTags contained skipwhite +syn match tidyTagsDelimiter ":" nextgroup=tidyWord contained skipwhite syn keyword tidyRepeatOption repeated-attributes contained nextgroup=tidyRepeatDelimiter syn match tidyRepeatDelimiter ":" nextgroup=tidyRepeat contained skipwhite @@ -79,57 +200,77 @@ syn match tidySorterDelimiter ":" nextgroup=tidySorter contained skipwhite syn keyword tidyStringOption alt-text error-file gnu-emacs-file output-file contained nextgroup=tidyStringDelimiter syn match tidyStringDelimiter ":" nextgroup=tidyString contained skipwhite +syn keyword tidyMuteOption mute contained nextgroup=tidyMuteDelimiter +syn match tidyMuteDelimiter ":" nextgroup=tidyMuteID contained skipwhite + syn cluster tidyOptions contains=tidy.*Option +" Option line anchor {{{1 syn match tidyStart "^" nextgroup=@tidyOptions +" Long standing bug - option lines (except the first) with leading whitespace +" are silently ignored. +syn match tidyErrorStart '^\s\+\ze\S' +" Comments {{{1 syn match tidyComment "^\s*//.*$" contains=tidyTodo syn match tidyComment "^\s*#.*$" contains=tidyTodo syn keyword tidyTodo TODO NOTE FIXME XXX contained +" Default highlighting {{{1 +hi def link tidyAttributesOption Identifier hi def link tidyAutoBooleanOption Identifier hi def link tidyBooleanOption Identifier hi def link tidyCSSSelectorOption Identifier +hi def link tidyCustomTagsOption Identifier hi def link tidyDoctypeOption Identifier hi def link tidyEncodingOption Identifier hi def link tidyIntegerOption Identifier +hi def link tidyMuteOption Identifier hi def link tidyNameOption Identifier hi def link tidyNewlineOption Identifier -hi def link tidyTagsOption Identifier hi def link tidyRepeatOption Identifier hi def link tidySorterOption Identifier hi def link tidyStringOption Identifier +hi def link tidyTagsOption Identifier +hi def link tidyAttributesDelimiter Special hi def link tidyAutoBooleanDelimiter Special hi def link tidyBooleanDelimiter Special hi def link tidyCSSSelectorDelimiter Special +hi def link tidyCustomTagsDelimiter Special hi def link tidyDoctypeDelimiter Special hi def link tidyEncodingDelimiter Special hi def link tidyIntegerDelimiter Special +hi def link tidyMuteDelimiter Special hi def link tidyNameDelimiter Special hi def link tidyNewlineDelimiter Special -hi def link tidyTagsDelimiter Special hi def link tidyRepeatDelimiter Special hi def link tidySorterDelimiter Special hi def link tidyStringDelimiter Special +hi def link tidyTagsDelimiter Special hi def link tidyAutoBoolean Boolean hi def link tidyBoolean Boolean +hi def link tidyCustomTags Constant hi def link tidyDoctype Constant hi def link tidyEncoding Constant +hi def link tidyMuteID Constant hi def link tidyNewline Constant -hi def link tidyTags Constant hi def link tidyNumber Number hi def link tidyRepeat Constant hi def link tidySorter Constant hi def link tidyString String +hi def link tidyWord Constant hi def link tidyComment Comment hi def link tidyTodo Todo +hi def link tidyErrorStart Error + +" Postscript {{{1 let b:current_syntax = "tidy" let &cpo = s:cpo_save unlet s:cpo_save -" vim: ts=8 +" vim: ts=8 fdm=marker diff --git a/runtime/tutor/tutor.ko b/runtime/tutor/tutor.ko index 942fdb44a8..f732bbc246 100644 --- a/runtime/tutor/tutor.ko +++ b/runtime/tutor/tutor.ko @@ -907,7 +907,7 @@ ce 는 단어를 치환하는 것 뿐만 아니라, 내용을 삽입할 수 있 5. 을 눌러 ":edit" 명령어를 완성해 봅니다. - 6. 이제 빈칸 하나를 추가한 뒤, 존재 파일 이름을 앞 부분을 입력합니다: :edit FIL + 6. 이제 빈칸 하나를 추가한 뒤, 존재하는 파일 이름의 앞 부분을 입력합니다: :edit FIL 7. 을 눌러 파일 이름을 완성 시킵니다. diff --git a/runtime/tutor/tutor.ko.euc b/runtime/tutor/tutor.ko.euc index 551b9a0ffb..74c81d9444 100644 --- a/runtime/tutor/tutor.ko.euc +++ b/runtime/tutor/tutor.ko.euc @@ -907,7 +907,7 @@ ce 5. ":edit" ɾ ϼ ϴ. - 6. ĭ ϳ ߰ , ̸ κ Էմϴ: :edit FIL + 6. ĭ ϳ ߰ , ϴ ̸ κ Էմϴ: :edit FIL 7. ̸ ϼ ŵϴ. diff --git a/runtime/tutor/tutor.ko.utf-8 b/runtime/tutor/tutor.ko.utf-8 index 942fdb44a8..f732bbc246 100644 --- a/runtime/tutor/tutor.ko.utf-8 +++ b/runtime/tutor/tutor.ko.utf-8 @@ -907,7 +907,7 @@ ce 는 단어를 치환하는 것 뿐만 아니라, 내용을 삽입할 수 있 5. 을 눌러 ":edit" 명령어를 완성해 봅니다. - 6. 이제 빈칸 하나를 추가한 뒤, 존재 파일 이름을 앞 부분을 입력합니다: :edit FIL + 6. 이제 빈칸 하나를 추가한 뒤, 존재하는 파일 이름의 앞 부분을 입력합니다: :edit FIL 7. 을 눌러 파일 이름을 완성 시킵니다. From ff0e57fe77b1a87a034191c629730b081f6fb7ad Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 25 Jan 2021 23:02:38 +0100 Subject: [PATCH 46/47] patch 8.2.2410: build failure without the +profiling feature Problem: Build failure without the +profiling feature. Solution: Add dummy argument to macro. --- src/version.c | 2 ++ src/vim9.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/version.c b/src/version.c index 279c49d0c1..7a25bc0d6d 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 */ +/**/ + 2410, /**/ 2409, /**/ diff --git a/src/vim9.h b/src/vim9.h index 76ec40303d..82fdfe6340 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -415,6 +415,6 @@ extern garray_T def_functions; ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \ ? (dfunc)->df_instr_prof : (dfunc)->df_instr) #else -# define PROFILING FALSE +# define PROFILING(ufunc) FALSE # define INSTRUCTIONS(dfunc) ((dfunc)->df_instr) #endif From 98989a00145cc4f5783bcc12a2968a2f716eabb9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 26 Jan 2021 12:06:30 +0100 Subject: [PATCH 47/47] patch 8.2.2411: profile test fails on MS-Windows Problem: Profile test fails on MS-Windows. Solution: Do the profiling in a separate Vim command. --- src/testdir/test_profile.vim | 7 ++++++- src/version.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index 3abe898052..c8c877d5c1 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -593,11 +593,16 @@ func Test_vim9_profiling() enddef def Crash() enddef - prof start /tmp/profile.log + prof start Xprofile_crash.log prof func Func Func() END + call writefile(lines, 'Xprofile_crash.vim') + call system(GetVimCommandClean() . ' -es -c "so Xprofile_crash.vim" -c q') + call assert_equal(0, v:shell_error) call CheckScriptSuccess(lines) + call delete('Xprofile_crash.vim') + call delete('Xprofile_crash.log') endfunc diff --git a/src/version.c b/src/version.c index 7a25bc0d6d..086d79f15a 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 */ +/**/ + 2411, /**/ 2410, /**/