To: vim_dev@googlegroups.com Subject: Patch 8.2.4861 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4861 Problem: It is not easy to restore saved mappings. Solution: Make mapset() accept a dict argument. (Ernie Rael, closes #10295) Files: runtime/doc/builtin.txt, src/errors.h, src/evalfunc.c, src/map.c, src/typval.c, src/proto/typval.pro, src/testdir/test_map_functions.vim, src/testdir/test_vim9_builtin.vim *** ../vim-8.2.4860/runtime/doc/builtin.txt 2022-05-03 11:01:59.058826963 +0100 --- runtime/doc/builtin.txt 2022-05-04 15:30:45.712569245 +0100 *************** *** 5291,5296 **** --- 5310,5316 ---- "lnum" The line number in "sid", zero if unknown. "nowait" Do not wait for other, longer mappings. (|:map-|). + "abbr" True if this is an |abbreviation|. The dictionary can be used to restore a mapping with |mapset()|. *************** *** 5361,5369 **** mapset({mode}, {abbr}, {dict}) *mapset()* ! Restore a mapping from a dictionary returned by |maparg()|. ! {mode} and {abbr} should be the same as for the call to ! |maparg()|. *E460* {mode} is used to define the mode in which the mapping is set, not the "mode" entry in {dict}. Example for saving and restoring a mapping: > --- 5381,5398 ---- mapset({mode}, {abbr}, {dict}) *mapset()* ! mapset({dict}) ! Restore a mapping from a dictionary, possibly returned by ! |maparg()| or |maplist()|. A buffer mapping, when dict.buffer ! is true, is set on the current buffer; it is up to the caller ! to insure that the intended buffer is the current buffer. This ! feature allows copying mappings from one buffer to another. ! The dict.mode value may restore a single mapping that covers ! more than one mode, like with mode values of '!', ' ', 'nox', ! or 'v'. *E1276* ! ! In the first form, {mode} and {abbr} should be the same as ! for the call to |maparg()|. *E460* {mode} is used to define the mode in which the mapping is set, not the "mode" entry in {dict}. Example for saving and restoring a mapping: > *************** *** 5372,5379 **** ... call mapset('n', 0, save_map) < Note that if you are going to replace a map in several modes, ! e.g. with `:map!`, you need to save the mapping for all of ! them, since they can differ. match({expr}, {pat} [, {start} [, {count}]]) *match()* --- 5401,5422 ---- ... call mapset('n', 0, save_map) < Note that if you are going to replace a map in several modes, ! e.g. with `:map!`, you need to save/restore the mapping for ! all of them, when they might differ. ! ! In the second form, with {dict} as the only argument, mode ! and abbr are taken from the dict. ! Example: > ! vim9script ! var save_maps = maplist()->filter( ! (_, m) => m.lhs == 'K') ! nnoremap K somethingelse ! cnoremap K somethingelse2 ! # ... ! unmap K ! for d in save_maps ! mapset(d) ! endfor match({expr}, {pat} [, {start} [, {count}]]) *match()* *** ../vim-8.2.4860/src/errors.h 2022-04-17 15:06:31.042622659 +0100 --- src/errors.h 2022-05-04 15:23:24.912707862 +0100 *************** *** 3262,3265 **** --- 3262,3267 ---- #ifdef FEAT_EVAL EXTERN char e_string_or_function_required_for_arrow_parens_expr[] INIT(= N_("E1275: String or function required for ->(expr)")); + EXTERN char e_illegal_map_mode_string_str[] + INIT(= N_("E1276: Illegal map mode string: '%s'")); #endif *** ../vim-8.2.4860/src/evalfunc.c 2022-04-28 17:52:19.532130311 +0100 --- src/evalfunc.c 2022-05-04 15:33:30.232502013 +0100 *************** *** 422,427 **** --- 422,442 ---- } /* + * Check "type" is a string or a dict of 'any' + */ + static int + arg_string_or_dict_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) + { + if (type->tt_type == VAR_ANY + || type->tt_type == VAR_UNKNOWN + || type->tt_type == VAR_STRING + || type->tt_type == VAR_DICT) + return OK; + arg_type_mismatch(&t_string, type, context->arg_idx + 1); + return FAIL; + } + + /* * Check "type" is a string or a blob */ static int *************** *** 998,1005 **** static argcheck_T arg3_string_any_dict[] = {arg_string, NULL, arg_dict_any}; static argcheck_T arg3_string_any_string[] = {arg_string, NULL, arg_string}; static argcheck_T arg3_string_bool_bool[] = {arg_string, arg_bool, arg_bool}; - static argcheck_T arg3_string_bool_dict[] = {arg_string, arg_bool, arg_dict_any}; static argcheck_T arg3_string_number_bool[] = {arg_string, arg_number, arg_bool}; static argcheck_T arg3_string_string_bool[] = {arg_string, arg_string, arg_bool}; static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any}; static argcheck_T arg3_string_string_number[] = {arg_string, arg_string, arg_number}; --- 1013,1020 ---- static argcheck_T arg3_string_any_dict[] = {arg_string, NULL, arg_dict_any}; static argcheck_T arg3_string_any_string[] = {arg_string, NULL, arg_string}; static argcheck_T arg3_string_bool_bool[] = {arg_string, arg_bool, arg_bool}; static argcheck_T arg3_string_number_bool[] = {arg_string, arg_number, arg_bool}; + static argcheck_T arg3_string_or_dict_bool_dict[] = {arg_string_or_dict_any, arg_bool, arg_dict_any}; static argcheck_T arg3_string_string_bool[] = {arg_string, arg_string, arg_bool}; static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any}; static argcheck_T arg3_string_string_number[] = {arg_string, arg_string, arg_number}; *************** *** 2053,2059 **** ret_list_dict_any, f_maplist}, {"mapnew", 2, 2, FEARG_1, arg2_mapnew, ret_first_cont, f_mapnew}, ! {"mapset", 3, 3, FEARG_1, arg3_string_bool_dict, ret_void, f_mapset}, {"match", 2, 4, FEARG_1, arg24_match_func, ret_any, f_match}, --- 2068,2074 ---- ret_list_dict_any, f_maplist}, {"mapnew", 2, 2, FEARG_1, arg2_mapnew, ret_first_cont, f_mapnew}, ! {"mapset", 1, 3, FEARG_1, arg3_string_or_dict_bool_dict, ret_void, f_mapset}, {"match", 2, 4, FEARG_1, arg24_match_func, ret_any, f_match}, *** ../vim-8.2.4860/src/map.c 2022-04-26 21:36:14.402164072 +0100 --- src/map.c 2022-05-04 15:36:18.096428302 +0100 *************** *** 2283,2289 **** mapblock_T *mp, dict_T *dict, char_u *lhsrawalt, // may be NULL ! int buffer_local) // false if not buffer local mapping { char_u *lhs = str2special_save(mp->m_keys, TRUE); char_u *mapmode = map_mode_to_chars(mp->m_mode); --- 2283,2290 ---- mapblock_T *mp, dict_T *dict, char_u *lhsrawalt, // may be NULL ! int buffer_local, // false if not buffer local mapping ! int abbr) // true if abbreviation { char_u *lhs = str2special_save(mp->m_keys, TRUE); char_u *mapmode = map_mode_to_chars(mp->m_mode); *************** *** 2307,2312 **** --- 2308,2314 ---- dict_add_number(dict, "buffer", (long)buffer_local); dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L); dict_add_string(dict, "mode", mapmode); + dict_add_number(dict, "abbr", abbr ? 1L : 0L); vim_free(mapmode); } *************** *** 2381,2387 **** } else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL) mapblock2dict(mp, rettv->vval.v_dict, ! did_simplify ? keys_simplified : NULL, buffer_local); vim_free(keys_buf); vim_free(alt_keys_buf); --- 2383,2390 ---- } else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL) mapblock2dict(mp, rettv->vval.v_dict, ! did_simplify ? keys_simplified : NULL, ! buffer_local, abbr); vim_free(keys_buf); vim_free(alt_keys_buf); *************** *** 2448,2454 **** vim_free(lhs); mapblock2dict(mp, d, ! did_simplify ? keys_buf : NULL, buffer_local); vim_free(keys_buf); } } --- 2451,2458 ---- vim_free(lhs); mapblock2dict(mp, d, ! did_simplify ? keys_buf : NULL, ! buffer_local, abbr); vim_free(keys_buf); } } *************** *** 2490,2495 **** --- 2494,2549 ---- } /* + * Get the mapping mode from the mode string. + * It may contain multiple characters, eg "nox", or "!", or ' ' + * Return 0 if there is an error. + */ + static int + get_map_mode_string(char_u *mode_string, int abbr) + { + char_u *p = mode_string; + int mode = 0; + int tmode; + int modec; + const int MASK_V = VISUAL + SELECTMODE; + const int MASK_MAP = VISUAL + SELECTMODE + NORMAL + OP_PENDING; + const int MASK_BANG = INSERT + CMDLINE; + + if (*p == NUL) + p = (char_u *)" "; // compatibility + while ((modec = *p++)) + { + switch (modec) + { + case 'i': tmode = INSERT; break; + case 'l': tmode = LANGMAP; break; + case 'c': tmode = CMDLINE; break; + case 'n': tmode = NORMAL; break; + case 'x': tmode = VISUAL; break; + case 's': tmode = SELECTMODE; break; + case 'o': tmode = OP_PENDING; break; + case 't': tmode = TERMINAL; break; + case 'v': tmode = MASK_V; break; + case '!': tmode = MASK_BANG; break; + case ' ': tmode = MASK_MAP; break; + default: + return 0; // error, unknown mode character + } + mode |= tmode; + } + if ((abbr && (mode & ~MASK_BANG) != 0) + || (!abbr && (mode & (mode-1)) != 0 // more than one bit set + && ( + // false if multiple bits set in mode and mode is fully + // contained in one mask + !(((mode & MASK_BANG) != 0 && (mode & ~MASK_BANG) == 0) + || ((mode & MASK_MAP) != 0 && (mode & ~MASK_MAP) == 0))))) + return 0; + + return mode; + } + + /* * "mapset()" function */ void *************** *** 2518,2542 **** mapblock_T **abbr_table = &first_abbr; int nowait; char_u *arg; if (in_vim9script() ! && (check_for_string_arg(argvars, 0) == FAIL ! || check_for_bool_arg(argvars, 1) == FAIL ! || check_for_dict_arg(argvars, 2) == FAIL)) return; ! which = tv_get_string_buf_chk(&argvars[0], buf); ! if (which == NULL) ! return; ! mode = get_map_mode(&which, 0); ! is_abbr = (int)tv_get_bool(&argvars[1]); ! if (argvars[2].v_type != VAR_DICT) { ! emsg(_(e_key_not_present_in_dictionary)); return; } ! d = argvars[2].vval.v_dict; // Get the values in the same order as above in get_maparg(). lhs = dict_get_string(d, (char_u *)"lhs", FALSE); --- 2572,2622 ---- mapblock_T **abbr_table = &first_abbr; int nowait; char_u *arg; + int dict_only; + // If first arg is a dict, then that's the only arg permitted. + dict_only = argvars[0].v_type == VAR_DICT; if (in_vim9script() ! && (check_for_string_or_dict_arg(argvars, 0) == FAIL ! || (dict_only && check_for_unknown_arg(argvars, 1) == FAIL) ! || (!dict_only ! && (check_for_string_arg(argvars, 0) == FAIL ! || check_for_bool_arg(argvars, 1) == FAIL ! || check_for_dict_arg(argvars, 2) == FAIL)))) return; ! if (dict_only) ! { ! d = argvars[0].vval.v_dict; ! which = dict_get_string(d, (char_u *)"mode", FALSE); ! is_abbr = dict_get_bool(d, (char_u *)"abbr", -1); ! if (which == NULL || is_abbr < 0) ! { ! emsg(_(e_entries_missing_in_mapset_dict_argument)); ! return; ! } ! } ! else ! { ! which = tv_get_string_buf_chk(&argvars[0], buf); ! if (which == NULL) ! return; ! is_abbr = (int)tv_get_bool(&argvars[1]); ! if (argvars[2].v_type != VAR_DICT) ! { ! emsg(_(e_dictionary_required)); ! return; ! } ! d = argvars[2].vval.v_dict; ! } ! mode = get_map_mode_string(which, is_abbr); ! if (mode == 0) { ! semsg(_(e_illegal_map_mode_string_str), which); return; } ! // Get the values in the same order as above in get_maparg(). lhs = dict_get_string(d, (char_u *)"lhs", FALSE); *** ../vim-8.2.4860/src/typval.c 2022-05-02 22:53:41.384211031 +0100 --- src/typval.c 2022-05-04 15:23:24.916707862 +0100 *************** *** 360,365 **** --- 360,379 ---- #endif /* + * Give an error and return FAIL unless "args[idx]" is unknown + */ + int + check_for_unknown_arg(typval_T *args, int idx) + { + if (args[idx].v_type != VAR_UNKNOWN) + { + semsg(_(e_too_many_arguments), idx + 1); + return FAIL; + } + return OK; + } + + /* * Give an error and return FAIL unless "args[idx]" is a string. */ int *** ../vim-8.2.4860/src/proto/typval.pro 2022-03-01 19:23:20.544357315 +0000 --- src/proto/typval.pro 2022-05-04 15:23:24.916707862 +0100 *************** *** 9,14 **** --- 9,15 ---- varnumber_T tv_get_bool(typval_T *varp); varnumber_T tv_get_bool_chk(typval_T *varp, int *denote); float_T tv_get_float(typval_T *varp); + int check_for_unknown_arg(typval_T *args, int idx); int check_for_string_arg(typval_T *args, int idx); int check_for_nonempty_string_arg(typval_T *args, int idx); int check_for_opt_string_arg(typval_T *args, int idx); *** ../vim-8.2.4860/src/testdir/test_map_functions.vim 2022-04-26 21:36:14.402164072 +0100 --- src/testdir/test_map_functions.vim 2022-05-04 15:23:24.916707862 +0100 *************** *** 19,31 **** \ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16", \ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 1, ! \ 'rhs': 'isfoo', 'buffer': 0}, \ maparg('foo', '', 0, 1)) call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar', \ 'lhsraw': 'bar', 'mode': 'v', \ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 2, ! \ 'rhs': 'isbar', 'buffer': 1}, \ 'bar'->maparg('', 0, 1)) let lnum = expand('') map foo bar --- 19,31 ---- \ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16", \ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 1, ! \ 'rhs': 'isfoo', 'buffer': 0, 'abbr': 0}, \ maparg('foo', '', 0, 1)) call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar', \ 'lhsraw': 'bar', 'mode': 'v', \ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 2, ! \ 'rhs': 'isbar', 'buffer': 1, 'abbr': 0}, \ 'bar'->maparg('', 0, 1)) let lnum = expand('') map foo bar *************** *** 33,39 **** \ 'lhsraw': 'foo', 'mode': ' ', \ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 1, 'rhs': 'bar', ! \ 'buffer': 1}, \ maparg('foo', '', 0, 1)) let lnum = expand('') tmap baz foo --- 33,39 ---- \ 'lhsraw': 'foo', 'mode': ' ', \ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 1, 'rhs': 'bar', ! \ 'buffer': 1, 'abbr': 0}, \ maparg('foo', '', 0, 1)) let lnum = expand('') tmap baz foo *************** *** 41,48 **** \ 'lhsraw': 'baz', 'mode': 't', \ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 1, 'rhs': 'foo', ! \ 'buffer': 0}, \ maparg('baz', 't', 0, 1)) map abc xx call assert_equal("xrx", maparg('abc')) --- 41,57 ---- \ 'lhsraw': 'baz', 'mode': 't', \ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, \ 'lnum': lnum + 1, 'rhs': 'foo', ! \ 'buffer': 0, 'abbr': 0}, \ maparg('baz', 't', 0, 1)) + let lnum = expand('') + iab A B + call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'A', + \ 'lhsraw': 'A', 'mode': 'i', + \ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1, + \ 'lnum': lnum + 1, 'rhs': 'B', + \ 'buffer': 0, 'abbr': 1}, + \ maparg('A', 'i', 1, 1)) + iuna A map abc xx call assert_equal("xrx", maparg('abc')) *************** *** 250,259 **** bwipe! call assert_fails('call mapset([], v:false, {})', 'E730:') ! call assert_fails('call mapset("i", 0, "")', 'E716:') call assert_fails('call mapset("i", 0, {})', 'E460:') endfunc func Check_ctrlb_map(d, check_alt) call assert_equal('', a:d.lhs) if a:check_alt --- 259,414 ---- bwipe! call assert_fails('call mapset([], v:false, {})', 'E730:') ! call assert_fails('call mapset("i", 0, "")', 'E715:') call assert_fails('call mapset("i", 0, {})', 'E460:') endfunc + def Test_mapset_arg1_dir() + # This test is mostly about get_map_mode_string. + # Once the code gets past that, it's common with the 3 arg mapset. + + # GetModes() return list of modes for 'XZ' lhs using maplist. + # There is one list item per mapping + def GetModes(abbr: bool = false): list + return maplist(abbr)->filter((_, m) => m.lhs == 'XZ') + ->mapnew((_, m) => m.mode) + enddef + + const unmap_cmds = [ 'unmap', 'unmap!', 'tunmap', 'lunmap' ] + def UnmapAll(lhs: string) + for cmd in unmap_cmds + try | execute(cmd .. ' ' .. lhs) | catch /E31/ | endtry + endfor + enddef + + var tmap: dict + + # some mapset(mode, abbr, dict) tests using get_map_mode_str + map XZ x + tmap = maplist()->filter((_, m) => m.lhs == 'XZ')[0]->copy() + # this splits the mapping into 2 mappings + mapset('ox', false, tmap) + assert_equal(2, len(GetModes())) + mapset('o', false, tmap) + assert_equal(3, len(GetModes())) + # test that '' acts like ' ', and that the 3 mappings become 1 + mapset('', false, tmap) + assert_equal([' '], GetModes()) + # dict's mode/abbr are ignored + UnmapAll('XZ') + tmap.mode = '!' + tmap.abbr = true + mapset('o', false, tmap) + assert_equal(['o'], GetModes()) + + # test the 3 arg version handles bad mode string, dict not used + assert_fails("mapset('vi', false, {})", 'E1276:') + + + # get the abbreviations out of the way + abbreviate XZ ZX + tmap = maplist(true)->filter((_, m) => m.lhs == 'XZ')[0]->copy() + + abclear + # 'ic' is the default ab command, shows up as '!' + tmap.mode = 'ic' + mapset(tmap) + assert_equal(['!'], GetModes(true)) + + abclear + tmap.mode = 'i' + mapset(tmap) + assert_equal(['i'], GetModes(true)) + + abclear + tmap.mode = 'c' + mapset(tmap) + assert_equal(['c'], GetModes(true)) + + abclear + tmap.mode = '!' + mapset(tmap) + assert_equal(['!'], GetModes(true)) + + assert_fails("mapset({mode: ' !', abbr: 1})", 'E1276:') + assert_fails("mapset({mode: 'cl', abbr: 1})", 'E1276:') + assert_fails("mapset({mode: 'in', abbr: 1})", 'E1276:') + + # the map commands + map XZ x + tmap = maplist()->filter((_, m) => m.lhs == 'XZ')[0]->copy() + + # try the combos + UnmapAll('XZ') + # 'nxso' is ' ', the unadorned :map + tmap.mode = 'nxso' + mapset(tmap) + assert_equal([' '], GetModes()) + + UnmapAll('XZ') + # 'ic' is '!' + tmap.mode = 'ic' + mapset(tmap) + assert_equal(['!'], GetModes()) + + UnmapAll('XZ') + # 'xs' is really 'v' + tmap.mode = 'xs' + mapset(tmap) + assert_equal(['v'], GetModes()) + + # try the individual modes + UnmapAll('XZ') + tmap.mode = 'n' + mapset(tmap) + assert_equal(['n'], GetModes()) + + UnmapAll('XZ') + tmap.mode = 'x' + mapset(tmap) + assert_equal(['x'], GetModes()) + + UnmapAll('XZ') + tmap.mode = 's' + mapset(tmap) + assert_equal(['s'], GetModes()) + + UnmapAll('XZ') + tmap.mode = 'o' + mapset(tmap) + assert_equal(['o'], GetModes()) + + UnmapAll('XZ') + tmap.mode = 'i' + mapset(tmap) + assert_equal(['i'], GetModes()) + + UnmapAll('XZ') + tmap.mode = 'c' + mapset(tmap) + assert_equal(['c'], GetModes()) + + UnmapAll('XZ') + tmap.mode = 't' + mapset(tmap) + assert_equal(['t'], GetModes()) + + UnmapAll('XZ') + tmap.mode = 'l' + mapset(tmap) + assert_equal(['l'], GetModes()) + + UnmapAll('XZ') + + # get errors for modes that can't be in one mapping + assert_fails("mapset({mode: 'nxsoi', abbr: 0})", 'E1276:') + assert_fails("mapset({mode: ' !', abbr: 0})", 'E1276:') + assert_fails("mapset({mode: 'ix', abbr: 0})", 'E1276:') + assert_fails("mapset({mode: 'tl', abbr: 0})", 'E1276:') + assert_fails("mapset({mode: ' l', abbr: 0})", 'E1276:') + assert_fails("mapset({mode: ' t', abbr: 0})", 'E1276:') + enddef + func Check_ctrlb_map(d, check_alt) call assert_equal('', a:d.lhs) if a:check_alt *** ../vim-8.2.4860/src/testdir/test_vim9_builtin.vim 2022-04-23 10:50:18.971609285 +0100 --- src/testdir/test_vim9_builtin.vim 2022-05-04 15:23:24.916707862 +0100 *************** *** 2463,2469 **** sid: SID(), scriptversion: 999999, rhs: 'bar', ! buffer: 0}) unmap foo v9.CheckDefAndScriptFailure(['maparg(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) v9.CheckDefAndScriptFailure(['maparg("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) --- 2463,2470 ---- sid: SID(), scriptversion: 999999, rhs: 'bar', ! buffer: 0, ! abbr: 0}) unmap foo v9.CheckDefAndScriptFailure(['maparg(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) v9.CheckDefAndScriptFailure(['maparg("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) *************** *** 2545,2551 **** enddef def Test_mapset() ! v9.CheckDefAndScriptFailure(['mapset(1, true, {})'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) v9.CheckDefAndScriptFailure(['mapset("a", 2, {})'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) v9.CheckDefAndScriptFailure(['mapset("a", false, [])'], ['E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3']) enddef --- 2546,2552 ---- enddef def Test_mapset() ! v9.CheckDefAndScriptFailure(['mapset(1, true, {})'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1223: String or Dictionary required for argument 1']) v9.CheckDefAndScriptFailure(['mapset("a", 2, {})'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) v9.CheckDefAndScriptFailure(['mapset("a", false, [])'], ['E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3']) enddef *** ../vim-8.2.4860/src/version.c 2022-05-03 11:01:59.062826957 +0100 --- src/version.c 2022-05-04 15:38:48.612358985 +0100 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 4861, /**/ -- I AM THANKFUL... ...for the piles of laundry and ironing because it means I have plenty of clothes to wear. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///