aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-07-30 07:35:25 +0800
committerGitHub <noreply@github.com>2024-07-30 07:35:25 +0800
commit4b852bc555121f888a284dde45a56a0b7a42b851 (patch)
treeef2853df0c60b432398ba802a497ee1470ff34ec /src
parentd131c48c823c30f519506eddcaef662dad5afa43 (diff)
downloadrneovim-4b852bc555121f888a284dde45a56a0b7a42b851.tar.gz
rneovim-4b852bc555121f888a284dde45a56a0b7a42b851.tar.bz2
rneovim-4b852bc555121f888a284dde45a56a0b7a42b851.zip
vim-patch:9.1.0642: Check that mapping rhs starts with lhs fails if not simplified (#29909)
Problem: Check that mapping rhs starts with lhs doesn't work if lhs is not simplified. Solution: Keep track of the mapblock containing the alternative lhs and also compare with it (zeertzjq). fixes: vim/vim#15376 closes: vim/vim#15384 https://github.com/vim/vim/commit/9d997addc7bd0fd132a809cf497ed816e61fcd25 Cherry-pick removal of save_m_str from patch 8.2.4059.
Diffstat (limited to 'src')
-rw-r--r--src/nvim/getchar.c24
-rw-r--r--src/nvim/mapping.c71
-rw-r--r--src/nvim/mapping_defs.h3
3 files changed, 60 insertions, 38 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index a73824bdf5..6e441757dc 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2341,8 +2341,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
const int save_m_noremap = mp->m_noremap;
const bool save_m_silent = mp->m_silent;
char *save_m_keys = NULL; // only saved when needed
- char *save_m_str = NULL; // only saved when needed
- const LuaRef save_m_luaref = mp->m_luaref;
+ char *save_alt_m_keys = NULL; // only saved when needed
// Handle ":map <expr>": evaluate the {rhs} as an
// expression. Also save and restore the command line
@@ -2356,9 +2355,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
may_garbage_collect = false;
save_m_keys = xstrdup(mp->m_keys);
- if (save_m_luaref == LUA_NOREF) {
- save_m_str = xstrdup(mp->m_str);
- }
+ save_alt_m_keys = mp->m_alt != NULL ? xstrdup(mp->m_alt->m_keys) : NULL;
map_str = eval_map_expr(mp, NUL);
if ((map_str == NULL || *map_str == NUL)) {
@@ -2409,11 +2406,18 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
if (save_m_noremap != REMAP_YES) {
noremap = save_m_noremap;
- } else if (strncmp(map_str, save_m_keys != NULL ? save_m_keys : mp->m_keys,
- (size_t)keylen) != 0) {
- noremap = REMAP_YES;
- } else {
+ } else if (save_m_expr
+ ? strncmp(map_str, save_m_keys, (size_t)keylen) == 0
+ || (save_alt_m_keys != NULL
+ && strncmp(map_str, save_alt_m_keys,
+ strlen(save_alt_m_keys)) == 0)
+ : strncmp(map_str, mp->m_keys, (size_t)keylen) == 0
+ || (mp->m_alt != NULL
+ && strncmp(map_str, mp->m_alt->m_keys,
+ strlen(mp->m_alt->m_keys)) == 0)) {
noremap = REMAP_SKIP;
+ } else {
+ noremap = REMAP_YES;
}
i = ins_typebuf(map_str, noremap, 0, true, cmd_silent || save_m_silent);
if (save_m_expr) {
@@ -2421,7 +2425,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
}
}
xfree(save_m_keys);
- xfree(save_m_str);
+ xfree(save_alt_m_keys);
*keylenp = keylen;
if (i == FAIL) {
return map_result_fail;
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 167111f3ae..dfb540da84 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -151,7 +151,9 @@ static void mapblock_free(mapblock_T **mpp)
{
mapblock_T *mp = *mpp;
xfree(mp->m_keys);
- if (!mp->m_simplified) {
+ if (mp->m_alt != NULL) {
+ mp->m_alt->m_alt = NULL;
+ } else {
NLUA_CLEAR_REF(mp->m_luaref);
xfree(mp->m_str);
xfree(mp->m_orig_str);
@@ -493,13 +495,13 @@ static int str_to_mapargs(const char *strargs, bool is_unmap, MapArguments *mapa
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 args "rhs", "rhs_lua", "orig_rhs", "expr", "silent", "nowait",
+/// "replace_keycodes" and "desc" fields are used.
/// @param sid 0 to use current_sctx
-static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, const char *keys,
- MapArguments *args, int noremap, int mode, bool is_abbr, scid_T sid,
- linenr_T lnum, bool simplified)
+static mapblock_T *map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table,
+ const char *keys, MapArguments *args, int noremap, int mode,
+ bool is_abbr, scid_T sid, linenr_T lnum, bool simplified)
+ FUNC_ATTR_NONNULL_RET
{
mapblock_T *mp = xcalloc(1, sizeof(mapblock_T));
@@ -516,11 +518,6 @@ static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table,
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;
@@ -551,6 +548,7 @@ static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table,
mp->m_next = map_table[n];
map_table[n] = mp;
}
+ return mp;
}
/// Sets or removes a mapping or abbreviation in buffer `buf`.
@@ -571,6 +569,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
// mappings/abbreviations, not the globals.
mapblock_T **map_table = args->buffer ? buf->b_maphash : maphash;
mapblock_T **abbr_table = args->buffer ? &buf->b_first_abbr : &first_abbr;
+ mapblock_T *mp_result[2] = { NULL, NULL };
// For ":noremap" don't remap, otherwise do remap.
int noremap = args->script ? REMAP_SCRIPT
@@ -805,19 +804,16 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
mp->m_mode &= ~mode; // remove mode bits
if (mp->m_mode == 0 && !did_it) { // reuse entry
XFREE_CLEAR(mp->m_desc);
- if (!mp->m_simplified) {
+ if (mp->m_alt != NULL) {
+ mp->m_alt = mp->m_alt->m_alt = NULL;
+ } else {
NLUA_CLEAR_REF(mp->m_luaref);
- XFREE_CLEAR(mp->m_str);
- XFREE_CLEAR(mp->m_orig_str);
+ xfree(mp->m_str);
+ xfree(mp->m_orig_str);
}
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_noremap = noremap;
mp->m_nowait = args->nowait;
mp->m_silent = args->silent;
@@ -831,6 +827,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
if (args->desc != NULL) {
mp->m_desc = xstrdup(args->desc);
}
+ mp_result[keyround - 1] = mp;
did_it = true;
}
}
@@ -889,13 +886,24 @@ 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.
- map_add(buf, map_table, abbr_table, lhs, args, noremap, mode, is_abbrev,
- 0, // sid
- 0, // lnum
- keyround1_simplified);
+ mp_result[keyround - 1] = map_add(buf, map_table, abbr_table, lhs,
+ args, noremap, mode, is_abbrev,
+ 0, // sid
+ 0, // lnum
+ keyround1_simplified);
+ }
+
+ if (mp_result[0] != NULL && mp_result[1] != NULL) {
+ mp_result[0]->m_alt = mp_result[1];
+ mp_result[1]->m_alt = mp_result[0];
}
theend:
+ if (mp_result[0] != NULL || mp_result[1] != NULL) {
+ args->rhs = NULL;
+ args->orig_rhs = NULL;
+ args->rhs_lua = LUA_NOREF;
+ }
return retval;
}
@@ -2348,12 +2356,19 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
xfree(unmap_args.rhs);
xfree(unmap_args.orig_rhs);
+ mapblock_T *mp_result[2] = { NULL, NULL };
+
+ mp_result[0] = map_add(curbuf, map_table, abbr_table, lhsraw, &args,
+ noremap, mode, is_abbr, sid, lnum, false);
if (lhsrawalt != NULL) {
- map_add(curbuf, map_table, abbr_table, lhsrawalt, &args, noremap, mode, is_abbr,
- sid, lnum, true);
+ mp_result[1] = map_add(curbuf, map_table, abbr_table, lhsrawalt, &args,
+ noremap, mode, is_abbr, sid, lnum, true);
+ }
+
+ if (mp_result[0] != NULL && mp_result[1] != NULL) {
+ mp_result[0]->m_alt = mp_result[1];
+ mp_result[1]->m_alt = mp_result[0];
}
- map_add(curbuf, map_table, abbr_table, lhsraw, &args, noremap, mode, is_abbr,
- sid, lnum, false);
}
/// "maplist()" function
diff --git a/src/nvim/mapping_defs.h b/src/nvim/mapping_defs.h
index 05b8aef23a..4a04b1ebfb 100644
--- a/src/nvim/mapping_defs.h
+++ b/src/nvim/mapping_defs.h
@@ -10,6 +10,9 @@ enum { MAXMAPLEN = 50, }; ///< Maximum length of key sequence to be mapped.
typedef struct mapblock mapblock_T;
struct mapblock {
mapblock_T *m_next; ///< next mapblock in list
+ mapblock_T *m_alt; ///< pointer to mapblock of the same mapping
+ ///< with an alternative form of m_keys, or NULL
+ ///< if there is no such mapblock
char *m_keys; ///< mapped from, lhs
char *m_str; ///< mapped to, rhs
char *m_orig_str; ///< rhs as entered by the user