Merge pull request #19602 from zeertzjq/vim-8.2.0807

vim-patch:8.2.{0807,0809,0812,0815,0832,1773,2804,4831,5106},9.0.0127: first part of mapset()
This commit is contained in:
zeertzjq
2022-08-01 22:19:30 +08:00
committed by GitHub
9 changed files with 441 additions and 169 deletions

View File

@@ -295,6 +295,8 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]])
rhs of mapping {name} in mode {mode} rhs of mapping {name} in mode {mode}
mapcheck({name} [, {mode} [, {abbr}]]) mapcheck({name} [, {mode} [, {abbr}]])
String check for mappings matching {name} String check for mappings matching {name}
mapset({mode}, {abbr}, {dict})
none restore mapping from |maparg()| result
match({expr}, {pat} [, {start} [, {count}]]) match({expr}, {pat} [, {start} [, {count}]])
Number position where {pat} matches in {expr} Number position where {pat} matches in {expr}
matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]]) matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
@@ -4716,6 +4718,7 @@ map({expr1}, {expr2}) *map()*
Can also be used as a |method|: > Can also be used as a |method|: >
mylist->map(expr2) mylist->map(expr2)
maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()* maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
When {dict} is omitted or zero: Return the rhs of mapping When {dict} is omitted or zero: Return the rhs of mapping
{name} in mode {mode}. The returned String has special {name} in mode {mode}. The returned String has special
@@ -4749,7 +4752,10 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
When {dict} is there and it is |TRUE| return a dictionary When {dict} is there and it is |TRUE| return a dictionary
containing all the information of the mapping with the containing all the information of the mapping with the
following items: following items:
"lhs" The {lhs} of the mapping. "lhs" The {lhs} of the mapping as it would be typed
"lhsraw" The {lhs} of the mapping as raw bytes
"lhsrawalt" The {lhs} of the mapping as raw bytes, alternate
form, only present when it differs from "lhsraw"
"rhs" The {rhs} of the mapping as typed. "rhs" The {rhs} of the mapping as typed.
"silent" 1 for a |:map-silent| mapping, else 0. "silent" 1 for a |:map-silent| mapping, else 0.
"noremap" 1 if the {rhs} of the mapping is not remappable. "noremap" 1 if the {rhs} of the mapping is not remappable.
@@ -4768,6 +4774,9 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
"nowait" Do not wait for other, longer mappings. "nowait" Do not wait for other, longer mappings.
(|:map-<nowait>|). (|:map-<nowait>|).
The dictionary can be used to restore a mapping with
|mapset()|.
The mappings local to the current buffer are checked first, The mappings local to the current buffer are checked first,
then the global mappings. then the global mappings.
This function can be used to map a key even when it's already This function can be used to map a key even when it's already
@@ -4813,6 +4822,22 @@ mapcheck({name} [, {mode} [, {abbr}]]) *mapcheck()*
Can also be used as a |method|: > Can also be used as a |method|: >
GetKey()->mapcheck('n') GetKey()->mapcheck('n')
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: >
let save_map = maparg('K', 'n', 0, 1)
nnoremap K somethingelse
...
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 differe.
match({expr}, {pat} [, {start} [, {count}]]) *match()* match({expr}, {pat} [, {start} [, {count}]]) *match()*
When {expr} is a |List| then this returns the index of the When {expr} is a |List| then this returns the index of the
first item where {pat} matches. Each item is used as a first item where {pat} matches. Each item is used as a

View File

@@ -2121,7 +2121,7 @@ void ex_loadkeymap(exarg_T *eap)
vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s %s", vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s %s",
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from, ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to); ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
(void)do_map(0, buf, MODE_LANGMAP, false); (void)do_map(MAPTYPE_MAP, buf, MODE_LANGMAP, false);
} }
p_cpo = save_cpo; p_cpo = save_cpo;
@@ -2158,7 +2158,7 @@ static void keymap_unload(void)
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) { for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
vim_snprintf(buf, sizeof(buf), "<buffer> %s", kp[i].from); vim_snprintf(buf, sizeof(buf), "<buffer> %s", kp[i].from);
(void)do_map(1, (char_u *)buf, MODE_LANGMAP, false); (void)do_map(MAPTYPE_UNMAP, (char_u *)buf, MODE_LANGMAP, false);
} }
keymap_ga_clear(&curbuf->b_kmap_ga); keymap_ga_clear(&curbuf->b_kmap_ga);

View File

@@ -250,6 +250,7 @@ return {
map={args=2, base=1}, map={args=2, base=1},
maparg={args={1, 4}, base=1}, maparg={args={1, 4}, base=1},
mapcheck={args={1, 3}, base=1}, mapcheck={args={1, 3}, base=1},
mapset={args=3, base=1},
match={args={2, 4}, base=1}, match={args={2, 4}, base=1},
matchadd={args={2, 5}, base=1}, matchadd={args={2, 5}, base=1},
matchaddpos={args={2, 5}, base=1}, matchaddpos={args={2, 5}, base=1},

View File

@@ -428,6 +428,66 @@ static int str_to_mapargs(const char_u *strargs, bool is_unmap, MapArguments *ma
return 0; return 0;
} }
/// @param args "rhs", "rhs_lua", "orig_rhs", "expr", "silent", "nowait", "replace_keycodes" and
/// and "desc" fields are used.
/// "rhs", "rhs_lua", "orig_rhs" fields are cleared if "simplified" is false.
/// @param sid -1 to use current_sctx
static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, const char_u *keys,
MapArguments *args, int noremap, int mode, bool is_abbr, scid_T sid,
linenr_T lnum, bool simplified)
{
mapblock_T *mp = xcalloc(1, sizeof(mapblock_T));
// If CTRL-C has been mapped, don't always use it for Interrupting.
if (*keys == Ctrl_C) {
if (map_table == buf->b_maphash) {
buf->b_mapped_ctrl_c |= mode;
} else {
mapped_ctrl_c |= mode;
}
}
mp->m_keys = vim_strsave(keys);
mp->m_str = args->rhs;
mp->m_orig_str = args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!simplified) {
args->rhs = NULL;
args->orig_rhs = NULL;
args->rhs_lua = LUA_NOREF;
}
mp->m_keylen = (int)STRLEN(mp->m_keys);
mp->m_noremap = noremap;
mp->m_nowait = args->nowait;
mp->m_silent = args->silent;
mp->m_mode = mode;
mp->m_simplified = simplified;
mp->m_expr = args->expr;
mp->m_replace_keycodes = args->replace_keycodes;
if (sid >= 0) {
mp->m_script_ctx.sc_sid = sid;
mp->m_script_ctx.sc_lnum = lnum;
} else {
mp->m_script_ctx = current_sctx;
mp->m_script_ctx.sc_lnum += sourcing_lnum;
nlua_set_sctx(&mp->m_script_ctx);
}
mp->m_desc = NULL;
if (args->desc != NULL) {
mp->m_desc = xstrdup(args->desc);
}
// add the new entry in front of the abbrlist or maphash[] list
if (is_abbr) {
mp->m_next = *abbr_table;
*abbr_table = mp;
} else {
const int n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
mp->m_next = map_table[n];
map_table[n] = mp;
}
}
/// Sets or removes a mapping or abbreviation in buffer `buf`. /// Sets or removes a mapping or abbreviation in buffer `buf`.
/// ///
/// @param maptype @see do_map /// @param maptype @see do_map
@@ -452,7 +512,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
abbr_table = &first_abbr; abbr_table = &first_abbr;
// For ":noremap" don't remap, otherwise do remap. // For ":noremap" don't remap, otherwise do remap.
if (maptype == 2) { if (maptype == MAPTYPE_NOREMAP) {
noremap = REMAP_NONE; noremap = REMAP_NONE;
} else { } else {
noremap = REMAP_YES; noremap = REMAP_YES;
@@ -470,10 +530,10 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
const bool has_lhs = (args->lhs[0] != NUL); const bool has_lhs = (args->lhs[0] != NUL);
const bool has_rhs = args->rhs_lua != LUA_NOREF || (args->rhs[0] != NUL) || args->rhs_is_noop; const bool has_rhs = args->rhs_lua != LUA_NOREF || (args->rhs[0] != NUL) || args->rhs_is_noop;
const bool do_print = !has_lhs || (maptype != 1 && !has_rhs); const bool do_print = !has_lhs || (maptype != MAPTYPE_UNMAP && !has_rhs);
// check for :unmap without argument // check for :unmap without argument
if (maptype == 1 && !has_lhs) { if (maptype == MAPTYPE_UNMAP && !has_lhs) {
retval = 1; retval = 1;
goto theend; goto theend;
} }
@@ -507,13 +567,11 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
goto theend; goto theend;
} }
if (is_abbrev && maptype != 1) { if (is_abbrev && maptype != MAPTYPE_UNMAP) {
//
// If an abbreviation ends in a keyword character, the // If an abbreviation ends in a keyword character, the
// rest must be all keyword-char or all non-keyword-char. // rest must be all keyword-char or all non-keyword-char.
// Otherwise we won't be able to find the start of it in a // Otherwise we won't be able to find the start of it in a
// vi-compatible way. // vi-compatible way.
//
int same = -1; int same = -1;
const int first = vim_iswordp(lhs); const int first = vim_iswordp(lhs);
@@ -551,7 +609,8 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
} }
// Check if a new local mapping wasn't already defined globally. // Check if a new local mapping wasn't already defined globally.
if (args->unique && map_table == buf->b_maphash && has_lhs && has_rhs && maptype != 1) { if (args->unique && map_table == buf->b_maphash && has_lhs && has_rhs
&& maptype != MAPTYPE_UNMAP) {
// need to loop over all global hash lists // need to loop over all global hash lists
for (int hash = 0; hash < 256 && !got_int; hash++) { for (int hash = 0; hash < 256 && !got_int; hash++) {
if (is_abbrev) { if (is_abbrev) {
@@ -581,7 +640,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
} }
// When listing global mappings, also list buffer-local ones here. // When listing global mappings, also list buffer-local ones here.
if (map_table != buf->b_maphash && !has_rhs && maptype != 1) { if (map_table != buf->b_maphash && !has_rhs && maptype != MAPTYPE_UNMAP) {
// need to loop over all global hash lists // need to loop over all global hash lists
for (int hash = 0; hash < 256 && !got_int; hash++) { for (int hash = 0; hash < 256 && !got_int; hash++) {
if (is_abbrev) { if (is_abbrev) {
@@ -616,7 +675,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
// entry with a matching 'to' part. This was done to allow ":ab foo bar" // entry with a matching 'to' part. This was done to allow ":ab foo bar"
// to be unmapped by typing ":unab foo", where "foo" will be replaced by // to be unmapped by typing ":unab foo", where "foo" will be replaced by
// "bar" because of the abbreviation. // "bar" because of the abbreviation.
for (int round = 0; (round == 0 || maptype == 1) && round <= 1 for (int round = 0; (round == 0 || maptype == MAPTYPE_UNMAP) && round <= 1
&& !did_it && !got_int; round++) { && !did_it && !got_int; round++) {
int hash_start, hash_end; int hash_start, hash_end;
if (has_lhs || is_abbrev) { if (has_lhs || is_abbrev) {
@@ -650,7 +709,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
p = mp->m_keys; p = mp->m_keys;
} }
if (STRNCMP(p, lhs, (size_t)(n < len ? n : len)) == 0) { if (STRNCMP(p, lhs, (size_t)(n < len ? n : len)) == 0) {
if (maptype == 1) { if (maptype == MAPTYPE_UNMAP) {
// Delete entry. // Delete entry.
// Only accept a full match. For abbreviations // Only accept a full match. For abbreviations
// we ignore trailing space when matching with // we ignore trailing space when matching with
@@ -746,7 +805,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
} }
} }
if (maptype == 1) { if (maptype == MAPTYPE_UNMAP) {
// delete entry // delete entry
if (!did_it) { if (!did_it) {
if (!keyround1_simplified) { if (!keyround1_simplified) {
@@ -780,51 +839,10 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
} }
// Get here when adding a new entry to the maphash[] list or abbrlist. // Get here when adding a new entry to the maphash[] list or abbrlist.
mp = xmalloc(sizeof(mapblock_T)); map_add(buf, map_table, abbr_table, lhs, args, noremap, mode, is_abbrev,
-1, // sid
// If CTRL-C has been mapped, don't always use it for Interrupting. 0, // lnum
if (*lhs == Ctrl_C) { keyround1_simplified);
if (map_table == buf->b_maphash) {
buf->b_mapped_ctrl_c |= mode;
} else {
mapped_ctrl_c |= mode;
}
}
mp->m_keys = vim_strsave(lhs);
mp->m_str = args->rhs;
mp->m_orig_str = args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!keyround1_simplified) {
args->rhs = NULL;
args->orig_rhs = NULL;
args->rhs_lua = LUA_NOREF;
}
mp->m_keylen = (int)STRLEN(mp->m_keys);
mp->m_noremap = noremap;
mp->m_nowait = args->nowait;
mp->m_silent = args->silent;
mp->m_mode = mode;
mp->m_simplified = keyround1_simplified; // Notice this when porting patch 8.2.0807
mp->m_expr = args->expr;
mp->m_replace_keycodes = args->replace_keycodes;
mp->m_script_ctx = current_sctx;
mp->m_script_ctx.sc_lnum += sourcing_lnum;
nlua_set_sctx(&mp->m_script_ctx);
mp->m_desc = NULL;
if (args->desc != NULL) {
mp->m_desc = xstrdup(args->desc);
}
// add the new entry in front of the abbrlist or maphash[] list
if (is_abbrev) {
mp->m_next = *abbr_table;
*abbr_table = mp;
} else {
n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
mp->m_next = map_table[n];
map_table[n] = mp;
}
} }
theend: theend:
@@ -863,7 +881,9 @@ theend:
/// for :cabbr mode is MODE_CMDLINE /// for :cabbr mode is MODE_CMDLINE
/// ``` /// ```
/// ///
/// @param maptype 0 for |:map|, 1 for |:unmap|, 2 for |noremap|. /// @param maptype MAPTYPE_MAP for |:map|
/// MAPTYPE_UNMAP for |:unmap|
/// MAPTYPE_NOREMAP for |noremap|.
/// @param arg C-string containing the arguments of the map/abbrev /// @param arg C-string containing the arguments of the map/abbrev
/// command, i.e. everything except the initial `:[X][nore]map`. /// command, i.e. everything except the initial `:[X][nore]map`.
/// - Cannot be a read-only string; it will be modified. /// - Cannot be a read-only string; it will be modified.
@@ -880,7 +900,7 @@ theend:
int do_map(int maptype, char_u *arg, int mode, bool is_abbrev) int do_map(int maptype, char_u *arg, int mode, bool is_abbrev)
{ {
MapArguments parsed_args; MapArguments parsed_args;
int result = str_to_mapargs(arg, maptype == 1, &parsed_args); int result = str_to_mapargs(arg, maptype == MAPTYPE_UNMAP, &parsed_args);
switch (result) { switch (result) {
case 0: case 0:
break; break;
@@ -1977,9 +1997,9 @@ void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// @param mp The maphash that contains the mapping information /// @param mp The maphash that contains the mapping information
/// @param buffer_value The "buffer" value /// @param buffer_value The "buffer" value
/// @param compatible True for compatible with old maparg() dict /// @param compatible True for compatible with old maparg() dict
static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, long buffer_value, static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp,
bool compatible) const char *lhsrawalt, long buffer_value, bool compatible)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ARG(1, 2)
{ {
char *const lhs = str2special_save((const char *)mp->m_keys, char *const lhs = str2special_save((const char *)mp->m_keys,
compatible, !compatible); compatible, !compatible);
@@ -2011,6 +2031,11 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, l
tv_dict_add_allocated_str(dict, S_LEN("desc"), xstrdup(mp->m_desc)); tv_dict_add_allocated_str(dict, S_LEN("desc"), xstrdup(mp->m_desc));
} }
tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs); tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs);
tv_dict_add_str(dict, S_LEN("lhsraw"), (const char *)mp->m_keys);
if (lhsrawalt != NULL) {
// Also add the value for the simplified entry.
tv_dict_add_str(dict, S_LEN("lhsrawalt"), lhsrawalt);
}
tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value); tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value);
tv_dict_add_nr(dict, S_LEN("script"), mp->m_noremap == REMAP_SCRIPT ? 1 : 0); tv_dict_add_nr(dict, S_LEN("script"), mp->m_noremap == REMAP_SCRIPT ? 1 : 0);
tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0); tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0);
@@ -2027,18 +2052,6 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, l
static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
{ {
char *keys_buf = NULL;
char_u *alt_keys_buf = NULL;
bool did_simplify = false;
char_u *rhs;
LuaRef rhs_lua;
int mode;
bool abbr = false;
bool get_dict = false;
mapblock_T *mp = NULL;
int buffer_local;
int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
// Return empty string for failure. // Return empty string for failure.
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
@@ -2048,8 +2061,11 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
return; return;
} }
char buf[NUMBUFLEN];
const char *which; const char *which;
char buf[NUMBUFLEN];
bool abbr = false;
bool get_dict = false;
if (argvars[1].v_type != VAR_UNKNOWN) { if (argvars[1].v_type != VAR_UNKNOWN) {
which = tv_get_string_buf_chk(&argvars[1], buf); which = tv_get_string_buf_chk(&argvars[1], buf);
if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_UNKNOWN) {
@@ -2065,13 +2081,19 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
return; return;
} }
mode = get_map_mode((char **)&which, 0); char *keys_buf = NULL;
char_u *alt_keys_buf = NULL;
bool did_simplify = false;
const int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
const int mode = get_map_mode((char **)&which, 0);
char_u *keys_simplified char_u *keys_simplified
= (char_u *)replace_termcodes(keys, = (char_u *)replace_termcodes(keys, STRLEN(keys), &keys_buf, flags, &did_simplify,
STRLEN(keys), &keys_buf, flags, &did_simplify,
CPO_TO_CPO_FLAGS); CPO_TO_CPO_FLAGS);
rhs = check_map(keys_simplified, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); mapblock_T *mp = NULL;
int buffer_local;
LuaRef rhs_lua;
char_u *rhs = check_map(keys_simplified, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua);
if (did_simplify) { if (did_simplify) {
// When the lhs is being simplified the not-simplified keys are // When the lhs is being simplified the not-simplified keys are
// preferred for printing, like in do_map(). // preferred for printing, like in do_map().
@@ -2100,7 +2122,8 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
tv_dict_alloc_ret(rettv); tv_dict_alloc_ret(rettv);
if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) { if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) {
// Return a dictionary. // Return a dictionary.
mapblock_fill_dict(rettv->vval.v_dict, mp, buffer_local, true); mapblock_fill_dict(rettv->vval.v_dict, mp, did_simplify ? (char *)keys_simplified : NULL,
buffer_local, true);
} }
} }
@@ -2108,6 +2131,74 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
xfree(alt_keys_buf); xfree(alt_keys_buf);
} }
/// "mapset()" function
void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char buf[NUMBUFLEN];
const char *which = tv_get_string_buf_chk(&argvars[0], buf);
if (which == NULL) {
return;
}
const int mode = get_map_mode((char **)&which, 0);
const bool is_abbr = tv_get_number(&argvars[1]) != 0;
if (argvars[2].v_type != VAR_DICT) {
emsg(_(e_dictreq));
return;
}
dict_T *d = argvars[2].vval.v_dict;
// Get the values in the same order as above in get_maparg().
char *lhs = tv_dict_get_string(d, "lhs", false);
char *lhsraw = tv_dict_get_string(d, "lhsraw", false);
char *lhsrawalt = tv_dict_get_string(d, "lhsrawalt", false);
char *rhs = tv_dict_get_string(d, "rhs", false);
if (lhs == NULL || lhsraw == NULL || rhs == NULL) {
emsg(_("E460: entries missing in mapset() dict argument"));
return;
}
char *orig_rhs = rhs;
char *arg_buf = NULL;
rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
int noremap = tv_dict_get_number(d, "noremap") ? REMAP_NONE : 0;
if (tv_dict_get_number(d, "script") != 0) {
noremap = REMAP_SCRIPT;
}
MapArguments args = { // TODO(zeertzjq): support restoring "callback"?
.rhs = (char_u *)rhs,
.rhs_lua = LUA_NOREF,
.orig_rhs = vim_strsave((char_u *)orig_rhs),
.expr = tv_dict_get_number(d, "expr") != 0,
.silent = tv_dict_get_number(d, "silent") != 0,
.nowait = tv_dict_get_number(d, "nowait") != 0,
.replace_keycodes = tv_dict_get_number(d, "replace_keycodes") != 0,
.desc = tv_dict_get_string(d, "desc", false),
};
scid_T sid = (scid_T)tv_dict_get_number(d, "sid");
linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum");
bool buffer = tv_dict_get_number(d, "buffer") != 0;
// mode from the dict is not used
mapblock_T **map_table = buffer ? curbuf->b_maphash : maphash;
mapblock_T **abbr_table = buffer ? &curbuf->b_first_abbr : &first_abbr;
// Delete any existing mapping for this lhs and mode.
MapArguments unmap_args = MAP_ARGUMENTS_INIT;
set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, 0, &unmap_args);
unmap_args.buffer = buffer;
buf_do_map(MAPTYPE_UNMAP, &unmap_args, mode, false, curbuf);
xfree(unmap_args.rhs);
xfree(unmap_args.orig_rhs);
if (lhsrawalt != NULL) {
map_add(curbuf, map_table, abbr_table, (char_u *)lhsrawalt, &args, noremap, mode, is_abbr,
sid, lnum, true);
}
map_add(curbuf, map_table, abbr_table, (char_u *)lhsraw, &args, noremap, mode, is_abbr,
sid, lnum, false);
}
/// "maparg()" function /// "maparg()" function
void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr) void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
@@ -2130,11 +2221,11 @@ void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// @param buffer If true, make a buffer-local mapping for curbuf /// @param buffer If true, make a buffer-local mapping for curbuf
void add_map(char *lhs, char *rhs, int mode, bool buffer) void add_map(char *lhs, char *rhs, int mode, bool buffer)
{ {
MapArguments args = { 0 }; MapArguments args = MAP_ARGUMENTS_INIT;
set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, 0, &args); set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, 0, &args);
args.buffer = buffer; args.buffer = buffer;
buf_do_map(2, &args, mode, false, curbuf); buf_do_map(MAPTYPE_NOREMAP, &args, mode, false, curbuf);
xfree(args.rhs); xfree(args.rhs);
xfree(args.orig_rhs); xfree(args.orig_rhs);
} }
@@ -2314,7 +2405,8 @@ static void do_exmap(exarg_T *eap, int isabbrev)
char *cmdp = eap->cmd; char *cmdp = eap->cmd;
mode = get_map_mode(&cmdp, eap->forceit || isabbrev); mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'), switch (do_map((*cmdp == 'n') ? MAPTYPE_NOREMAP
: (*cmdp == 'u') ? MAPTYPE_UNMAP : MAPTYPE_MAP,
(char_u *)eap->arg, mode, isabbrev)) { (char_u *)eap->arg, mode, isabbrev)) {
case 1: case 1:
emsg(_(e_invarg)); emsg(_(e_invarg));
@@ -2474,11 +2566,11 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod
} }
// buf_do_map() reads noremap/unmap as its own argument. // buf_do_map() reads noremap/unmap as its own argument.
int maptype_val = 0; int maptype_val = MAPTYPE_MAP;
if (is_unmap) { if (is_unmap) {
maptype_val = 1; maptype_val = MAPTYPE_UNMAP;
} else if (is_noremap) { } else if (is_noremap) {
maptype_val = 2; maptype_val = MAPTYPE_NOREMAP;
} }
switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) { switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) {
@@ -2536,7 +2628,7 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua)
} }
// Check for correct mode // Check for correct mode
if (int_mode & current_maphash->m_mode) { if (int_mode & current_maphash->m_mode) {
mapblock_fill_dict(dict, current_maphash, buffer_value, false); mapblock_fill_dict(dict, current_maphash, NULL, buffer_value, false);
Object api_dict = vim_to_object((typval_T[]) { { .v_type = VAR_DICT, Object api_dict = vim_to_object((typval_T[]) { { .v_type = VAR_DICT,
.vval.v_dict = dict } }); .vval.v_dict = dict } });
if (from_lua) { if (from_lua) {

View File

@@ -48,6 +48,11 @@ typedef struct map_arguments MapArguments;
#define MAP_ARGUMENTS_INIT { false, false, false, false, false, false, false, false, \ #define MAP_ARGUMENTS_INIT { false, false, false, false, false, false, false, false, \
{ 0 }, 0, { 0 }, 0, NULL, 0, LUA_NOREF, false, NULL, 0, NULL } { 0 }, 0, { 0 }, 0, NULL, 0, LUA_NOREF, false, NULL, 0, NULL }
// Used for the first argument of do_map()
#define MAPTYPE_MAP 0
#define MAPTYPE_UNMAP 1
#define MAPTYPE_NOREMAP 2
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mapping.h.generated.h" # include "mapping.h.generated.h"
#endif #endif

View File

@@ -1,12 +1,12 @@
" Tests for maparg(). " Tests for maparg(), mapcheck() and mapset().
" Also test utf8 map with a 0x80 byte. " Also test utf8 map with a 0x80 byte.
" Also test mapcheck() " Also test mapcheck()
function s:SID() func s:SID()
return str2nr(matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')) return str2nr(matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$'))
endfun endfunc
function Test_maparg() func Test_maparg()
new new
set cpo-=< set cpo-=<
set encoding=utf8 set encoding=utf8
@@ -17,24 +17,28 @@ function Test_maparg()
vnoremap <script> <buffer> <expr> <silent> bar isbar vnoremap <script> <buffer> <expr> <silent> bar isbar
call assert_equal("is<F4>foo", maparg('foo<C-V>')) call assert_equal("is<F4>foo", maparg('foo<C-V>'))
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo<C-V>', call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo<C-V>',
\ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16",
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, \ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1,
\ 'rhs': 'is<F4>foo', 'buffer': 0}, \ 'rhs': 'is<F4>foo', 'buffer': 0},
\ maparg('foo<C-V>', '', 0, 1)) \ maparg('foo<C-V>', '', 0, 1))
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar', 'mode': 'v', call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar',
\ 'lhsraw': 'bar', 'mode': 'v',
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'lnum': lnum + 2, \ 'nowait': 0, 'expr': 1, 'sid': sid, 'lnum': lnum + 2,
\ 'rhs': 'isbar', 'buffer': 1}, \ 'rhs': 'isbar', 'buffer': 1},
\ '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
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo', 'mode': ' ', call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo',
\ 'lhsraw': 'foo', 'mode': ' ',
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'bar', \ 'nowait': 1, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'bar',
\ 'buffer': 1}, \ 'buffer': 1},
\ maparg('foo', '', 0, 1)) \ maparg('foo', '', 0, 1))
let lnum = expand('<sflnum>') let lnum = expand('<sflnum>')
tmap baz foo tmap baz foo
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'baz', 'mode': 't', call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'baz',
\ 'lhsraw': 'baz', 'mode': 't',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'foo', \ 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'foo',
\ 'buffer': 0}, \ 'buffer': 0},
\ maparg('baz', 't', 0, 1)) \ maparg('baz', 't', 0, 1))
map abc x<char-114>x map abc x<char-114>x
@@ -81,6 +85,12 @@ function Test_maparg()
call assert_equal(['{', 'w', 's'], [d.lhs, d.rhs, d.mode]) call assert_equal(['{', 'w', 's'], [d.lhs, d.rhs, d.mode])
sunmap { sunmap {
map <C-I> foo
unmap <Tab>
" This used to cause a segfault
call maparg('<C-I>', '', 0, 1)
unmap <C-I>
map abc <Nop> map abc <Nop>
call assert_equal("<Nop>", maparg('abc')) call assert_equal("<Nop>", maparg('abc'))
unmap abc unmap abc
@@ -89,7 +99,8 @@ function Test_maparg()
let d = maparg('esc', 'i', 1, 1) let d = maparg('esc', 'i', 1, 1)
call assert_equal(['esc', "\<C-V>\<C-V>\<Esc>", '!'], [d.lhs, d.rhs, d.mode]) call assert_equal(['esc', "\<C-V>\<C-V>\<Esc>", '!'], [d.lhs, d.rhs, d.mode])
abclear abclear
endfunction unlet d
endfunc
func Test_mapcheck() func Test_mapcheck()
call assert_equal('', mapcheck('a')) call assert_equal('', mapcheck('a'))
@@ -130,7 +141,7 @@ func Test_mapcheck()
unabbr ab unabbr ab
endfunc endfunc
function Test_range_map() func Test_range_map()
new new
" Outside of the range, minimum " Outside of the range, minimum
inoremap <Char-0x1040> a inoremap <Char-0x1040> a
@@ -145,6 +156,147 @@ function Test_range_map()
inoremap <Char-0xf040> d inoremap <Char-0xf040> d
execute "normal a\uf040\<Esc>" execute "normal a\uf040\<Esc>"
call assert_equal("abcd", getline(1)) call assert_equal("abcd", getline(1))
endfunction endfunc
func One_mapset_test(keys)
exe 'nnoremap ' .. a:keys .. ' original<CR>'
let orig = maparg(a:keys, 'n', 0, 1)
call assert_equal(a:keys, orig.lhs)
call assert_equal('original<CR>', orig.rhs)
call assert_equal('n', orig.mode)
exe 'nunmap ' .. a:keys
let d = maparg(a:keys, 'n', 0, 1)
call assert_equal({}, d)
call mapset('n', 0, orig)
let d = maparg(a:keys, 'n', 0, 1)
call assert_equal(a:keys, d.lhs)
call assert_equal('original<CR>', d.rhs)
call assert_equal('n', d.mode)
exe 'nunmap ' .. a:keys
endfunc
func Test_mapset()
call One_mapset_test('K')
call One_mapset_test('<F3>')
" Check <> key conversion
new
inoremap K one<Left>x
call feedkeys("iK\<Esc>", 'xt')
call assert_equal('onxe', getline(1))
let orig = maparg('K', 'i', 0, 1)
call assert_equal('K', orig.lhs)
call assert_equal('one<Left>x', orig.rhs)
call assert_equal('i', orig.mode)
iunmap K
let d = maparg('K', 'i', 0, 1)
call assert_equal({}, d)
call mapset('i', 0, orig)
call feedkeys("SK\<Esc>", 'xt')
call assert_equal('onxe', getline(1))
iunmap K
" Test literal <CR> using a backslash
let cpo_save = &cpo
set cpo-=B
inoremap K one\<CR>two
call feedkeys("SK\<Esc>", 'xt')
call assert_equal('one<CR>two', getline(1))
let orig = maparg('K', 'i', 0, 1)
call assert_equal('K', orig.lhs)
call assert_equal('one\<CR>two', orig.rhs)
call assert_equal('i', orig.mode)
iunmap K
let d = maparg('K', 'i', 0, 1)
call assert_equal({}, d)
call mapset('i', 0, orig)
call feedkeys("SK\<Esc>", 'xt')
call assert_equal('one<CR>two', getline(1))
iunmap K
" Test literal <CR> using CTRL-V
inoremap K one<CR>two
call feedkeys("SK\<Esc>", 'xt')
call assert_equal('one<CR>two', getline(1))
let orig = maparg('K', 'i', 0, 1)
call assert_equal('K', orig.lhs)
call assert_equal("one\x16<CR>two", orig.rhs)
call assert_equal('i', orig.mode)
iunmap K
let d = maparg('K', 'i', 0, 1)
call assert_equal({}, d)
call mapset('i', 0, orig)
call feedkeys("SK\<Esc>", 'xt')
call assert_equal('one<CR>two', getline(1))
iunmap K
let &cpo = cpo_save
bwipe!
call assert_fails('call mapset([], v:false, {})', 'E730:')
endfunc
func Check_ctrlb_map(d, check_alt)
call assert_equal('<C-B>', a:d.lhs)
if a:check_alt
call assert_equal("\x80\xfc\x04B", a:d.lhsraw)
call assert_equal("\x02", a:d.lhsrawalt)
else
call assert_equal("\x02", a:d.lhsraw)
endif
endfunc
func Test_map_local()
nmap a global
nmap <buffer>a local
let prev_map_list = split(execute('nmap a'), "\n")
call assert_match('n\s*a\s*@local', prev_map_list[0])
call assert_match('n\s*a\s*global', prev_map_list[1])
let mapping = maparg('a', 'n', 0, 1)
call assert_equal(1, mapping.buffer)
let mapping.rhs = 'new_local'
call mapset('n', 0, mapping)
" Check that the global mapping is left untouched.
let map_list = split(execute('nmap a'), "\n")
call assert_match('n\s*a\s*@new_local', map_list[0])
call assert_match('n\s*a\s*global', map_list[1])
nunmap a
endfunc
func Test_map_restore()
" Test restoring map with alternate keycode
nmap <C-B> back
let d = maparg('<C-B>', 'n', 0, 1)
call Check_ctrlb_map(d, 1)
let dsimp = maparg("\x02", 'n', 0, 1)
call Check_ctrlb_map(dsimp, 0)
nunmap <C-B>
call mapset('n', 0, d)
let d = maparg('<C-B>', 'n', 0, 1)
call Check_ctrlb_map(d, 1)
let dsimp = maparg("\x02", 'n', 0, 1)
call Check_ctrlb_map(dsimp, 0)
nunmap <C-B>
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -25,6 +25,7 @@ describe('nvim_get_keymap', function()
local foo_bar_string = 'nnoremap foo bar' local foo_bar_string = 'nnoremap foo bar'
local foo_bar_map_table = { local foo_bar_map_table = {
lhs='foo', lhs='foo',
lhsraw='foo',
script=0, script=0,
silent=0, silent=0,
rhs='bar', rhs='bar',
@@ -56,6 +57,7 @@ describe('nvim_get_keymap', function()
command('nnoremap foo_longer bar_longer') command('nnoremap foo_longer bar_longer')
local foolong_bar_map_table = shallowcopy(foo_bar_map_table) local foolong_bar_map_table = shallowcopy(foo_bar_map_table)
foolong_bar_map_table['lhs'] = 'foo_longer' foolong_bar_map_table['lhs'] = 'foo_longer'
foolong_bar_map_table['lhsraw'] = 'foo_longer'
foolong_bar_map_table['rhs'] = 'bar_longer' foolong_bar_map_table['rhs'] = 'bar_longer'
eq({foolong_bar_map_table, foo_bar_map_table}, eq({foolong_bar_map_table, foo_bar_map_table},
@@ -87,6 +89,7 @@ describe('nvim_get_keymap', function()
command('nnoremap foo_longer bar_longer') command('nnoremap foo_longer bar_longer')
local foolong_bar_map_table = shallowcopy(foo_bar_map_table) local foolong_bar_map_table = shallowcopy(foo_bar_map_table)
foolong_bar_map_table['lhs'] = 'foo_longer' foolong_bar_map_table['lhs'] = 'foo_longer'
foolong_bar_map_table['lhsraw'] = 'foo_longer'
foolong_bar_map_table['rhs'] = 'bar_longer' foolong_bar_map_table['rhs'] = 'bar_longer'
local buffer_table = shallowcopy(foo_bar_map_table) local buffer_table = shallowcopy(foo_bar_map_table)
@@ -283,6 +286,16 @@ describe('nvim_get_keymap', function()
command('onoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\') command('onoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\')
command('onoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\') command('onoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\')
-- wrapper around get_keymap() that drops "lhsraw" and "lhsrawalt" which are hard to check
local function get_keymap_noraw(...)
local ret = meths.get_keymap(...)
for _, item in ipairs(ret) do
item.lhsraw = nil
item.lhsrawalt = nil
end
return ret
end
for _, cmd in ipairs({ for _, cmd in ipairs({
'set cpo-=B', 'set cpo-=B',
'set cpo+=B', 'set cpo+=B',
@@ -290,22 +303,23 @@ describe('nvim_get_keymap', function()
command(cmd) command(cmd)
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'), eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')}, cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')},
meths.get_keymap('n')) get_keymap_noraw('n'))
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'), eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'),
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')}, cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')},
meths.get_keymap('x')) get_keymap_noraw('x'))
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'), eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'),
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')}, cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')},
meths.get_keymap('s')) get_keymap_noraw('s'))
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'), eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'),
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')}, cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')},
meths.get_keymap('o')) get_keymap_noraw('o'))
end end
end) end)
it('always uses space for space and bar for bar', function() it('always uses space for space and bar for bar', function()
local space_table = { local space_table = {
lhs='| |', lhs='| |',
lhsraw='| |',
rhs='| |', rhs='| |',
mode='n', mode='n',
script=0, script=0,
@@ -340,6 +354,7 @@ describe('nvim_get_keymap', function()
mapargs[1].callback = nil mapargs[1].callback = nil
eq({ eq({
lhs='asdf', lhs='asdf',
lhsraw='asdf',
script=0, script=0,
silent=0, silent=0,
expr=0, expr=0,
@@ -356,6 +371,7 @@ describe('nvim_get_keymap', function()
meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"}) meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"})
eq({ eq({
lhs='lhs', lhs='lhs',
lhsraw='lhs',
rhs='rhs', rhs='rhs',
script=0, script=0,
silent=0, silent=0,
@@ -413,7 +429,11 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
-- Gets a maparg() dict from Nvim, if one exists. -- Gets a maparg() dict from Nvim, if one exists.
local function get_mapargs(mode, lhs) local function get_mapargs(mode, lhs)
return funcs.maparg(lhs, normalize_mapmode(mode), false, true) local mapargs = funcs.maparg(lhs, normalize_mapmode(mode), false, true)
-- drop "lhsraw" and "lhsrawalt" which are hard to check
mapargs.lhsraw = nil
mapargs.lhsrawalt = nil
return mapargs
end end
it('error on empty LHS', function() it('error on empty LHS', function()
@@ -817,6 +837,8 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
local mapargs = funcs.maparg('asdf', 'n', false, true) local mapargs = funcs.maparg('asdf', 'n', false, true)
assert(type(mapargs.callback) == 'number', 'callback is not luaref number') assert(type(mapargs.callback) == 'number', 'callback is not luaref number')
mapargs.callback = nil mapargs.callback = nil
mapargs.lhsraw = nil
mapargs.lhsrawalt = nil
eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs) eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs)
end) end)

View File

@@ -1,59 +0,0 @@
-- Tests for maparg().
-- Also test utf8 map with a 0x80 byte.
local helpers = require('test.functional.helpers')(after_each)
local clear, feed = helpers.clear, helpers.feed
local command, expect = helpers.command, helpers.expect
local poke_eventloop = helpers.poke_eventloop
describe('maparg()', function()
setup(clear)
it('is working', function()
command('set cpo-=<')
-- Test maparg() with a string result
command('map foo<C-V> is<F4>foo')
command('vnoremap <script> <buffer> <expr> <silent> bar isbar')
command([[call append('$', maparg('foo<C-V>'))]])
command([[call append('$', string(maparg('foo<C-V>', '', 0, 1)))]])
command([[call append('$', string(maparg('bar', '', 0, 1)))]])
command('map <buffer> <nowait> foo bar')
command([[call append('$', string(maparg('foo', '', 0, 1)))]])
command('map abc x<char-114>x')
command([[call append('$', maparg('abc'))]])
command('map abc y<S-char-114>y')
command([[call append('$', maparg('abc'))]])
feed('Go<esc>:<cr>')
poke_eventloop()
-- Outside of the range, minimum
command('inoremap <Char-0x1040> a')
command([[execute "normal a\u1040\<Esc>"]])
-- Inside of the range, minimum
command('inoremap <Char-0x103f> b')
command([[execute "normal a\u103f\<Esc>"]])
-- Inside of the range, maximum
command('inoremap <Char-0xf03f> c')
command([[execute "normal a\uf03f\<Esc>"]])
-- Outside of the range, maximum
command('inoremap <Char-0xf040> d')
command([[execute "normal a\uf040\<Esc>"]])
-- Remove empty line
command('1d')
-- Assert buffer contents.
expect([[
is<F4>foo
{'lnum': 0, 'script': 0, 'silent': 0, 'noremap': 0, 'lhs': 'foo<C-V>', 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': 0, 'rhs': 'is<F4>foo', 'buffer': 0}
{'lnum': 0, 'script': 1, 'silent': 1, 'noremap': 1, 'lhs': 'bar', 'mode': 'v', 'nowait': 0, 'expr': 1, 'sid': 0, 'rhs': 'isbar', 'buffer': 1}
{'lnum': 0, 'script': 0, 'silent': 0, 'noremap': 0, 'lhs': 'foo', 'mode': ' ', 'nowait': 1, 'expr': 0, 'sid': 0, 'rhs': 'bar', 'buffer': 1}
xrx
yRy
abcd]])
end)
end)

View File

@@ -3,7 +3,10 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear local clear = helpers.clear
local eq = helpers.eq local eq = helpers.eq
local eval = helpers.eval local eval = helpers.eval
local expect = helpers.expect
local feed = helpers.feed
local funcs = helpers.funcs local funcs = helpers.funcs
local meths = helpers.meths
local nvim = helpers.nvim local nvim = helpers.nvim
local source = helpers.source local source = helpers.source
local command = helpers.command local command = helpers.command
@@ -13,6 +16,7 @@ describe('maparg()', function()
local foo_bar_map_table = { local foo_bar_map_table = {
lhs='foo', lhs='foo',
lhsraw='foo',
script=0, script=0,
silent=0, silent=0,
rhs='bar', rhs='bar',
@@ -141,6 +145,7 @@ describe('maparg()', function()
local function acmap(lhs, rhs) local function acmap(lhs, rhs)
return { return {
lhs = ac(lhs), lhs = ac(lhs),
lhsraw = ac(lhs),
rhs = ac(rhs), rhs = ac(rhs),
buffer = 0, buffer = 0,
@@ -161,3 +166,32 @@ describe('maparg()', function()
eq(acmap('e`', 'f`'), funcs.maparg(ac('e`'), 'n', 0, 1)) eq(acmap('e`', 'f`'), funcs.maparg(ac('e`'), 'n', 0, 1))
end) end)
end) end)
describe('mapset()', function()
before_each(clear)
it('can restore mapping description from the dict returned by maparg()', function()
meths.set_keymap('n', 'lhs', 'rhs', {desc = 'map description'})
eq('\nn lhs rhs\n map description',
helpers.exec_capture("nmap lhs"))
local mapargs = funcs.maparg('lhs', 'n', false, true)
meths.del_keymap('n', 'lhs')
eq('\nNo mapping found', helpers.exec_capture("nmap lhs"))
funcs.mapset('n', false, mapargs)
eq('\nn lhs rhs\n map description',
helpers.exec_capture("nmap lhs"))
end)
it('can restore "replace_keycodes" from the dict returned by maparg()', function()
meths.set_keymap('i', 'foo', [['<l' .. 't>']], {expr = true, replace_keycodes = true})
feed('Afoo')
expect('<')
local mapargs = funcs.maparg('foo', 'i', false, true)
meths.set_keymap('i', 'foo', [['<l' .. 't>']], {expr = true})
feed('foo')
expect('<<lt>')
funcs.mapset('i', false, mapargs)
feed('foo')
expect('<<lt><')
end)
end)