mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.4861: it is not easy to restore saved mappings
Problem: It is not easy to restore saved mappings. Solution: Make mapset() accept a dict argument. (Ernie Rael, closes #10295)
This commit is contained in:
parent
05cf63e9bd
commit
51d04d16f2
@ -5310,6 +5310,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
|
|||||||
"lnum" The line number in "sid", zero if unknown.
|
"lnum" The line number in "sid", zero if unknown.
|
||||||
"nowait" Do not wait for other, longer mappings.
|
"nowait" Do not wait for other, longer mappings.
|
||||||
(|:map-<nowait>|).
|
(|:map-<nowait>|).
|
||||||
|
"abbr" True if this is an |abbreviation|.
|
||||||
|
|
||||||
The dictionary can be used to restore a mapping with
|
The dictionary can be used to restore a mapping with
|
||||||
|mapset()|.
|
|mapset()|.
|
||||||
@ -5380,9 +5381,18 @@ mapnew({expr1}, {expr2}) *mapnew()*
|
|||||||
|
|
||||||
|
|
||||||
mapset({mode}, {abbr}, {dict}) *mapset()*
|
mapset({mode}, {abbr}, {dict}) *mapset()*
|
||||||
Restore a mapping from a dictionary returned by |maparg()|.
|
mapset({dict})
|
||||||
{mode} and {abbr} should be the same as for the call to
|
Restore a mapping from a dictionary, possibly returned by
|
||||||
|maparg()|. *E460*
|
|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,
|
{mode} is used to define the mode in which the mapping is set,
|
||||||
not the "mode" entry in {dict}.
|
not the "mode" entry in {dict}.
|
||||||
Example for saving and restoring a mapping: >
|
Example for saving and restoring a mapping: >
|
||||||
@ -5391,8 +5401,22 @@ mapset({mode}, {abbr}, {dict}) *mapset()*
|
|||||||
...
|
...
|
||||||
call mapset('n', 0, save_map)
|
call mapset('n', 0, save_map)
|
||||||
< Note that if you are going to replace a map in several modes,
|
< 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
|
e.g. with `:map!`, you need to save/restore the mapping for
|
||||||
them, since they can differ.
|
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()*
|
match({expr}, {pat} [, {start} [, {count}]]) *match()*
|
||||||
|
@ -3262,4 +3262,6 @@ EXTERN char e_no_script_file_name_to_substitute_for_script[]
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
EXTERN char e_string_or_function_required_for_arrow_parens_expr[]
|
EXTERN char e_string_or_function_required_for_arrow_parens_expr[]
|
||||||
INIT(= N_("E1275: String or function required for ->(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
|
#endif
|
||||||
|
@ -421,6 +421,21 @@ arg_string_or_list_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *con
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* Check "type" is a string or a blob
|
||||||
*/
|
*/
|
||||||
@ -998,8 +1013,8 @@ static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
|
|||||||
static argcheck_T arg3_string_any_dict[] = {arg_string, NULL, arg_dict_any};
|
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_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_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_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_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_dict[] = {arg_string, arg_string, arg_dict_any};
|
||||||
static argcheck_T arg3_string_string_number[] = {arg_string, arg_string, arg_number};
|
static argcheck_T arg3_string_string_number[] = {arg_string, arg_string, arg_number};
|
||||||
@ -2053,7 +2068,7 @@ static funcentry_T global_functions[] =
|
|||||||
ret_list_dict_any, f_maplist},
|
ret_list_dict_any, f_maplist},
|
||||||
{"mapnew", 2, 2, FEARG_1, arg2_mapnew,
|
{"mapnew", 2, 2, FEARG_1, arg2_mapnew,
|
||||||
ret_first_cont, f_mapnew},
|
ret_first_cont, f_mapnew},
|
||||||
{"mapset", 3, 3, FEARG_1, arg3_string_bool_dict,
|
{"mapset", 1, 3, FEARG_1, arg3_string_or_dict_bool_dict,
|
||||||
ret_void, f_mapset},
|
ret_void, f_mapset},
|
||||||
{"match", 2, 4, FEARG_1, arg24_match_func,
|
{"match", 2, 4, FEARG_1, arg24_match_func,
|
||||||
ret_any, f_match},
|
ret_any, f_match},
|
||||||
|
92
src/map.c
92
src/map.c
@ -2283,7 +2283,8 @@ mapblock2dict(
|
|||||||
mapblock_T *mp,
|
mapblock_T *mp,
|
||||||
dict_T *dict,
|
dict_T *dict,
|
||||||
char_u *lhsrawalt, // may be NULL
|
char_u *lhsrawalt, // may be NULL
|
||||||
int buffer_local) // false if not buffer local mapping
|
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 *lhs = str2special_save(mp->m_keys, TRUE);
|
||||||
char_u *mapmode = map_mode_to_chars(mp->m_mode);
|
char_u *mapmode = map_mode_to_chars(mp->m_mode);
|
||||||
@ -2307,6 +2308,7 @@ mapblock2dict(
|
|||||||
dict_add_number(dict, "buffer", (long)buffer_local);
|
dict_add_number(dict, "buffer", (long)buffer_local);
|
||||||
dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
|
dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
|
||||||
dict_add_string(dict, "mode", mapmode);
|
dict_add_string(dict, "mode", mapmode);
|
||||||
|
dict_add_number(dict, "abbr", abbr ? 1L : 0L);
|
||||||
|
|
||||||
vim_free(mapmode);
|
vim_free(mapmode);
|
||||||
}
|
}
|
||||||
@ -2381,7 +2383,8 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
|||||||
}
|
}
|
||||||
else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
|
else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
|
||||||
mapblock2dict(mp, rettv->vval.v_dict,
|
mapblock2dict(mp, rettv->vval.v_dict,
|
||||||
did_simplify ? keys_simplified : NULL, buffer_local);
|
did_simplify ? keys_simplified : NULL,
|
||||||
|
buffer_local, abbr);
|
||||||
|
|
||||||
vim_free(keys_buf);
|
vim_free(keys_buf);
|
||||||
vim_free(alt_keys_buf);
|
vim_free(alt_keys_buf);
|
||||||
@ -2448,7 +2451,8 @@ f_maplist(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
vim_free(lhs);
|
vim_free(lhs);
|
||||||
|
|
||||||
mapblock2dict(mp, d,
|
mapblock2dict(mp, d,
|
||||||
did_simplify ? keys_buf : NULL, buffer_local);
|
did_simplify ? keys_buf : NULL,
|
||||||
|
buffer_local, abbr);
|
||||||
vim_free(keys_buf);
|
vim_free(keys_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2489,6 +2493,56 @@ f_mapcheck(typval_T *argvars, typval_T *rettv)
|
|||||||
get_maparg(argvars, rettv, FALSE);
|
get_maparg(argvars, rettv, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* "mapset()" function
|
||||||
*/
|
*/
|
||||||
@ -2518,25 +2572,51 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
mapblock_T **abbr_table = &first_abbr;
|
mapblock_T **abbr_table = &first_abbr;
|
||||||
int nowait;
|
int nowait;
|
||||||
char_u *arg;
|
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()
|
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_string_arg(argvars, 0) == FAIL
|
||||||
|| check_for_bool_arg(argvars, 1) == FAIL
|
|| check_for_bool_arg(argvars, 1) == FAIL
|
||||||
|| check_for_dict_arg(argvars, 2) == FAIL))
|
|| check_for_dict_arg(argvars, 2) == FAIL))))
|
||||||
return;
|
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);
|
which = tv_get_string_buf_chk(&argvars[0], buf);
|
||||||
if (which == NULL)
|
if (which == NULL)
|
||||||
return;
|
return;
|
||||||
mode = get_map_mode(&which, 0);
|
|
||||||
is_abbr = (int)tv_get_bool(&argvars[1]);
|
is_abbr = (int)tv_get_bool(&argvars[1]);
|
||||||
|
|
||||||
if (argvars[2].v_type != VAR_DICT)
|
if (argvars[2].v_type != VAR_DICT)
|
||||||
{
|
{
|
||||||
emsg(_(e_key_not_present_in_dictionary));
|
emsg(_(e_dictionary_required));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d = argvars[2].vval.v_dict;
|
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().
|
// Get the values in the same order as above in get_maparg().
|
||||||
lhs = dict_get_string(d, (char_u *)"lhs", FALSE);
|
lhs = dict_get_string(d, (char_u *)"lhs", FALSE);
|
||||||
|
@ -9,6 +9,7 @@ varnumber_T tv_get_number_chk(typval_T *varp, int *denote);
|
|||||||
varnumber_T tv_get_bool(typval_T *varp);
|
varnumber_T tv_get_bool(typval_T *varp);
|
||||||
varnumber_T tv_get_bool_chk(typval_T *varp, int *denote);
|
varnumber_T tv_get_bool_chk(typval_T *varp, int *denote);
|
||||||
float_T tv_get_float(typval_T *varp);
|
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_string_arg(typval_T *args, int idx);
|
||||||
int check_for_nonempty_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);
|
int check_for_opt_string_arg(typval_T *args, int idx);
|
||||||
|
@ -19,13 +19,13 @@ func Test_maparg()
|
|||||||
\ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16",
|
\ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16",
|
||||||
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
|
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
|
||||||
\ 'lnum': lnum + 1,
|
\ 'lnum': lnum + 1,
|
||||||
\ 'rhs': 'is<F4>foo', 'buffer': 0},
|
\ 'rhs': 'is<F4>foo', 'buffer': 0, 'abbr': 0},
|
||||||
\ maparg('foo<C-V>', '', 0, 1))
|
\ maparg('foo<C-V>', '', 0, 1))
|
||||||
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar',
|
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar',
|
||||||
\ 'lhsraw': 'bar', 'mode': 'v',
|
\ 'lhsraw': 'bar', 'mode': 'v',
|
||||||
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1,
|
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1,
|
||||||
\ 'lnum': lnum + 2,
|
\ 'lnum': lnum + 2,
|
||||||
\ 'rhs': 'isbar', 'buffer': 1},
|
\ 'rhs': 'isbar', 'buffer': 1, 'abbr': 0},
|
||||||
\ 'bar'->maparg('', 0, 1))
|
\ 'bar'->maparg('', 0, 1))
|
||||||
let lnum = expand('<sflnum>')
|
let lnum = expand('<sflnum>')
|
||||||
map <buffer> <nowait> foo bar
|
map <buffer> <nowait> foo bar
|
||||||
@ -33,7 +33,7 @@ func Test_maparg()
|
|||||||
\ 'lhsraw': 'foo', 'mode': ' ',
|
\ 'lhsraw': 'foo', 'mode': ' ',
|
||||||
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1,
|
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1,
|
||||||
\ 'lnum': lnum + 1, 'rhs': 'bar',
|
\ 'lnum': lnum + 1, 'rhs': 'bar',
|
||||||
\ 'buffer': 1},
|
\ 'buffer': 1, 'abbr': 0},
|
||||||
\ maparg('foo', '', 0, 1))
|
\ maparg('foo', '', 0, 1))
|
||||||
let lnum = expand('<sflnum>')
|
let lnum = expand('<sflnum>')
|
||||||
tmap baz foo
|
tmap baz foo
|
||||||
@ -41,8 +41,17 @@ func Test_maparg()
|
|||||||
\ 'lhsraw': 'baz', 'mode': 't',
|
\ 'lhsraw': 'baz', 'mode': 't',
|
||||||
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
|
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
|
||||||
\ 'lnum': lnum + 1, 'rhs': 'foo',
|
\ 'lnum': lnum + 1, 'rhs': 'foo',
|
||||||
\ 'buffer': 0},
|
\ 'buffer': 0, 'abbr': 0},
|
||||||
\ maparg('baz', 't', 0, 1))
|
\ maparg('baz', 't', 0, 1))
|
||||||
|
let lnum = expand('<sflnum>')
|
||||||
|
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 x<char-114>x
|
map abc x<char-114>x
|
||||||
call assert_equal("xrx", maparg('abc'))
|
call assert_equal("xrx", maparg('abc'))
|
||||||
@ -250,10 +259,156 @@ func Test_mapset()
|
|||||||
bwipe!
|
bwipe!
|
||||||
|
|
||||||
call assert_fails('call mapset([], v:false, {})', 'E730:')
|
call assert_fails('call mapset([], v:false, {})', 'E730:')
|
||||||
call assert_fails('call mapset("i", 0, "")', 'E716:')
|
call assert_fails('call mapset("i", 0, "")', 'E715:')
|
||||||
call assert_fails('call mapset("i", 0, {})', 'E460:')
|
call assert_fails('call mapset("i", 0, {})', 'E460:')
|
||||||
endfunc
|
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<string>
|
||||||
|
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<any>
|
||||||
|
|
||||||
|
# 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)
|
func Check_ctrlb_map(d, check_alt)
|
||||||
call assert_equal('<C-B>', a:d.lhs)
|
call assert_equal('<C-B>', a:d.lhs)
|
||||||
if a:check_alt
|
if a:check_alt
|
||||||
|
@ -2463,7 +2463,8 @@ def Test_maparg()
|
|||||||
sid: SID(),
|
sid: SID(),
|
||||||
scriptversion: 999999,
|
scriptversion: 999999,
|
||||||
rhs: 'bar',
|
rhs: 'bar',
|
||||||
buffer: 0})
|
buffer: 0,
|
||||||
|
abbr: 0})
|
||||||
unmap foo
|
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(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'])
|
v9.CheckDefAndScriptFailure(['maparg("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2'])
|
||||||
@ -2545,7 +2546,7 @@ def Test_mapnew()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_mapset()
|
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(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", 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<any> but got list<unknown>', 'E1206: Dictionary required for argument 3'])
|
v9.CheckDefAndScriptFailure(['mapset("a", false, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<unknown>', 'E1206: Dictionary required for argument 3'])
|
||||||
enddef
|
enddef
|
||||||
|
14
src/typval.c
14
src/typval.c
@ -359,6 +359,20 @@ tv_get_float(typval_T *varp)
|
|||||||
}
|
}
|
||||||
#endif
|
#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.
|
* Give an error and return FAIL unless "args[idx]" is a string.
|
||||||
*/
|
*/
|
||||||
|
@ -746,6 +746,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
4861,
|
||||||
/**/
|
/**/
|
||||||
4860,
|
4860,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user